Networking

WireGuard DNS, PersistentKeepalive & MTU (Fix Drops & Leaks)

3 min read

Once the tunnel handshakes, three wg0.conf settings fix the usual real-world problems.

DNS — stop leaks on a full tunnel

On a client doing a full tunnel, set a DNS server so queries go through the tunnel, not your local resolver:

[Interface]
Address = 10.0.0.2/24
PrivateKey = CLIENT_PRIVATE_KEY
DNS = 1.1.1.1

wg-quick applies this via resolvconf or systemd-resolved — install one if DNS seems ignored. Without it, a full tunnel can still leak DNS to your ISP.

PersistentKeepalive — stop idle drops behind NAT

A client behind NAT loses its mapping after ~30–180s of silence, so the server can’t reach it. Add to the [Peer] on the side behind NAT (usually the client):

[Peer]
PublicKey = SERVER_PUBLIC_KEY
Endpoint = SERVER_PUBLIC_IP:51820
AllowedIPs = 0.0.0.0/0
PersistentKeepalive = 25

25 seconds is the standard value — small enough to keep any NAT mapping alive.

MTU — fix “handshakes but slow / stalls on big transfers”

The default WireGuard MTU is 1420. Over PPPoE, double-NAT, or some mobile networks, packets get fragmented and large transfers stall. Lower it on the [Interface]:

[Interface]
MTU = 1280

1280 is a safe floor (the IPv6 minimum). Try 1380 first if you want to give up less throughput.

Verify

# DNS goes through the tunnel:
resolvectl status        # or: cat /etc/resolv.conf
# big transfer no longer stalls after lowering MTU:
curl -o /dev/null https://speed.cloudflare.com/__down?bytes=100000000

Symptom → fix: DNS leaks → set DNS. Works then dies after a minute → PersistentKeepalive = 25. Pings fine but downloads hang → lower MTU. These three solve the large majority of “it connects but…” reports.

Open the full version (with copy buttons) ↗

← All recipes