Since two weeks, most of my sites are available through HTTPS and are properly using a certificate (only one!) corresponding to their hostnames.
Before I set this up for myself, I believed, that there was no way to run multiple vhosts with Apache on a single IP with SSL enabled. Recently Walter pointed me to a very interesting article on the Net which made me aware of a not so well known field inside x509 certificates: subjectAltName
With this field correctly used, it is possible to use a certificate for multiple virtual hosts inside Apache. The subjectAltName can contain some kind of alias for each hostname the certificate will be valid for. Thus it is possible to set the fields content to correspond to all the possible used hostnames for the IP Apache is running on. This leads to at least one drawback: The restriction that there is only one Certificate per IP is still in place.
Upon starting a SSL connection Apache will use the certificate and the browser will honor the subjectAltName in the same way as the CN field and thereby validate the hostname of the vhost.In my case I created a CSR for cacert.org which included all the hostnames of my vhosts with a little script that asks for all necessary values. After I got this signed, the certificate and the key were placed on the server and included in the config. A good location for certificates used by servers is /etc/ssl/private/ as it's protected from other users by default. I moved my cetificate to /etc/ssl/private/uni.fladi.at_cacert.crt and my key to /etc/ssl/private/uni.fladi.at_cacert.key and granted rights only to the group ssl-cert:
chown root:ssl-cert /etc/ssl/private/uni.fladi.at_cacert.* chmod 640 /etc/ssl/private/uni.fladi.at_cacert.*
For each vhost I created at least two files. One containing the custom configuration for this host and two vhosts,and one for HTTP and HTTPS, which includes the custom configuration file.
For mail.fladi.at this would be:
Custom configuration in /etc/apache2/includes/mail.fladi.at:
DocumentRoot /var/www/vhosts/mail.fladi.at ServerName mail.fladi.at CustomLog /var/log/apache2/access.mail.fladi.at.log combined ErrorLog /var/log/apache2/error.mail.fladi.at.log
Both vhosts in /etc/apache2/sites-available/mail.fladi.at:
<IfModule mod_ssl.c> <VirtualHost *:443> Include /etc/apache2/includes/mail.fladi.at Include /etc/apache2/includes/default-ssl </VirtualHost> </IfModule> <VirtualHost *:80> Include /etc/apache2/includes/mail.fladi.at </VirtualHost>
The file /etc/apache2/includes/default-ssl contains all the configuration needed to set up HTTPS for a vhost:
SSLEngine on SSLCertificateFile /etc/ssl/private/uni.fladi.at_cacert.crt SSLCertificateKeyFile /etc/ssl/private/uni.fladi.at_cacert.key BrowserMatch ".*MSIE.*" \ nokeepalive ssl-unclean-shutdown \ downgrade-1.0 force-response-1.0
No normal user should have read-access to /etc/ssl/private/uni.fladi.at_cacert.crt and /etc/ssl/private/uni.fladi.at_cacert.key. I've ensured this by adding the user www-data to the group ssl-cert which grants read-access to the files in /etc/ssl/private/:
usermod -a -G ssl-cert www-data
This SSL configuration can now be used for any host included in the subjectAltName of the certificate /etc/ssl/private/uni.fladi.at_cacert.crt.
If you get a warning upon restarting Apache make sure that a NameVirtualHost is enabled for hosts on port 443. This should be done in /etc/apache2/ports.conf:
NameVirtualHost *:443