Stop WireGuard from blackholing your traffic when the interface flaps
Technical Briefing | 7/25/2026
WireGuard is generally set-and-forget, until your peer link goes down and the kernel routing table decides it knows better than you do. I’ve spent more than one late night staring at a server that was perfectly reachable via SSH but completely unable to resolve a DNS query because the interface marked itself as down and took the static routes with it. It’s a silent failure mode that catches you off guard because the interface doesn’t actually disappear; it just stops carrying traffic while the kernel keeps trying to force packets into a tunnel that’s effectively a black hole.
Why the kernel drops the ball
When you assign an IP to a wg interface, the kernel automatically adds a link-local route. If that peer disconnects, the routing table doesn’t always handle the removal of those routes gracefully during interface state changes. You end up with lingering routes pointing to a dead interface, which is exactly where your packets go to die. Stop relying on default behavior and force the issue by pinning your routes and using persistent keepalives to prevent the state from going stale in the first place.
ip route add 10.0.0.0/24 dev wg0 table main proto static metric 100
- Use persistent keepalives to prevent NAT state timeouts on middleboxes
- Avoid using 0.0.0.0/0 AllowedIPs unless you actually want to route all internet traffic
- Check your table ID to ensure you aren’t fighting other network namespaces
- Set a lower metric on your WireGuard routes to prioritize them over flaky uplinks
If you are running this in a cloud environment, double-check your VPC routes. Cloud providers often override your local routing table via metadata agents, which can lead to a messy conflict where the agent thinks it knows better than your WireGuard config. Keep your routing table tidy, verify your metrics, and you’ll stop chasing ghosts when the tunnel drops.
