NurdleTech
A 'How To' Guide for the Nanopublisher


Securing Apache 2 using SSL

This is a set of notes I created after struggling to get my web server configured to provide HTTPS service. For context, I was configuring Apache 2 to use OpenSSL (vers. 0.9.7d) on a server running SuSE 9.1 Linux. I used the following web pages as reference:

Apache HTTP Server Version 2.0 Documentation
Securing Your Apache 2 Server with SSL
How to SETUP SSL Apache MODSSL
Apache-SSL: Certificates, Configuration and More

Planning

It is good to start by carefully thinking about how your secure site is accessed relative to your insecure site. There are a few things to keep in mind while doing so. Remember that the insecure site will have the http:// prefix whereas the secure site will use https://. Also realize that the certificate used to validate your secure site is tied to a single domain, and not subdomains. Thus, if you specify mydomain.com as your domain when requesting your certificate, people that use www.mydomain.com will receive a disturbing but otherwise harmless message about how the certificate does not match the domain. For these reasons, you might consider dedicating a subdomain to your secure site. For example, if you have a general site and would like to provide a secure mail capability, you could use mail.mydomain.com as your secure domain.

Also you should be aware up front that if you use name-based virtual hosting you will not be able to use different keys for different virtual hosts. This is because the host name is contained within the encrypted traffic, and so cannot be used to determine which key to use. For this reason, Apache will always use the key of the first virtual host that references a key. If you need to use different keys for your hosts, each will need its own IP address.

Keys

The first step is to use OpenSSL to produce the keys that are used to secure your site. These are the keys that used when encrypting and decrypting the traffic to your secure site. To do so, run

openssl genrsa -out mydomain.key 1024

Typing the above on the command line will create a 1024 bit private key and puts it in the file mydomain.key, which will later be placed in the proper directory. This private key is not encrypted and protected by a pass phrase. To encrypt the key, add -des3 to the above command line. Be aware in doing so that you will always need to be available to type in the pass phrase whenever the server restarts. If you choose not to encrypt the key, be sure to keep it secure. In particular, it should be placed in a directory that is only readable by the web server.

Certificates

A certificate is a validated public key. It is used by the secure web server to prove its identity to the remote web browser (this is the 'validated' part), and then it is used by the remote browser to encrypt the traffic to the web server (this is the 'public key' part). The certificate is validated by signing it. You can either sign it yourself, which is only appropriate if you are only after the encryption and not the validation. Alternatively, you can prove your identity to a Certificate Authority, and then have them sign your certificate.

Self-Signed Certificates

Generate your own certificate by going back to the command line and entering the following:

openssl req -new -key mydomain.key -x509 -out mydomain.crt

This command creates a self-signed SSL certificate in the file mydomain.crt, which will later be placed in the proper directory.

Certificate Authority Signed Certificates

If instead you choose to use a certificate authority to sign your key, you will need to generate a certificate request using your private key. The certificate authority uses this to create your signed certificate. Generate the certificate request using:

openssl req -new -key mydomain.key -out mydomain.csr

This command will ask you questions that are used to identify the certificate. Most are optional. The most important is the common name. Use the domain name of your secure site. In this example, we might use mail.mydomain.com.

Now you need a certificate authority. Most certificate authorities charge hundreds of dollars a year to provide you with a certificate, and what you get for that is an authority that most browsers trust. I was unwilling to pay that amount of money, so instead I used CA-Cert. It is a less well established certificate authority that does not charge for its certificates. To get a certificate from CA-Cert, first go to their website (www.cacert.org), create an account and log in. First you need to add your domain to your account. It will then validate your authority over the domain by sending a confirmation email to the administrator of your domain (as specified when your domain name was registered). Once your administrator responds, you can request your server certificate. In doing so, you will upload the contents of mydomain.csr to CA-Cert, which responds with your certificate, which you save into a file mydomain.crt. Be sure to note the expiration date for the certificate. You will want to put a reminder on your calendar to renew the certificate before it expires.

Installing the Site Certificate

It is now time to place the private key and the certificate in locations where they will be found by Apache. My installation wants the private key (mydomain.key) to be placed in /etc/apache2/ssl.key/ and the certificate (mydomain.crt) to be in /etc/apache2/ssl.crt/. Assure that the ssl.key directory is only readable by root and that if you keep any other copies of your private key, that they cannot be read by others.

Configuring Apache

To configure Apache, you will need to edit the httpd.conf file that for my installation is found in /etc/apache2. SuSE Linux discourages you from editing this file directly and instead allows you to specify a file that is included into httpd.conf that you can modify. I chose to use local.conf. I specified this by running yast2 and then navigating to System, then /etc/sysconfig Editor, then Network, then WWW, then Apache2. From here I added /etc/apache2/local.conf to APACHE_CONF_INCLUDE_FILES.

To support secure traffic over SSL, Apache needs to have mod_ssl installed and enabled. It comes pre installed with SuSE, and I enabled it by again running yast2 and then navigating to Network Services, then HTTP Server, then modules. I then clicked on edit and then made sure that ssl was enabled.

The rest of the work in involved in getting /etc/apache2/local.conf right. Apache's virtual host capability is used to provide the secure site.

The original local.conf file contained

NameVirtualHost *

<VirtualHost *>
ServerAdmin webmaster@mydomain.com
DocumentRoot /srv/www/htdocs/mydomain
ServerName www.mydomain.com
ServerAlias mydomain.com
</VirtualHost>

The new version of local.conf contains

NameVirtualHost *:80
NameVirtualHost *:443
Listen 443

<VirtualHost *:80>
ServerAdmin webmaster@mydomain.com
DocumentRoot /srv/www/htdocs/mydomain
ServerName www.mydomain.com
ServerAlias mydomain.com
</VirtualHost>

<VirtualHost *:443>
ServerAdmin webmaster@mydomain.com
DocumentRoot /srv/www/htdocs/mydomain-secure
ServerName mail.mydomain.com
SSLEngine on
SSLCertificateFile /etc/apache2/ssl.crt/mydomain.crt
SSLCertificateKeyFile /etc/apache2/ssl.key/mydomain.key
</VirtualHost>

<Directory /srv/www/htdocs/mydomain-secure>
SSLRequireSSL
</Directory>

<VirtualHost *:80>
ServerAdmin webmaster@mydomain.com
DocumentRoot /srv/www/htdocs/mydomain
ServerName mail.mydomain.com
RedirectMatch permanent (/.*) https://mail.mydomain.com$1
</VirtualHost>

The first two NameVirtualHost lines indicate that virtual host traffic should be expected on ports 80 and 443 at any IP address. Port 80 is associated with insecure traffic (http) and 443 with secure traffic (https). The Listen command tells Apache to listen for traffic on port 443 (Apache is generally already configured to listen on port 80).

The first VirtualHost block services the insecure www.mydomain.com and mydomain.com site. The only change to this block is on the VirtualHost statement itself, where the port number was added.

A new VirtualHost block was added for the secure site. Notice that in this block the port number is 443 and the server name is mail.mydomain.com. Also, the location of the files that contain the private key and the certificate are given along with the command that enables SSL transport for this host.

A Directory block is added with a directive that indicates that SSL must always be active when serving the contents of the secure directory. This prevents its contents from ever being inadvertently made available without SSL active.

The last VirtualHost is also new. It acts to automatically redirect any traffic to mail.mydomain.com on port 80 to the secure site.

Configuring your Firewall

Be sure to add a incoming service rule to your firewall so that it passes HTTPS traffic on port 443 to your server.

Debugging Apache

When first attempting to get Apache to talk through SSL it is best to make the change in two steps and make sure the first step works before moving to the second. This way if you have a problem you reduce the number of things that can be causing it.

So to start, you should configure Apache to communicate to your new site over port 443 without SSL. To do so, edit your local.conf file so that it contains the new VirtualHosts, comment out the Directory block, and replace

SSLEngine on

with

SSLEngine off

Then in your browser, test your secure and insecure sites. To access your secure site, use http://mail.mydomain.com:443 (do not try mail.mydomain.com directly, as the redirect will not work yet). Once you are confident that your sites are working correctly without SSL, re-enable SSL by changing SSLEngine back to on and un-comment the Directory block. Now test everything again. Assure that https://mail.mydomain.com takes you to your secure site and that the lock icon on your browser is locked, indicating a secure connection. Also verify that http://mail.mydomain.com is redirected to your secure site.

If the SSL layer does not work properly, you can use OpenSSL to help debug the problem. In particular, running

openssl s_client -state -quiet -connect mail.mydomain.com:443

connects to your site and allows you to test it. When I was having trouble I ran this command and amongst the output I got the following message:

19732: error: 140770FC:SSL routines: SSL23_GET_SERVER_HELLO: unknown protocol: s23_clnt.c: 475:

I spent considerable Google time trying to track down the source of this message, and I concluded that it has no single cause, rather that it is an indicator that Apache is not configured properly. So I went back and after carefully studying the Apache directives, adjusted local.conf until the error went away. In particular, it was adding the port numbers to the NameVirtualHost and VirtualHost statements solved the problem.

SSL on Multiple Virtual Hosts

Apache allows one server to service several websites through its Virtual Hosts feature. When multiple virtual hosts exist, Apache must determine which host should serve each request. It does this in one of two ways: based on the host IP address or the host name. When using the host IP address, the server must have multiple IP addresses, one for each virtual host. When using name-based virtual hosts, all sites use the same IP address and the browser sends the name of the site with each request and Apache uses the name to determine which host should serve the request.

With name-based virtual hosts, the host name is contained in the data stream, which is encrypted by SSL. To access the name, Apache must first decrypt the stream, which requires a certificate. Thus, it must choose a certificate before it knows the virtual host. For this reason, when using name-based virtual hosting there can only be one certificate. Apache uses the certificate mentioned first in its configuration file. If you specify multiple certificates, one for each virtual host, Apache will use the one for the first host without generating any errors or warnings.

If instead you use IP address-based virtual hosts, Apache can determine which certificate to use without first decrypting the stream based on the IP address used by the address. In this way, each virtual host can have its own certificate.

Additional Resources

You can learn about SSL in depth with the following books. Clicking on the images on the right takes you to Amazon, where you can learn more about them.

Any questions or comments on these notes can be directed to theNurds@nurdletech.com.

Created and hosted by