blog.back_article_list

Why DNS still leaks past Pi-hole over WireGuard

Why DNS still leaks past Pi-hole over WireGuard

Updated and tested 14 October 2026

A handshake proves the tunnel is up. It proves nothing about where your DNS queries go. WireGuard moves packets whose destination falls inside AllowedIPs and ignores everything else, and a DNS query is a packet like any other: if the device decides to ask a different resolver, over a different port, through a different adapter, the tunnel never sees it and Pi-hole never logs it. The ads come back, the dashboard stays flat and wg show on the VPS reports a fresh handshake the whole time.

The setup every cause below assumes is the one from Pi-hole on a VPS behind WireGuard: resolver on 10.100.0.1, reachable only through the tunnel, with the client's DNS line pointing at it. Each cause is a device, an app or a config line deciding otherwise, and each has a different fix.

A missing or wrong DNS line in the client config

The DNS = 10.100.0.1 line is what tells the device to use the Pi-hole. Without it, WireGuard brings up the interface, routes packets for 10.100.0.1 through it, and the operating system goes on asking whatever resolver the network handed out over DHCP. nslookup on the device names that resolver on its Server: line, doubleclick.net resolves to a real address instead of 0.0.0.0, and Pi-hole's log has nothing from the device. The same happens when the line names the VPS's public IP instead of its tunnel address: the query leaves over the normal interface, hits a firewalled port 53 and times out, so this one at least is visible.

nslookup example.com on a tunnel client without a DNS line: Server is a public resolver, not 10.100.0.1

Without a DNS line the client keeps asking its old resolver, so Pi-hole never sees the query.

Check the file on the device. A config pasted into a desktop app by hand can lose the line; a QR code scanned from the server's copy can't.

AllowedIPs without the resolver's address

A query to 10.100.0.1 only enters the tunnel if 10.100.0.1 is inside AllowedIPs. 10.100.0.1/32, 10.100.0.0/24 and 0.0.0.0/0 all contain it. A list someone narrowed to a LAN behind the server, say 192.168.1.0/24 alone, does not. The split tunnel for DNS only article goes through what each value of that line carries; the short version is that the resolver's address has to be in it. With it missing, the DNS line points at an address the device has no route to.

The Android app's tunnel editor has an "Exclude private IPs" switch, and 10.100.0.1 is a private address, but the switch keeps the resolver covered. It only appears on a config with a single peer and 0.0.0.0/0 in AllowedIPs, and when it swaps that range for the list of public ones, PeerProxy.kt in the app's source adds every IPv4 address on the DNS line back as a /32. The AllowedIPs line the app shows afterwards includes 10.100.0.1/32.

Android Private DNS overrides the tunnel resolver

Android has a system-wide Private DNS setting. When it's set to a hostname (dns.google, one.one.one.one, a provider's DoT address), the phone sends its lookups over DNS over TLS to that provider, and the resolver the tunnel handed out is not consulted. The setting sits above every VPN on the device. Set Private DNS to Off, or to Automatic, which uses the resolver the phone already has and falls back to plain DNS when that resolver doesn't speak TLS, which a stock Pi-hole doesn't.

On a phone that "connects but doesn't block", check this setting before anything in WireGuard or Pi-hole. The phone was told, by its owner or by an earlier setup guide, to encrypt DNS to a specific company, and it's doing exactly that.

iCloud Private Relay on iPhone and Mac

Private Relay routes Safari traffic and DNS through Apple's relays, and a device with it on asks Apple's resolvers, not yours. Pi-hole handles this server-side with a setting that is on by default. The config reference's entry for dns.specialDomains.iCloudPrivateRelay asks if Pi-hole should "always reply with NXDOMAIN to A and AAAA queries of mask.icloud.com and mask-h2.icloud.com to disable Apple's iCloud Private Relay to prevent Apple devices from bypassing Pi-hole", following Apple's own guidance to network operators. So when the device does ask Pi-hole for those names, Private Relay fails to start and the device falls back to normal DNS through the tunnel.

pihole.log: iCloud Private Relay domains and the Mozilla canary answered NXDOMAIN by Pi-hole

Pi-hole answers the Private Relay and Firefox canary domains with NXDOMAIN by default.

The order matters. Pi-hole can only answer the mask.icloud.com lookup if the lookup reached Pi-hole, which brings this back to the DNS line and AllowedIPs above. On an iPhone with the line set, the packet tunnel settings generator in the app's source hands the system a single empty match domain whenever a DNS server is set, which forces every query through the tunnel DNS.

Firefox DNS over HTTPS and the Mozilla canary

Firefox can resolve names over HTTPS to a provider of its own, inside the browser, and a query that never leaves the browser as plain DNS is invisible to the tunnel's resolver. Mozilla ships a canary domain so networks can opt out of the automatic mode, and Pi-hole answers it by default:

Should Pi-hole always reply with NXDOMAIN to A and AAAA queries of use-application-dns.net to disable Firefox automatic DNS-over-HTTP?

That's dns.specialDomains.mozillaCanary in the config reference, default true, with the Mozilla support page it follows linked under it. The word that limits it is "automatic". A Firefox profile where someone switched DoH on by hand, at the strictest level, is a browser setting and only a browser setting changes it: in Firefox's own DNS over HTTPS preference, set it off or back to the default level so the canary is honoured again.

The third key in the same group, dns.specialDomains.designatedResolver, answers NODATA for the resolver.arpa zone so that devices using Discovery of Designated Resolvers (RFC 9462) don't upgrade themselves to an encrypted resolver behind Pi-hole's back. It is also on by default. Each of the three leaves its own line in /var/log/pihole/pihole.log when it fires, which makes them easy to grep for: Apple iCloud Private Relay domain mask.icloud.com is NXDOMAIN, Mozilla canary domain use-application-dns.net is NXDOMAIN and Designated Resolver domain _dns.resolver.arpa is NODATA. If any of the three has been switched off on your install, sudo pihole-FTL --config dns.specialDomains.mozillaCanary prints the current value and the same command with true on the end restores it.

Browsers and apps with their own DoH

Chrome, Edge and Brave have a secure DNS setting of their own, and more and more apps ship with a DoH client and a resolver address compiled in. None of them honour the Mozilla canary; it's Mozilla's convention. What Pi-hole can do is refuse to resolve the DoH provider's hostname when the app does ask for it, which is a job for a blocklist entry. What it can't do is see traffic that goes straight to a hard-coded IP over port 443. For the browsers, turn secure DNS off or point it at the operating system's resolver; for an app with its own resolver baked in there is no DNS-level fix, and Pi-hole won't see that app's lookups.

Windows uses other adapters' resolvers without the kill switch

On Windows the WireGuard app sets the DNS servers from the config on the tunnel adapter, and the Ethernet or Wi-Fi adapter keeps the resolvers it got from DHCP. Which one a given lookup uses is Windows' decision, and the project's netquirk document is explicit about when the tunnel service steps in: only with a single peer whose AllowedIPs contains 0.0.0.0/0 or ::/0 (the "Block untunneled traffic" checkbox in the editor) are packets to port 53 restricted to the configured DNS servers and all other untunneled traffic blocked. With a split tunnel that rule doesn't exist, and a program that names its own resolver can reach it over the normal adapter.

Does that mean a DNS-only tunnel can't work on Windows? The configured servers are set on the adapter, so the system resolver has them; what the tunnel service doesn't do with a split tunnel is stop anything from asking elsewhere. If the guarantee matters, switch that one client to 0.0.0.0/0 with the kill switch on, and give the VPS the forwarding and NAT a full tunnel needs.

The DNS line failed on Linux without resolvconf

On a Linux laptop wg-quick applies the DNS line by calling resolvconf. A Debian 12 install without systemd-resolved has no such command and wg-quick doesn't check, so wg-quick up prints resolvconf: command not found, deletes the interface and the system keeps its old resolvers. That is a leak with an error message attached, the only one on this page that announces itself. On such a machine, install openresolv. On a system that runs systemd-resolved (some Debian 12 images do), the command already exists, and installing openresolv would remove systemd-resolved; there, replace the DNS line with a PostUp that calls resolvectl dns %i 10.100.0.1 and resolvectl domain %i ~.. On Ubuntu 24.04 systemd-resolved provides the resolvconf command itself and maps wg-quick's -x flag to a ~. routing domain, so the tunnel's resolver wins for all names and this cause doesn't apply.

How to check where the queries go

Three checks, in this order, and the first settles it. From the device with the tunnel up, open http://10.100.0.1/admin/ and watch the Query Log while you load a page in the browser. Lines with your tunnel address as the client, 10.100.0.2 for the first peer, mean the lookups reach Pi-hole. No lines while the page loads means they go somewhere else, and the cause is on this page. Without a browser on the device, sudo tail -f /var/log/pihole/pihole.log on the VPS shows the same thing: each query ends in from 10.100.0.2. (If the admin page itself won't open, the pi.hole/admin page covers that separately; it's usually the missing /admin/ on the URL.)

pihole.log showing A and AAAA queries for debian.org names from the tunnel client 10.100.0.2

The client's own lookups arrive at Pi-hole from its tunnel address.

Second, nslookup pi.hole with no server argument. Pi-hole answers that name for itself and nothing else on the internet does, so an answer of 10.100.0.1 proves the operating system's resolver is the Pi-hole. Success here with a Query Log that stays empty while you browse points at a browser doing its own DoH.

Third, the leak test the Pi-hole client guide recommends, at dnsleaktest.com. It should list only the upstream you set in Pi-hole or, with Unbound on the VPS, only the VPS's own public address. A home ISP's resolver in that list is the leak, and the longer set of Pi-hole checks has the same test with the open-resolver probe added. Then go back to the Query Log: the leak test says that something leaked, the log says which device and which name, and the name tells you which section above to read.

Questions?

Do I still need DNS over HTTPS if my queries already go through WireGuard?

Not between the device and Pi-hole: a query to 10.100.0.1 travels inside the tunnel, which WireGuard encrypts with ChaCha20 and Poly1305, so the networks in between see only UDP packets to the VPS. The readable leg is the one after Pi-hole, because FTL forwards to its upstreams as plain DNS. With a public upstream, that provider sees every name you look up; with Unbound on the VPS, the queries go unencrypted to root, TLD and authoritative servers, though no single operator sees all of them. If you want that leg encrypted too, the Pi-hole docs' dnscrypt-proxy guide sets up a local proxy that forwards over DNS over HTTPS; their cloudflared guide now carries a warning that the feature it relies on is deprecated and new installations are not recommended.

Philippe Ménard
About the author

Philippe Ménard

Some evenings Philippe is at a small community radio station in Montréal, helping with recording or presenting a late-evening music programme. He was born in Lyon and moved to Montréal for graduate studies in computer science, then stayed: application support first, then infrastructure security (where technical communication became a larger part of the job once he started producing internal material for teams). He writes about security, Linux administration, cloud infrastructure, AI, automation. His record collection is mostly jazz and French music inherited from his father.

Deploy your next project in seconds

Bring your winning ideas online faster, with modern hardware and unmetered bandwidth. Join a European cloud trusted by thousands of developers and businesses worldwide.