Adding a WireGuard peer for one narrow purpose feels like a small, low-risk change. Monitoring, a mail relay, whatever. Get one setting wrong and it quietly reroutes every other connection on that host into a dead end. Including the SSH session you are using to fix it. This happened for real. It took down two live public services for about 49 minutes, and the cause had nothing to do with what the tunnel was for.
AllowedIPs actually controlsOn a WireGuard peer definition, AllowedIPs looks like it only answers "which destination
addresses does this tunnel carry". It does more. On Linux, wg-quick uses that value to build
real kernel-level policy routing. ip rule entries keyed off an fwmark, forcing matching traffic
through the tunnel's routing table instead of the host's normal one. Set it to a single peer's address, a
/32, and only traffic to that one address is affected. Exactly as expected. Set it to
0.0.0.0/0, ::/0 on a server that is supposed to keep doing everything else it already does, and
you have told the kernel to route all outbound traffic from that host through this one new
tunnel. Its own SSH replies. Its own outbound HTTPS. Everything. That value is a full-tunnel or road-warrior
config, meant for a laptop that should route all its traffic through a VPN.
A new WireGuard tunnel was added to a production server to set up monitoring. It started from a standard full-tunnel client template rather than one scoped to the single monitoring host it needed to reach. Within minutes the server's live public services went unreachable. No ping, no HTTPS, no SSH. Those services had nothing to do with the new tunnel. About 49 minutes of downtime before anyone found the cause.
None of these was the cause. Each looked plausible enough to chase, so here they are, to save you the detour:
Two commands confirmed it directly:
wg show
The new peer's entry had allowed ips: 0.0.0.0/0, ::/0. And the real giveaway, no
latest handshake line at all. Every other healthy tunnel on the box showed one. A peer
with no handshake is a peer that has never connected.
ip rule show
That showed the fwmark-based policy rule from the new tunnel, ranked ahead of the normal routing tables. It was intercepting traffic before the kernel reached the routing table that would have delivered it normally.
wg-quick down <interface> on the bad tunnel. That tears down the policy-routing
rules it created and restores normal connectivity immediately.systemctl disable wg-quick@<interface> so it does not come back on reboot.Verify with real external checks, not "the service looks up in a log somewhere". A real curl or
ping from outside the network. And if anything on the box depends on a separate tunnel you never
touched, confirm that one is still carrying real traffic too, not just reporting healthy.
The fix above is cleanup. The prevention is simpler than it looks. Scope AllowedIPs to
exactly the one address you need to reach, every single time. A /32 for a single peer,
or a /128 for IPv6. Never a broad range on any tunnel whose purpose is "reach this one specific
thing", which is nearly every server-side WireGuard use case. A tunnel done correctly on a similar project
looked like this. The generated client config defaulted to the same dangerous
0.0.0.0/0, ::/0, and got hand-edited down to the single peer address before it was ever
installed. Only that one destination's traffic could be affected, whatever else went wrong with the
tunnel.
Go further, too. Even with AllowedIPs scoped correctly, add a firewall rule on the receiving
end permitting this one peer to reach the one port it needs. Nothing else on the internal network. Then a
mistake in the tunnel config and a mistake in the firewall config both have to happen at once for anything to
go wrong, instead of either one alone being enough.
Address field to
something that does not collide. The lesson is the same as above. A config file generated by someone else's
tooling is a starting point, not something to trust blindly. Open it and read it before you install it. Every
time. Especially the two fields that decide what it can touch, Address and
AllowedIPs.