Karthikey Hegde's Podman container couldn't reach a site. Almost all of their plaintext lookups, through Google DNS, Cloudflare and others, returned the same IP, and that IP belonged to their ISP. Cloudflare's DoH endpoint returned the real address.
So if a site won't load on your connection but works elsewhere, and a forum told you to set your DNS to 1.1.1.1 or 8.8.8.8, that advice may have changed nothing. These commands check whether your ISP is hijacking your DNS, and the table further down ranks the fixes that still work when it is.
Why changing DNS to 1.1.1.1 or 8.8.8.8 does nothing here
A plaintext query to 1.1.1.1 is a UDP packet to port 53 with no authentication. The IP in @1.1.1.1 is only a destination address. Anything on the path can catch that packet and reply while pretending to be Cloudflare, and dig has no way to tell. As bityard put it in the Lobsters thread, UDP DNS interception and rewriting is trivial.
That means several resolvers agreeing proves very little, because you may be talking to one box with several names. Hegde says in the same thread that their ISP tampers with all DNS traffic over port 53, which also catches a self-hosted recursive Unbound.
Hegde's post only has screenshots, so these are the standard commands for the same test.
How to check if your ISP is hijacking DNS
Use the domain that fails for you. Don't bother with google.com, because an ISP filtering a blocklist leaves it alone.
D=example.com # the domain that fails for you
# 1. Plaintext, against several public resolvers
for r in 1.1.1.1 8.8.8.8 9.9.9.9; do
echo "== $r"; dig +short +time=2 +tries=1 "$D" @"$r"
done
# 2. Same question over HTTPS, which the ISP can't rewrite in transit
curl -s -H 'accept: application/dns-json' \
"https://cloudflare-dns.com/dns-query?name=$D&type=A" | jq -r '.Answer[]?.data'
# 3. Who owns the plaintext answer? Paste the IP from step 1.
whois 203.0.113.7 | grep -iE '^(orgname|org-name|netname|descr):'The DoH endpoint and accept header come from Cloudflare's docs. 203.0.113.7 is a placeholder. dig +short may print CNAMEs before the IPs, and the order of multiple A records changes between queries, so compare the set of IPs.
Interception can also be partial. One Let's Encrypt forum user found their ISP only touched 53/udp, and a Lobsters commenter saw IPv4 and IPv6 behave differently on the same ISP. Test both:
dig +short +tcp "$D" @1.1.1.1
dig +short -6 "$D" @2606:4700:4700::1111If the second command says network unreachable, your machine has no IPv6 route, so that test tells you nothing.
How to read the result: tampering or just a CDN?
A mismatch alone proves nothing. CDNs hand out different IPs by location, and Cloudflare doesn't send EDNS Client Subnet, so its answers can differ from a resolver that does. OONI warns about the same false positives in its own measurements. Start with whois, then use the certificate check under the table if the IP belongs to your ISP.
| Plaintext vs DoH | Owner of the plaintext IP | What it means |
|---|---|---|
| Same | Anyone | No sign of tampering on this name. Look elsewhere. |
| Different | A CDN or the site's host | Probably geography, so you have no case |
| Different | Your ISP | Probably tampering, same as Hegde's case. Run the certificate check. |
| Plaintext fails, DoH answers | n/a | Interference or a broken path. Run the whoami test below. |
| DoH fails too | n/a | Your ISP may block DoH as well. Try another endpoint. |
An ISP-owned IP can still be legitimate, because CDNs such as Netflix and Google put cache servers inside ISP networks. So make that IP prove it can serve the site over TLS:
IP=203.0.113.7 # the plaintext answer
curl -sS -o /dev/null -w '%{http_code}\n' --max-time 10 --resolve "$D:443:$IP" "https://$D/"Any HTTP status means the box holds a valid certificate for that name. A curl: (60) certificate error means it doesn't, and that's what you get pointing example.com at 8.8.8.8. As Psentee notes in the Lobsters thread, most ISPs can't easily mint certs for any domain. A timeout is weaker evidence, since it could be a dead box or a block on that IP.
Check the path itself with whoami.ds.akahelp.net
The domain test only catches tampering on that one name. Akamai's debug hostname tests the path:
dig +short TXT whoami.ds.akahelp.net @1.1.1.1
dig +short TXT whoami.ds.akahelp.net @8.8.8.8The ns field is the address that reached Akamai's server. Big resolvers contact authoritative servers from their own ranges, so a Cloudflare query should show a Cloudflare address. The ns lines from a clean connection look like this, and whois puts them at Cloudflare and Google LLC:
"ns" "2400:cb00:523:1024::ac47:6d93"
"ns" "172.253.235.19"In the forum thread above, a query to 1.1.1.1 came back with "ns" "151.5.216.254", and whois traced that to WIND, the poster's network operator.
A reply with no ecs field is also suspicious. mnordhoff gives that rule for 8.8.8.8 in the thread, and Cloudflare's FAQ names this hostname as its one ECS exception, so it should apply to 1.1.1.1 too. A clean result doesn't clear your ISP, though, because "an improbably clever interceptor could lie". If you want a measurement you can compare against a control server, OONI does that, and robalex recommends it in the Lobsters thread.
DNSSEC detects this on about 7% of domains
The usual reply is "just use DNSSEC". The November 2026 Defaults.Exposed census counts 23,854,462 of 334,831,177 graded domains as DNSSEC signed and valid, 7.1%. Hegde's post cites the October edition at 7.03%. That's a count of domains, dead ones included, so it says nothing about what share of your traffic is covered.
Without a valid chain, a validator has nothing to catch a forged answer with. On the signed minority, you only benefit if you validate locally, because a validating 1.1.1.1 does nothing for you when the ISP answers in its place. And a failed validation gets you SERVFAIL rather than the real IP. You learn about the tampering and the site stays down. DNSSEC also doesn't encrypt anything, so the ISP still reads your queries.
Fixes for ISP DNS hijacking, ranked
| Fix | Beats port 53 interception? | The catch |
|---|---|---|
| dnscrypt-proxy behind AdGuard | Yes, for the whole LAN | Most setup |
| Unbound with a DoT forward-zone | Yes | Port 853 is easy to block |
| systemd-resolved with DoT | Yes, one machine | Same port 853 problem |
| Browser DoH | Yes, that browser only | Containers and CLI tools still use port 53 |
| Plain recursive Unbound | No | Its queries are usually plaintext UDP |
| DNSSEC alone | No, it only detects | About 7% of domains, and you get SERVFAIL |
My pick is the first row. Hegde hit this because a Podman container couldn't reach a site, and a browser toggle never touches that traffic. Their setup is AdGuard as local DNS with dnscrypt-proxy handling upstream. Move the proxy off port 53, since AdGuard needs it. Avoid 5353 as well, because that's the mDNS port and dnscrypt-proxy dies with bind: address already in use if Avahi or anything else holds it. Change these two lines in your copy of the example config:
# dnscrypt-proxy.toml
listen_addresses = ['127.0.0.1:5300']
server_names = ['cloudflare']# AdGuardHome.yaml
dns:
upstream_dns:
- 127.0.0.1:5300The example config lists plaintext bootstrap_resolvers, and that looks alarming until you read the comment above them. They're for one-shot bootstrap lookups, and your queries are never sent to them. The cloudflare entry is DoH, so this runs over port 443 and doesn't care about a block on 853. Point DHCP at AdGuard, then rerun dig +short "$D" @ and compare with the DoH answer.
If you already run Unbound, forward it over TLS. Without a CA bundle, the connection can't be authenticated. The bundle path below is Debian's, and the hostname is Cloudflare's documented one.
server:
tls-cert-bundle: /etc/ssl/certs/ca-certificates.crt
forward-zone:
name: "."
forward-tls-upstream: yes
forward-addr: 1.1.1.1@853#one.one.one.one
forward-addr: 1.0.0.1@853#one.one.one.oneBoth proxies were tested with these exact settings: dnscrypt-proxy 2.1.20 logged [cloudflare] OK (DoH) and Unbound 1.26.2 answered queries through that forward-zone. The test connection had no tampering, so that shows the configs work and says nothing about a given ISP's blocks.
On a single Linux box, systemd-resolved needs three lines in /etc/systemd/resolved.conf:
[Resolve]
DNS=1.1.1.1#one.one.one.one 1.0.0.1#one.one.one.one
DNSOverTLS=yes
Domains=~.Before committing to DoT, check that port 853 is reachable with Cloudflare's own test: kdig -d @1.1.1.1 +tls-ca +tls-host=one.one.one.one example.com. bazzargh reports in the Lobsters thread that Virgin Media in the UK tampers with port 53, blocks DoT outright and blocks DoH to some well-known servers. They got out by finding a DoH server Virgin hadn't blocked and running Pi-hole with Unbound. If you can't find one either, Hegde's suggestion in that thread is to tunnel DNS over WireGuard to a relay.
What encrypted DNS still doesn't fix
The resolver operator can still alter answers, so you're picking who gets to lie to you. I'd still choose a company with a published policy over an ISP doing it silently. vpr's preference for ODoH through dnscrypt-proxy is reasonable. Hegde uses Anonymized DNSCrypt instead, and is skeptical of ODoH because Apple and Cloudflare started it, and because of some relay providers' privacy policies.
Your ISP also still sees the hostname through SNI unless the browser and the site both use ECH, and it can sometimes infer the site from the destination IP. If the site stays unreachable after DNS comes back correct, the block has moved down a layer and no resolver will help. Hegde runs Mullvad through a Tailscale exit node for this, which hands the same trust question to the VPN provider.
The live argument in the thread is about DoH itself. bityard objects that DoT and DoH let software bypass local network controls, xetera says DoH is the real offender because DoT on 853 is easy to block, and Psentee doubts the two problems can be reconciled at all. My view: a filter on a network you run should be enforced on the devices you run. Losing a network-level DNS filter is a fair price for making silent rewrites by a carrier harder.
If you think DoH does more harm than the rewriting it stops, make that case below. And once you've run the check: is your ISP tampering with your DNS, and which ISP is it?
