Emergency default-route failover via phone tether (USB/WiFi) for ifupdown/Debian boxes — project writeup + generic reusable guide
Find a file
Jarvis 0a5498b869 Document Router02 iPhone tether emergency uplink project + generic reusable guide
- README.md: project writeup (why, design, what's deployed, what was
  tested, lessons learned, rollback)
- generic-guide.md: Debian/ifupdown-agnostic reusable pattern for phone-
  tether default-route failover, with gotchas and verification steps
- files/: sanitized config snapshots (wpa_supplicant psk redacted)

Context: ggs netz ag HFC maintenance window 2026-10-07. WiFi tether path
live-tested both directions (connect/disconnect). USB path staged, same
hook logic, not live-tested this session.
2026-10-07 02:10:46 +02:00
files Document Router02 iPhone tether emergency uplink project + generic reusable guide 2026-10-07 02:10:46 +02:00
generic-guide.md Document Router02 iPhone tether emergency uplink project + generic reusable guide 2026-10-07 02:10:46 +02:00
README.md Document Router02 iPhone tether emergency uplink project + generic reusable guide 2026-10-07 02:10:46 +02:00

Router02 — iPhone Tether Emergency Uplink

Status: Live and tested (WiFi path), staged-but-untested (USB path). Deployed 2026-10-07.

Why

PDC's primary uplink (VyOS, PPPoE via ggs netz ag) goes through a scheduled HFC maintenance window. Router02 (Debian 13, PC Engines APU2e4) sits as a transit box between VyOS and the internal network on a dedicated interlink VLAN (enp3s0.1300, 10.10.8.2/31, peer 10.10.8.3). It's positioned to act as a stopgap internet path via an iPhone's Personal Hotspot — either over USB (ipheth) or WiFi — for the duration of any outage.

This is intentionally a temporary, manual-attach path. No HA, no automatic failback beyond what the kernel/dhcp client already gives you, no inbound services. Outbound-only for whatever's behind Router02's internal interfaces.

Design

Two interfaces, same logic, independently:

  • WiFi (wlp4s0 → SSID h@x-P, the iPhone's hotspot name) — live-tested, confirmed working both directions.
  • USB (enxfa10939f8b51, ipheth driver, MAC-stable interface name) — same hooks staged, not yet live-tested (no physical USB connect event during this session).

On interface up (phone connects):

  1. DHCP lease acquired from the phone (WiFi: 172.20.10.0/28 typical iPhone hotspot range; USB: similar via ipheth).
  2. post-up hook installs a persistent static route for internal/PDC address space (10.0.0.0/8) via the original uplink peer (10.10.8.3) — so internal traffic never follows the default route onto the phone, even transiently.
  3. post-up hook removes the existing static default route via 10.10.8.3. DHCP's own default route (installed at a high metric, e.g. 200 vs. the original's 50) becomes the only default — traffic now egresses via the phone.

On interface down (phone disconnects):

  1. pre-down hook explicitly re-asserts default via 10.10.8.3 (belt and suspenders — dhcpcd also removes its own route on interface teardown, but this closes any ordering gap).

No NAT/masquerade rules were added — Router02's existing nftables ruleset already masquerades outbound traffic by egress interface in the general case; this design works within that existing posture rather than building a parallel, interface-specific NAT stack.

No OSPF redistribution. The 10.0.0.0/8 static route and the default route switch are both plain kernel routes, local to Router02, invisible to FRR/OSPF. This was an explicit directive (Mykola, LL network authority) — a route announced into OSPF for a consumer-grade, single-point, phone-dependent uplink is a bad idea; other OSPF speakers shouldn't ever consider routing through it.

What's deployed

  • /etc/network/interfaces — wlp4s0 stanza, post-up/pre-down hooks (see generic-guide.md for the template)
  • /etc/network/interfaces.d/60-iphone-tether — enxfa10939f8b51 stanza, same hook pattern
  • /etc/wpa_supplicant/wpa_supplicant-wlp4s0.conf — scoped to only the iPhone's hotspot SSID (a prior config also matched the regular home WiFi AP at higher priority, which associated by accident during testing — removed, see Lessons below)
  • /etc/resolv.conf — unrelated bug found en route: file had zero nameservers (empty, dhcpcd-generated). Added 1.1.1.1 as a stopgap.

All changes backed up in place with .bak-<timestamp> suffixes before editing. No destructive edits — every change was additive or clearly reversible.

What was tested

# WiFi connect
$ ifup wlp4s0
...
wlp4s0: connected to Access Point: h@x-P
wlp4s0: leased 172.20.10.4 for 3600 seconds

$ ip route show default
default via 172.20.10.1 dev wlp4s0 proto dhcp src 172.20.10.4 metric 3005

$ ping -c2 1.1.1.1    # via phone, 1.1.1.1 ttl 56, ~30ms
$ ping -c2 10.0.2.42  # internal net, still direct, unaffected

# WiFi disconnect
$ ifdown wlp4s0
$ ip route show default
default via 10.10.8.3 dev enp3s0.1300 metric 50   # restored

Both directions confirmed working. Internal traffic was never observed transiting the phone during either state.

USB path has the identical hook logic staged in /etc/network/interfaces.d/60-iphone-tether but was not live-tested — no physical USB connect occurred this session. idevicepair trust was established (idevicepair pair → SUCCESS, idevicepair validate → SUCCESS) so the device trust relationship is ready; only the physical cable-in event remains to verify.

Lessons / gotchas

  • wpa_supplicant SSID priority matters more than you'd think. The tethering-interface's wpa_supplicant config initially had two network blocks: the iPhone hotspot (priority 1) and the regular home WiFi AP (priority 10). wpa_supplicant picked the higher-priority network — the home AP — which is not useless exactly (it's still a working uplink) but defeats the purpose of an iPhone-specific emergency path and silently masks whether the actual target (the phone) is even reachable. Fix: keep the tethering-dedicated wpa_supplicant config scoped to only the emergency SSID.
  • A previous session had already deployed a more complex, OSPF-integrated version of this (udev rule → systemd oneshot service → tether-updown script managing dedicated nftables tables and vtysh ... default-information originate). That stack was dormant (never triggered) but present on disk. It was found via MemPalace search after this session's simpler design was already live — a reminder that mempalace_search before touching infra is not optional, even mid-project, even same-night. The OSPF-originate behavior in that stack directly conflicted with an explicit "don't redistribute this into OSPF" directive given in this session. Removed (moved to /root/removed-stall-files-20261007/ on Router02, not deleted) to leave a single, non-conflicting automation path.
  • /etc/resolv.conf can silently go empty under dhcpcd-managed setups without obviously breaking connectivity (ICMP/raw IP worked fine, DNS quietly didn't). Worth a periodic sanity check independent of this project.

Rollback

To fully remove this setup and return to original state:

# WiFi
mv /etc/network/interfaces.bak-20261007-0157 /etc/network/interfaces
mv /etc/wpa_supplicant/wpa_supplicant-wlp4s0.conf.bak-20261007-0155 \
   /etc/wpa_supplicant/wpa_supplicant-wlp4s0.conf

# USB
mv /etc/network/interfaces.d/60-iphone-tether.bak-20261007-0144 \
   /etc/network/interfaces.d/60-iphone-tether

ifdown wlp4s0 2>/dev/null; ifup wlp4s0

(resolv.conf nameserver addition was left as-is — unrelated fix, not part of rollback scope.)

Generic guide

See generic-guide.md for a reusable, Hx/Router02- agnostic version of this pattern — any Debian-family ifupdown box, any upstream peer IP, any tether source.