Setting up OpenSSL with Resin 4.0.32 on Ubuntu 12.0.4

From Resin 4.0 Wiki

Jump to: navigation, search

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".

Personal tools
TOOLBOX
LANGUAGES