How it works
DNS leak test: what the result actually means, and what it misses
Before your browser opens a connection, something else happens first: the device asks a resolver to turn a hostname into an IP address. That question travels ahead of everything else, and it is not automatically routed the same way as the traffic that follows. When it takes a path you did not intend, that is a DNS leak. Below: what actually escapes, how to read a test result, and why the popular test pages answer only part of the question.
What a DNS query actually reveals
The query carries the hostname you are about to visit. The resolver that answers it sees three things: the name, the time, and the address of whoever asked. It does not see the page or the request body - that connection is separate, and to an HTTPS site its contents are encrypted. But a stream of names with timestamps, coming from one address, is a browsing history under a different label.
There is a second audience. Classic DNS runs over plain UDP port 53 with no encryption. Any device on the path - the local router, the Wi-Fi operator, the ISP - can read the question and substitute the answer. DNSSEC can authenticate the data where it is deployed, but it encrypts nothing and most stub resolvers do not validate it themselves. Encrypted transports were built to close the reading half of that problem.
Two different failures, both called a DNS leak
They get the same name and need different fixes, so it is worth keeping them apart.
- Wrong path. The query leaves over the physical interface instead of the tunnel. Your ISP sees the name, sees your real address asking, and on port 53 can rewrite the answer. This is the classic leak.
- Wrong resolver. The query goes through the tunnel exactly as intended, but ends at a resolver you never chose - the one a captive portal pushed, the one a browser turned on by itself, the one left over in a network profile. Nothing left the tunnel. A party you did not pick is still assembling a list of names.
There is a third arrangement, and it fails differently: no local query at all. A proxy protocol that accepts a hostname rather than an address - SOCKS5 with remote resolution, or VLESS carrying the domain through - lets the server resolve on your behalf. Nothing is generated on your side, so there is nothing on the local network to leak. Be clear about what that buys: the names are now seen by the server operator and whatever upstream resolver it uses, instead of by your ISP. It relocates the observer. More on how that transport works in the guide on VLESS Reality.
Why leak test pages tell you only half of it
The mechanism is simple and worth knowing, because it explains the limits. The page loads a series of unique subdomains under a nameserver it controls, then reports which recursive resolvers showed up to ask about them. That is a real measurement, but a narrow one.
- It shows resolvers, not your configuration. What you get is the egress address of the recursive resolver, which for a large anycast operator has no fixed relationship to the address you configured.
- It only sees the browser. Chrome and Firefox can run their own DoH independently of the system resolver. The page can look clean while every other process on the machine resolves over the physical adapter - or the reverse.
- Cache hides leaks. A name already held in the OS or browser cache produces no query at all, so a test right after connecting and the same test after a reboot can disagree.
- It measures a steady state. The dangerous window is reconnect: the tunnel drops, routes revert for a few seconds, queries go out in the clear, the tunnel returns. A page you load once will never observe that.
- It cannot speak to logging or ownership. Not leaking means the query arrived where you sent it. Whether that operator keeps a record is a separate question with no technical test.
How to read the result
What you are looking at is a list of resolver addresses with an ASN and a country attached. Some shapes matter and some do not.
- A real leak: a resolver belonging to an operator you never configured. Your own ISP is the clearest case - your address is in someone else’s log next to a hostname. Country alone does not settle it; ownership does.
- Also a real leak: your ISP resolver appearing alongside the expected one. Parallel resolution across several interfaces produces exactly this shape - you get the right answer and send the wrong query at the same time.
- Usually fine: several addresses belonging to one large operator. Recursive fleets query from many addresses, and seeing four of them is not four leaks.
- Usually fine: a resolver in a different country from your exit node. Anycast answers from the site nearest the query as the network routes it, which need not be the site nearest you.
- Not measured at all: whether the exit address matches what you expect. That is a separate check on the same page and says nothing about DNS.
DNS, WebRTC and IPv6 leaks are three different things
They get listed together on the same test pages, which suggests they are variations of one problem. They are not: different mechanisms, different observers, different severity.
- DNS leak - a metadata channel. What escapes is the name you asked about and the address that asked. The site you visit learns nothing new from it. The parties that learn something are the resolver operator and, on port 53, anyone in between.
- WebRTC leak - a browser API. When a page opens a peer connection, the browser gathers candidate addresses and may ask a STUN server how the connection looks from outside. The result is handed to the page’s JavaScript, so here the site itself learns an address directly, with no resolver involved. Chrome and Firefox now replace local interface addresses with random mDNS names ending in
.local- though in Chrome that masking drops away once the page has been granted camera or microphone access. The residual risk is the reflexive candidate: if a second interface has a working route outside the tunnel, the STUN request goes out over it and reports the public address it sees there. - IPv6 leak - real traffic, not metadata. If the tunnel carries only IPv4 while the host has working IPv6, a dual-stack destination is reached directly over v6. The site sees your real address. Unlike an IPv4 address shared behind carrier NAT, a delegated v6 prefix normally covers a single subscriber line, though how often the ISP rotates it varies. This is the default outcome rather than an edge case: an AAAA record comes back and the browser prefers it.
Only the last of the three moves your actual traffic outside the tunnel. It is the one worth checking first, and in practice it is the one people check last.
Where leaks come from, by platform
- The route table. A client that installs a genuine default route captures everything; one that only adds a few prefixes leaves gaps. Confirm that
::/0was captured, not just0.0.0.0/0- a v4-only tunnel on a dual-stack host is the leak described above. - Windows. Resolving a name across several interfaces in parallel and taking the fastest answer is standard behaviour. The right answer wins, and the query still left through the other adapter. What stops it is an NRPT rule or a client that clears the resolvers on the remaining adapters.
- Linux with systemd-resolved. DNS is per link. Unless the tunnel link claims the default routing domain
~., anything not matching a specific domain can go to the resolvers of the physical link.resolvectl statusshows the split per interface. - macOS.
scutil --dnsprints the scoped resolver list with the search order attached. What you are looking for is any resolver ranked ahead of the ones the tunnel installed. - Browsers. Secure DNS in Chrome and DoH in Firefox are resolver decisions made inside the browser, independent of the system. Firefox also has heuristics that switch its own DoH off when it detects certain network configurations, which means the effective resolver can change without you touching anything.
- Local name protocols. mDNS, LLMNR and NetBIOS resolve names on the local segment and are not DNS at all. They stay on the LAN, which is usually harmless, though a device name broadcast on a hotel network is not nothing.
Checking it yourself, without a test page
- 1Read the resolver list before running any test.
scutil --dnson macOS,resolvectl statuson Linux,Get-DnsClientServerAddressin PowerShell. If your ISP resolver is still listed on a physical adapter, you already have your answer. - 2Ask a name that reports back.
dig +short whoami.akamai.netanddig +short TXT o-o.myaddr.l.google.comboth go out through your configured resolver and return the address the authoritative server saw it arrive from. Compare that with the resolver you believe you set. - 3Note the difference between that and
dig +short TXT o-o.myaddr.l.google.com @ns1.google.com. Adding@talks to the authoritative server directly and skips your resolver entirely, so the answer is your own egress address, not your resolver’s. Useful, but it is an exit-address check rather than a DNS one. - 4Check IPv6 on its own. Look for a v6 default route -
ip -6 route show defaulton Linux,netstat -rn -f inet6on macOS. If one exists and the tunnel did not create it, dual-stack sites are going around the tunnel. - 5Test the reconnect window: run a query in a loop once per second, drop the tunnel, bring it back, and watch which resolver answers in between.
- 6Repeat after clearing the caches -
ipconfig /flushdns,resolvectl flush-caches,sudo dscacheutil -flushcache- otherwise you are testing what was remembered rather than what the network does.
On the client side, the arrangement with the fewest failure modes is not to resolve locally at all. In Xray that means leaving domainStrategy in the routing section at AsIs: the other values resolve the hostname locally so an IP rule can match it, and that lookup is a real query on a real interface. In sing-box the equivalent is not attaching a domain resolver to a proxy outbound, so the name travels inside the connection. Where the client runs in TUN mode and has to answer queries itself, hijacking port 53 into the client’s own DNS with a single upstream is what keeps the path predictable. The thing to look out for is a routing rule that hands some domains to a direct resolver for local resolution - it works as designed, and it is also a leak you configured on purpose.
What a clean result does not mean
A clean test means one narrow thing: during that page load, the queries the browser made reached the resolver you expected. It is not a statement about anonymity.
- The resolver still sees every name you look up. You changed who holds that list, not whether one exists.
- The destination still sees a connection arriving. The exit address is shared rather than absent, and it still carries a timestamp.
- Nothing about the device changed. Browser fingerprint, OS-level identifiers and any account you sign into sit entirely outside what a tunnel touches - see the guide on VPNs and anonymity.
A DNS leak is worth fixing because it is cheap to fix and it quietly undoes the one thing a tunnel is actually good at: keeping your network address and your destination out of the same log. Fix the IPv6 path first, then the resolver, then verify during a reconnect rather than at rest. That is the whole job.
What does it mean if a DNS leak test shows my ISP?
It means at least some queries left over the physical interface instead of the tunnel, so your ISP resolver saw the hostname and the address asking for it. It usually points at one of three things: the tunnel did not install a real default route, another network adapter still has its own resolvers configured, or the operating system is resolving across several interfaces in parallel. The traffic itself may still be going through the tunnel - the query is the part that escaped.
Is it a leak if the resolver is in a different country from my VPN server?
Usually not. Large public resolvers are anycast, so a query entering the network in one city can be answered by a site in another country, and the address the test reports belongs to the recursive fleet rather than to the entry point you configured. What matters is whether the resolver belongs to an operator you chose. A resolver inside your own ISP network is a leak regardless of which country the test shows.
Does encrypted DNS such as DoH or DoT prevent DNS leaks?
It solves a different problem. Encryption stops anyone on the path from reading or rewriting the query, which is real protection on an untrusted network. It does not decide which interface the query leaves through or which resolver receives it, and those are what a leak is about. An encrypted query sent outside the tunnel to a resolver you never chose is still a leak - just an unreadable one for the network in between.
Which leak should I fix first, DNS or IPv6?
IPv6. A DNS leak exposes metadata: the names you resolve and the address that asked. An IPv6 leak sends the actual connection outside the tunnel, so the destination sees your real address directly, and a delegated v6 prefix normally belongs to one subscriber line rather than being shared behind carrier NAT. Either capture the v6 default route in the tunnel or disable IPv6 on the interface, then deal with the resolver.
If my DNS leak test is clean, am I anonymous?
No. A clean result says the queries went where you intended during that test. The resolver still has the list of names, the sites you visit still see a connection with a timestamp, and none of that touches identifiers above the network layer - browser fingerprint, operating system telemetry, or any account you sign into during the same session. A tunnel changes your network address; anonymity is a separate and much larger problem.