Stockio

Prevent DNS Leaks on Linux With Custom Network Setups

Configure Linux resolver ownership and VPN DNS routing, then verify UDP, TCP, IPv6, and browser behavior with repeatable tests and a redacted audit record.

By Ravi Desai

DevOps & Security Engineer ·

On this page

A Linux VPN can route web connections correctly while DNS queries still leave through the Wi-Fi interface. The usual cause is not broken encryption: it is a mismatch between the program managing the tunnel and the program choosing DNS servers.

This guide uses NetworkManager with systemd-resolved as a concrete example. You will identify resolver ownership, assign VPN DNS deliberately, and verify the result with packet captures rather than relying on a single browser leak-test page.

Record a resolver baseline you can compare

A DNS leak is a query taking a path outside your intended policy. For a full-tunnel privacy profile, that might mean contacting an ISP resolver directly. For a corporate split tunnel, sending public names to the normal local resolver may be intentional. Define the desired policy before calling every outside query a leak.

Use the JSON Formatter & Syntax Linter below to maintain a small, redacted audit record containing the connection name, intended resolver, domain scope, and test outcome. It helps catch malformed JSON and makes before-and-after changes readable. It does not inspect your system, change DNS settings, or detect leaks by itself.

{
"connection": "privacy-vpn",
"policy": "full-tunnel",
"expected_dns": ["10.66.0.1"],
"routing_domain": "~.",
"physical_dns_packets_seen": false,
"ipv6_tested": false
}

Do not record real browsing history or internal hostnames in a shared diagnostic document. That example describes intent, not proof: a false value must come from a completed observation, and an untested address family should remain explicitly unverified.

Identify who owns DNS on this machine

On many desktop distributions, NetworkManager supplies per-link DNS settings to systemd-resolved. Applications contact a local stub, commonly at 127.0.0.53, and resolved selects an upstream server. Other installations use dnsmasq, a static resolver file, or a VPN application's own service. Determine which arrangement you actually have.

Start with read-only inspection:

readlink -f /etc/resolv.conf
cat /etc/resolv.conf
systemctl is-active systemd-resolved
resolvectl status
nmcli -f NAME,TYPE,DEVICE connection show --active

A stub address in the file is not the upstream resolver. Inspect the per-link servers and routing domains in resolvectl status. Conversely, if resolved is not active, its commands cannot establish your application's resolver path. Consult your distribution's configuration instead of enabling a second resolver blindly.

Do not replace /etc/resolv.conf with a static public DNS address as a universal fix. That can break split DNS, local name resolution, and updates from the connection manager. First identify whether the file is a managed symlink and which component is expected to maintain it.

The authoritative systemd-resolved manual explains per-link routing and stub behavior. Its selection rules matter more than the superficial order of nameservers in a file.

Set VPN DNS and its routing scope

For this example, the VPN is already working, NetworkManager owns it, and 10.66.0.1 is a DNS server actually provided on the tunnel. A WireGuard gateway does not automatically run a resolver. Confirm reachability and service availability before assigning that address.

The following profile changes configure IPv4 DNS and the resolved route-only domain ~., which makes the VPN link the preferred scope for ordinary names. Use the actual profile name, and reactivate it only when you can tolerate a brief interruption.

nmcli connection modify "privacy-vpn"   ipv4.ignore-auto-dns yes   ipv4.dns "10.66.0.1"   ipv4.dns-search "~."   ipv4.dns-priority -50
nmcli connection down "privacy-vpn"
nmcli connection up "privacy-vpn"
resolvectl flush-caches
resolvectl status

With NetworkManager, a negative DNS priority can exclude higher-numbered DNS configurations when active; check the installed version's behavior and active profiles. These properties do not establish VPN routes or a kill switch. The resolver address must itself travel through the intended tunnel.

For a split-DNS profile, use a specific route-only domain such as ~internal.example.com instead of ~. and avoid a global exclusion policy that suppresses required public resolution. This intentionally lets unrelated queries use other links. The NetworkManager documentation describes profile properties and DNS backend differences.

Audit IPv6 DNS separately. If the profile receives automatic IPv6 DNS servers, decide whether they belong in the policy and configure the corresponding IPv6 properties. Do not disable IPv6 merely to hide an untested configuration; either support it through the tunnel or enforce a deliberate, tested restriction.

Observe actual traffic, including application exceptions

Choose a hostname under a domain you control, vary the query label to reduce cache hits, and resolve it while capturing the physical interface. The expected result for a full-tunnel policy is no direct plaintext DNS from that interface. Queries inside the encrypted tunnel should not appear there as port 53 traffic.

Use a short packet capture with tcpdump, installed from your distribution packages. On the physical interface identified earlier, run sudo tcpdump -ni enp1s0 'udp port 53 or tcp port 53 or tcp port 853', replacing the interface name. In another terminal run resolvectl query audit-001.example.com using your controlled domain. An NXDOMAIN answer can still demonstrate that a query occurred; the packet path is what matters.

Check both UDP and TCP because DNS can use either. Port 853 observations can reveal DNS-over-TLS connections, but this capture cannot identify DNS-over-HTTPS hidden among HTTPS traffic. The Wireshark documentation is useful when a saved capture needs deeper inspection.

Review browser secure-DNS settings, container resolver files, and application-specific proxy settings. A browser may deliberately use an independent encrypted resolver. That can hide queries from the local network while still violating a policy requiring the VPN's resolver. Test the application itself, not just the operating system resolver.

Test reconnects and distinguish routing from blocking

A correct resolver choice while connected is not a fail-closed policy. When the VPN stops, NetworkManager may restore the Wi-Fi resolver and normal routing. If that is unacceptable, use a tested client kill switch or an independently maintained firewall design covering DNS and ordinary traffic.

Test startup, reconnect, suspend and resume, and tunnel failure. Repeat the physical-interface capture while a controlled application generates queries. Check IPv6 destinations as well as IPv4. An unavailable resolver can create long delays without providing any evidence that fallback is safely blocked.

Keep a rollback record before changing a working corporate or remote-access profile. Save the original DNS values locally and confirm how to restore them through the connection manager. Avoid editing a production server's resolver remotely without console access, especially when management tools depend on internal DNS.

Use the JSON formatter again to compare sanitized findings after each test. Record which cases passed and which remain untested rather than reporting one blanket “no leaks” result. For scripted checks, continue with the VPN connection automation guide. Follow employer policy when changing managed DNS, since internal resolvers may provide required security and service discovery.

Key takeaways

  • Establish resolver ownership before editing files or adding another DNS service.
  • Make routing scope explicit: full-tunnel DNS and split DNS solve different problems.
  • Verify real packets, browser overrides, IPv6, and reconnect behavior rather than trusting one test page.
  • Separate resolver selection from fail-closed enforcement, and preserve a tested rollback path.
Featured sponsor

Reach designers & developers at work

Put your product next to the tools people use every day. One sponsor per placement, no tracking pixels.

Become a sponsor

Keep reading

Related articles

More in VPN & Online Privacy
VPN & Online Privacy

Automate VPN Connections With Scripts and Task Tools

Build a systemd VPN health check that distinguishes interfaces, handshakes, and real reachability, with structured status output and safe recovery rules.

Includes: JSON formatterRavi DesaiRavi Desai
Backend & APIs

10 Best API Testing Tools

Choose an API testing tool for quick requests, shared collections, or automated checks, with clear notes on each option’s workflow, strengths, limitations, and pricing model.

Includes: JSON formatterChidi NwosuChidi Nwosu
Dev Tools & AI Coding

8 Best AI Code Review Tools

Compare eight AI-assisted code review tools for pull requests, security checks, and repository workflows, with practical cautions about false alarms, context, and human responsibility.

Includes: JSON formatterSofia MarchettiSofia Marchetti
AI Builders & APIs

10 Best Vector Databases Compared for RAG and AI Apps

Compare ten vector database choices for AI search and retrieval, from managed services to open-source projects, with practical notes on setup, scale, trade-offs, and choosing a fit.

Includes: JSON formatterChidi NwosuChidi Nwosu
Design Systems

8 Best Design Token Tools

Compare eight ways to create, organise, and ship design tokens across design files and code, including approachable options for small teams and advanced pipelines.

Includes: JSON formatterJonah WeissJonah Weiss
JavaScript & Frameworks

10 Best JavaScript Charting Libraries

Compare ten JavaScript chart libraries for dashboards, reports, and interactive data stories. See where each excels, what it costs, and how to choose based on your app and team.

Includes: JSON formatterSofia MarchettiSofia Marchetti