When hosting multiple sites on a single IP, HTTP1.1 has the necessary items on board to route the request to the correct site. This works because an HTTP 1.1 request includes a Host: header, which indicates to the server which site the client wishes to access.

When using SSL-secured connections, this doesn’t work anymore. The problem is similar to the situation in HTTP1.0: The server needs to know to which SSL-host the connection is addressed. SNI introduces a similar solution: It specifies an extension to the SSL negotiation to indicate which server the client wishes to access.

This extension opens up a small security hole: Since you send the server the expected hostname before the SSL negotiation starts, the server could, theoretically, generate a matching certificate on-the-fly. This certificate will probably be rejected by your browser, since it won’t be signed with a trusted root certificate. Another consideration is that the hostname you are connecting to is sent in plain text, before the secure channel is set up. However, a reverse lookup of the destination IP will usually return the same information.

Since SNI is an extension, support isn’t automatic. Ubuntu 9.10 (Karmic) supports SNI in apache out of the box. Paul Kehrer’s blog has the full story, but it’s as simple as it seems:

NameVirtualHost *:443

    ServerAdmin webmaster@localhost
    DocumentRoot /my/doc/root
    ServerName mydomain.com
    SSLEngine On
    SSLCertificateFile /path/to/domain.crt
    SSLCertificateKeyFile /path/to/domain.key

    ServerAdmin webmaster@localhost
    DocumentRoot /my/doc/root
    ServerName mydomain2.com
    SSLEngine On
    SSLCertificateFile /path/to/domain2.crt
    SSLCertificateKeyFile /path/to/domain2.key

On the browser side, Wikipedia has a list of compatible browsers. Most notably:

  • IE7 under XP does NOT support SNI
  • Mobile Safari on iPhone (3.0.2) does NOT support SNI

Non-SNI compatible browsers will get the SSL certificate of the first vhost, which is probably wrong. You can require SNI-support by setting

SSLStrictSNIVHostCheck on

This will return a 403 to non-compliant browsers.

Update 2010-07-01

I just upgraded to iOS 4, which seems to have SNI-support (and IPv6 support as well)!