Apache Name Based SSL Virtual Hosting using Server Name Identification (SNI)

One difficulty when it comes to hosting multiple websites on single servers has always been SSL. By the nature of how the web works when you open a website in your browser a HTTP Header with the requested host is present. A web server can then read this information and direct traffic to the appropriate Virtual Host matching the Host Header. With SSL this information is encrypted when the request first hits the Web Server so the Web Server replies with the default site, once the data is decrypted the header can be read but by this time it is too late in the process and the default Virtual Host replies.

The way to get around this in the past has been to assign each SSL host to its own IP Address on sub interfaces so the Web Server can distinguish between the various sites. This approach has worked however it becomes quite a maintenance nightmare in your Apache configuration as well as your server’s network configuration.

The solution to this problem is an extension to the SSL protocol named Server Name Identification (SNI) introduced in RFC 4366 which allows the client to include the requested hostname in the first message of the SSL handshake allowing the Web Server to determine which Named Virtual Host to send the request to and setup the connection accordingly.

Starting with Apache 2.2.12 and later you can take advantage of SNI for your SSL Virtual Hosting. There are some requirements for SNI to work properly.

  • You must be running OpenSSL 0.9.8f or later
  • You must configure OpenSSL with the TLS Extensions Enabled
  • Apache must be built with OpenSSL Support (–with-ssl)

Another requirement is the Client must support SNI. Below is a list of Browsers supporting SNI

  • Mozilla Firefox 2.0 or later
  • Opera 8.0 or later (with TLS 1.1 enabled)
  • Internet Explorer 7.0 or later (on Vista, not XP)
  • Google Chrome
  • Safari 3.2.1 on Mac OS X 10.5.6

If the client does not support SNI Apache will return a 403 Error Response to the user. You can disable Strict Host Checking in which the default Virtual Host will respond as before when a request came in that did not match any defined Virtual Hosts, this is because once again the server is unable to read the Host header until it completed the SSL negotiation and can read the data.

To enable Named Based Virtual Hosting for SSL you have to make a few changes to your existing Apache Configurations. Below you can find a sample configuration for two different domains running SSL.

 

NameVirtualHost *:443

<VirtualHost *:443>
    ServerName www.domain-one.com
    DocumentRoot  /var/www/domain-one.com

    SSLEngine on
    SSLProtocol all -SSLv2
    SSLCipherSuite ALL:!ADH:!EXPORT:!SSLv2:RC4+RSA:+HIGH:+MEDIUM:+LOW
    SSLCertificateFile conf.d/www.domain-one.com.crt
    SSLCertificateKeyFile conf.d/www.domain-one.com.key
    ErrorLog logs/www.domain-one.com_error_log
    CustomLog logs/www.domain-one.com_access_log
</VirtualHost>

<VirtualHost *:443>
    ServerName www.domain-two.com
    DocumentRoot  /var/www/domain-two.com

    SSLEngine on
    SSLProtocol all -SSLv2
    SSLCipherSuite ALL:!ADH:!EXPORT:!SSLv2:RC4+RSA:+HIGH:+MEDIUM:+LOW
    SSLCertificateFile conf.d/www.domain-two.com.crt
    SSLCertificateKeyFile conf.d/www.domain-two.com.key
   ErrorLog logs/www.domain-two.com_error_log
   CustomLog logs/www.domain-two.com_access_log
</VirtualHost>