diff --git a/13-inch-thin-cannon/wireguard.nix b/13-inch-thin-cannon/wireguard.nix index 20633f6..0f188f5 100644 --- a/13-inch-thin-cannon/wireguard.nix +++ b/13-inch-thin-cannon/wireguard.nix @@ -7,9 +7,31 @@ wg0 = { ips = ["10.0.0.3/24"]; privateKeyFile = config.age.secrets."wireguard-key-13-inch-thin-cannon".path; + # Route the tunnel's allowed-IPs (0.0.0.0/0, ::/0) through a dedicated + # table so NetworkManager -- which only manages table "main" -- can never + # clobber the default route when the physical link reconnects. fwMark + # tags the WireGuard socket's own packets so they bypass the tunnel and + # egress over the physical link (otherwise the endpoint would loop). + table = "51820"; + fwMark = "0xca6c"; + # The phone tether exposes MTU 1500 but the real cellular path is + # smaller (PMTU black-hole: small packets/DNS/tor cells pass, larger + # TCP flows stall). 1280 is the IPv6 minimum and safe on any path. + mtu = 1280; + # Re-run `wg set` periodically so a fresh handshake is attempted after + # physical link changes / rebuilds (roaming USB-tether environments). + dynamicEndpointRefreshSeconds = 30; + postSetup = '' + ${pkgs.iproute2}/bin/ip rule add to 255.255.255.255/32 table main pref 50 || true + ${pkgs.iproute2}/bin/ip rule add to 224.0.0.0/4 table main pref 51 || true + ${pkgs.iproute2}/bin/ip rule add to ff00::/8 table main pref 52 || true + ${pkgs.iproute2}/bin/ip rule add to fe80::/10 table main pref 53 || true + ${pkgs.iproute2}/bin/ip rule add not fwmark 0xca6c table 51820 pref 100 || true + ${pkgs.iproute2}/bin/ip rule add fwmark 0xca6c table main pref 101 || true + ''; peers = [ { - publicKey = "sn2DwUHXSLYbub6dVFKRhE2QHcji5I8TMSotCTlGFw0"; + publicKey = "sn2DwUHXSLYbub6dVFKRhE2QHcji5I8TMSotCTlGFw0="; allowedIPs = ["0.0.0.0/0" "::/0"]; endpoint = "185.159.158.226:51820"; persistentKeepalive = 25; @@ -17,4 +39,29 @@ ]; }; }; + + # The peer unit only adds the table-51820 routes once at start, and the + # kernel flushes device routes when wg0 goes down (`ip link set wg0 down`), + # so the tunnel default route can silently vanish. Keep it re-added while + # running: a route to a *down* wg0 is still fail-closed (unreachable), and + # it becomes live again the moment wg0 comes back up. + systemd.services.wireguard-wg0-route = { + description = "Keep WireGuard default routes in table 51820"; + after = ["wireguard-wg0.service"]; + wants = ["wireguard-wg0.service"]; + wantedBy = ["multi-user.target"]; + path = [pkgs.iproute2]; + serviceConfig = { + Type = "simple"; + Restart = "always"; + RestartSec = "10"; + }; + script = '' + while true; do + ip route replace 0.0.0.0/0 dev wg0 table 51820 || true + ip route replace ::/0 dev wg0 table 51820 || true + sleep 10 + done + ''; + }; }