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 :</span></b>.</font></font> </p>

 

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

* RFC 3546 – Section 3.1 * RFC 4366 – Section 3.1 * RFC 6066 – Section 3

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]
</p>
RFC 6066              TLS Extension Definitions               April 2011
</p>
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:



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

</bindings></font>

</td> </tr> </tbody> </table>

 

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

Legacy SSL binding. Neither uses SNI nor CCS

1

1

SSL binding using SNI.

1

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 </p>

SSL Certificate bindings:

</font></span>————————-

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 

       </td> </tr> </tbody> </table>

 

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: </p>

    HKLM\SYSTEM\CurrentControlSet\Services\HTTP\Parameters\SslSniBindingInfo</span></font></div> </li>

  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.
  7. </ol>

    More Information:

     

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

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

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

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