How HTTP Works

Glossary Term

SNI (Server Name Indication)

SNI is a TLS extension that sends the hostname in the ClientHello so one IP can serve many certificates. Learn debugging with curl and nginx upstream pitfalls.

Reviewed 2 min readadvanced3 sourcesMarkdown
On this page

TL;DR: SNI puts the hostname in the first, unencrypted TLS message so a server hosting many sites on one IP can present the right certificate. Host is the HTTP-level equivalent, but it arrives too late for that job.

Server Name Indication (SNI) is a TLS extension, defined in RFC 6066, that lets a client include the hostname it is trying to reach in its ClientHello. Servers and load balancers use it to select the certificate and often the backend before any HTTP is exchanged. Without it, one IP address and port could serve only one certificate.

Seeing it with curl

curl -v https://www.example.com/

curl sends www.example.com as SNI automatically. To test a specific IP while keeping both SNI and Host correct, use --resolve:

curl -v --resolve www.example.com:443:203.0.113.10 https://www.example.com/

Writing curl https://203.0.113.10/ -H 'Host: www.example.com' is different: SNI is the IP (or absent), so the server may present its default certificate, and you get a name mismatch.

Non-obvious facts

  • SNI and Host can disagree. A client can send one name in SNI and another in Host. Many servers answer from the Host value after choosing a certificate from SNI. For HTTP/2 reuse across hostnames, the server may reply 421 Misdirected Request to say “wrong server for this name”.
  • nginx does not send SNI to upstreams by default. For proxy_pass https://backend, you need proxy_ssl_server_name on; (and usually proxy_ssl_name) or an SNI-based backend fails the handshake. In the nginx error log this appears as SSL_do_handshake() failed ... while SSL handshaking to upstream, and clients see a 502.
  • It leaks the destination. Even with HTTPS, the SNI hostname is visible to networks and middleboxes, which is how many filters work. Encrypted Client Hello is the fix, but it is not universal.
  • Name mismatch errors come from here. Chrome’s ERR_CERT_COMMON_NAME_INVALID often means the server returned its default certificate because the request carried the wrong SNI, or none.
  • IP addresses are not sent as SNI. RFC 6066 says literal IP addresses are not permitted in the server_name field.

Go deeper

Frequently asked questions

What is SNI?

Server Name Indication is a TLS extension in which the client states the hostname it wants in the ClientHello, so the server can choose the matching certificate before encryption starts.

Why is SNI needed when HTTP has a Host header?

The Host header is inside the encrypted HTTP request, which is sent after the handshake. The server needs the name earlier to know which certificate to present.

Is SNI encrypted?

Not in standard TLS. The hostname is visible to anyone on the network path. Encrypted Client Hello (ECH) is the mechanism designed to hide it, and it needs support from both the client and the server or CDN.

What happens if a client sends no SNI?

The server falls back to a default certificate, which often does not match the hostname, producing a name mismatch error. Very old clients and some scripts connecting by raw IP behave this way.

Sources

  1. RFC 6066: TLS Extensions (Server Name Indication)rfc-editor.org
  2. MDN Web Docs: Server Name Indicationdeveloper.mozilla.org
  3. nginx: proxy_ssl_server_namenginx.org

Keep going

Browse /search