SNI (Server Name Indication) is a TLS extension that allows a client to indicate the hostname it is trying to reach during the TLS handshake, enabling proxies to correctly route or terminate TLS connections for multiple domains hosted on a single IP address.
Before SNI, a server required a unique IP address for each SSL certificate if multiple secure websites were hosted on the same server. This limitation arose because the TLS handshake occurred before the HTTP Host header was sent, preventing the server from knowing which certificate to present. SNI, specified in RFC 6066, resolves this by including the desired hostname in the ClientHello message, allowing the server (or proxy) to select the correct certificate and configuration.
How SNI Works
The client includes the target hostname in the extension_data field of the server_name extension within the ClientHello message. This occurs before any encrypted data is exchanged and before the server presents its certificate.
ClientHello
Version: TLS 1.2
Random: ...
Session ID: ...
Cipher Suites: ...
Extensions:
...
Server Name (SNI)
Server Name Type: host_name (0)
Server Name: example.com
...
The server or an intermediary proxy receives this ClientHello and can extract the example.com hostname. This information is then used to determine which TLS certificate to present and how to route or process the subsequent connection.
Proxy Handling of SNI
Proxies interact with SNI differently based on their type, operational mode, and whether they perform TLS termination or passthrough.
Transparent Proxies
A transparent proxy intercepts traffic without the client being explicitly configured to use it. For TLS traffic, a transparent proxy often operates at Layer 4 (TCP). It typically forwards the raw TCP stream, including the ClientHello message with SNI, directly to the destination server.
- SNI Visibility: A transparent proxy can inspect the
ClientHellomessage to extract the SNI hostname. This allows for basic routing, logging, or filtering rules based on the destination domain, even if the payload itself remains encrypted. - TLS Termination: Transparent proxies typically do not terminate TLS for the client unless specifically configured for deep packet inspection (DPI) or man-in-the-middle (MITM) operations, which requires client trust in the proxy's root CA. In a standard transparent setup, the proxy passes the
ClientHelloto the origin server, which then performs the TLS handshake directly with the client.
Forward Proxies
A forward proxy acts as an intermediary for clients requesting resources from external servers. Clients are explicitly configured to use a forward proxy.
CONNECT Method
For HTTPS traffic, clients typically use the HTTP CONNECT method to instruct the forward proxy to establish a TCP tunnel to the destination server.
CONNECT example.com:443 HTTP/1.1
Host: example.com:443
Proxy-Connection: Keep-Alive
After the CONNECT request succeeds (proxy responds with HTTP/1.1 200 Connection established), the client initiates the TLS handshake directly with the destination server through the established tunnel.
- SNI Visibility (without interception): In this mode, the forward proxy generally does not process the SNI value from the
ClientHellomessage because it's simply relaying the raw encrypted TCP stream. TheCONNECTrequest provides the destination hostname, which the proxy uses for routing. - TLS Termination: The proxy does not terminate TLS; the TLS handshake occurs end-to-end between the client and the origin server.
TLS Interception (MITM)
Some forward proxies are configured for TLS interception (also known as SSL inspection or MITM proxying). This involves the proxy terminating the client's TLS connection and establishing a new TLS connection to the origin server.
- Client initiates TLS handshake with proxy: The client sends a
ClientHelloto the proxy. - Proxy extracts SNI: The proxy reads the SNI hostname from the
ClientHello. - Proxy generates certificate: Using its own CA certificate (trusted by the client), the proxy dynamically generates a server certificate for the SNI hostname.
- Proxy completes handshake with client: The proxy presents the generated certificate to the client.
- Proxy establishes new TLS connection to origin: The proxy initiates a new TLS handshake with the actual origin server, using the extracted SNI hostname in its
ClientHello. - Proxy decrypts/re-encrypts traffic: The proxy decrypts client traffic, inspects it, and then re-encrypts it before sending to the origin, and vice-versa.
- SNI Usage: SNI is crucial for TLS interception. The proxy uses the SNI value to:
- Determine which hostname to impersonate for the client.
- Determine which hostname to request from the origin server.
- Security Implications: Requires the client to trust the proxy's root CA. This mode allows the proxy full visibility into encrypted traffic.
Reverse Proxies
A reverse proxy sits in front of one or more web servers, directing client requests to the appropriate backend server. Clients connect to the reverse proxy, unaware of the backend architecture.
- SNI Usage: When a client initiates a TLS handshake with the reverse proxy, the proxy receives the
ClientHellomessage containing the SNI hostname. The reverse proxy uses this SNI value to:- Select the correct server certificate to present to the client if it hosts multiple domains.
- Route the request to the appropriate backend server or application pool.
- Apply domain-specific policies (e.g., WAF rules, caching, load balancing).
- TLS Termination: Reverse proxies almost always terminate TLS connections from clients. They decrypt the traffic, process it, and then may re-encrypt it for communication with backend servers (re-encryption, or backend TLS).
Example: Nginx Reverse Proxy with SNI
http {
# Default server for requests without SNI or for unknown SNI
server {
listen 443 ssl default_server;
server_name _; # Catch-all
ssl_certificate /etc/nginx/ssl/default.crt;
ssl_certificate_key /etc/nginx/ssl/default.key;
return 404;
}
# Backend for example.com
server {
listen 443 ssl;
server_name example.com;
ssl_certificate /etc/nginx/ssl/example.com.crt;
ssl_certificate_key /etc/nginx/ssl/example.com.key;
location / {
proxy_pass https://backend_example_com;
proxy_ssl_server_name on; # Pass SNI to backend
}
}
# Backend for api.example.com
server {
listen 443 ssl;
server_name api.example.com;
ssl_certificate /etc/nginx/ssl/api.example.com.crt;
ssl_certificate_key /etc/nginx/ssl/api.example.com.key;
location / {
proxy_pass https://backend_api_example_com;
proxy_ssl_server_name on; # Pass SNI to backend
}
}
}
In this Nginx configuration, the server_name directive matches the SNI presented by the client. Nginx then uses the corresponding ssl_certificate and routes the request to the specified proxy_pass backend. proxy_ssl_server_name on ensures Nginx includes the SNI hostname when establishing a new TLS connection to the backend.
SNI and Layer 4 vs. Layer 7 Proxies
The distinction between Layer 4 (TCP) and Layer 7 (Application) proxies also influences SNI handling.
-
Layer 4 Proxies: Operate at the TCP level. They can inspect the
ClientHellopacket to extract SNI without decrypting the entire TLS stream. This allows for SNI-based routing or filtering before the TLS handshake completes, without needing to terminate TLS. HAProxy in TCP mode can perform this.listen https_frontend bind *:443 mode tcp tcp-request inspect-delay 5s tcp-request content accept if { req_ssl_hello_type 1 } tcp-request content track-sc0 src # Route based on SNI use_backend backend_example_com if { req_ssl_sni -i example.com } use_backend backend_api_example_com if { req_ssl_sni -i api.example.com } default_backend backend_default
This HAProxy configuration usesreq_ssl_snito inspect the SNI from theClientHelloand route the TCP connection accordingly, without terminating TLS itself. -
Layer 7 Proxies: Operate at the application layer (e.g., HTTP/HTTPS). They must terminate TLS to access application-layer headers (like HTTP Host, URL path, etc.). Upon terminating TLS, they use the SNI from the initial
ClientHelloto select the correct server certificate and then proceed to process the decrypted HTTP request. Reverse proxies are typically L7 proxies. Forward proxies performing TLS interception are also L7.
Comparison: Proxy SNI Handling Modes
| Feature | Transparent Proxy (L4 Passthrough) | Forward Proxy (CONNECT, no MITM) | Forward Proxy (TLS Interception/MITM) | Reverse Proxy (TLS Termination) |
|---|---|---|---|---|
| Client TLS Terminates At | Origin Server | Origin Server | Proxy | Proxy |
| Proxy TLS Terminates At | N/A (passthrough) | N/A (passthrough) | Origin Server | N/A (initiates new if backend TLS) |
| SNI Visibility to Proxy | Yes (cleartext in ClientHello) | No (after CONNECT) | Yes (cleartext in ClientHello) | Yes (cleartext in ClientHello) |
| SNI Usage by Proxy | Routing, logging, basic filtering | Not directly from ClientHello | Certificate generation, origin selection | Certificate selection, routing, policy enforcement |
| Proxy Decrypts Traffic | No | No | Yes | Yes |
| Client Trust Requirement | None | None | Proxy's Root CA | Origin's Certificate (presented by proxy) |
Security and Privacy Considerations
SNI, by design, is transmitted in cleartext within the ClientHello message. This means that network intermediaries, including proxies and ISPs, can observe which hostname a client is attempting to connect to, even if the rest of the TLS communication is encrypted.
This cleartext exposure has privacy implications. To address this, the IETF has developed Encrypted SNI (ESNI), which is evolving into Encrypted Client Hello (ECH). ESNI/ECH encrypts the Server Name extension within the ClientHello message, making it opaque to passive observers.
- Impact on Proxies: ESNI/ECH significantly changes how proxies (especially L4 proxies or those performing SNI-based routing without full TLS termination) operate. If the SNI is encrypted, the proxy cannot use it for cleartext routing decisions. Proxies capable of ESNI/ECH support would need to participate in the key exchange or rely on other mechanisms (e.g., IP address, DNS) for initial routing, or decrypt ECH if they are the intended ECH endpoint. For TLS-terminating proxies (like reverse proxies or MITM forward proxies), they would still need to decrypt the ECH to learn the intended hostname for certificate selection and routing.