Setting up OpenSSL with Resin 4.0.32 on Ubuntu 12.0.4
From Resin 4.0 Wiki
For this exercise, I am using Amazon EC2 to startup a clean Ubuntu 12.0.4 instance. One advantage that Resin has over other similar products is integration with OpenSSL. OpenSSL is much faster and less resource intensive than the SSL/TLS support that ships with Java. If you use Resin, you want to use OpenSSL, it is more scalable and faster.
For this exercise, I started up a 64 bit large instance in Amazon EC2 and I am using Ubuntu 12.0.4 with Resin 4.0.32.
Contents |
Install Resin
I am following the instructions here for setup:
$ sudo add-apt-repository http://caucho.com/download/debian
Then update the repo cache
$ sudo apt-get update
This is now broken with Ubuntu 12.0.4. It will work again in Resin 4.0.33 and beyond.
If you are using Resin 4.0.32 and before do this instead:
$ wget http://www.caucho.com/download/debian/dists/unstable/multiverse/binary-amd64/resin-pro_4.0.32-amd64.deb
Install Java 7 SDK (or Java 6 SDK) and OpenSSL as follows:
$ sudo apt-get -f install $ sudo apt-get install openjdk-7-jdk $ sudo apt-get install libssl-dev $ sudo dpkg -i resin-pro_4.0.32-amd64.deb
(sudo apt-get install works in Resin 4.0.33 for Debian, but not for Resin 4.0.32.)
Generate a resin password.
$ resinctl password-generate admin mypassword admin_user : admin admin_password : {SSHA}yAKopu5id740xAoePKZOGyAtu78DpZck
Add the username and password to /etc/resin/resin.properties and turn stuff on. (Leave most of resin.properties alone, unless it is mentioned in the following listing.)
# Enable /resin-doc Resin documentation resin_doc : true app.https : 8443 web.http : 8080 web.https : 8443 # Must be identical between web, app, and cache clusters. cluster_system_key : changeme # Enable remote admin (for remote CLI and for EC2 ext: triad discovery) remote_admin_enable : true # Enable /resin-admin web administration console web_admin_enable : true # Permit access to /resin-admin from non-local network ip-addresses web_admin_external : true # Require HTTPS to access /resin-admin web_admin_ssl : true # Enable Resin REST Admin rest_admin_enable : true # Require SSL for REST Admin rest_admin_ssl : true admin_user : admin admin_password : {SSHA}ypqpON4IGSWY6XZ6NtU9uadsfasdfasdfasdfasdf
The above turns on the Resin web admin remotely over SSL and we can use that to test our SSL setup.
Resin will create a self signed certificate so go ahead and load the admin to test your Resin setup before we get started.
In order to get OpenSSL to work, you need a Resin license. If you don't have, contact us and get one.
You should be able to load the admin and such using SSL.
https://mydomain.com:8443/resin-admin/
It should all work now. The browser will complain because you are using a certificate that is not from a certificate authority. Proceed past there errors.
Setup OpenSSL with a self-signed certificate
Next let's create a openssl.cnf file in /etc/resin/keys/openssl.cnf
/etc/resin/keys/openssl.cnf
[ req ] default_bits = 1024 distinguished_name = Caucho [ Caucho ] C = US C_default = US ST = CA ST_default = CA L = San Francisco L_default = San Francisco O = Caucho Tech O_default = Caucho Tech OU = QA Documentation OU_default = QA Documentation CN = www.caucho.com CN_default = www.caucho.com emailAddress = info@caucho.com emailAddress_default = info@caucho.com
The above file is not needed per se, but it will save you a lot of typing later on.
Next create your private key file with openssl.
$ cd /etc/resin/keys $ pwd /etc/resin/keys $ sudo openssl genrsa -des3 -out myprivate.key 1024
The above generates an RSA key which can be used both for encryption and for signing.
You will be prompted for a protecting pass phrase.
(Note that 2048 or higher is recommended for RSA keys, as fewer amount of bits is considered less secure.)
RSA is an algorithm for public-key cryptography that is based on the difficulty of factoring large integers.
RSA acronym is for the names of the three creators.
RSA creates and then publishes the product of two large prime numbers, along with an another value, as the public key.
Output
Generating RSA private key, 1024 bit long modulus ...++++++ ..........................++++++ e is 65537 (0x10001) Enter pass phrase for /etc/resin/myprivate.key: Verifying - Enter pass phrase for /etc/resin/myprivate.key:
Enter in a password twice. Remember this password, you will need it later.
At this stage, just create a self-signed certificate to see if openssl is working and installed correctly.
$ sudo openssl req -config openssl.cnf -new -key myprivate.key -x509 -out my-self-signed-certificate.crt
Certificates are for public key cryptography and contain the public key. Public keys are easily derived from private keys, and this is why we created the private key first. The certificate is a file that has the organizations information and the public key.
To know if SSL is working, you want to check to see if you can load resin-admin.
Then look in the resin log (/var/log/resin/jvm*.log), and look for the following:
Resin Professional 4.0.32 (built Mon, 01 Oct 2012 02:34:38 PDT) Copyright(c) 1998-2012 Caucho Technology. All rights reserved. [13-01-17 21:35:23.624] {main} 1013792.license -- 1 Resin server Caucho 1013792.license -- 1 Resin server Caucho Starting Resin Professional on Thu, 17 Jan 2013 21:35:21 +0000 (UTC) ... ... [13-01-17 21:35:27.616] {main} http listening to *:8080 OpenSSL support compiled for OpenSSL 0.9.8o 01 Jun 2010 [13-01-17 21:35:27.710] {main} https listening to *:8443
If you see those two things then all should be well.
Testing your openssl setup if something goes wrong
If for some reason OpenSSL is not working, then you can use the tools that ship with OpenSSL to verify your setup.
Open up two terminals.
$ cd /etc/resin/keys $ sudo openssl s_server -accept 9999 -key myprivate.key -cert my-self-signed-certificate.crt
The above opens up a TLS server listening on port 9999 that is using the key and certificate that you just generated.
See http://www.openssl.org/docs/apps/s_server.html# for more details.
Now in a separate terminal window connect to this utility server.
$ openssl s_client -connect localhost:9999 CONNECTED(00000003) depth=0 C = US, ST = CA, L = San Francisco, O = Caucho Tech, OU = QA Documentation, CN = www.caucho.com, emailAddress = info@caucho.com verify error:num=18:self signed certificate verify return:1 depth=0 C = US, ST = CA, L = San Francisco, O = Caucho Tech, OU = QA Documentation, CN = www.caucho.com, emailAddress = info@caucho.com verify return:1 --- Certificate chain 0 s:/C=US/ST=CA/L=San Francisco/O=Caucho Tech/OU=QA Documentation/CN=www.caucho.com/emailAddress=info@caucho.com i:/C=US/ST=CA/L=San Francisco/O=Caucho Tech/OU=QA Documentation/CN=www.caucho.com/emailAddress=info@caucho.com --- Server certificate -----BEGIN CERTIFICATE----- MIICsTCCAhoCCQCbeymZWYc9lzANBgkqhkiG9w0BAQUFADCBnDELMAkGA1UEBhMC VVABCDEFGNVBAgTAkNBMRYwFAYDVQQHEw1TYW4gRnJhbmNpc2NvMRQwEgYDVQQK EwtDYXVjaG8gVGVjaDEZMBcGA1UECxMQUUEgRG9jdW1lbnRhdGlvbjEXMBUGA1UE AxMOd3d3LmNhdWNoby5jb20xHjAcBgkqhkiG9w0BCQEWD2luZm9AY2F1Y2hvLmNv bTAeFw0xMzAxMTcyMDU2MjhaFw0xMzAyMTYyMDU2MjhaMIGcMQswCQYDVQQGEwJV ... ... -----END CERTIFICATE----- subject=/C=US/ST=CA/L=San Francisco/O=Caucho Tech/OU=QA Documentation/CN=www.caucho.com/emailAddress=info@caucho.com issuer=/C=US/ST=CA/L=San Francisco/O=Caucho Tech/OU=QA Documentation/CN=www.caucho.com/emailAddress=info@caucho.com --- No client certificate CA names sent --- SSL handshake has read 1246 bytes and written 376 bytes --- New, TLSv1/SSLv3, Cipher is ECDHE-RSA-AES256-SHA Server public key is 1024 bit Secure Renegotiation IS supported Compression: zlib compression Expansion: zlib compression SSL-Session: Protocol : TLSv1.1 Cipher : ECDHE-RSA-AES256-SHA Session-ID: 07C6B7627821D29E814F069D2C7Casdfasdfasdfasdfasdfasdfasdfasdf Session-ID-ctx: Master-Key: C38B943A0E5570A2662695ABCDEFlkjalkj;lkjl;kjasdlfkjasdlkfjasl;kdfjalksdjf Key-Arg : None PSK identity: None PSK identity hint: None SRP username: None TLS session ticket lifetime hint: 300 (seconds) TLS session ticket: 0000 - 71 24 62 44 f1 c0 bc 95-8f e7 04 FF 73 c1 5c de q$bD...00...s.\. 0010 - 13 54 e8 f3 20 1d 2b 82-e8 83 05 62 4d 46 f9 3c .T.. .+....bMF.< ... 0040 - db 2b 3f d3 fa 7d b9 04-9f 65 95 d8 bb 10 d3 ca .+?..}...e...... 0050 - 47 79 cf 0c 65 67 e5 5f-90 4e a5 43 c7 b0 31 bb Gy..eg._.N.C..1. 0060 - f3 9b a4 c4 72 9c 24 18-5b 7a 90 63 4f 25 35 2c ....r.$.[z.cO%5, ... Compression: 1 (zlib compression) Start Time: 1358459991 Timeout : 300 (sec) Verify return code: 18 (self signed certificate)
See http://www.openssl.org/docs/apps/s_client.html# for more details.
To try this out in Resin, you just need to modify etc/resin/resin.properties as follows:
# OpenSSL certificate configuration # Keys are typically stored in the resin configuration directory. openssl_file : keys/my-self-signed-certificate.crt openssl_key : keys/myprivate.key openssl_password : password
Just navigate to:
https://mydomain.com:8443/resin-admin/
It should all work now. The browser will complain because you are using a certificate that is not from a certificate authority. Proceed past there errors.
GoDaddy is becoming a popular SSL certificate authority because it is a low cost alternative. Let's use GoDaddy to setup a real SSL to show how it is done.
Using GoDaddy
Setup a GoDaddy account.
You have to change the size of the private key to 2048 as follows:
$ sudo openssl genrsa -des3 -out myprivate.key 2048 $ sudo openssl req -new -config openssl.cnf -key myprivate.key -out CA_request.csr
The above creates a request file. You can take this request file to any certificate authority. You give them money. Wait 2 to 24 hours and then they give you a certificate.
Go to https://certs.godaddy.com/ to find out more information.
(This is not an endorsement of GoDaddy. I mainly picked it because it was the cheapest.)
You have to cut & paste the file CA_request.csr into the godaddy.com text box associated with creating a new SSL certificate.
Wait for two days and argue with GoDaddy tech support that I am in fact a real person, and I am not in fact going to use SSL certificate to bludgeon baby seals with Louisville slugger.
With any luck, the GoDaddy certificate shows up into my account under the domain I registered. www.mydomain.com.
Stick the zip file with the certificates somewhere where you can get it. Upload certificate zip to server.
$ unzip mydomain.com.zip
There should be two files in here:
$ ls go_bundle.crt mydomain.com.crt
You need to move these where Resin can find them.
$ sudo mv gd_bundle.crt /etc/resin/keys $ sudo mv mydomain.info.crt /etc/resin/keys $ cd /etc/resin/keys $ ls CA_request.csr mydomain.info.crt my-self-signed-certificate.crt gd_bundle.crt myprivate.key openssl.cnf
You should back these file up in a safe place.
Now we need to modify Resin to take an SSL chain file.
You can specify the certificate-chain-file as follows:
<http port="443"> <openssl> <certificate-key-file>keys/your_domain.key</certificate-key-file> <certificate-file>keys/your_domain.crt</certificate-file> <certificate-chain-file>keys/chain.txt</certificate-chain-file> <password>test123</password> </openssl> </http>
By default openssl is setup by resin.properties and cluster-default.xml.
Here is a snippet from /etc/resin/cluster-default.xml
<resin:when test="${openssl_file != null}"> <http address="${http_address?:'*'}" port="${https}"> <openssl> <certificate-file>${file_lookup(openssl_file,__DIR__)}</certificate-file> <certificate-key-file>${file_lookup(openssl_key, __DIR__)}</certificate-key-file> <password> <resin:Password>${openssl_password}</resin:Password> </password> </openssl> </http> </resin:when>
The problem is that it does not specify the chain file, which might be a fairly common thing, but not common enough to make it into resin.properties by default. (If you were using Verisign or a more well known CA authority, you would only need the chain file, this is mostly to support GoDaddy and other lesser known authorities, full explanation at bottom on this entry.)
Try this. Modify /etc/resin/cluster-default.xml as follows:
<resin:when test="${openssl_file != null}"> <http address="${http_address?:'*'}" port="${https}"> <openssl> <certificate-file>${file_lookup(openssl_file,__DIR__)}</certificate-file> <certificate-key-file>${file_lookup(openssl_key, __DIR__)}</certificate-key-file> <certificate-chain-file>${file_lookup(openssl_chain_file,__DIR__)}</certificate-chain-file> <password> <resin:Password>${openssl_password}</resin:Password> </password> </openssl> </http> </resin:when>
Notice that I added <certificate-chain-file> to the cluster-default and I point it to the property openssl_chain_file.
If you were using Verisign or a more well known CA authority, you would only need this:
# OpenSSL certificate configuration # Keys are typically stored in the resin configuration directory. openssl_file : keys/mydomain.com.crt openssl_key : keys/myprivate.key openssl_password : password
You would not need the chain file with Verisign.
But for this example, we do need the chain file so let's try to configure it.
Then modify your /etc/resin/resin.properties as follows (this configuration is wrong, but from the docs it sounds like this is what they are telling you to do):
# OpenSSL certificate configuration # Keys are typically stored in the resin configuration directory. openssl_file : keys/mydomain.com.crt openssl_key : keys/myprivate.key openssl_chain_file : keys/gd_bundle.crt openssl_password : password
The above did not work from the browser so let's debug it, but it does work from the command line tools from openssl.
$ sudo openssl s_server -accept 9999 -key myprivate.key -cert javaeefun.info.crt -CAfile gd_bundle.crt
$ openssl s_client -connect localhost:9999
That does work. So now we know we need to add mydomain.com.crt to the chain. (Ok that was a pretty big leap so let me explain what a chain.txt file is right after I show you how to create it properly.)
The test client and server did work so lets cat the mydomain.com.crt to the chain as follows:
$ sudo cat mydomain.com.crt gd_bundle.crt > chain.txt
The gd_bundle.crt file is a complete chain of SSL certificates from GoDaddy but it does not contain our certificate which we need. We used cat to add gd_bundle.crt after our mydomain.com.crt.
Now retest with the openssl tools as follows:
$ sudo openssl s_server -accept 9999 -key myprivate.key -cert mydomain.com.crt -CAfile chain.txt
$ openssl s_client -connect localhost:9999
The openssl tools likes our new setup. We can connect from the client.
Now configure resin to use the chain.txt file instead of just our file.
# OpenSSL certificate configuration # Keys are typically stored in the resin configuration directory. openssl_file : keys/mydomain.com.crt openssl_key : keys/myprivate.key openssl_chain_file : keys/chain.txt openssl_password : password
Now retest from the browser.
https://mydomain.com:8443/resin-admin/
All should be well.
Note: if you see a ' T_CLIENT_HELLO:no shared cipher ' on the server side, please make sure that you properly included mydomain.com.crt and gd_bundle.crt into chain.txt.
{resin-port-443-46} BadRequestException: java.io.IOException: errno=0 openssl='139770598954752:error:1408A0C1:SSL routines:SSL3_GET_CLIENT_HELLO:no shared cipher:s3_srvr.c:1230:
Some more background on certificate chains and why they are needed with GoDaddy
This information was derived from and other places: http://bloggit.livejournal.com/26595.html
GoDaddy has good prices and decent service. Sadly their explanations are a bit terse as is the documentation for OpenSSL.
Browsers like Opera and Internet Explorer know about GoDaddy. But Firefox, Chrome, Safari and other applications do not. So as far as a CA certificate goes, its recognition is not as good as Verisign and others (so far). If you just use their CA certificate then your device or browser might give you the old "Unknown Authority". This is not what you want from a CA authority at all.
SSL Certificates are encryption packets that reference other encryption packets, to form a a chain of trust. It's a bit like asking for references. Your browser or app or devices knows a few top-level authorities, but certainly not all. When you hit a new SSL certificate, your browser (or SSL library or app) checks the new certificate against the browser's own list of trusted authorities.
You can view the list of authorities in your browser pretty easily: Firefox: Options - Advanced - View Certificates - Authorities.
The trick is to provide a chain of references from your certificate up through GoDaddy, all the way up to a trusted authority that Firefox already knows about. That is what the chain.txt file we constructed did. It put GoDaddy chain concatenated on to our chain. Firefox does not trust GoDaddy, but it trusts GoDaddy parent company Starfield so the chain we created was mydomain.com->godaddy.com->startfield.com. Firefox says I don't know mydomain.com. Then it looks at the next certificate in the chain and says, I don't know GoDaddy either, then it sees the next one in the chain and says I do know Starfield. Then Firefox asks Starfield (more or less) do you trust GoDaddy. Startfield says yes. Then FireFox asks GoDaddy do you trust mydomain.com, and GoDaddy says yes. Then the trust results are cached, now Firefox knows about GoDaddy and MyDomain.com. Whoot!
We will do this by including the certificate "chain".