SSL and Virtualhosting

Warning: This blogpost has been posted over two years ago. That is a long time in development-world! The story here may not be relevant, complete or secure. Code might not be complete or obsoleted, and even my current vision might have (completely) changed on the subject. So please do read further, but use it with caution.
Posted on 12 Dec 2010
Tagged with: [ apache ]  [ sni ]  [ ssl ]  [ tls ]  [ virtualhosting

SSL and virtualhosting on 1 IP address? I can’t be done! Well, this might have been the case a few years ago but times has changed. Let’s explore the possibilites to have multiple hosts running on the same IP address AND all of them have their own separate SSL domain and certificates. It’s possible, but with a few catches..

What is virtualhosting?

Virtualhosting is the ability to host multiple websites on the same IP address and port. Normally, every website points to an IP-address and your browser will connect to port 80 of that IP address for the actual communication with the webserver. The communication is done though the HTTP v1.0 protocol. The first message from the browser to the server would be something like: “give me page X”. That’s it. No more information is transfered, except for maybe some cookies and information about the browser. The server will respond with returning page X of the website that is hosted on that particular IP. There is NO information transfered about the domain name itself. The browser assumes that the server knows which domain it hosts (which is ok, if you live in 1982 I guess).

For big hosters this would mean they need a lot of IP-address to host all their sites on different IP-addresses. They could need thousands of IP-addresses!  Since we have a (very) limited stock of IP-addresses (well, at least for ipv4) this is not really an option, let alone the massive administration that comes with handling all those IP-addresses.

So in 1997 a new version of the HTTP protocol has been released called HTTP v1.1. This protocol makes it mandatory that a browser must send information about which domain it requests information from. So instead of the standard “give me page X”, it will tell the server “give me page X for domain”. This makes it possible for a webserver to actually look up page X for (probably inside a subdirectory).

Virtualhosting is born and webservers are capable of hosting literally thousands of sites on one single IP.

Why HTTP and not HTTPS? Meet chicken & egg…

As you probably know, HTTPS means secure HTTP. When a connection to a webserver is made, the first thing that will take place is a discussion on HOW the communcation will proceed called the TLS handshake. The browser will tell the server which kind of encryptions it can handle and the server will pick an encryption method (probably the best) and gives some information about the domain by issueing an SSL certificate. The browser will verify some data from this certificate and when everything is found to be in order, both the server and browser will continue conversing over an encrypted channel. The communcation INSIDE this channel is plain HTTP. The secure channel is called TLS (or SSL in the early days).

Now, before the server can recieve even one single byte of HTTP data we must setup the encryption channel. But as I said before, one of the steps in this process is that the server issues an SSL certificate from the domain. But.. the browser never tells WHICH domain it wants. It just connects to the https-port on the IP from the domain it needs. If the server sends an incorrect SSL certificate, the browser will display an error on the users screen saying that the certificate does not match the hostname so it’s mandatory for the server to return the correct certificate.

Sounds like HTTP v1.0 all over again? Yes… yes it does… but with an extra twist…

The server only receives the actual domain that the browser wants in the HTTP communication but we need to know the domain during the TLS communication in order to send the SSL certificate for the correct domain. Indeed a chicken/egg problem.

Introduction SNI, the new Host: Header

So what is the solution for a problem that is almost 100% similar to the HTTP problem? Easy, we use the same solution! In the new TLS version (which coincidental is also version 1.1, go figure), the browser CAN (in contrast to MUST in http/1.1) send additional information about the domain it wants to connect to. What is called the “host”-header in HTTP,  is called “Server Name Indication” in TLS.

Now, with this extra data which is given to the server BEFORE any SSL-certificate has to be send to the browser, the server can decide WHICH certificate it needs to send. This opens the possibility for virtual SSL hosting..

Browser support

SNI is a fairly new concept and still comes with some issues. However, all the commonly used browsers are capable of using SNI AND actually send the hostname to the server. The only exception is Internet Explorer 6.0 which does not support TLS1.1 (and thus SNI). The newer versions IE7 and up do support TLS v1.1 and SNI.

Webserver support

Webserver support is a bit more tricky. Most webservers do NOT support SNI out of the box. Apache, the most widely used webserver, supports SNI from version 2.2.14 and up, but most distributions do not compile their webserver packages with SNI. You must compile the server yourself if you need the SNI support. Another server NGINX does support SNI, but again, not all distributions compile their server with SNI support.

If you need to compile your own SNI-capable webserver, there are many blogs about it. For instance:


HTTPS virtualhosting is something that nowadays is possible because of the adoption by browsers. Sure, there ARE still browsers outthere that don’t support SNI, but then again, there are also browsers that don’t support HTTP/1.1.  For security reasons you should not support IE6 anyway so if you can live with that, SNI might be perfect for you if you don’t mind a little custom-compiling…