This article walks through practical, technical methods to ensure DNS queries remain private when using WireGuard. It is written for administrators, developers, and enterprise operators who require deterministic, leak-free DNS behavior from client and server deployments. You will find configuration examples, troubleshooting steps, and best practices for common resolver stacks such as systemd-resolved, dnsmasq, Unbound, and cloud DNS providers.

Why DNS leaks matter with WireGuard

DNS queries reveal which domains a client is resolving irrespective of the encrypted tunnel. Even when application traffic flows through a WireGuard tunnel, DNS can still be resolved by the OS or an ISP resolver outside the tunnel, exposing activity logically equivalent to a metadata leak. For compliance, auditing, or privacy-sensitive deployments, avoiding DNS leaks is as important as securing the tunnel itself.

Key leak vectors:

  • System resolver (e.g., systemd-resolved) still using local/ISP DNS after WG interface activation.
  • Incorrect AllowedIPs or routing rules that exclude DNS traffic.
  • IPv6 dual-stack causing DNS via native network while IPv4 flows in WireGuard.
  • Split-DNS misconfiguration that unintentionally queries public resolvers.

WireGuard DNS basics

WireGuard itself does not implement or force a DNS resolver. The common practice is to push a DNS server address to the client using the DNS option in the Peer section when using wg-quick or to configure clients explicitly. That address is then consumed by the client’s resolver stack (NetworkManager, systemd-resolved, resolvconf, etc.). However, the presence of that address alone does not guarantee queries go over the tunnel.

Understand the resolver stack on your clients

Before changing WireGuard settings, identify the resolver behavior on your client OS. Common stacks include:

  • systemd-resolved (Linux): uses a per-interface link-resolver and supports DNS over TLS with stub resolver at 127.0.0.53. It can prefer the DNS attached to the WireGuard interface if configured correctly.
  • NetworkManager: often configures /etc/resolv.conf or delegates to systemd-resolved. GUI tools may override DNS settings.
  • resolvconf/dhcpcd: legacy resolver helpers that update /etc/resolv.conf.
  • Windows and macOS: manage per-interface DNS settings differently; the WireGuard apps set DNS per tunnel but system priority rules vary.

Confirm current resolver behavior with tools like resolvectl status, nmcli device show, or by inspecting /etc/resolv.conf.

Server-side setup to support private DNS

Provide a resolver reachable only via the WireGuard tunnel: either a DNS service bound to the server’s WireGuard IP (e.g., 10.0.0.1) or forwarder like Unbound running on the server. Examples:

  • Bind dnsmasq/Unbound to the WireGuard interface address and firewall off UDP/TCP 53 from the public network.
  • Use DNS over TLS/HTTPS for upstream queries on the server to prevent upstream observers from learning client domains.

Example Unbound minimal snippet (bind to WireGuard IP):

interface: 10.0.0.1
access-control: 10.0.0.0/24 allow
forward-zone:
name: "."
forward-addr: 1.1.1.1@853 # DoT upstream

Client configuration: wireguard + DNS routing

There are two dimensions to correct client configuration: (1) ensuring resolver is configured to use your DNS, (2) ensuring IP routing forces DNS traffic through the WireGuard interface.

1. Configure the client to use the tunnel DNS

When using wg-quick, add a DNS entry to the Peer configuration for the client or set it in the system GUI. Example in /etc/wireguard/wg0.conf:

[Interface] Address = 10.0.0.2/32
DNS = 10.0.0.1

However, remember this alone won’t prevent leaks if the OS ignores that DNS or prefers another resolver. For systemd-resolved you may need to create a dedicated .network file or use resolvectl to set per-link DNS. For NetworkManager, ensure the WireGuard connection has the DNS specified and “ignore automatically obtained DNS” options are set.

2. Ensure DNS packets are routed into the tunnel

If your server’s DNS is at 10.0.0.1 and your client gets that DNS, the next requirement is routing. Since DNS uses UDP/TCP port 53, ensure that packets to that IP are routed via the WireGuard interface. If you use AllowedIPs = 0.0.0.0/0, ::/0 on the client, all traffic (including DNS) will go through WireGuard. For more granular setups (split-tunneling), ensure you add a specific route for the DNS server:

PostUp = ip route add 10.0.0.1/32 dev %i (on client or via system routes)

On Linux clients using iptables, make sure you don’t SNAT DNS traffic back to the public interface. If you manage server-side NAT, only NAT client outbound traffic to upstream if necessary; avoid changing source IP for packets to the internal DNS resolver.

Common resolver integrations and fixes

systemd-resolved

systemd-resolved can create per-link DNS servers. After the WireGuard interface comes up, verify with resolvectl status wg0. If links are not added, enable DNS via a .network file or add a hook to set link DNS using resolvectl dns wg0 10.0.0.1 in a PostUp command in wg-quick.

Example PostUp/PostDown in client config:

PostUp = resolvectl dns %i 10.0.0.1
PostDown = resolvectl revert %i

NetworkManager

When using NetworkManager, ensure the WireGuard connection profile sets the DNS and the method to “ignore automatically obtained DNS” from other interfaces. For headless or scripted installs, use nmcli to set ipv4.dns and ipv4.ignore-auto-dns.

resolv.conf based systems

Some systems still rely on /etc/resolv.conf. If your resolver stack overwrites resolv.conf with public DNS, create a resolv.conf hook in /etc/wireguard/wg0.up to replace resolv.conf with the tunnel DNS and restore on down. Be careful: this can conflict with DHCP client expectations.

Protecting IPv6 DNS queries

Dual-stack systems often leak DNS via native IPv6 if the WireGuard setup only routes IPv4. Options:

  • Disable IPv6 entirely if not required (sysctl or network config).
  • Ensure AllowedIPs includes ::/0 and the server is configured for IPv6 routing.
  • Push an IPv6 DNS server over WireGuard and configure client resolvers accordingly.

Example AllowedIPs for full-tunnel dual-stack:

AllowedIPs = 0.0.0.0/0, ::/0

Advanced: DNS over HTTPS / DNS over TLS from the client

For extra privacy, run a client-side DoH or DoT proxy that directs requests through the WireGuard interface. Two patterns work well:

  • Run a local encrypted stub (e.g., cloudflared, doh-proxy) bound to 127.0.0.1 and force it to use the WireGuard interface for upstream connections via routing policy.
  • Use the server as an encrypted forwarder (Unbound with DoT upstream) and access it via the tunnel IP, ensuring upstream confidentiality.

Example: bind cloudflared to 127.0.0.1:5053 and set your system DNS to 127.0.0.1#5053. Then use policy routing to ensure cloudflared’s outgoing connections are sourced via the WireGuard IP.

Firewall rules: enforce DNS over tunnel

On the client side, you can enforce that DNS can only be sent over the WireGuard interface by blocking outgoing port 53 on other interfaces:

  • With iptables (IPv4): iptables -I OUTPUT ! -o wg0 -p udp --dport 53 -j REJECT
  • For IPv6, use ip6tables similarly for port 53.

Be cautious: such rules can disrupt legitimate local DNS services. Test carefully and add exceptions for local resolver addresses if necessary.

Testing and validation

After configuring, validate with multiple tests:

  • Check the effective resolver: resolvectl status or cat /etc/resolv.conf.
  • Use dig @10.0.0.1 example.com to confirm tunnel DNS responds.
  • Run public leak tests from the client: DNSLeakTest, IPLeak.
  • Capture traffic with tcpdump: tcpdump -n -i any port 53 and verify that DNS packets go over the WireGuard device (look for wg0 in output).

If you see DNS traffic on your physical interface (e.g., eth0) rather than wg0, revisit routing and resolver configuration.

Troubleshooting checklist

  • Verify AllowedIPs includes the DNS server IP ranges or is set to route all traffic through the tunnel if required.
  • Check that the WireGuard DNS entry is actually applied to the system resolver.
  • Confirm firewall rules are not accidentally permitting DNS to escape the tunnel.
  • Review IPv6 behavior — many leaks are IPv6-based.
  • Use packet capture to observe actual flow and the interface used by DNS packets.

Operational recommendations for enterprises

For scalable deployments:

  • Run authoritative forwarders (Unbound/dnsmasq) per region bound to the WireGuard network to reduce latency and centralize DoT/DoH upstreams.
  • Automate client post-up hooks to configure systemd-resolved or NetworkManager properly.
  • Integrate DNS leak tests into onboarding and monitoring pipelines to detect regressions when clients or OS updates change resolver behavior.
  • Document the exact resolver stack and policies for desktop and mobile clients, including IPv6 handling.

Security controls such as per-client firewall policies and host-based enforcement will prevent accidental leaks even if a client is misconfigured.

Conclusion

Preventing DNS leaks with WireGuard requires an understanding of both the tunnel configuration and the client resolver stack. Use a combination of server-side private resolvers bound to the WireGuard IP, deliberate client-side DNS configuration, routing rules (AllowedIPs or explicit routes), and firewall enforcement. Regular testing — including packet captures and public DNS leak tests — is essential to ensure that changes to OS resolvers do not reintroduce leaks.

For more practical guides and configuration snippets that can be deployed in professional environments, visit Dedicated-IP-VPN: https://dedicated-ip-vpn.com/