From 203808567790af463ab572d7f93e4bae6c896b21 Mon Sep 17 00:00:00 2001 From: etrobert-bot Date: Thu, 9 Jul 2026 15:22:27 +0200 Subject: [PATCH 1/3] fix(lan): point split-horizon DNS at a second tower address to dodge the router's WiFi filter MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The Vodafone Station drops traffic from WiFi clients to the port-forward target IP (tower, .10) on the forwarded ports (80/443), making every web service unreachable from WiFi. A firmware audit found no setting to lift the filter — but it is keyed to the forward's target IP, not the port: the same services on a second tower address pass fine (verified live from aaron, HTTP 200). - add 192.168.0.11 as a second address on tower's enp11s0 profile - point pi's split-horizon host-records at .11 instead of .10 The port forwards keep targeting .10, so the external path is unchanged. An AAAA/IPv6 approach was tried first and abandoned: the Station advertises no IPv6 default route (and no external v6 exists), and without one macOS/iOS getaddrinfo filters out AAAA answers entirely. Documented in CLAUDE.md. Co-Authored-By: Claude Fable 5 --- CLAUDE.md | 21 +++++++++++++++++---- modules/hosts/tower/configuration.nix | 8 ++++++++ modules/lan-dns.nix | 22 +++++++++++++--------- 3 files changed, 38 insertions(+), 13 deletions(-) diff --git a/CLAUDE.md b/CLAUDE.md index da9ac4bf..a5e4adab 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -113,8 +113,12 @@ the insecure package, the assertion fails and prompts removal. **Home router:** Vodafone Station Arris CGA6444VF (`192.168.0.1`). WAN IP: `91.64.99.245`. No NAT hairpin. DHCP is disabled (pi handles it). Ports 80/443 -are port-forwarded to tower (`.10`). The router **blocks LAN→LAN traffic on -port-forwarded ports** — WiFi clients cannot reach tower:80/443 directly. +are port-forwarded to tower (`.10`). The router **drops traffic from WiFi +clients to the port-forward target IP (`.10`) on the forwarded ports** (80/443). +The filter is keyed to the target IP, not the port — the same services on +tower's second address `.11` pass fine, which is what the split-horizon DNS +exploits. No router setting can change the filter (full firmware audit 2026-07); +wired clients are unaffected. **LAN DHCP + DNS:** served by `pi` via `dnsmasq` (`modules/lan-dns.nix`, listening on `end0`, static `.18`). Pi auto-upgrades from main nightly — test @@ -125,8 +129,17 @@ before merging. `modules/hosts/tower/configuration.nix` — not a pi DHCP reservation). Tower's NM profile uses pi (`.18`) for DNS so split-horizon resolution works on tower too. -**Split-horizon DNS targets:** `test/creatures/files/adele.etiennerobert.com`. -Dnsmasq overrides these to **`192.168.0.10` (tower)**. +**Split-horizon DNS targets:** the eight `*.etiennerobert.com` service names +(see `modules/lan-dns.nix`). Dnsmasq overrides these to **`192.168.0.11`** — +tower's second address, which dodges the router's WiFi filter (above). The port +forwards must keep targeting `.10`; if they're ever changed to `.11` the filter +moves with them. + +**IPv6 is not usable for LAN services:** the Station advertises SLAAC prefixes +(clients get GUAs) but no default route (router lifetime 0) and there is no +external IPv6 connectivity. Without a v6 default route, macOS/iOS getaddrinfo +filters out AAAA answers entirely, so AAAA-based split horizon does not work for +Apple clients even though on-link IPv6 traffic flows fine. **Testing the public/external path:** LAN clients resolve these names to tower directly (split-horizon) and bypass the port-forward, so they can't exercise the diff --git a/modules/hosts/tower/configuration.nix b/modules/hosts/tower/configuration.nix index 27423212..49572166 100644 --- a/modules/hosts/tower/configuration.nix +++ b/modules/hosts/tower/configuration.nix @@ -39,6 +39,14 @@ ipv4 = { method = "manual"; address1 = "192.168.0.10/24,192.168.0.1"; + + # Second address for LAN clients (published by pi's split-horizon + # DNS): the Vodafone Station drops LAN-side traffic from WiFi clients + # to .10 on the port-forwarded ports (80/443), but the filter is keyed + # to the forward's target IP, so the same services on .11 pass. Keep + # the port forwards themselves pointing at .10. + address2 = "192.168.0.11/24"; + dns = "192.168.0.18;"; }; }; diff --git a/modules/lan-dns.nix b/modules/lan-dns.nix index b12eb43f..b3e45dce 100644 --- a/modules/lan-dns.nix +++ b/modules/lan-dns.nix @@ -22,15 +22,19 @@ _: { "1.1.1.1" "9.9.9.9" ]; - host-record = [ - "test.etiennerobert.com,192.168.0.10" - "creatures.etiennerobert.com,192.168.0.10" - "files.etiennerobert.com,192.168.0.10" - "adele.etiennerobert.com,192.168.0.10" - "umami.etiennerobert.com,192.168.0.10" - "images.etiennerobert.com,192.168.0.10" - "rift.etiennerobert.com,192.168.0.10" - "rack.etiennerobert.com,192.168.0.10" + # .11 is tower's second address, required for WiFi clients: the + # Vodafone Station drops LAN-side traffic from its WLAN to the + # port-forward target (.10) on the forwarded ports (80/443), but + # the filter is keyed to that target IP, so .11 passes. + host-record = map (name: "${name}.etiennerobert.com,192.168.0.11") [ + "test" + "creatures" + "files" + "adele" + "umami" + "images" + "rift" + "rack" ]; dhcp-range = "192.168.0.50,192.168.0.250,12h"; dhcp-option = [ "option:router,192.168.0.1" ]; From f4b35072fdfd3f2c38becdc254c1af124985be05 Mon Sep 17 00:00:00 2001 From: etrobert-bot Date: Thu, 9 Jul 2026 15:55:32 +0200 Subject: [PATCH 2/3] docs(claude): condense router wifi filter details and split-horizon dns notes --- CLAUDE.md | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/CLAUDE.md b/CLAUDE.md index a5e4adab..db6439ad 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -113,12 +113,7 @@ the insecure package, the assertion fails and prompts removal. **Home router:** Vodafone Station Arris CGA6444VF (`192.168.0.1`). WAN IP: `91.64.99.245`. No NAT hairpin. DHCP is disabled (pi handles it). Ports 80/443 -are port-forwarded to tower (`.10`). The router **drops traffic from WiFi -clients to the port-forward target IP (`.10`) on the forwarded ports** (80/443). -The filter is keyed to the target IP, not the port — the same services on -tower's second address `.11` pass fine, which is what the split-horizon DNS -exploits. No router setting can change the filter (full firmware audit 2026-07); -wired clients are unaffected. +are port-forwarded to tower (`.10`). **LAN DHCP + DNS:** served by `pi` via `dnsmasq` (`modules/lan-dns.nix`, listening on `end0`, static `.18`). Pi auto-upgrades from main nightly — test @@ -129,12 +124,6 @@ before merging. `modules/hosts/tower/configuration.nix` — not a pi DHCP reservation). Tower's NM profile uses pi (`.18`) for DNS so split-horizon resolution works on tower too. -**Split-horizon DNS targets:** the eight `*.etiennerobert.com` service names -(see `modules/lan-dns.nix`). Dnsmasq overrides these to **`192.168.0.11`** — -tower's second address, which dodges the router's WiFi filter (above). The port -forwards must keep targeting `.10`; if they're ever changed to `.11` the filter -moves with them. - **IPv6 is not usable for LAN services:** the Station advertises SLAAC prefixes (clients get GUAs) but no default route (router lifetime 0) and there is no external IPv6 connectivity. Without a v6 default route, macOS/iOS getaddrinfo From 2c83fc5795acbf0bb4a1b467626d363f1fdacfe8 Mon Sep 17 00:00:00 2001 From: etrobert-bot Date: Thu, 9 Jul 2026 15:55:57 +0200 Subject: [PATCH 3/3] docs(claude): remove ipv6 split-horizon notes about apple client limitations --- CLAUDE.md | 6 ------ 1 file changed, 6 deletions(-) diff --git a/CLAUDE.md b/CLAUDE.md index db6439ad..020a74b6 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -124,12 +124,6 @@ before merging. `modules/hosts/tower/configuration.nix` — not a pi DHCP reservation). Tower's NM profile uses pi (`.18`) for DNS so split-horizon resolution works on tower too. -**IPv6 is not usable for LAN services:** the Station advertises SLAAC prefixes -(clients get GUAs) but no default route (router lifetime 0) and there is no -external IPv6 connectivity. Without a v6 default route, macOS/iOS getaddrinfo -filters out AAAA answers entirely, so AAAA-based split horizon does not work for -Apple clients even though on-link IPv6 traffic flows fine. - **Testing the public/external path:** LAN clients resolve these names to tower directly (split-horizon) and bypass the port-forward, so they can't exercise the real external path. To test as an outside visitor would (public DNS →