Multiple Secure Subdomains with a Wildcard SSL Certificate

This guide is a walk through for configuring multiple secure subdomains using a wildcard SSL certificate and Apache2 on Ubuntu 8.04.

For those not familiar with the problems for this setup, a little background is in order (if you want to get to the meat of things, just skip down). If you have your domain, example.com, it is convenient to organize things into subdomains. For example, maybe you have code repositories at code.example.com or a development environment for testing at test.example.com. But what if you want both of these subdomains to be secure? A standard SSL certificate for example.com does not validate for any of the subdomains since the addresses do not match. You could get separate certificates for each subdomain, but configuring those can be tricky and time consuming. Wildcard SSL certificates allow a single certificate for any immediate subdomain of the base, i.e. *.example.com.

So problem solved right? Well, not exactly... due to the SSL protocol you cannot use name-based virtual hosts in Apache with SSL. Since only IP-based virtual hosts can be used Apache requires a single Virtual Host for all port 443 (SSL) traffic per IP address. The way around this is to dynamically set the document root after receiving a request on port 443. It may sound complicated, but the steps are pretty easy once you see how it is done.

Generating the Wildcard Certificate

First off, you need a wildcard SSL certificate. You can purchase one commercially or just generate one yourself. If you want to roll your you have to have Apache with mod-ssl. (Note that if you are not running as root you will need to sudo all of the below commands):

apt-get install apache2 apache2-common

Now we can generate the certificate. First we generate a key:

openssl genrsa -out server.key 2048
chmod 400 server.key

Next we generate a certificate signing request (CSR). This is where we can designate the wildcard. Run the command below and you will be prompted with a series of questions. When prompted for Common Name, you would normally enter your domain name. We want a wildcard so enter *.example.com, replacing example.com with your domain name:

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

Finally, create the self-signed wildcard certificate (the below example is valid for a year; change the number of days to reflect how long you want the certificate to be valid):

openssl x509 -req -days 365 -in server.csr -signkey server.key -out server.crt

Configuring Apache

First enable the Apache SSL module if it isn't already:

a2enmod ssl

We also need to enable the vhost_alias module:

a2enmod vhost_alias

Apache needs to be told to listen on port 443. Edit the ports.conf file in /etc/apache2 and add the following:

Listen 443

Now we need a Virtual Host to handle all the port 443 traffic. I recommend creating and editing a new file in /etc/apache2/sites-available:

vi /etc/apache2/sites-available/ssl.example.com

Now to configure the Virtual Host. Add the following to the newly created file:

ServerAdmin webmaster@localhost
ServerName *.example.com
SSLEngine On
SSLCertificateFile /etc/apache2/ssl/apache.pem
SSLProtocol all
SSLCipherSuite HIGH:MEDIUM
VirtualDocumentRoot /var/www/%0/

A little explanation is in order here. The ServerName (and any ServerAlias as well) uses the wildcard notation (i.e. *.example.com) since we want to handle multiple subdomains. Next are the directives to enable SSL and you will need to adjust the SSLCertificateFile path to point to your certificate. The last line is where the magic happens using the VirtualDocumentRoot directive. Thanks to the vhost_alias module, we can set the document root based on the address.

Say we have the two example subdomains from earlier, code.example.com and test.example.com. We have our wildcard certificate in place and someone tries to go to http://code.example.com. The %0 signifies that the entire string from the address should be substituted, yielding a DocumentRoot of /var/www/code.example.com. If someone tried test.example.com, it would become /var/www/test.example.com. The documentation on the vhost_alias module shows all the options for getting parts or all of the address string for substituting into the DocumentRoot.

Using this method, you can dynamically determine what the root document path should be and serve the correct information. The only catch is that you will have to adhere to a naming scheme that follows however you design your rewrite rule (in my example above, it will be /var/www/<full subdomain path>. But being forced to use a consistent naming scheme for your sites (which should probably be done anyway...) is a pretty good tradeoff for running multiple secure subdomains on a single IP address with a single SSL certificate.

One last thing, make sure to reload Apache so the changes take effect:

/etc/init.d/apache force-reload

If you are looking for a good host that will give you full control over your server, be sure to check out Linode. We use them for all our Linux hosting and love it!

blog comments powered by Disqus
Posted:

Tags: