The tunnel is up, wg show reports a recent handshake, you can ping the server's tunnel address, and nothing beyond it answers. The instinct is to regenerate keys or re-share the config. That changes the one part of the path that is already proven to work.

A completed handshake says the two peers agree on keys, that UDP reaches the endpoint, and that the crypto routing accepts the packet. It says nothing about whether the packet can leave the server afterwards.

So follow one packet instead of guessing. There are four places it can die, and each leaves a different trace.

What the handshake actually proves

WireGuard is a UDP protocol that establishes a session with a Noise handshake and then encrypts packets for a peer. When wg show lists a handshake a few seconds old and a rising transfer counter, the endpoint, the keys, and the peer's public key are all correct.

What it does not prove is that your client sends internet-bound traffic into the interface at all, that the server is willing to forward it, or that a reply can find its way back. Those are kernel routing and firewall decisions, and they are made outside the tunnel.

This is why pinging the server's tunnel address is such a misleading test. That packet is addressed to the server itself, so it terminates locally. It never needs forwarding, never needs translation, and never needs a return route from the internet.

AllowedIPs is a routing decision

On the client, AllowedIPs does two jobs. It is the cryptokey routing table that decides which destination addresses are sent into this peer's tunnel, and it is the list of source addresses the peer will accept from you. If the client config lists only 10.8.0.0/24, public destinations never enter the interface and your normal default route carries them outside the tunnel. The tunnel then works perfectly and does nothing you wanted.

Look at what the client actually installed rather than what the config file says:

wg show wg0 allowed-ips
ip route get 1.1.1.1

The second command is the decisive one. If the answer names your physical interface and the normal gateway, the packet is not being tunnelled and no server-side change will fix it. Add 0.0.0.0/0 for IPv4 and ::/0 for IPv6 separately; a catch-all for one family leaves the other on its original path, which is a common cause of a working IPv4 tunnel and a stalled IPv6 lookup.

Where the packet dies on the gateway

If the route is correct and the packet still goes nowhere, it is arriving at the server and stopping there. Four checks cover most gateways.

Forwarding. sysctl net.ipv4.ip_forward returning 0 is the classic answer, and many distributions still default to 0. It must be 1, and set persistently in a sysctl drop-in rather than with a command that disappears at reboot. IPv6 forwarding is a separate switch.

The filter policy. A FORWARD chain with a default drop policy will discard tunnelled traffic while allowing traffic to the host itself, which matches the symptom exactly. Read the live ruleset, not a saved file: nft list ruleset or iptables -S.

Translation or routing. Clients using private tunnel addresses need either source NAT on the server's egress interface or a routed prefix that the upstream network knows how to return. Choosing between them follows the address plan. Adding MASQUERADE to a network that already routes your prefix back is harmless but pointless, and omitting it where no route exists leaves replies addressed to an unroutable private range.

The return path. In routed designs, the upstream router needs a route pointing at your server. Provider networking can also block it: several clouds enable a source and destination check on the instance, which silently drops packets whose source is not the instance's own address until that check is disabled.

DNS fails differently from routing

A packet to a known address and a name lookup are separate failures, and the error messages mislead in opposite directions. If ping 1.1.1.1 works and a browser cannot load anything, the route is fine and name resolution is not. If the ping itself fails, DNS is irrelevant and you are back to the previous section.

wg-quick can set a resolver from the DNS = line in the config, and systemd-resolved has its own per-link behaviour. A VPN that overwrites the resolver with an address reachable only inside the tunnel will fail every lookup the moment the tunnel drops, which looks like the tunnel breaking the internet.

SymptomLayer to inspect
Tunnel address pings, nothing else doesClient route, then gateway forwarding
Public IP pings, hostnames failResolver selection and reachability
Handshake completes, no reply everFORWARD policy or missing NAT on the server
Small requests work, large transfers stallMTU and TCP MSS clamping

An order that produces evidence

Run the client-side check first, because it is one command and it eliminates half the possibilities. Then confirm the server is meant to be an internet exit at all; a gateway built for private access is not broken when public destinations fail.

On the server, watch the interface while you send a ping from the client: tcpdump -ni wg0 icmp should show the request, and tcpdump -ni eth0 icmp should show it leaving, translated or not. If it appears on the first and never on the second, the stop is local to the server. If it leaves and no reply returns, the problem is upstream, and that is a different conversation.

Finally make the fix survive a restart. Forwarding belongs in a sysctl file, firewall rules belong in the service that loads them, and client routes belong in the config that brings the interface up rather than in a shell you will forget. Reconnect, repeat the same two tests, and confirm the counters move.

متعلقہ مضامین