Skip to main content
Back to Blog
· 14 min read

The Durable VPN + DNS Anti-Tracking Setup - A Cross-Platform Guide

Most privacy guides give you a list of apps and send you on your way. This one describes a single architecture you can reproduce on macOS, iOS, Windows, and Linux. It keeps working when you switch networks, reboot, or change devices, and it fails closed instead of silently leaking when something breaks.

The core idea is layering. No single tool blocks everything. A VPN hides your IP from websites but sees all your traffic itself. DNS filtering blocks ads and trackers system-wide but does not hide your IP. A hardened browser blocks fingerprinting and client-side tracking, but only inside that browser. Stacked, each layer covers the other's blind spots. If one layer fails, the next one still limits the damage.

Why VPN + Filtered DNS Together

A VPN encrypts your traffic and replaces your IP, but it does nothing about the dozens of tracking domains every page and app contacts. A filtering DNS resolver blocks those domains before a connection is ever made, for every app on the device, not just the browser. The two are complementary:

  • VPN: Answers who can see where you connect from.
  • DNS filtering: Answers who you can connect to at all.

Doing both through encrypted channels (WireGuard for the VPN, DoH or DoT for DNS) also removes your ISP's ability to log your DNS queries. Otherwise, plain DNS is visible to every network operator between you and the resolver.

Choose the Components

VPN Provider or Your Own Server

Use a commercial VPN built on WireGuard with three non-negotiable features: a system-level kill switch, enforced DNS inside the tunnel, and a publicly stated no-logs policy backed by an independent audit. WireGuard matters for speed, and also because its stateful, always-on design makes silent leaks on reconnect far rarer than with legacy OpenVPN setups. You still have to re-test for leaks after any protocol or server switch. The Private Proxy Guide and VPNSmith both walk through why that re-test matters in 2026.

Reputable candidates: Mullvad, Proton VPN, IVPN. All three support WireGuard, all three have passed independent audits, and all three allow manual WireGuard configuration, which matters for Linux and for routers. Avoid free VPNs without a transparent business model.

Advanced option: rent a €5/month VPS and run your own WireGuard endpoint. You trade a provider's shared IP pool (good for anonymity) for full control and zero third-party trust. Running your own endpoint is legal in the EU, the US, and Canada. This is the sovereign path: powerful, but you become your own sysadmin.

DNS Resolver

Three solid options, by level of involvement:

  • NextDNS: The default recommendation for this guide. A free tier with a generous monthly quota, granular blocklists (ads, trackers, telemetry, malware, per-country disinformation), per-device profiles, a real-time log for debugging, and adjustable log retention from one hour to disabled entirely (itechguides). You get a unique endpoint like abcdef.dns.nextdns.io that identifies your config, and only your config, not your name.
  • AdGuard DNS: Zero-signup public endpoints (94.140.14.14) with the strongest out-of-the-box default blocklist, DoH, DoT, and DoQ support, and post-quantum crypto on its encrypted endpoints (DNS Benchmark). Pick this if you want filtering with no account at all.
  • Control D: Preset public resolvers with no logging on the free tiers, and fully customizable paid configs. A good middle ground.

Self-hosted alternatives (Pi-hole or AdGuard Home on a Raspberry Pi at home, or Pi-hole on a VPS) give maximum control and add a maintenance burden. They are worth it only if you want full query visibility on hardware you own (getblockify).

NextDNS is the reference setup here because its per-config endpoints make the instructions identical on every OS. If you point a device at the bare anycast addresses, link that device or IP in the NextDNS dashboard. Otherwise those addresses answer queries without your blocklists.

Choose Your Aggressiveness Level

Configure NextDNS, or your resolver of choice, in one of three tiers. You can move between them without touching your devices, because the filtering lives server-side:

  • Conservative: Ad and tracker blocklist, plus Block Disguised Trackers (CNAME uncloaking) only. Breaks almost nothing.
  • Balanced: Conservative, plus Threat Intelligence Feeds, plus telemetry blocks for Microsoft, Apple, and Samsung. Occasional breakage, fixed by allowlisting. This is the tier to start with.
  • Aggressive: Balanced, plus Hagezi Pro or OISD full lists, plus an AI chatbot blocker, plus ID4CAN and the remaining aggressive lists. Noticeably cleaner web, more breakage on streaming and apps. Expect to maintain an allowlist (factually.co, itechguides).

Two resilience settings matter at every tier. Enable CNAME uncloaking, because trackers increasingly hide behind first-party-looking subdomains. Set log retention to the shortest useful window: analytics for a day, then nothing.

Wire It Up Per Platform

The design principle is the same everywhere: filtering DNS as the device's only resolver, VPN on top with a kill switch, and no fallback to plaintext DNS.

macOS

  • Install the VPN app. Mullvad or Proton are the straightforward choices. Enable the kill switch ("block internet without VPN" or "advanced kill switch") and set it to auto-connect. If you use the CLI or a manual WireGuard config, use the official WireGuard app from the App Store.
  • Set DNS per network. Open System Settings, then Network, then Wi-Fi (and Ethernet), then Details, then DNS. Add the NextDNS IPv4 addresses shown on your NextDNS setup page, for example 45.90.28.0 and 45.90.30.0, then remove everything else. macOS has no per-network global DNS override, so repeat this for each network you use regularly.
  • Prefer encrypted DNS. Install a signed DNS-over-HTTPS configuration profile, the NextDNS macOS app, or dnscrypt-proxy. The app and dnscrypt-proxy handle DoH and fallback logic. Manual DNS entries do not.
  • Verify. Visit test.nextdns.io. It must show your profile ID. Then connect the VPN and run a DNS leak test. Every resolver shown must belong to your VPN provider or to NextDNS.

macOS sometimes re-appends the router-provided DNS after a network change. dnscrypt-proxy, or the NextDNS app, is the durable fix. The manual network-settings route can silently revert.

iOS and iPadOS

  • Install the NextDNS app from the App Store and activate your profile. That installs a system-wide encrypted DNS configuration through Apple's NEDNSSettingsManager. It is far more durable than manual DNS settings and survives network changes.
  • Install your VPN app. Enable "Block connections without VPN" in the per-VPN settings. Supervised devices (MDM) can also use Always-on VPN. Without MDM, keep VPN auto-connect enabled at minimum.
  • Disable Wi-Fi Assist under Settings, Cellular, Wi-Fi Assist. It can route traffic outside the tunnel on flaky Wi-Fi, and the VPN kill switch does not always cover it cleanly.
  • Verify with test.nextdns.io and a leak test while toggling airplane mode on and off.

iOS is the most reliable platform for this setup because DNS profiles and VPN profiles are first-class system features. The main gap: you cannot firewall per-app leaks on iOS without MDM, so the VPN has to stay on.

Windows

  • Install your VPN app and enable the kill switch ("Advanced kill switch" or "always-on firewall", depending on the provider) plus DNS leak protection. If the provider offers both, prefer the firewall-based kill switch. It loads before the desktop finishes booting, which matters on resume-from-sleep (perfectiongeeks).
  • Set DNS on the adapter. Settings, Network and Internet, your adapter, DNS server assignment, Edit. Add the NextDNS IPv4 and IPv6 addresses. Turn on the DNS over HTTPS template and paste your NextDNS DoH endpoint. Windows 11 supports native DoH. Use it.
  • Or use the NextDNS Windows app, which applies the same settings and locks the configuration.
  • Leave IPv6 on if your VPN tunnels it. Mullvad does, and most reputable providers do now. Disable IPv6 on the adapter only after you have confirmed the VPN does not handle it. An untunneled IPv6 path is a leak. A disabled IPv6 stack is the fallback, not the goal.
  • Verify with test.nextdns.io and a leak test, including immediately after reboot and after switching Wi-Fi networks. Windows network-awareness reconnects are the classic leak window (leak-test field guide).

Linux

Linux is where you can make the setup genuinely hard to bypass, because the kill switch can live in the firewall rather than in an app.

  • Install WireGuard (wg-quick) with a config from your provider or from your own server.
  • Full-tunnel the peer. In /etc/wireguard/wg0.conf, set DNS to your NextDNS addresses and set AllowedIPs = 0.0.0.0/0, ::/0.
  • Arm a firewall kill switch with iptables, nftables, or UFW, hooked into the interface lifecycle so it arms when the tunnel comes up and disarms when it goes down. Default-deny outbound traffic, allow the WireGuard handshake, and allow everything on wg0 (vucense).

wg-quick marks its own handshake packets. Reject every outbound packet that is not on the tunnel and does not carry that mark. Pair the IPv4 rule with the same rule in ip6tables, or IPv6 walks around the kill switch:

[Interface]
PrivateKey = YOUR_PRIVATE_KEY
Address = 10.8.0.2/32
DNS = 45.90.28.0, 45.90.30.0

PostUp = iptables -I OUTPUT ! -o %i -m mark ! --mark $(wg show %i fwmark) -m addrtype ! --dst-type LOCAL -j REJECT
PostUp = ip6tables -I OUTPUT ! -o %i -m mark ! --mark $(wg show %i fwmark) -m addrtype ! --dst-type LOCAL -j REJECT
PreDown = iptables -D OUTPUT ! -o %i -m mark ! --mark $(wg show %i fwmark) -m addrtype ! --dst-type LOCAL -j REJECT
PreDown = ip6tables -D OUTPUT ! -o %i -m mark ! --mark $(wg show %i fwmark) -m addrtype ! --dst-type LOCAL -j REJECT

[Peer]
PublicKey = YOUR_SERVER_PUBLIC_KEY
Endpoint = YOUR_SERVER_IP:51820
AllowedIPs = 0.0.0.0/0, ::/0
PersistentKeepalive = 25

UFW is the shorter version of the same idea: ufw default deny outgoing, allow outbound traffic to your server on the WireGuard port, and allow all outbound traffic on wg0 (USAVPS). Apply the same policy to IPv6.

For DNS, enable systemd-resolved with a DoH or DoT upstream, or point /etc/resolv.conf at a local dnscrypt-proxy instance using your NextDNS endpoint. dnscrypt-proxy is the more durable option because it also covers processes that bypass systemd-resolved.

Verify with test.nextdns.io, wg show, and a packet capture on the physical interface while the tunnel is up:

tcpdump -i eth0 port 53 or port 853

Replace eth0 with your real interface. Any DNS traffic there is a leak. Repeat the capture for the WireGuard UDP port only long enough to confirm the handshake itself is the traffic you expect.

The Browser Layer

DNS blocking stops the connection. The browser has to handle everything that does not need a new connection: fingerprinting, client-side tracking, and first-party analytics that run on the page's own domain.

Firefox, or a Firefox derivative such as LibreWolf, is the reference hardened browser:

  • Set privacy.resistFingerprinting to true. LibreWolf ships with it on.
  • Set network.trr.mode to 3 and network.trr.uri to your NextDNS DoH URL. Mode 3 is DNS-over-HTTPS with no fallback to the system resolver, which matches the fail-closed rule.
  • Enable Total Cookie Protection.
  • Install uBlock Origin with EasyPrivacy, the uBlock filters, and Hagezi's Pro list. In aggressive mode, also disable prefetching and enable uBlock hard mode if you accept more breakage.
  • Use Multi-Account Containers or, at minimum, separate browser profiles for work, personal, and shopping. Cookie partitioning handles most of this. Profiles are simpler and work everywhere.

On Chromium, use Brave if you want hardened defaults (shields up, per-session fingerprint randomization, ephemeral third-party storage). If you are locked into Chrome or Edge, use uBlock Origin Lite. On Apple platforms, Safari with "Prevent cross-site tracking" enabled, Lockdown Mode left off for daily use, and Firefox Focus as the browser you open for untrusted links, is a reasonable low-effort stack.

Whatever DNS filtering blocks, the browser can still leak a fingerprint: fonts, screen size, timezone, GPU string. A VPN changes nothing about that. uBlock and the hardening settings narrow it. A fingerprint test such as amiunique or Cover Your Tracks shows where you actually stand.

Verify and Monitor

Every layer needs a test. Run the tests per device, per network (home, cellular, public Wi-Fi), and in each failure mode you can trigger:

  • DNS filtering: test.nextdns.io, or the status page for your resolver. Confirms your profile is active and encrypted.
  • DNS leak: Any leak-test site, with a limit you should remember. It checks for common leaks, not all of them. For a high-assurance setup, add a packet capture on the physical interface (leak-test field guide).
  • Kill switch: Connect the VPN, then force the tunnel to drop. Disable the VPN interface, block the server on your router, or switch networks mid-session. The device must lose connectivity entirely. If anything loads, the kill switch is misconfigured.
  • Reconnect: The most common real-world leak. Resume from sleep, switch from Ethernet to Wi-Fi, toggle airplane mode. Each transition is a window where pre-tunnel traffic can escape if the firewall is not armed at boot.
  • Fingerprint: A tracking-test site, per browser, per profile.

Put a quarterly reminder on your calendar, and run the same suite after every major OS update, VPN app update, or DNS config change. The maintenance budget is about fifteen minutes, four times a year.

Failure Modes and Durability

A setup that silently degrades is worse than no setup, because you stop checking. The durable choices:

  • Filtering DNS that follows the device. NextDNS or AdGuard apps, or system profiles, not the router. Filtering then works on cellular, in hotels, and on every other network.
  • Kill switch at the firewall or OS profile, not inside a user-space app. It survives the app crashing or failing to launch at boot (vucense).
  • VPN auto-connect on every network, with untrusted-network rules if your provider supports them. Many public networks actively block VPN. Knowing that is the cause, rather than a broken setup, saves hours of debugging.
  • No plaintext fallback. Remove the ISP and router DNS entries from device configs. When your filtering resolver is unreachable, DNS fails instead of reverting to your ISP. Failing closed is the feature. The device shows "no internet", and you investigate, instead of leaking.
  • Server-side filter configuration. Blocklists live in the NextDNS dashboard. A new phone or a reinstalled OS is a five-minute profile install, not a reconfiguration session.

Common Breakage and How to Fix It

Aggressive DNS filtering breaks things. That is a trade, not a defect. The fix is a deliberate allowlist, not turning filtering off.

  • Streaming that refuses to play: Usually the analytics or ad domains bundled with the service. Allowlist the specific domain in your resolver dashboard. Do not allowlist the whole service.
  • App store or OS updates failing: Allow the OS telemetry domain temporarily, or switch that device profile to the Conservative tier while updating.
  • Login flows that break: Many banks' anti-fraud scripts look like trackers. Add them to the allowlist once, in the dashboard. The fix reaches every device immediately, which is why server-side filtering beats per-device blockers.
  • Split horizon: You use a VPN but still need your home or office network directly. Use the VPN's split-tunnel rules for those CIDRs, and keep the firewall blocking plaintext DNS. A second WireGuard peer for that route works too.

What This Setup Does Not Protect You Against

Limits are part of a durable design:

  • A VPN provider that logs, lies about logging, or is subpoenaed. Mitigate with audited providers or your own server. Trust still has to live somewhere.
  • State-level adversaries and compelled disclosure. Different threat model, different tools.
  • First-party tracking. The site you are logged into can correlate your account activity. No DNS filter blocks the page's own JavaScript. That is the browser layer's job, and even the browser cannot stop a logged-in service from knowing what you do there.
  • Fingerprinting on accounts you are already logged into. If you sign into Google and browse, the session itself is the identifier.
  • Your own mistakes, and other people's breaches. A social media post, or your data on someone else's server, is outside this stack.

Bottom Line

The promise is narrower than total privacy. Your ISP and public networks see almost nothing useful. Your traffic carries no ad or tracker beacons beyond your control. Your identity is not trivially linkable to your IP. Any failure in the stack is loud rather than silent. That is achievable, cross-platform, and, with quarterly checks, sustainable for years.