The SNI leak encrypted DNS doesn't fix — and what ECH does about it
You did everything right. You moved your network off the ISP's plaintext resolver and onto encrypted DNS — DoH, DoT, take your pick. The lookups that used to fly over UDP/53 in the clear are now wrapped in TLS, invisible to anyone sitting on the wire between you and the resolver. So an on-path observer can no longer see which domains you resolve. Privacy problem solved, right?
Not quite. Encrypt the DNS query all you want — the very next thing your browser does is open a TLS connection to the resolved IP and announce, in clear text, the exact hostname it wants. That field is called the Server Name Indication, and for the better part of two decades it has quietly undone half the privacy work that DNS encryption tries to achieve. This article is about that leak: what it is, why the first attempt to plug it failed, how Encrypted Client Hello finally addresses it in 2026, and the stubborn residual leak that no amount of TLS magic will ever close.
What SNI is, and why it leaks
SNI exists for a mundane reason: virtual hosting. One IP address routinely serves thousands of distinct websites — that is the whole economic model of shared hosting and CDNs. When your client connects, the server has to know which certificate to present before the TLS handshake can complete, because the certificate has to match the hostname. But the server doesn't yet know the hostname, because the encrypted channel isn't up. Chicken, meet egg.
The fix, standardized in RFC 6066, was to have the client put the target hostname into the very first message it sends — the TLS ClientHello — as a plaintext extension. The server reads it, picks the right certificate, and the handshake proceeds. It works beautifully. It is also sent before any encryption is negotiated, which means it travels in the clear, byte-for-byte readable by anyone on the path.
ClientHello
├─ version, random, cipher_suites ...
└─ extension: server_name
host_name = "secret-forum.example" <-- plaintext, on the wire
This isn't theoretical. SNI inspection is the workhorse of nation-state censorship, corporate web filtering, and ISP-level traffic analysis. It's cheap — no decryption, no man-in-the-middle, no certificate gymnastics. You just grep the ClientHello. If your threat model includes a passive on-path adversary, encrypted DNS without SNI protection is a screen door on a submarine.
ESNI: the right idea, the wrong shape
The TLS community saw this coming. Around 2018 the first serious attempt arrived: Encrypted SNI (ESNI). The concept was direct — publish a public key in DNS, have the client encrypt just the server_name value to that key, and ship the ciphertext in the ClientHello instead of the cleartext hostname.
It even saw real deployment: Cloudflare turned it on, Firefox shipped it behind a flag, and for a while you could genuinely hide your SNI. But ESNI had two structural problems that ultimately killed it.
- It only encrypted one field. ESNI wrapped the hostname but left the rest of the ClientHello in the clear. That turned out to be a privacy half-measure: the unencrypted portions still carry a rich fingerprint, and the mere presence of an ESNI extension was itself a signal that some networks chose to simply block. A field that only privacy-conscious users send is a beacon, not a cloak.
- It was ossification-prone. Because middleboxes could see the handshake structure, they learned to depend on it, and any field that's visible eventually gets inspected, mangled, or blocked. ESNI had no defense against the network deciding it didn't like what it saw.
The lesson the working group took from ESNI: don't encrypt one field, encrypt the entire ClientHello, and make the encrypted variant indistinguishable from the unencrypted one. Anything less just paints a target.
How ECH actually works
Encrypted Client Hello — specified across the long-running draft-ietf-tls-esni work — is ESNI's successor and a far more thorough design. The core trick is a nested handshake built around the distinction between two names:
| Name | Visible on the wire? | What it is |
|---|---|---|
| Outer (public) name | Yes — plaintext SNI | A shared, generic front-end hostname (e.g. a CDN's public name) that reveals nothing about the real destination. |
| Inner (real) name | No — encrypted | The actual hostname you want, sealed inside an encrypted ClientHello carried as a payload. |
Mechanically: the client builds a complete inner ClientHello (with the real SNI and everything else), encrypts it using HPKE (Hybrid Public Key Encryption, RFC 9180) against the server's published ECH public key, and embeds that ciphertext as an extension inside an outer ClientHello that carries only the innocuous public name. The front-end server decrypts the inner hello and routes the connection to the real back-end. On the wire, every connection to that front-end looks identical — same public SNI, opaque encrypted blob. The real hostname never appears in plaintext.
Where the public key comes from — and the chicken-and-egg
The client needs that public key before it connects. Where does it get it? From DNS — specifically the HTTPS resource record (and its generic sibling SVCB), standardized in RFC 9460. The ECH configuration, including the public key, is published as an ech parameter in that record:
example.com. HTTPS 1 . alpn="h3,h2" ech="AED+DQBA...base64-encoded-ECHConfig..."
And here is the dependency that makes the whole thing fragile in an interesting way: to hide your hostname in TLS, you first have to fetch a DNS record about that hostname. If that DNS lookup happens in the clear, an observer just reads the QNAME and learns exactly what you were trying to conceal — defeating the point before the TLS handshake even begins.
GREASE and the war on ossification
Remember ESNI's fatal flaw — that sending the extension at all marked you as a target? ECH's designers answered with a defensive trick borrowed from the broader TLS playbook: GREASE (Generate Random Extensions And Sustain Extensibility, RFC 8701).
The idea is to make ECH traffic statistically invisible by having clients that aren't using real ECH send a plausible, well-formed but meaningless ECH extension anyway — "GREASE ECH." Random bytes that look exactly like a genuine encrypted ClientHello. If a large fraction of connections carry an ECH-shaped extension whether or not they're actually protecting anything, a network can no longer use "has ECH" as a discriminator. Block it and you break ordinary traffic; allow it and you can't tell who's hiding.
GREASE turns the censor's heuristic against itself. The presence of the extension stops being a signal precisely because everyone sends it. The only way to block ECH cleanly becomes blocking the entire front-end — a far more expensive and collateral-heavy decision.
This anti-ossification posture is the philosophical heart of modern TLS: keep the network from depending on anything it can see, so the protocol stays free to evolve and the privacy properties can't be cheaply stripped by a middlebox.
Deployment reality in 2026
ECH is no longer a lab curiosity, but it's not universal either. The state of play:
- Browsers. Both major engines support it. Firefox shipped ECH on by default some time ago — gated on its encrypted-DNS path being active, because of the dependency chain above. Chrome enabled it as well, similarly tied to its secure-DNS settings. In both, ECH only kicks in when the client can fetch the
HTTPSrecord privately and that record actually carries anechparameter. - The serving side. A handful of very large CDNs and front-end providers publish ECH configs and terminate the inner handshake, which means a meaningful slice of the most-visited web is reachable with ECH today. But the long tail of self-hosted and small-host sites overwhelmingly does not publish an ECH config — and a site that publishes nothing gets the plaintext SNI, full stop.
- The spec. ECH has spent years as an IETF draft and is, at the time of writing, on the cusp of finalization. That long incubation is partly the cost of getting the anti-ossification design right.
So the honest 2026 summary is: ECH protects your connections to the big platforms that have opted in, when your browser is configured for encrypted DNS, and provides graceful (cleartext-SNI) fallback everywhere else. Coverage is real and growing, but partial.
The residual leak ECH can't fix: the IP address
Here is the part nobody selling "encrypted everything" likes to dwell on. Even with encrypted DNS and ECH both working perfectly, your packets still have to go somewhere. The destination IP address sits in the IP header, in the clear, by the fundamental design of the internet. You cannot encrypt the address you're routing to and still expect the packet to arrive.
How much does the IP leak? It depends entirely on what's behind it:
| Hosting model | What the destination IP reveals |
|---|---|
| Dedicated IP, one site | Essentially everything. Reverse-DNS or a passive IP→host database maps it straight back to the hostname. ECH bought you nothing. |
| Small shared host (dozens of sites) | Narrows you to a short list. Combined with timing and packet-size analysis, often enough to guess. |
| Large CDN front-end (thousands of sites) | The IP is genuinely ambiguous. This is the case where ECH delivers real anonymity — the address points at a shared pool, and the SNI that would have disambiguated it is now encrypted. |
This is the crux. ECH's privacy benefit scales with how many sites hide behind the same IP. Co-tenancy on a big front-end is what gives you an anonymity set; a site on its own IP has an anonymity set of one, and no ClientHello encryption changes that. There's an entire research literature on website fingerprinting — inferring the visited site from traffic timing, packet sizes, and burst patterns alone, even when hostname and content are fully encrypted — and the destination IP is the single most powerful feature it leans on.
ECH does not make you anonymous. It removes one specific, cheap, exact identifier — the plaintext hostname — and replaces it with a noisier, probabilistic one: the destination IP plus traffic shape. Against a passive logger that's a large win. Against a determined analyst with a good IP database, it's an inconvenience, not a wall.
How encrypted DNS and ECH compose
Step back and look at the full path of a single web request, and you can see exactly which leak each layer closes:
| Stage | Leaks the hostname? | What protects it |
|---|---|---|
| DNS lookup of the site | Yes, as the query QNAME | Encrypted DNS (DoH/DoT/DoQ/DNSCrypt) |
DNS lookup of the HTTPS record for ECH key | Yes, same QNAME | Encrypted DNS — same channel |
| TLS ClientHello SNI | Yes, in clear text | ECH (encrypts the inner hello) |
| Destination IP routing | Partially — depends on co-tenancy | Nothing fully; large shared front-ends dilute it |
| Traffic timing / packet sizes | Statistically | Padding, multiplexing — out of scope here |
The two layers are complementary, not redundant. Encrypted DNS without ECH closes the first two rows and leaves the SNI wide open. ECH without encrypted DNS closes the SNI but reopens the hostname in the very DNS query that fetches the ECH key. Only together do they cover the controllable hostname leaks — and even then the IP row remains, a reminder that perfect transport privacy is a property of the internet's architecture, not a checkbox.
For a network operator, the practical takeaway is concrete. Encrypted DNS is the layer you actually control and deploy: push DoH, DoT, DoQ or DNSCrypt to every device, and you've closed the DNS-side leak for the whole estate and laid the mandatory foundation ECH depends on. ECH then rides for free on the connections to providers that support it, with safe cleartext fallback everywhere else. You can't make ECH happen for sites that don't publish a config, and you can't encrypt the IP header — but you can make sure the one piece in your hands, the resolver, is encrypted, validating, and not quietly narrating your users' browsing to whoever owns the wire.
Encrypting your DNS is not the finish line of transport privacy — it's the entry fee. The SNI was always the bigger, more obvious leak, and ECH is the first design that plugs it without painting a target on the people who care. But the IP address in the header is the leak that never goes away, and any honest privacy story has to say so out loud.
Encrypted DNS is step one
UnveilDNS gives every device DoH, DoT, DoQ and DNSCrypt — the encrypted foundation ECH builds on.
Deploy UnveilDNS free