Server Name Indication
SNI is an extension to TLS and enables HTTPS clients to send the host name of the server it wants to connect to at the start of the handshake request. This is an important feature, as the host name information is sent inside the HTTP header and the header is only sent after the handshake (TLS connection already established).
With SNI, the server host to which the client wants to connect to is send outside the HTTP header. When the connection is established, the server reads the server name from the SNI extension field and knows the server name the client wants to connect to. This is very important in the cloud world, as many services are running behind a reverse proxy. That is, a server in front of them handles the incoming requests, establishes a secure connection and then forwards the client requests to the correct backend. In case your client does not support SNI, you do have a serious problem connecting securely to cloud services.
Without SNI, when the TLS connection is established, the HTTPS server does not know to which host name (FQDN) the client wants to connect to: the default TLS certificate of the server is sent. If the client wants to connect to www.itsfullofstars.de, and this is a virtual host, and the server’s default host is test.itsfullofstars.de, the certificate for test.itsfullofstars.de will be send.
The below image should help you to understand the flow and how a web server selects the correct data to send back. A client connects to host services.odata.org. The FQDN of the server is send as a value in the HTTP header. As the client supports SNI, the same information is send in the TLS SNI extension during the handshake process. The server selects the TLS certificate for services.odata.org thanks to SNI, and then loads the data from the virtual host services.odata.org as indicated in the HTTP header.
You can test this using the OData.org sample services. When you access services.odata.org:
The browser sends the server in the HTTP header field host. This field is used by the web server to evaluate by which virtual server the request is handled.
Using the value in the host header, the web server knows which data to send, including the correct TLS certificate.
If you want to know how this works in reality and how SNI looks like, Wireshark can be used to capture the TLS connection flow. Client Hello is sent when the client initiates the TLS connection.
When the browser sends Client Hello, SNI with the host name is included in the request. As SNI is a TLS extension, it appears in the list of TLS extensions. The data is still unencrypted.
The server is sending its certificate in Server Hello, which is a response to Client Hello.
This shows clearly why with SNI the client can send the server host information and why the web server can read the value and respond with the correct server TLS certificate.
In case the host header and SNI are not pointing to an existing virtual host, the default configuration of the web server is used. You can easily simulate this by accessing the web server via IP address. The web server behind services.odata.org is running on IP 220.127.116.11. If you open that page in your browser:
The SNI information is empty, therefore the server will respond with its own certificate. Also, as no virtual host is found, it’s a web page saying that it could not find the correct web page.
Note that the connection is still using TLS and the default server certificate was used: default TLS certificate is issued for azurewebsites.net.
Why this certificate is sent instead of the one for services.odata.org? Let’s take a look at the above graphic and use it to follow the red line indicating the information flow. The browser is not sending a valid virtual host in the HTTP header field (IP address). The web server therefore cannot identify a valid virtual host and is using its default configuration. Which is to use the information and certificate of the web server itself. Instead of accessing the virtual host services.odata.org, the browser is accessing 18.104.22.168 and the server certificate is for *.azurewebsites.net. Of course, this is not a valid communication with TLS.
The same happens when a client is not supporting SNI. The HTTP header information is sent after the TLS handshake, which means the information is sent after establishing a trusted connection. When the server cannot read the host field, the default configuration of the web server is used. Result: default server certificate is send. As the browser expects a certificate issued to a different server name, the browser will not accept the TLS session. For the browser the TLS connection is faulty. It looks like a hacking attempt. Without SNI, you can only connect to web servers that do not depend on a virtual host configuration.