skip to content

When one IP address serves many HTTPS sites, what job does the TLS SNI extension do compared with the HTTP Host header, and what should a server do when the two names disagree?

level: middleimportance: should knowfreq 42%

answer

  1. SNI = ClientHello, plaintext, picks the cert
  2. Host = inside TLS, picks the vhost
  3. SNI first, Host second
  4. Mismatch → 421 Misdirected Request
  5. Domain fronting = deliberate mismatch; ECH hides SNI

basics

~20 s

SNI is sent in the TLS ClientHello, before encryption, so the server can pick the right certificate. Host is sent inside the encrypted HTTP request and picks the application/virtual host. They should match; a mismatch means the server is not authoritative and can answer 421.

solid answer

~60 s

They answer the same question — *which site?* — at two different layers and two different moments. **SNI (Server Name Indication)** is a TLS extension in the ClientHello. It is sent in the clear, before any key exchange, because the server has to choose a certificate before it can encrypt anything. Without SNI, one IP could serve only one certificate. **Host** (or `:authority` in HTTP/2 and HTTP/3) is sent inside the finished TLS tunnel, as part of the HTTP request, and selects the virtual host or backend that handles the request. So the order is: TCP connect → ClientHello with SNI → certificate chosen → handshake completes → HTTP request with Host. A correct server validates that Host is one it is authoritative for on this connection — meaning it is covered by the certificate that was served. If Host names a site this connection is not authoritative for, `421 Misdirected Request` is the defined answer; it tells the client to retry on a fresh connection. Blindly trusting Host after an unrelated SNI is how domain fronting and some cache-poisoning tricks work.

code

bash · 5 lines
bash
openssl s_client -connect 203.0.113.10:443 -servername shop.example.com </dev/null | openssl x509 -noout -subject

# Deliberate mismatch: SNI for one name, Host for another
curl -v --resolve a.example.com:443:203.0.113.10 \
     -H 'Host: b.example.com' https://a.example.com/

go deeper

for a junior

Know that SNI picks the certificate during the TLS handshake and Host picks the site inside HTTP, and that SNI comes first.

for a middle

Explain the ordering and the visibility difference (SNI plaintext, Host encrypted), and that they normally carry the same name.

for a senior

Discuss mismatch handling: 421, HTTP/2 coalescing, domain fronting, and the fact that SNI disappears at a TLS-terminating proxy so the origin routes on Host alone.

for a principal

Decide where authority is validated across the edge, how origins are protected once SNI is gone, whether coalescing is desirable for your certificate topology, and what SNI leakage means for your privacy or censorship-resistance posture.

## Two names, two layers When you open `https://shop.example.com/cart`, the hostname is needed twice, by two different pieces of software, at two different times. 1. **TLS needs it first.** Before a byte of HTTP exists, the client and server must agree on a certificate. A certificate is bound to specific names; a server hosting fifty domains on one IP holds fifty certificates and must pick one *before* encryption starts. The client therefore puts the hostname into the very first message it sends, the **ClientHello**, in an extension called **SNI (Server Name Indication)**. 2. **HTTP needs it second.** Once the tunnel is up, the HTTP request goes through it, carrying `Host: shop.example.com` (HTTP/1.1) or the `:authority` pseudo-header (HTTP/2, HTTP/3). This is what the web server or gateway uses to pick a virtual host, an upstream pool, or a routing rule. ## The timeline ``` TCP SYN/ACK ClientHello (SNI = shop.example.com) <-- plaintext ServerHello + Certificate for shop.example.com ... handshake completes, tunnel established ... GET /cart HTTP/1.1 <-- encrypted Host: shop.example.com ``` The practical consequence of that ordering is that **SNI is visible to anyone on the path** — routers, corporate middleboxes, censors — while Host is not. SNI leaks which site you visit even though the URL path and content are protected. Encrypted Client Hello (ECH) is the ongoing effort to close that leak by encrypting the ClientHello's sensitive parts; it is deployed in places but not universal. ## What each one selects - **SNI selects a certificate** (and, at a TLS-terminating load balancer, often the listener/backend too). - **Host selects the application** — the vhost, the route, the tenant, the cache key. They are frequently handled by different components. A CDN or an L7 load balancer terminates TLS using SNI, then forwards a plaintext HTTP/1.1 request to an origin, which routes on Host alone. At that inner hop SNI no longer exists. ## When they disagree Nothing at the protocol level forces the two to be equal — the client controls both, independently. So a client can complete a handshake with `SNI: a.example.com` and then send `Host: b.example.com`. Three things can happen: - **Legitimate connection reuse.** HTTP/2 permits *connection coalescing*: if the served certificate also covers `b.example.com` and the name resolves to the same address, the client may reuse the existing connection and send `:authority: b.example.com`. This is a feature — it saves handshakes. The server is authoritative for both names, so it serves the request. - **Misdirection.** If the server is *not* authoritative for the Host it received on that connection, the defined response is **421 Misdirected Request**. 421 tells the client the request went to the wrong place and it should retry over a new connection; unlike most 4xx codes, it is safe to retry automatically. - **Abuse.** Historically, deliberately mismatching SNI and Host was the mechanics of **domain fronting**: connect with an SNI for an innocuous domain hosted on the same CDN, then send a Host for a blocked domain, so on-path observers see only the innocuous name. Major CDNs now reject SNI/Host mismatches for this reason. The same mismatch can be used to reach internal vhosts behind a shared edge if the edge routes purely on Host without checking authority. ## Configuration reality - nginx exposes `$ssl_server_name` (SNI) and `$host` (Host) separately, so you can compare them and `return 421` on mismatch. - Old clients without SNI (very old Android, some embedded and scripting stacks) will get the default certificate for the listener; they typically fail certificate validation. Tools like `openssl s_client` need `-servername` explicitly, which is why `openssl s_client -connect ip:443` alone often returns the "wrong" certificate. - Health checks and internal callers that dial an IP directly send no SNI or an IP-shaped SNI and land on the default server — the same failure mode as with Host. ## Summary for an interview SNI = plaintext, TLS layer, first message, picks the certificate. Host/`:authority` = encrypted, HTTP layer, picks the application. They normally match; when they do not, the server should either be genuinely authoritative for both (coalescing) or answer 421. Trusting Host without checking authority is the hole that domain fronting and edge-bypass tricks walk through.

  • Why is 421 Misdirected Request safe for a client to retry automatically, unlike most 4xx responses?
    421 says nothing about the request being malformed — it says this connection was the wrong place to send it. The defined client behaviour is to retry the same request over a new connection to the correct server, so no request semantics are violated by the retry. That is what makes HTTP/2 connection coalescing safe: a client can optimistically reuse a connection and fall back cleanly if the server disagrees.
  • A CDN terminates TLS and forwards plaintext HTTP to your origin. What identifies the site at the origin, and what does that imply for security?
    Only the Host header — SNI ended at the CDN and does not exist on the inner hop. So the origin's routing is entirely at the mercy of whatever Host the CDN forwards, which means the origin must be reachable only from the CDN (network policy, mTLS, shared secret header) and should still validate Host against an allowlist. Otherwise anyone who can reach the origin IP directly can pick any vhost by setting Host.

SNI is the name you shout at the gate so the guard brings out the right ID badge; Host is the name you write on the visitor form once you are inside the building. Everyone in the street hears the shout; only the receptionist reads the form.

saying these in an interview costs you the question

  • Saying SNI is encrypted — it is in the plaintext ClientHello, which is exactly why ECH exists.
  • Claiming the server can read Host to choose a certificate; the certificate must be chosen before HTTP is readable.
  • Assuming the protocol forces SNI and Host to match — the client controls both independently.
  • Treating a SNI/Host mismatch as always malicious; HTTP/2 coalescing produces legitimate mismatches when one certificate covers both names.
  • Confusing 421 with 400 or 404; 421 specifically means wrong server for this authority and is retryable.

context