DEV Community

Remdore
Remdore

Posted on AI-assisted

Only 10 of the top 1000 sites hide the hostname you are visiting. I built the tool that counts.

A few days ago I wrote about how the name of the site you visit over HTTPS travels across the network in plain text, sitting in the TLS ClientHello where anything on the path can read it. The reaction I did not expect was how many people wanted to know the same thing about their own sites, and had no quick way to find out. So I built the quick way, a small web app that answers one question: does this domain's hostname leak, and could it not?

The checker showing a domain whose hostname leaks

You type a domain, it reads that domain's public DNS, and it tells you two things. Whether the site publishes an Encrypted ClientHello config, which is the only thing that can hide the hostname, and if it does, what cover name a watcher would see instead of the real one. It performs no handshake and needs no key, because the whole point of the original piece was that none of this is secret in the first place.

What it actually does

The interesting information lives entirely in DNS, which surprised me when I first worked it out. A site that supports ECH publishes its public key in a DNS record of type HTTPS, the same record that carries things like the ALPN list and IP hints. So the check is: fetch that record over DoH, look for an ech= parameter, and if it is there, decode it far enough to read the version, the key-exchange algorithm and the public_name. That is the cover hostname, the decoy that appears on the wire in place of wherever you were really going.

When a domain does publish ECH, the tool shows you the lot:

The checker showing a domain that publishes ECH, with the cover name and key details

The whole check is one short function. It reads public DNS, sends nothing to the site you are asking about, and keeps no record of what you type, because there is nothing it would need them for. That also makes it cheap and safe to run, which matters for the next part.

So I pointed it at the top thousand sites

A single-domain checker answers your question about your site. The more interesting question is how common ECH actually is, so I fed the tool a list instead of a box. The command-line side of it takes a file of domains and reports how many publish ECH, and I ran it over the top 1000 domains by traffic.

Ten of them publish ECH. Ten, out of a thousand. That is one per cent, and 992 of the rest leak their hostname exactly the way the first post described, with the remainder failing to resolve.

The ten are the part worth staring at:

tinyurl.com          cover=cloudflare-ech.com
cedexis.net          cover=cloudflare-ech.com
sagepub.com          cover=cloudflare-ech.com
sxyprn.com           cover=cloudflare-ech.com
gizmodo.com          cover=cloudflare-ech.com
animeflv.net         cover=cloudflare-ech.com
remove.bg            cover=cloudflare-ech.com
arnebrachhold.de     cover=cloudflare-ech.com
yayoye-spiele.com    cover=cloudflare-ech.com
Enter fullscreen mode Exit fullscreen mode

Every single one hides behind the same cover name, cloudflare-ech.com. Not one of them is Google or Amazon or Microsoft or a bank. They are a scattering of ordinary sites that happen to sit on Cloudflare, in zones where Cloudflare has switched the feature on. ECH in the top 1000 is not really a story about those sites choosing privacy; it is a story about one provider flipping a setting for some of its customers and not others. Even cloudflare.com itself, the apex, does not publish it, though the test host crypto.cloudflare.com does.

I pointed the tool at my own sites too, because it felt dishonest not to. extratime.world, a football quiz site I run, leaks its hostname just like the other 992. I have not turned ECH on either, and having now built the thing that measures it, I understand exactly why almost nobody has: it is off by default, it needs your DNS provider and your CDN to cooperate, and it only helps at all if the visitor's DNS is encrypted too. It is not a checkbox, it is a small alignment of four different parties, and the survey is what that looks like from the outside.

The number that is not the number

The tempting headline is "one per cent of the web supports ECH", and I want to be careful, because that is not quite what I measured. I measured the top 1000 by a particular traffic ranking, on one day, resolved through one DoH provider. A different list, or the same list next month, would give a different count, and the long tail of small Cloudflare-hosted sites almost certainly has a higher rate than the giants at the top. So the honest claim is narrower and more interesting than the headline: among the most-visited sites, the ones whose traffic a network observer would most want to profile, ECH is essentially absent, and where it exists it is one company's doing.

Where it ran, and where it is now

I hosted the live copy on a 1 vCPU DigitalOcean droplet in Frankfurt while I took the screenshots above, which is the honest way to check that a thing actually serves traffic rather than just runs on my laptop. I have since taken that droplet down, so there is no public instance to link you to and nothing accruing a bill.

That is deliberate, and it is the better shape for this kind of tool anyway. The whole thing is open source, it is one small container, and running your own copy is two commands:

git clone https://github.com/oceanforge/sni-leak-check
cd sni-leak-check && docker compose up --build
Enter fullscreen mode Exit fullscreen mode

Then it is on localhost:8000 and it is yours. A tool that inspects your infrastructure is better run by you than pointed at someone else's server, and this one is small enough that there is no reason not to.

What I got wrong on the way

The first time I started the container to test it, the page that came back was not my app. It was the admin API of a completely different project of mine that happens to run on the same machine, because I had mapped my new container to port 8000 and something was already sitting there. The health check even passed, because there was a healthy service on that port, just not mine. For a confused minute I thought my app was serving someone else's HTML.

It is the same lesson that keeps recurring in these posts, wearing yet another costume: a green check is not proof that the thing you think you are testing is the thing that answered. The fix was to move to a port nothing else was using, and to actually read the page title rather than trust the 200. I now check the title.

Contributing

The app does the one job well and there is a lot of obvious room to make it better, so I have left a set of good first issues on the repository: showing the raw ECH bytes with each field labelled, a bulk-check table, a shareable permalink, actively capturing a real ClientHello to show the leak rather than inferring it. They are small and self-contained on purpose. If you have been looking for something to contribute to during Hacktoberfest, this is an open invitation, and the issues are labelled to match.

The takeaway

The original post argued that HTTPS keeps two different promises and only one of them, the privacy of your traffic, has been kept for most of the web's life. This tool is the argument turned into a thing you can run against any domain, including your own. Check a few of the sites you use every day. Almost all of them will tell you the same thing, that the padlock protects the conversation and leaves the guest list in plain sight, and now you can see it for yourself in about a second.

Top comments (1)

Some comments may only be visible to logged-in visitors. Sign in to view all comments.