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