networked day to day technical issues

13Aug/111

Multiple domain selfsigned ssl/tls certificates for Apache (namebased ssl/tls vhosts)

This is an old problem: how to have ssl/tls name based virtual hosts with Apache .
The issue is that the ssl/tls connection is established before Apache even receives a HTTP request.When Apache receives the request already the SSL connection is established with a particular hostname - ip & ssl certificate combination so this means that it is capable of serving NameBased virtual hosts only for that particular ssl/tls certificate.

There are two possible solutions here:

  • Multi domain or wildcard SSL/TLS certificates. Those are certificates which are configured with more than one name so you can create virtual hosts (in case of apache) for those domains. This is fairly easy to set up and at least for me it has worked ok in the past.
  • Server Name Indication (SNI) which is an extension to the SSL/TLS protocol and allows the client to specify the desired domain earlier and the server to be notified so it supplies the correct SSL/TLS certificate depending on the requested hostname. The problem is SNI is fairly new and few server side software supports it, also client side software needs to be fairly new. On the long run this is going to be the best solution as it has been designed to overcome this specific problem


1. Multi domain and wildcard certificates can be bought/signed from most of the certificate authorities or you can generate your own. People at CAcert.org have been doing a lot of testing and documentation on how to overcome this issue and generate your own self signed multi domain certificates. Also this practical blog post. The best way is to generate a certificate with one CommonName and multiple AltName (Alternative Name) values.

For example if you have www.domain1.com www.domain2.org and www.domain3.edu you need to generate the certificate pairs:

openssl genrsa -out multidomain-server.key 1024

or if you want to password protect the private key(and supply the private key each time the server software is started) then

openssl genrsa -des3 -out multidomain-server.key 1024

Generate the certificate request:

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

When asked for the CommonName enter the first name, eg: www.domain1.com
Specify all names and a text file which will be used as the certificate extensions source

echo "subjectAltName=DNS:www.domain1.com,DNS:www.domain2.org,DNS:www.domain3.edu">cert_extensions

Now you can self sign the public certificate file , for let's say three years, using:

openssl x509 -req -in multidomain-server.csr -signkey multidomain-server.key -extfile cert_extensions -out multidomain-server.crt -days 1095

and clean up

rm cert_extensions multidomain-server.csr

Now for Apache you need to have mod_ssl enabled and working and in the config file have something like:

NameVirtualHost 1.2.3.4:443
<VirtualHost 1.2.3.4:443>
        ServerName www.domain1.com
        SSLEngine on
        SSLOptions +StrictRequire
        SSLProtocol -all +TLSv1 +SSLv3
        SSLCipherSuite HIGH
        SSLCertificateFile /path/to/multidomain-server.crt
        SSLCertificateKeyFile /path/to/multidomain-server.key
 
        DocumentRoot /srv/www/www.domain1.com/
        <Directory />
                Options FollowSymLinks
                AllowOverride All
                SSLRequireSSL
        </Directory>
        ErrorLog /var/log/apache2/www.domain1.com-ssl-error.log
        LogLevel warn
        CustomLog /var/log/apache2/www.domain1.com-ssl-access.log combined
        ServerSignature Off
</VirtualHost>
<VirtualHost 1.2.3.4:443>
        ServerName www.domain2.org
        SSLEngine on
        SSLOptions +StrictRequire
        SSLProtocol -all +TLSv1 +SSLv3
        SSLCipherSuite HIGH
        SSLCertificateFile /path/to/multidomain-server.crt
        SSLCertificateKeyFile /path/to/multidomain-server.key
 
        DocumentRoot /srv/www/www.domain2.org/
        <Directory />
                Options FollowSymLinks
                AllowOverride All
                SSLRequireSSL
        </Directory>
        ErrorLog /var/log/apache2/www.domain2.org-ssl-error.log
        LogLevel warn
        CustomLog /var/log/apache2/www.domain2.org-ssl-access.log combined
        ServerSignature Off
</VirtualHost>
<VirtualHost 1.2.3.4:443>
        ServerName www.domain3.edu
        SSLEngine on
        SSLOptions +StrictRequire
        SSLProtocol -all +TLSv1 +SSLv3
        SSLCipherSuite HIGH
        SSLCertificateFile /path/to/multidomain-server.crt
        SSLCertificateKeyFile /path/to/multidomain-server.key
 
        DocumentRoot /srv/www/www.domain3.edu/
        <Directory />
                Options FollowSymLinks
                AllowOverride All
                SSLRequireSSL
        </Directory>
        ErrorLog /var/log/apache2/www.domain3.edu-ssl-error.log
        LogLevel warn
        CustomLog /var/log/apache2/www.domain3.edu-ssl-access.log combined
        ServerSignature Off
</VirtualHost>

Of course replace 1.2.3.4 with your ip for those hostnames and also replace what else is needed and adjust the Apache config according to the needs.

You can vary the setup as needed, for example having two of the names with the same document root, using an ServerAlias directive and so on. You can also create another multi domain certificate which is bound for another ip and so on.


2. Server Name Indication has been purposely developed to overcome all the issues and it's major advantage is that it allows true name based virtual hosts, each vhost having it's own unique ssl certificate (and all hosts can share the same ip address). The requirements are: Apache 2.2.12 (according to wikipedia), OpenSSL 0.9.8f or later (0.9.8k has SNI support enabled by default) and a capable browser
Once you have them all you can define SSL/TLS virtual hosts as you define them for non ssl/tls ones except you add the SSL related (path to keys, enable ssh engine, etc) statements and also disable SSL version 2 as it doesn't support SNI and has a number of security flaws.
The only new statement in Apache config is SSLStrictSNIVHostCheck which if on then it will reject connections with error 403 for non SNI capable browsers. If it is off then it will serve the first configured SSL/TLS vhost so if you leave it off then it would be a good idea that in the first vhost you put a message notifying the user to upgrade his/her browser.

Example config files are available on the Gentoo Wiki and on the Apache wiki

Filed under: Apache, Linux, ssl, Web Leave a comment