SNI Readiness

The idiots who developed the SSL/TLS protocol did not build in a mechanism for using multiple certificates/sites on a single IP address. HTTP 1.1 could do named-based virtual hosting, but not with SSL. SNI is the solution to that. It is an extension to TLS by which the client indicates the hostname to which they are connecting during the handshake, so that the server can select the appropriate certificate.

However, SNI is an extension, and there is no guarantee of support for it in clients. I have avoided SNI until now because the degree to which it is supported was not clear. Yes, for web browsers, the adoption rate is probably high, but what about for API clients?

It appears that the answer can be found by capturing and analyzing network traffic. It should be possible to evaluate which existing clients, and what percentage of clients, implement SNI.

In the TLS conversation, the functional part of SNI appears as a server_name extension in the Client Hello packet (which is itself unencrypted). If we can capture the TLS "Client Hello" packets, we should be able to analyze whether they contain the SNI extension. From this, we can compile statistics about the adoption rate of SNI. For an API with a finite set of clients, we can make a count of how many clients, and a list of which clients, have not yet implemented SNI support.

Capture

The first step, then, is capturing. Ideally, we want to capture only the Client Hello packets, so that we can capture the greatest number of samples for a given amount of disk space. On Linux, this would be done with tcpdump. On Windows, this would be done with Wireshark or the accompanying dumpcap command-line utility. All of these utilize pcap, so a pcap filter expression is called for.

This is going to be little challenging. While tcpdump and Wireshark can decode and display information about the TLS protocol, pcap knows nothing about it.

However, it appears TLS handshake packets are identified as having 22 (decimal) as the first byte of the TCP payload. Among those, Client Hello packets are identified by having 1 as the sixth byte of the TCP payload. This appears to be true for SSL 3.0 and all versions of TLS, but not for SSL 2.0 or prior. You shouldn't be supporting SSL 2.0 or earlier anyway. If you do, then you should make a separate list of clients still using SSL 2.0, because SSL 2.0 doesn't support protocol extensions, including SNI.

(Ugh. SSL is so deprecated, the protocol specifications have been erased from history. RFC 6101 is a retrospective document for SSL 3.0, and draft-hickman-netscape-ssl-00 appears to be a draft specification for SSL 2.0.)

In any case, if this proves to be correct, then the pcap expression would be:

tcp port 443 and tcp[(tcp[12]>>2)] = 22 and tcp[((tcp[12]>>2)+5)] = 1

(Adjusting the port number for the appropriate protocol. Note that some of these characters need to be quoted or escaped if used on the command line.)

Analysis

Once we have a capture, analysis is easy with Wireshark. We can set a display filter to see all the Client Hello packets that include the SNI extension:

ssl.handshake.extension.type == 0

More importantly, we can set a display filter to see all the Client Hello packets that do not include the SNI extension:

!(ssl.handshake.extension.type == 0)

Even more useful than simply seeing the packets would be statistics on unique endpoints. In Wireshark, select from the menu Statistics -> Endpoints. In the new window that opens up, go to the IPv4 or IPv6 tab as appropriate. At the bottom, check the "Limit to display filter" box. The Packets column will indicate how many connections came from this IP address. Note that both the client and server IP addresses will appear in this list.

Also at the bottom of the Endpoints window, there is a Copy button, which can be used to copy the list to your clipboard as CSV, which you can then paste into Notepad and save with a .csv extension, and then open with Excel.

Preliminary Results

In a capture of a little over two hours, on a relatively low-usage web site, I captured 116 packets. Out of those, only two were missing the SNI. I didn't capture any other part of the conversations, so I don't know what happened, but neither IP address appeared in any of the access logs. One was specifically using SSL 3.0, which leads me to wonder whether it was part of a scan looking for vulnerable systems.

I should be doing a much longer capture, but so far this seems like a positive result for web clients. API clients may be another matter.