1

As I understand a webserver shall serve SNI first and ignore HOST header from HTTP 1.1 as TLS handshakes occurs before HTTPS, to test I came up with this example: two domain names under the same IP address stackexchange.com and stackoverflow.com:

(echo GET / HTTP/1.1
echo Host: stackoverflow.com 
echo Connection: close
echo) | openssl s_client -quiet -servername stackoverflow.com -connect 151.101.1.69:443 \
| grep URL

Returns <p>URL: stackoverflow.com/</p> - I expected this.

(echo GET / HTTP/1.1
echo Host: stackexchange.com 
echo Connection: close
echo) | openssl s_client -quiet -servername stackexchange.com -connect 151.101.1.69:443 \
| grep URL

Returns <p>URL: stackexchange.com/</p> - Expected.

(echo GET / HTTP/1.1
echo Host: stackexchange.com 
echo Connection: close
echo) | openssl s_client -quiet -servername stackoverflow.com -connect 151.101.1.69:443 \
| grep URL

Returns <p>URL: stackexchange.com/</p> - I expected to see stackoverflow.com instead, my question - why I did not get it?

1
  • WTF, stackexchange.com blocks requests that have no User-Agent header? (see curl --user-agent '' https://stackoverflow.com/)
    – marcelm
    Sep 20 at 6:41

1 Answer 1

3

Some confusion here : there are two layers that interact relatively little, the TLS session establishment, and the HTTP request. The SNI option of TLS session initiation permits the server to choose the right certificate to present to the client, in case it uses more than one certificate. In the case of the StackExchange sites, they seem to have one frontend mutualized between all sites, using subjectAltNames for every site, so the SNI option doesn't change anything. The TLS session establishment does not take into account the Host: header of the HTTP request at all, so OpenSSL doesn't prefer the header, because for OpenSSL the header is data and passed to the application layer untouched and unseen.

Once your TLS connection is established, normal HTTP behavior applies and the Host: header is used.

In many cases, one could establish connection with one hostname in the SNI extension, and another in the Host: header, and for all purpose the Host: header will take precedence. As @dave_thompson_085 mentioned, doing that on purpose is called domain fronting and it can actually be used to evade some form of censorship (when one entity forcibly close connections if the domain observed in the SNI extension is blacklisted).

3
  • 2
    Stack's certificate's SAN is detailed in this other Q from the same OP. Using different Host than SNI is or has been used to avoid censorship in some countries (which can see SNI and block based on it, but not Host) and is called 'domain fronting'. Sep 20 at 4:00
  • @dave_thompson_085 for example - server has two websites with individual tls certificates and I send a SNI record to use server1 and HOST header with server2, HOST header shall reroute a request and I will get a reply from server2, is it correct? Sep 20 at 4:55
  • 2
    @GhostRider: that's up to the server. SNI and Host are both supposed to represent the 'desired' server, so if they're different a server isn't required to accept it, but in practice (often? usually?) the TLS and HTTP parts of the software are separate and each doesn't care about the other. However if what you're talking to is actually a firewall, load balancer, CDN, or similar, they may well route based on SNI and the subsequent HTTP request with different Host won't work. Sep 20 at 6:34

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.