Real SSL Certificates

Summary

It's fairly easy to get Apache or IMAP running with a so-called self-signed SSL certificate. In fact, I show a basic procedure in the SubversionApache2 page. However, having a self-signed certificate in place is a bit of a pain. For one thing, every time you make a connection to a server using such a certificate, your underlying SSL library gives you a warning about how the certificate is untrusted.

Ideally, you'd like to have a "real" SSL certificate that's trusted by browsers and other applications by default. This kind of certificate comes from a company like Verisign, and costs real money (like $400+ per year in real money). If all you need SSL for is to give some friends access to your IMAP server, or to make Subversion available via https, that's a bit much.

The alternative is to create your own CA certificate (a "certificate authority certificate") and then create and sign all of your server certificates with the CA certificate. Then, if your customers are willing to "trust" the CA certificate (through a procedure that varies by platform), they won't get those annoying warnings any more.

The procedure below was developed on a Debian 'sarge' box, and I used what I think are the correct locations for files (but I can't be certain since the directories are empty upon install and I didn't see any notes about what is supposed to be put where).

References

I found the following references to be useful when working my way through this mess:

Creating your certificates

Fill in sensible OpenSSL configuration

Some of the OpenSSL utilities rely on the contents of the openssl.cnf file. It seems like sometimes there's no good way to override values in this file, so you're best off making sure it's right before you start.

On a Debian box, this file can be found in /etc/ssl/openssl.cnf. It may be in other places for other distributions.

I'm hesitant to tell you exactly what to change in this file, because I don't completely understand it. Start by changing dir in the CA_default section to just ./. Then, consider setting some more sensible defaults in the req_distinguished_name section.

Create the CA private key and certificate

First, generate the CA private key:

   daystrom:/etc/ssl# openssl genrsa -des3 -out private/ca.key 4096
   Generating RSA private key, 4096 bit long modulus
   ....................................................................++
   .............................................++
   e is 65537 (0x10001)
   Enter pass phrase for ca.key:
   Verifying - Enter pass phrase for ca.key:

Next, generate the CA certificate. This example generates a certificate that expires in around 10 years. Make sure to use a Common Name that represents the certificate authority you are creating, and choose a sensible email contact address.

   daystrom:/etc/ssl# openssl req -new -x509 -days 3650 -key private/ca.key -out certs/ca.crt
   Enter pass phrase for ca.key:
   You are about to be asked to enter information that will be incorporated
   into your certificate request.
   What you are about to enter is what is called a Distinguished Name or a DN.
   There are quite a few fields but you can leave some blank
   For some fields there will be a default value,
   If you enter '.', the field will be left blank.
   -----
   Country Name (2 letter code) [US]:
   State or Province Name (full name) []: Minnesota
   Locality Name (eg, city) []:
   Organization Name (eg, company) []: My Company
   Organizational Unit Name (eg, section) []:
   Common Name (eg, YOUR name) []: My Company Certificate Authority
   Email Address []: user@mycompany.com

Before going any further, set sensible permissions on the files you have created. I suggest setting ownership root:root and permissions 600 on all files in the private directory, including private/ca.key. Ownership root:root and permissions 640 should be OK for certs/ca.crt.

Create the server private key

This generates the server key itself:

   daystrom:/etc/ssl# openssl genrsa -des3 -out private/server.key 4096
   Generating RSA private key, 4096 bit long modulus
   ....................................++
   ...........................................++
   e is 65537 (0x10001)
   Enter pass phrase for server.key:
   Verifying - Enter pass phrase for server.key:

Then, this generates an "insecure" version of the key which has no passphrase attached:

   daystrom:/etc/ssl# openssl rsa -in private/server.key -out private/server.key.insecure
   Enter pass phrase for server.key:
   writing RSA key

It seems kind of strange to have a secret key with no passphrase attached. Normally, you wouldn't want this. However, if you want Apache to be able to boot unattended, or if you want IMAP to be able to work from inetd, you need to make available a version of the key that can be opened without a passphrase.

Needless to say, make sure that this key is well-protected. I suggest setting ownership root:root and permissions 600 on all files in the private directory, including both private/server.key and private/server.key.insecure.

Generate the server certificate

There are two steps in generating a certificate. First, you generate a certificate request, which is then combined with the CA certificate to create the server certificate itself.

You might be thinking to yourself at this point: Great! I have my server key. Now's where I generate one certificate for each domain that my Apache instance serves. That way, my customers won't get errors like "connected to 'www.cedar-solutions.com', but certificate says 'cedar-solutions.com'". Well, if you're using Apache's name-based virtual hosting (and you probably are) this won't work. You can have one and only one SSL certificate for a given IP address and port combination in Apache. See Apache's SSL FAQ for more information.

So, first, generate the certificate request. Here, you should be sure to use the name of your domain for the Common Name. Just choose the domain name your customers are most likely to use (like what's on most of your URLs). Again, be sure to choose a sensible email address and organization name.

   daystrom:/etc/ssl# openssl req -new -key private/server.key -out server.csr
   Enter pass phrase for private/server.key:
   You are about to be asked to enter information that will be incorporated
   into your certificate request.
   What you are about to enter is what is called a Distinguished Name or a DN.
   There are quite a few fields but you can leave some blank
   For some fields there will be a default value,
   If you enter '.', the field will be left blank.
   -----
   Country Name (2 letter code) [US]:
   State or Province Name (full name) []: Minnesota
   Locality Name (eg, city) []:
   Organization Name (eg, company) []: My Company
   Organizational Unit Name (eg, section) []:
   Common Name (eg, YOUR name) []: mycompany.com
   Email Address [user@mycompany.com]:

   Please enter the following 'extra' attributes
   to be sent with your certificate request
   A challenge password []:
   An optional company name []:

Once you have created the CSR file, you use it to create the certificate. In this command, it's important to remember to bump the serial number ("01" in this example) every time you create a new certificate. This way, browsers and other clients will notice that there's a new certificate (otherwise, it might just look like the new certificate is corrupt or something, I guess).

   daystrom:/etc/ssl# openssl x509 -req -days 730 -in server.csr 
                      -CA certs/ca.crt -CAkey private/ca.key 
                      -set_serial 01 -out certs/server.crt   
   Signature ok
   subject=/C=US/ST=Minnesota/O=My Company/CN=mycompany.com/ emailAddress=user@mycompany.com
   Getting CA Private Key
   Enter pass phrase for private/ca.key

Make sure to delete the CSR file (server.csr) before going any further. Also, be sure to set ownership root:root and permissions 640 on certs/server.crt.

Using your certificates

Now that you've created your certificates, you need to know how to use them.

Make your CA certificate available

The first thing you should do is make your CA certificate -- not your CA key -- available for users to download. I suggest just creating an alias in Apache to point to the correct place:

   AddType application/x-x509-ca-cert .crt
   Alias /ca.crt /etc/ssl/certs/ca.crt

I did this for each of my virtual hosts, but you could do it in one general place if you want. I found that Debian's default configuration doesn't seem to provide the x509 MIME type, so I added it here.

Configure a browser like Firefox to trust your CA

This couldn't be easier. Just reference the URL for your CA certificate (the one you aliased above). Because the MIME type is set up properly, Firefox will notice it is dealing with a certificate, and will immediately prompt you to decide how you want to deal with it. After looking it over to make sure it's what you expected, you can add it to Firefox's trust store. If you want to remove it later, you can do this in Firefox's preferences under Advanced, Certificates, Manage Certificates.

Configure Windows to trust your CA

This should be straightforward, too, although I have to admit I have not tried it yet myself (I don't have much need for Windows). According to the Utah School of Computing's "SSL for Microsoft" page, the process is much like the one for Firefox (although I believe that when you trust a CA in Internet Explorer, this trust takes effect system-wide rather than just in the browser). It appears that when you download the certificate, you should choose to install it, and the place it in the "Trusted Root Certification Authorities" certificate store.

Configure Apache to use the new certificate

You probably configured Apache with a pair of lines like this when using a self-signed certificate:

   SSLEngine On
   SSLCertificateFile /etc/apache2/ssl/apache.pem

You're going to replace the SSLCertificateFile directive with a pair of new directives that reflect the new type of key you have available to you. Use something like this:

   SSLEngine On
   SSLCertificateFile /etc/ssl/certs/server.crt
   SSLCertificateKeyFile /etc/ssl/private/server.key.insecure 

Make sure to use the insecure key that does not have a passphrase. Using the real key will cause you problems.

Once you have made these changes, bounce Apache and the new certificate should take effect. If you've already installed the certificate into Firefox, an https URL should load immediately with no warnings.

Create a PEM certificate for use by UW IMAP (imapd) via IMAPS (secure IMAP)

This took me a lot longer than it should have to figure out. It turned out to be easy. Basically, a PEM file is a combination of secret key and certificate. Simply replace your existing /etc/ssl/imapd.pem file with a new one created using your new certificate and insecure key.

daystrom:/etc/ssl/certs# mv 2ec93514.0 ~/tmp    # save off self-signed cert
daystrom:/etc/ssl/certs# mv imapd.pem ~/tmp     # save off self-signed cert
daystrom:/etc/ssl/certs# cat server.crt ../private/server.key.insecure > imapd.pem 

As with Apache, make sure you use the insecure key here. If you don't do this, the symptom will be that IMAP clients seem to "hang". You will also see lots and lots of "stuck" imapd processes in your process listing. I gather that these processes are all blocked waiting for a passphrase on stdin (which of course will never arrive). Getting rid of them requires a kill -9.

Of course, you should also set appropriate permissions on the new file. I suggest ownership of root:root and permissions of either 600 or 640.

RealSSL (last edited 2008-07-09 06:21:57 by localhost)