Bypass route creation fails on a table that does not exist yet #63

Merged
mysticalsoap merged 1 commit from mysticalsoap/fix/bypass-route-replace into trunk 2026-08-19 13:22:28 -04:00 AGit
Owner

Problem

#61's rule dedup landed, and live retest showed exactly one fwmark rule -- but table 11 still didn't exist and bypassed traffic still left through the tunnel. The remaining blocker sat one line further down: create_cgroup runs ip route flush table 11 before the route add, and modern iproute2 errors out flushing a table that does not exist yet ("FIB table does not exist") -- which is every first bypass setup after boot. The CalledProcessError aborts the block, the route add never runs, and the table is never created. Same modern-iproute2 breakage class as the duplicate-rule refusal, previously masked by it.

Fix

ip route replace instead of flush-and-add, both families. The table only ever holds this single default route (the OpenVPN bypass scripts also just rewrite default), so replace subsumes the flush: it overwrites a stale route regardless of what it pointed at and creates the table when absent, on old and new iproute2 alike. scripts/bypass_up.sh's del-and-add pair gets the same treatment -- its del errors the same way on a route that is not there.

Verification

  • pytest/ruff clean locally; CI runs both
  • Live-verified on an installed branch build (bypass on + VPN up): ip route show table 11 shows the physical default route, and curl icanhazip.com from a shell joined to the bypass cgroup prints the home IP while an unbypassed shell prints the VPN exit -- first end-to-end working bypass on this host

Related fixes: third round of #58's live-test fallout, after #61.

Assisted-by: claude-fable-5

## Problem #61's rule dedup landed, and live retest showed exactly one fwmark rule -- but table 11 still didn't exist and bypassed traffic still left through the tunnel. The remaining blocker sat one line further down: `create_cgroup` runs `ip route flush table 11` before the route add, and modern iproute2 errors out flushing a table that does not exist yet ("FIB table does not exist") -- which is every first bypass setup after boot. The `CalledProcessError` aborts the block, the route add never runs, and the table is never created. Same modern-iproute2 breakage class as the duplicate-rule refusal, previously masked by it. ## Fix `ip route replace` instead of flush-and-add, both families. The table only ever holds this single default route (the OpenVPN bypass scripts also just rewrite `default`), so replace subsumes the flush: it overwrites a stale route regardless of what it pointed at and creates the table when absent, on old and new iproute2 alike. `scripts/bypass_up.sh`'s del-and-add pair gets the same treatment -- its `del` errors the same way on a route that is not there. ## Verification - pytest/ruff clean locally; CI runs both - Live-verified on an installed branch build (bypass on + VPN up): `ip route show table 11` shows the physical default route, and `curl icanhazip.com` from a shell joined to the bypass cgroup prints the home IP while an unbypassed shell prints the VPN exit -- first end-to-end working bypass on this host Related fixes: third round of #58's live-test fallout, after #61. Assisted-by: claude-fable-5
fix: create the bypass route with replace, not flush-and-add
All checks were successful
ci / test (pull_request) Successful in 38s
ci / test (push) Successful in 40s
64d7c8b7db
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Sign in to join this conversation.
No description provided.