The SNI Problem Nobody Talks About
You upgraded to TLS 1.3. Everything's encrypted now, right?
Wrong. Every time your browser connects to a website, it shouts the hostname in plain text during the TLS handshake. This is SNI (Server Name Indication), and it's been leaking your browsing patterns since 2003.
ISPs can see it. Firewalls log it. Governments collect it. You think you're safe because the payload is encrypted, but anyone on the network knows exactly which sites you're visiting, when, and how often. TLS 1.3 fixed a lot, but SNI remained a gaping hole until ESNI and ECH came along.
Why SNI Exists (And Why It Leaks)
SNI was created to solve virtual hosting. One IP, multiple websites. The server needs to know which certificate to present before encryption starts, so the client sends the hostname in cleartext.
Made sense in 2003. Less sense now when privacy matters and state-level surveillance is the norm.
Here's what a normal TLS 1.3 handshake looks like without encryption:
ClientHello:
- TLS Version: 1.3
- Cipher Suites: [...]
- SNI: example.com // <- THIS IS CLEARTEXT
- Supported Groups: x25519, secp256r1
// Anyone sniffing packets sees "example.com" here
// before any encryption happens
Network admins love this. It powers content filtering, analytics, and "security" products. But it also enables censorship and mass surveillance at scale. China blocks sites by SNI. Corporate firewalls categorize your browsing in real-time. Your ISP sells aggregated SNI data to advertisers.
ESNI: The First Attempt That Almost Worked
Encrypted SNI (ESNI) was the first attempt to fix this. Published in 2018, it encrypted the SNI field using a public key fetched from DNS.
The flow looked like this:
1. Client queries DNS for example.com
2. DNS returns A record + TXT record with ESNI public key
3. Client encrypts SNI using that public key
4. Server decrypts SNI with its private key
5. Handshake proceeds normally, hostname hidden
Clever. But it had problems.
First, ESNI only encrypted the SNI extension. Other parts of ClientHello (like ALPN protocols, supported groups) still leaked metadata. Not as bad as the hostname, but enough for fingerprinting.
Second, CDNs hated it. Cloudflare and Fastly host thousands of domains per IP. With ESNI, they couldn't route traffic without decrypting ClientHello first, adding latency and complexity.
Third, DNS wasn't encrypted for most users back then. You'd encrypt SNI but leak the hostname via DNS anyway. DoH and DoT helped, but adoption was slow.
ESNI got Firefox support in 2019 but never made it to Chrome or Safari. By 2020, it was clear a better solution was needed.
ECH: Encrypted Client Hello (The Real Fix)
ECH is ESNI 2.0. Instead of encrypting just SNI, it encrypts the entire ClientHello message.
The difference matters. With ESNI, you still leaked cipher suites, extensions, and other handshake metadata. With ECH, all of that is hidden inside an encrypted envelope.
Here's how ECH works:
// Client sends TWO ClientHellos:
ClientHelloOuter (cleartext):
- TLS 1.3
- Minimal cipher suites
- SNI: public-name.example.com // fake/generic
- ECH extension with encrypted payload
ClientHelloInner (encrypted inside ECH extension):
- Real SNI: secret.example.com
- Real cipher suites
- Real extensions (ALPN, etc)
- Everything you don't want leaked
The outer ClientHello is a decoy. It looks like a normal TLS handshake to a public-facing domain. The inner ClientHello contains the real destination, encrypted using a key published in DNS (via HTTPS records, not TXT like ESNI).
Network middleboxes see the outer hello. They think you're connecting to "public-name.example.com". The server decrypts the inner hello and routes you to the real destination.
Why ECH Breaks Corporate Networks
If you run a corporate network with TLS inspection, ECH is your nightmare.
TLS inspection works by man-in-the-middling your traffic. The firewall terminates TLS, inspects plaintext, then re-encrypts to the destination. Requires installing a root CA on every device.
With ECH, the firewall can't see the real SNI anymore. It only sees the outer ClientHello, which might point to a CDN or generic domain. The actual destination is encrypted and unreadable without the server's private key.
Some networks are blocking ECH entirely:
// Firewall rule to block ECH
// (this is what enterprises are doing)
if (clientHello.extensions.contains("encrypted_client_hello")) {
drop_connection();
log("ECH blocked: potential policy bypass");
}
Is this legal? Depends on jurisdiction. Is it effective? For now. But as ECH adoption grows, blanket blocking becomes less tenable. You'd be breaking large chunks of the internet.
Browser Support and Deployment Reality
As of early 2026, ECH support is patchy:
Firefox: Supported since version 118 (Sept 2023), enabled by default when DoH is active. Works with Cloudflare's resolver (1.1.1.1).
Chrome: Experimental flag available, not enabled by default. Google's dragging its feet, likely due to enterprise pushback.
Safari: In beta testing for macOS/iOS. Apple's waiting to see how Chrome moves.
Server-side: Cloudflare supports ECH for all hosted domains. Nginx and Apache don't have stable support yet. You need OpenSSL 3.2+ with ECH patches, which most distros don't ship.
For self-hosted sites, enabling ECH is painful:
# Nginx with ECH (as of 2026, requires custom build)
# Most people aren't doing this yet
./configure --with-openssl=/path/to/openssl-3.2-ech --with-http_ssl_module --with-http_v3_module # ECH works best with QUIC
# Then publish ECH keys via DNS HTTPS records
# (separate process, needs DNSSEC for security)
The chicken-and-egg problem is real. Browsers won't prioritize ECH until more sites support it. Sites won't deploy ECH until browsers make it mandatory. We're stuck in the middle.
How to Check If ECH Is Working
If you're using Firefox with DoH enabled and visiting Cloudflare-hosted sites, ECH might already be active. Here's how to verify:
# Firefox: about:config
# Look for these prefs:
network.dns.echconfig.enabled = true
network.dns.http3_echconfig.enabled = true
# Then visit: https://crypto.cloudflare.com/cdn-cgi/trace
# Look for: "ech=on"
For packet-level verification, Wireshark can inspect TLS handshakes. If ECH is working, you'll see the encrypted_client_hello extension in ClientHello, and the SNI field will point to a generic domain instead of the real one.
The Privacy vs Security Tradeoff
ECH improves privacy but complicates security operations. Enterprises lose visibility into which sites employees are accessing. Parental controls can't block specific domains anymore. DLP tools that scan TLS traffic break.
There's no easy answer. Privacy advocates say tough luck, security is possible without SNI inspection. Enterprise security teams say they need visibility to stop exfiltration and malware C2.
The real answer is probably somewhere in the middle. If your threat model includes state-level surveillance or ISP tracking, ECH is essential. If you're running a corporate network and need content filtering, you'll fight ECH or implement alternative controls (endpoint agents, DNS filtering, etc).
What This Means for Certificate Monitoring
From a cert monitoring perspective, ECH doesn't change much. You're still validating certificates, checking expiration, monitoring CT logs. The handshake encryption is transparent to your monitoring tools since they're either on the server side or using proper TLS clients.
What does change: passive network monitoring gets harder. If you were relying on SNI logs for inventory or tracking certificate usage across infrastructure, that stops working with ECH. You'll need to shift to active probing or server-side logging instead.
For SaaS tools like CertGuard, nothing breaks. We connect as legitimate clients, so ECH just works. But if you're doing internal network monitoring via span ports or tap devices, expect blind spots as ECH adoption increases.
Plan accordingly. The era of cleartext SNI is ending, slowly but inevitably.