We host applications on a couple dozen domain names with more subdomains than I count offhand. We have a policy that anything over which passwords transit should be encrypted, so we have plenty of Apache mod_ssl virtual hosts along with TLS or SSL versions of POP, IMAP, SMTP and XMPP. To provide all that as cheaply as possible, we run our own certificate authority and issued our own root certificate. Certificate authority is a pretty big word for a bunch of Openssl commands, but they do the job fine until we deploy something else to help us. So far, so good.

Since our root certificate is of course not bundled with any browser or operating system, our users are constantly nagged by their browser and mail client until they store it locally. In addition, with no root authority for other servers to refer to, server to server communication is wide open to man in the middle attacks. So at the moment, our cryptography is about as good as snake oil.

The limitations of the current implementation of HTTPS make it difficult to deploy correctly on the cheap. When a client requests a HTTPS connection, it does not tell the server the name of the host it wants to connect to. So the server has no way to choose a certificate, and this is why there can be only one certificate per IP address. IP address being an expensive resource, having one for each virtual host can quickly be prohibitively expensive, at least until IPv6 becomes sufficiently widespread.

With multiple sub-domains, we could use wildcard certificates. They have more risks than benefits and they are not universally supported, but at least they provide a cheap solution. But we host multiple domains, so even that is not the way out for us, nor for the countless wretched sysadmins that share our predicament.

But despair not, wretched sysadmin : you savior has arrived, and its name is Server Name Indication ! SNI is a TLS extension that allows multiple certificates per IP address. Paul Querna has an excellent and easy explanation of what SNI is about – which I reproduce here :

When a client connects to a server using SSL, the server will send the Public Certificate to them. This enables them to actually decrypt the data sent from the server later. Here is a short simplified example:

1. C: (TLS Handshake) Hello, I support XYZ Encryption.
2. S: (TLS Handshake) Hi There, Here is my Public Certificate,
                      and lets use this encryption algorithm.
3. C: (TLS Handshake) Sounds good to me.
4. C: (Encrypted) HTTP Request
5. S: (Encrypted) HTTP Reply

The problem in HTTP is we don’t know which Public Certificate to send, until step 4. This is long after the public certificate has been sent. Protocols such as IMAP and SMTP, which use STARTTLS, have a different pattern:

1. C: (Cleartext) I am using server 'mail.example.com'
2. S: (Cleartext) By The Way, I also support TLS Encryptionn.
3. C: (Cleartext) Lets use Encryption, aka 'STARTTLS'.
4. C: (TLS Handshake) Hello, I support XYZ Encryption.
5. S: (TLS Handshake) Hi There, Here is my Public Certificate,
                      and lets use this encryption algorithm.
6. C: (TLS Handshake) Sounds good to me.
7. C & S: (Encrypted) Exchange Data

Since the client tells the server which host it is connecting to in step 1, the server can pick the correct certificate in step 5. It is possible to do this in HTTP, using TLS Upgrade. This is slightly more complicated, and presents other security issues. The Server Name Indication approach has a much simplier setup:

1. C: (TLS Handshake) Hello, I support XYZ Encryption, and
                      I am trying to connect to 'site.example.com'.
2. S: (TLS Handshake) Hi There, Here is my Public Certificate,
                      and lets use this encryption algorithm.
3. C: (TLS Handshake) Sounds good to me.
4. C: (Encrypted) HTTP Request
5. S: (Encrypted) HTTP Reply

The only difference is a few extra bytes sent in Step 1. The client passes along which hostname it wants, and the server now has a clue which public certificate to send.

The good people at CAcert are following closely how SNI is supported in major pieces of web infrastructure. To summarize, SNI has been supported in mod_gnutls since 2005, but the ominous warning on the mod_gnutls home page does not make mass deployment likely in the short term : “mod_gnutls is a very new module. If you truely care about making your server secure, do not use this module yet. With time and love, this module can be a viable alternative to mod_ssl, but it is not ready“. But fear not : Apache bug 34607 tracks the development of SNI support for mod_ssl, and it only has to wait for the 0.9.9 release of OpenSSL which is said to include support for SNI. So the future is bright ! Support on the client side is more patchy at the moment, but it will likely improve fast as soon as the servers are available.

So when I say the the savior has arrived, I should rather say that it is still underway and it is taking its time. SNI is described in section 3.1 of RFC3546 which dates from June 2003 ! And Paul’s post is from April 2005 – although at that time SNI was already supported in mod_gnutls. I am surprised that the development of such a liberating feature so critical to the providers of collective hosting has been so slow in a an essential pillar of infrastructure such as OpenSSL. I am even more surprised that I have not heard of it before – but now I am quite excited about it !

Since CAcert is tracking SNI support, I guess they will eventually offer name based certificates. Count me in !