Your VPN Pushes Three DNS Servers: Which One Answers?
Extra entries can be a fallback, a per-domain route or a leftover from the physical link. Map each one to a scope before you call the list a leak.
Open the settings page after connecting and three DNS addresses are listed; the audit question is which one handled your last query. The count alone answers nothing, because a client push, a physical interface and a per-domain policy all write into the same view. Those entries carry different scopes, and scope rather than position decides who answers. Start by separating the sources, then test the one that owns the name you care about.
Why the List Is Longer Than Your Profile
A VPN client pushes resolver addresses for the tunnel link, and the operating system keeps them beside whatever the physical interface already had. A router, a corporate DHCP lease, a second VPN and a per-domain policy each contribute an entry of their own. Three addresses on the page can therefore mean three scopes rather than three candidates for one job. Reading the count as evidence of a leak is the first mistake in this audit.
Within one interface a client does try its servers in order, so an ordered list is not meaningless. What is not a queue is the merged view, where entries from the profile, the physical link and per-domain rules sit side by side without a single ranking. That distinction decides what you test: order explains behaviour inside one scope, and scope explains everything else.
Encrypted DNS breaks the picture from inside an application. A browser or a chat client with its own DNS-over-HTTPS resolver sends queries past the operating system list entirely, so the addresses on the settings page describe traffic the app never generated. Check the app's own resolver setting before blaming the profile for a name that came out wrong.
Which of the Three Checks Tells You What
Each source leaves its mark in a different place, and no single command shows all of them. This is the mapping worth keeping beside the settings page:
| Entry source | Where it is visible | What it proves |
|---|---|---|
| Tunnel profile | Link-scoped DNS on the tunnel device | Which servers the VPN asked you to use, not which one answered |
| Per-domain policy | Suffix list or routing domains | Which names are steered to a particular resolver |
| Physical link | DNS on the LAN interface | Whether a second scope still exists outside the tunnel |
| Application resolver | App settings, absent from the OS list | Whether the system list was consulted at all |
On a system using systemd-resolved, resolvectl status is authoritative, because it reports DNS per link together with the routing domains. macOS answers through scutil --dns, which lists scoped resolvers in the order they are tried. Windows splits the two halves: Get-DnsClientServerAddress for per-interface servers and Get-DnsClientNrptPolicy for the suffix rules. Run the command that belongs to the resolver actually in use, since a machine with a container runtime and a desktop resolver can have more than one installed.
A Backup Resolver That Cannot Answer Your Zone
A second entry is usually there for availability, and availability only works if the backup knows the names. Ask a public resolver for an internal hostname and it returns NXDOMAIN, or a wildcard answer from a search domain that has nothing to do with you. A failover nobody checked then produces an outage at exactly the moment it is needed.
Split DNS exists to prevent that: company suffixes go to a resolver holding the zone, and public names stay on the default path. The design is sound, and it depends on the suffix list being complete. Microsoft documents the per-suffix resolver policy that drives this on Windows, and the same idea appears as routing domains in systemd-resolved and as scoped resolvers on macOS.
Compare the zones the backup may answer with the suffixes present in the policy. That comparison finds the gap before a user reports that one internal site stopped resolving after a tunnel change.
Query Through the Policy, Not Around It
Query through the operating system resolver, because a direct query to a server bypasses policy and reports only what that server would say. The gap between the two answers is the whole point:
resolvectl query intranet.example.com
dig +short intranet.example.com @198.51.100.53
If the system query returns a private address while the direct query returns NXDOMAIN, policy is working and the backup is the weak point. If both return the same public answer, the name is being resolved outside the scope you intended, and the suffix list is where to look. Keep both outputs, because a resolver argument settles faster with two lines than with a screenshot of the settings page.
Then exercise the failure path, since a fallback nobody tested is an assumption. Blackhole the preferred resolver for one query and watch which address comes back:
ip route add blackhole 198.51.100.53/32
resolvectl query intranet.example.com
ip route del blackhole 198.51.100.53/32
Delete that route as soon as the query finishes, or the next person inherits a mystery. If internal names still resolve in that window, something outside the intended scope answered them. If they time out instead, the fallback is missing or correctly scoped, and the resolver's own log tells you which of the two it was.
Decide: Keep, Scope or Remove
Keep a second resolver when it answers the namespace you need and stays reachable under the profile. Scope it when it should see one suffix and nothing else, and remove it when it has neither a scope nor a documented purpose. An entry with no job is a future leak with no benefit, and a vendor default is not a purpose.
Record the outcome as four columns: suffix, resolver, interface and owner. That line answers the next audit question faster than any screenshot, and it survives the client update that quietly reorders the list.