Today I went on an unusual journey, and it involved paying the price for configuring Microsoft’s web server (specifically, IIS 8.0 and 8.5) with scant regard for why it works the way it does. Let me start at the beginning..
As of Internet Information Services (IIS) 8.0 (Windows Server 2012) and continuing in the latest version, 8.5 (Windows Server 2012 R2) there is now support for “Server Name Indication”, or SNI. IIS allows you to set this value when configuring HTTPS site bindings on websites, as per below:
“Require Server Name Indication” or “make IIS support multiple SSL/TLS certificates” as I used to call it is a feature of IIS which allows you to bind different digital certificates to different websites within IIS using the same IP address.
Prior to IIS 8.0, you could only bind a single certificate to an individual IP address which you could only bind to one website, due to the way that handshaking worked at the time. From Wikipedia:
Server Name Indication (SNI) is an extension to the TLS computer networking protocol by which a client indicates which hostname it is attempting to connect to at the start of the handshaking process.
This allows a server to present multiple certificates on the same IP address and TCP port number and hence allows multiple secure (HTTPS) websites (or any other Service over TLS) to be served off the same IP address without requiring all those sites to use the same certificate. It is the conceptual equivalent to HTTP/1.1 name-based virtual hosting, but for HTTPS.
Now there’s a caveat with SNI, and one which I did not truly appreciate until today – some older “legacy” browsers, applications and libraries do not support SNI.
No support for SNI
The following combinations do not implement SNI (from Wikipedia again):
- WebClient service (for WebDAV) included in any Windows version
- Internet Explorer 6 or earlier and any IE version on Windows XP or earlier
- Safari on Windows XP or earlier
- BlackBerry OS 7.1 or earlier
- Windows Mobile up to 6.5
- Android default browser on Android 2.x (Fixed in Honeycomb for tablets and Ice Cream Sandwich for phones)
- wget before 1.14
- Nokia Browser for Symbian at least on Series60
- Opera Mobile for Symbian at least on Series60
- SAP (according to some consultants)
- Qt client side up to 4.7
- Mozilla NSS server side
- Java before 1.7
- Python 2.x (except 2.7.9), 3.0, 3.1 (
This begs the painful question..
What happens when something which does not support SNI tries to call a website or web service which relies on SNI – such as websites hosted within IIS?
Consider what happens when a client which supports SNI makes a request of IIS 8.0 or 8.5:
Because the site name indicator is supplied, IIS is able to locate the correct certificate for the named site and return it as part of the TLS handshake (prior to receiving HTTPS headers). If no named site is found, it will resort to the default certificate/HTTPS binding if there is one – note: you should have a default certificate set!
Now, let’s compare that with what would happen when SNI is not supported by the client:
Because the initial TLS handshake does not include the server name indicator (the name of the requested site) IIS will default to returning whatever’s bound by default. This will likely not match the certificate expected!
Some symptoms of clients not supporting SNI:
- Certificate mismatch (requested URI doesn’t match certificate common name) – default certificate is returned
- Intended website has no requests logged (but HTTP requests are logged – assuming a http binding is also used!)
- Intended request is logged against the default site instead of the intended site
One potential solution
If most of your sites use the same domain, you can assign a wildcard certificate to be the default for https/443 binding. When the non-SNI request arrives, the wildcard will match and then the subsequent HTTPS headers will result in the correct website being accessed:
I’m not sure if the sites would have to use the same wildcard certificate or not – this is currently being tested.
..could be to place a network load balancing (NLB) appliance in front of your webserver, if it supports HTTPS/SSL/TLS offloading. This way, traffic coming from the NLB would actually be HTTP, not HTTPS. This is obviously far less secure as the HTTPS traffic would terminate on the load balancer, but it does solve the problem in theory.
Well that was a fun find. The moral of the story is.. take time to understand why certain settings “make things work”, or else chances are you’ll find out the hard way. I hope this article helped someone out there.