vpn: dump wg transfer counters + routes on handshake timeout for diagnosis

This commit is contained in:
Konstantin Passig PC
2026-08-25 17:59:56 +02:00
parent 85ae1fb184
commit 61d2425ed6
+21 -3
View File
@@ -220,7 +220,7 @@ def down(cfg) -> None:
_sudo(["rm", "-rf", f"/etc/netns/{ns}"])
def wait_for_handshake(cfg, timeout: float = 15.0) -> bool:
def wait_for_handshake(cfg, timeout: float = 20.0) -> bool:
import time
deadline = time.monotonic() + timeout
while time.monotonic() < deadline:
@@ -230,6 +230,20 @@ def wait_for_handshake(cfg, timeout: float = 15.0) -> bool:
return has_handshake(cfg)
def _diagnose(cfg) -> str:
"""Collect tunnel state to explain why a handshake isn't happening."""
ns, iface = netns_name(cfg), iface_name(cfg)
parts = []
for title, args in (
("wg", ["ip", "netns", "exec", ns, "wg", "show", iface]),
("routes", ["ip", "netns", "exec", ns, "ip", "route", "show", "default"]),
("rules", ["ip", "netns", "exec", ns, "ip", "rule", "show"]),
):
rc, out = _sudo_out(args)
parts.append(f"--- {title} ---\n{out or '(none)'}")
return "\n".join(parts)
def ensure_up(cfg) -> None:
if has_handshake(cfg):
return
@@ -237,11 +251,15 @@ def ensure_up(cfg) -> None:
down(cfg) # converge from any stale half-configured state
up(cfg)
if not wait_for_handshake(cfg):
log.error("no WireGuard handshake within timeout — tunnel state:\n%s",
_diagnose(cfg))
down(cfg)
raise RuntimeError(
"WireGuard tunnel came up but no handshake was established — "
"check the endpoint/reachability and that the tunnel is actually "
"active. Refusing to download over a dead tunnel."
"see tunnel state above. If 'transfer' shows sent bytes but 0 "
"received, the endpoint is unreachable (try a different Mullvad "
"server); if 0 sent, the namespace has no route out. "
"Refusing to download over a dead tunnel."
)