Understanding HTTP host header and SNI
Do you know the difference between SNI and HTTP host headers ? It is sometimes very confusing. I think we should properly understand these technologies if we bulid a website in a public cloud.
In this blog, I'll write FQDN and HTTP host headers used to access to websites, and Server Name Indication (SNI) which is one of the TLS extensions. In Azure, these are used by Application Gateway, FrontDoor, AppService, etc. These technologies must be used when we build a website, but as these technologies are a little complicated so I'll explain them in this article.
Host headers and Server Name Indication (SNI)
What is host header ?
Is one of the HTTP headers and in the form of "Host: xxx". In HTTP headers, there are various headers such as Location, User-Agent, connection, etc. The host header is in RFC 7230, and is used to define the hostname of the HTTP request. We can find the header in the network tab of the developer tool in a web browser.
This is an example of host header when I accessed a Microsoft document.
Many PaaS services provided by Azure are multitenant so we share same platform with other users. In the case of web services, the platform checks the FQDN set on the PaaS service to see whether the host header of the HTTP request is the same or not in order to identify user requests. I will refer HTTPS later ni this document.
What is Server Name Indication ?
SNI is another of the TLS extensions, defined in RFC 6066, and it indicates the FQDN from the client in a TLS handshake. The TLS handshake is similar to a TCP 3-way handshake but while the TCP handshake establishes a TCP connection, the TLS handshake starts after the TCP connection so TLS is in an upper layer if the OSI model. We need to confirm SNI in a the packet capture as we can’t find it in the browser.
Below is a packet capture on the client when I accessed a Microsoft document. After the TCP 3-way handshake (blue), the Client Hello was sent from the client (red), which includes "Server Name : docs.microsoft.com” as the Server Name Indicate extension in the packet (green).
On the web server side, it validates the FQDN in the certificate on the server based on the SNI and then proceeds to the TLS handshake. After the TLS handshake is established, the HTTP Request is sent from the client, and the client can view the web page in their browser when they get the response.
Not supported clients
The latest PC and mobile devices generally have no problems using SNI, but sometimes very old devices, such as filp phones are not supported so we need to care them.
SNI support list: https://en.wikipedia.org/wiki/Server_Name_Indication
If we use devices which don’t support SNI, the client does not indicate the FQDN even though the URL includes the FQDN. We need to consider the situation because these clients can’t access services like FrontDoor, AppService, etc, without supporting SNI.
When we use IP address like “https://IP address” to access a website, it doesn’t use SNI. Application rule of Azure Firewall evaluate the HTTPS traffic based on SNI resulting in traffic without SNI being blocked. In these cases, when we view the logs, we will see "Action: Deny. Reason: SNI TLS extension was missing".
Azure Firewall uses SNI TLS headers to filter HTTPS and MSSQL traffic
When the traffic doesn’t have SNI, there is also no server_name extension in the ClientHello packet as seen below.
Diagram of web access
The following diagram illustrates the process sequence to open a website in a browser. At step 5, the client sent the Server Name Indication (SNI). At step 6, the client sent the host header and got the web page. In this diagram, testsite1.example.com is used as the SNI and host header and the web service respond with the web page which matches the FQDN.
When we configure CDN, WAF, reverse proxies or such services, depending on the requirements, we have to set same custom domain between the reverse proxy and backend service. It depends on the requirements. For example, cookies having domain attributes, Location headers, etc. Please see the link below regarding these common issues.
Troubleshoot App Service issues in Application Gateway
In this configuration, we need to set different FQDNs between each services to avoid looping. In addition, the FQDN for the live traffic needs to be the same custom domain making it very confusing. I recommend you consider the FQDN for name resolution, TLS SNI, and HTTP host headers separately to make it easier to grasp.
In the following diagram, the FQDN is different between 1-1 and 2-1, but SNI of 1-5 and 2-5 and the host headers of 1-6 and 2-6 are the same FQDN.
When we use general browsers like Edge r Chrome, the FQDN in the URL will be the FQDN for name resolution, TLS SNI and HTTP host header. We can change those FQDNs if we use curl or openssl command as the client.
Curl command
I use curl command on Windows WSL to change the FQDN between TLS SNI and HTTP host header. In the case of curl, the SNI depends on the URL so I add “Host header” option. We can see the request details with -v option.
curl -v https://<FQDN [SNI]> -H 'Host: <FQDN [Host header]>'
Below are the logs of the request. The FQDN in the URL and in the certificate match but host header is different.
If you would like to access to an IP address which is different from the DNS result, you can use “--resolve” option. It is a useful option in order to set the TLS SNI and host header as seen below.
curl -v https://testsite1.xxxxxxx.com -H 'Host: xxxxxx-xxxxxxxxhrfyfb.z01.azurefd.net' --resolve testsite1.xxxxxxx.com:13.107.xxx.xxx
OpenSSL command
The OpenSSL command enable us to set the destination IP address with the "-connect" option, TLS SNI with "-servername". If you don’t add the servername option, the request may not contain SNI. We can send an HTTP request after establishing a TLS handshake, so we can also add a HTTP header after the openssl s_client command.
openssl s_client -connect <IP address>:443 -servername <FQDN [SNI]>
~TLS handshake~
GET / HTTP/1.1
Host: <FQDN [Host header]>
Press Enter key
The logs from when I accessed the PHP site which returns the request headers are below. First, we can see the FQDN of the server name option matches to the domain of certificate. When then see the FQDN is sent as the host header to the web server.
What is domain fronting ?
As I described in this article, we can intentionally change the TLS SNI and HTTP host header but if we wanted, we could leverage this into a type of attack known as "domain fronting," and I have included an article with details on this below. For example, there is the possibility someone access a website using different SNI even though the domain should be restricted by the platform.
Securing our approach to domain fronting within Azure
Azure Front Door and CDN have already taken action to prevent this since November 8 , 2022. Those platforms block any HTTP request that exhibits domain fronting behavior by default.
How does Front Door handle ‘domain fronting’ behavior?
Beginning November 8, 2022, all newly created Azure Front Door (Standard, Premium and Classic tier) or Azure CDN Standard from Microsoft (classic) resources will block any HTTP request that exhibits domain fronting behavior. Requests where the host header in HTTP/HTTPS requests that doesn't match the original TLS SNI extension used during the TLS negotiation gets blocked.
Published on:
Learn more