Freigeben über


Server Name Indication (SNI) with IIS 8 (Windows Server 2012)

 

In my previous article I discussed on how scalability was achieved in IIS 8.

Here is the link: SSL Scalability with IIS 8.

 

In this blog I will discuss specifically about Server Name Indication aka SNI. We will learn how scalability is achieved through this.

 

During SSL handshake when the client sends a HTTPS request (Client Hello) to the web server, the HTTP headers are not available to the server. Once the SSL handshake is completed the client will encrypt the headers and send the encrypted HTTP request to the server. Therefore server cannot access the HTTP headers or the content until the request is encrypted. Hence, the problem. Smile

 

Before decrypting the request the only information available to the server will be the IP Address and the Port number. This is available through the TCP headers as only the HTTP headers are encrypted. This leads to the limitation of only one certificate can be bound to a combination of <IPAddress>:<Port> .

 

Legacy SSL handshake between client and IIS 7.x and earlier

  1. The client and the server establish a TCP connection via TCP handshake.
  2. The client then sends a Client Hello to the server. The only information available to the server from Client Hello is the IPAddress and the Port. The client sends a specific protocol version and the list of supported cipher suites as part of this client hello.
  3. The server checks the registry to find a certificate hash/thumbprint corresponding to the above combination of IP:Port. The server checks the below key to find the combination: HKLM\SYSTEM\CurrentControlSet\Services\HTTP\Parameters\SslBindingInfo
  4. Once it finds a match, the crypto API’s are called to retrieve the Server Certificate based on the thumbprint from the certificate store. This is then added to the Server Hello and sent to the client.
  5. The HTTP headers are not sent until the handshake is complete, as a result the server never knows which site/application the request corresponds to until the handshake completes.

NOTE: The Public key cryptography is used to decide on a symmetric key (session key), which is then used by the client and the server for both encryption and decryption of the HTTP Headers and the content body. If you realized by now, SSL handshake involves both asymmetric encryption and symmetric encryption. Symmetric encryption is used for encryption of the actual data.

 

All the SSL bindings on Windows OS prior to Windows Server 2008 R2/Windows 7 can be found under following registry key:

 

HKLM\SYSTEM\CurrentControlSet\Services\HTTP\Parameters\SslBindingInfo

 

Even if the client provides the server name in the client hello, the server wasn’t capable of using it. This is addressed in IIS 8. To solve this problem associated with SSL/TLS, IETF added a new TLS extension called Server Name Indication. It is mentioned in the following RFC’s

You could also read about SNI on Wikipedia.

As mentioned in the above RFC’s a TLS extension called ServerName was introduced to tackle this problem. Below is a snippet from RFC 6066.

 

 East Lake                  Standards Track                      [Page 5] 
 RFC 6066              TLS Extension Definitions               April 2011
 3. Server Name Indication

TLS does not provide a mechanism for a client to tell a server the name of the server it is contacting. It may be desirable for clients to provide this information to facilitate secure connections to servers that host multiple 'virtual' servers at a single underlying network address.

In order to provide the server name, clients MAY include an extension of type "server_name" in the (extended) client hello. The "extension_data" field of this extension SHALL contain "ServerNameList" where:

      struct {

          NameType name_type; select (name_type) { case host_name: HostName;           } name;       } ServerName;

      enum {           host_name(0), (255)       } NameType;

      opaque HostName<1..2^16-1>;

       struct {           ServerName server_name_list<1..2^16-1>        }ServerNameList;

 

Now the client can send the hostname it wants to access over https as a part of client hello. This helps the server to associate the client hello to a specific request and thus we overcome the limitation which was imposed earlier.

 

If you were to capture a network trace of SNI complaint browser accessing a HTTPS site you could see this extension as part of the client hello. I captured a Wireshark trace while accessing https://www.outlook.com. I filtered the trace by SSL and searched for Client Hello.

 

image

snapshot of a SSL trace in Wireshark 

***IMPORTANT***

 

One important thing to note here is that SNI is part of the Client Hello. So it is the client browsers that need to support this extension. Most of the current day browsers support SNI.

 

However, there are few browsers out there that don’t support SNI. For example, on Windows OS any version of IE running on Windows XP or lower versions do not support SNI. Vista onwards support for SNI was included for IE 7 and higher. There is a good list on Wikipedia on browsers that provide support for SNI. Below is a snippet from Wikipedia:

 

List of SNI Compliant Browsers:

  • Internet Explorer 7 or later, on Windows Vista or higher. Does not work on Windows XP, even Internet Explorer 8.
  • Mozilla Firefox 2.0 or later
  • Opera 8.0 or later (the TLS 1.1 protocol must be enabled)
  • Opera Mobile at least version 10.1 beta on Android[citation needed]
  • Google Chrome (Vista or higher. XP on Chrome 6 or newer.[6] OS X 10.5.7 or higher on Chrome 5.0.342.1 or newer)
  • Safari 2.1 or later (Mac OS X 10.5.6 or higher and Windows Vista or higher)
  • Konqueror/KDE 4.7 or later [7]
  • MobileSafari in Apple iOS 4.0 or later[8]
  • Android default browser on Honeycomb (v3.x) or newer[9]
  • Windows Phone 7
  • MicroB on Maemo

 

So far I was trying to explain the basics of SNI. We need to know this to understand the server side solution for this.

 

NOTE: SNI is available only on IIS 8 and may be future versions. It is not available on any of the previous versions of IIS like IIS 7.x, IIS6 etc.

SNI on IIS 8

 

IIS 8 supports Server Name Indication. This is enabled by default and no separate installation is required. Now while adding a HTTPS binding for a website on IIS 8, the option to enable SNI is available. This is how the UI looks like:

image

 

There are 2 things to remember when enabling SNI for a specific site on the server.

  • Selecting the above option enforces the site to use SNI i.e., it will expect the client to send a server_name as the part of the Client Hello during SSL handshake. If the server_name extension is not present then the SSL handshake would fail.

  • The hostname has to be provided, this is a strict mandate. The server will use this information to associate an incoming request to a specific site.

 How does the IIS know if a specific binding uses SNI?

 

When a SSL bindings is added for a site, there is also a small change in the configuration file i.e., the applicationhost.config. This is how the binding section looks like:

<bindings> <binding protocol="https" bindingInformation="*:443:SNI.IIS8.com" sslFlags="1" /> </bindings>

 

The highlighted attribute called sslFlags is. This attribute tells IIS what type of binding it is. This flag can be thought of as a doing an OR operation on 2 variables x and y. Below table would give you a gist of what this flag signifies.

 

Using CCS Using SNI

sslFlags

Description

0

0

0

Legacy SSL binding. Neither uses SNI nor CCS

0

1

1

SSL binding using SNI.

1

0

2

SSL binding uses CCS, but SNI is not enforced.

1

1

3

SSL binding uses CCS, but SNI is enforced.

 

Changes in Registry

 

In IIS 8 we have a new registry key where all the SNI bindings are stored. I had mentioned this in my previous blog post. This location of this registry key is

HKLM\SYSTEM\CurrentControlSet\Services\HTTP\Parameters\SslSniBindingInfo

 

Executing the following command “netsh http show sslcert” will read this key and show a formatted output as shown below:

 

C:\>netsh http show sslcert SSL Certificate bindings: ------------------------- Hostname:port : SNI.IIS8.com:443 Certificate Hash : 8d90a17d2851f802b0a5619bf695b03544b8f5cb Application ID : {4dc3e181-e14b-4a21-b022-59fc669b0914} Certificate Store Name : My Verify Client Certificate Revocation : Enabled Verify Revocation Using Cached Client Certificate Only : Disabled Usage Check : Enabled Revocation Freshness Time : 0 URL Retrieval Timeout : 0 Ctl Identifier : (null) Ctl Store Name : (null) DS Mapper Usage : Disabled Negotiate Client Certificate : Disabled       

 

So now we have 3 types of SSL bindings:

  1. IP:Port – Legacy SSL binding.

  2. Hostname:Port – SSL binding using SNI. (new in IIS 8)

  3. Central Certificate Store – SSL binding using Central Certificate Store. I will discuss this in detail in my next blog. (new in IIS 8)

There is a small problem that the administrators have to take care of while configuring SSL bindings to use SNI. If a non-SNI compliant browser connects to a site on which SNI is enforced, as I mentioned earlier the SSL handshake would fail.

 

To tackle this there is a fall-back mechanism in IIS where the it would try to determine a binding with the combination of IP:Port, if this is not present, then the SSL handshake fails. For this the IIS admin has to configure a binding which neither uses SNI nor CCS.

 

If legacy binding doesn’t exist, then the IIS UI will throw an alert as shown below. This message is a warning saying that there is no legacy binding, so in case of a failure the SSL handshake would fail.

 

No default SSL site has been created. To support browsers without SNI capabilities, it is recommended to create a default SSL site.

image

 

SSL Handshake between a SNI compliant browser and SNI Compliant Server

 

Below are the steps involved during SSL handshake between a SNI compliant Client and a site hosted on IIS 8 on which a SSL binding is configured to use SNI.

  1. The client and the server establish a TCP connection via TCP handshake.

  2. The client sends a Client Hello to the server. This packet contains the specific protocol version, list of supported cipher suites along with the hostname (let’s say www.outlook.com provided its a SNI compliant browser). The TCP/IP headers in the packet contain the IPAddress and the Port number.

  3. The server checks the registry (legacy bindings) to find a certificate hash/thumbprint corresponding to the above combination of IP:Port.

  4. If there is no legacy binding for that IP:Port, then server uses hostname information available from the Client Hello checks the registry to find a certificate hash corresponding to the above combination of Hostname:Port. The server checks the below key to find the combination:

    HKLM\SYSTEM\CurrentControlSet\Services\HTTP\Parameters\SslSniBindingInfo

  5. If the above step fails i.e., if the server couldn’t find a corresponding hostname:port, then it would use the IPAddress available to search for a legacy SSL binding for that IPAddress and PORT. (If this is absent then the SSL handshake would fail)

  6. Once it finds a match, the crypto API’s are called to retrieve the Server Certificate based on the thumbprint/certificate hash from the certificate store. The retrieved certificate is then added to the Server Hello and sent to the client.

More Information:

 

You could refer the following links on additional information on this topic:

https://en.wikipedia.org/wiki/Server_Name_Indication

https://learn.iis.net/page.aspx/1096/iis-80-server-name-indication-sni-ssl-scalability

https://blogs.iis.net/yaminij/archive/2012/06/25/sni-server-name-indication-readiness-tool-draft.aspx

Comments

  • Anonymous
    October 01, 2012
    Possible bug in HTTP.sys:
  1. Create SNI binding "123.123.123.123:443:sni.iis8.com" with certificate "cert1"
  2. Create non SNI binding "123.123.123.123:443:non-sni.iis8.com" with certificate "cert2"
  3. Browse https://sni.iis8.com by SNI complaint browser - I get "cert2" instead of "cert1"
  4. Remove non SNI binding and browse https://sni.iis8.com again - I get "cert1"
  • Anonymous
    October 10, 2012
    Could you provide more details about this environment. I don't see this behavior. What build are you on?

  • Anonymous
    October 15, 2012
    See forums.iis.net/.../1192170.aspx

  • Anonymous
    March 04, 2013
    Multiple SSL Certificates on Windows Azure Cloud Services Check it out: www.vic.ms/.../multiples-ssl-certificates-on-windows-azure-cloud-services

  • Anonymous
    September 25, 2013
    Superb post, thank you. Had seen a few brief mentions elsewhere about SNI but nice to get some proper detail. This adds another reason I look forward to XP being dead and buried once and for all, so this can safely be used.

  • Anonymous
    August 20, 2014
    Is it possible to configure a default web site for https using SNI and CCS? I tryed the following, but it didn't work:                <bindings>                    <binding protocol="http" bindingInformation=":80:" />                    <binding protocol="https" bindingInformation=":443:" sslFlags="3" />                </bindings> Please see my post at forums.iis.net/.../2082994.aspx

  • Anonymous
    September 02, 2014
    Hi , I seeing one issue in wireshark capture. SSL is sending the "client hello messages but server is not responding for the the same with "server hello " messages. and client has retransmiited the same packet many times.In the technical log files I have seen the error messages like "Certifiacate has expired". 1.Before sending the server hello messages is it checking the "certificate validation" or after sending the server hello messages it is checking the validition of the certificate.

  1. in the certification validation is it checking the client certificate validation or server certificate validation.
  2. according to your post it checking the certification validation before sending the "server hello" msg. If it is the case why in the wireshark caputure fcertification validation done after hello messages exchange .
  • Anonymous
    September 03, 2014
    Cpuld you please provide some inputs for my comment

  • Anonymous
    September 07, 2014
    Hi Mamatha, Sorry for the late response. I was out of town for few days. regarding your question I'm not sure what you are seeing. If I had the trace I could have given you a clear picture.

  1. As far as Server Hello is concerned, the server will send it once it has confirmed that it supports the requested protocol version and cipher suites. If you are not seeing the Server hello message then the certificate validation error is misleading. The Server certificate validation happens on the client side and not the server, but to perform this validation the client needs the server hello message in response.
  2. I'm not clear on what the design is so I cannot comment. The response above should make you understand few things.
  3. Could you point out where did I say that the certificate validation is made before Server Hello message? If I did, then I must say I'm wrong and I need to correct the statement.
  • Anonymous
    February 25, 2016
    Can you please explain in more detail what happens in the "SNI not enforced" case (sslFlags=2, i.e. "SSL binding uses CCS (Central Certificate Store), but SNI is not enforced"? What does IIS do if SNI is unchecked, but a host name is indicated in the HTTPS binding? How is that different from not having a host name specified at all? I would understand this much better if there was no SNI checkbox, and if SNI was used whenever a host name is set for the HTTPS binding (like HTTP 1.1. host names). But using one without the other, it's not clear what that would do :)

    • Anonymous
      April 20, 2016
      The comment has been removed
  • Anonymous
    July 22, 2016
    Great article - thanks!

  • Anonymous
    August 08, 2016
    Why on earth is the default behaviour to look for an IP:Port binding(step 3) before checking for Hostname:Port(step 4)? Surely this means that one site configured on a server with a legacy IP:Port binding breaks every SNI site on there as they'll all suddenly start presenting the client with the certificate from the legacy site as that's found first!

  • Anonymous
    December 22, 2016
    Useful post - thanks. But this business at the end re "No default SSL site has been created. To support browsers without SNI capabilities, it is recommended to create a default SSL site." .... it would be helpful to give some advice about what one is supposed to do about it! How do I create a default SSL site on a server with (say) 50 websites on it?

    • Anonymous
      January 23, 2017
      @Phil.Create a website, and add a sample html page indicating that if they landed on this page, then their client is not SNI-Compliant and they need to use a different browse that is SNI compliant.
  • Anonymous
    February 22, 2017
    Great info Kaushal! I've a quick question, I've a sub-domain say "https://secure.example.com" for which we've setup SSL certificate. In order to support non-SNI clients (say Win XP with IE 6.0), do I need to create following binding:Type: httpsIP: my dedicated IP addressPort: 443Host Name: Blank?Require Server Name Indication: Off?Certificate: my SSL certificate.Regards,-Mateen

    • Anonymous
      February 28, 2017
      The comment has been removed
      • Anonymous
        March 02, 2017
        In order to support non-SNI clients, I need to create a default site with legacy binding, can I know which SSL Certificate do I need to binding this default site?