Files
esh-pfi-infrastructure/persistent-memory.d/2026-09-15-nh3-dev-ts-input-masquerade.md
T
vh 838132cd6b memory: snapshot — FV cross-site routing fixed, fleet conventions pinned
Session captured: the FV outbound-NAT root cause and its diagnostic signature,
the fv-ml1 dead man's switch, fleet identity/group/path conventions and the
root:docker normalization, nh3-dev's ts-input reachability fix, ESPHome
modernisation and the kb KB-search tool, and the Hermes bearer rotation
release. Six new detail files.

Tried-and-abandoned gains three: probing OPNsense endpoints by POSTing at them
(which rebooted the FV firewall), advertising a /32 from nh3-dev, and the
nh3-scale remote-site masquerade rules that fired but were not the fix.

Housekeeping: 8 Recent-decisions entries archived to archival-memory.md, and 21
oversized inline entries split into detail files per the two-tier rule -- they
had been sitting fully inline in the index, which is what the split exists to
prevent. Two pointers to a detail file archived this run were repointed at
archival-memory.md.

The index is 389 lines, still over the ~300 soft cap. The archival guards stop
it there: only 4 further entries are old enough to move and every one carries an
open deferred-work pointer. An over-cap file that keeps live decisions beats a
scannable one that lost a deferred call.
2026-09-15 00:53:48 -07:00

1.7 KiB

[2026-09-15] nh3-dev unreachable from the mesh at its LAN address — ts-input anti-spoof

nh3-dev.nh3.internal (10.100.10.50) failed from a mesh client while every other NH3 host worked. Not DNS, not routing.

Cause

A host that runs Tailscale installs an anti-spoof rule:

-A ts-input -s 100.64.0.0/10 ! -i tailscale0 -j DROP

The fleet's subnet routers run NoSNAT: true with RFC1918 exempted from masquerade — deliberate source preservation, and a departure from Tailscale's own --snat-subnet-routes=true default. So a mesh client's packet reached nh3-dev's ens18 still sourced 100.64.x and died there, silently. Every NH3 host that does not run Tailscale was unaffected, which is what made it look like a name-resolution fault.

Control that settled it: nh3-pve (10.100.250.60) is off-link, needs a gateway hop, and works fine — it has no Tailscale and therefore no ts-input chain.

Fix

One rule on nh3-scale (CT 107), above the RFC1918 RETURNs in /usr/local/sbin/mesh-exit-masq.sh: -d 10.100.10.50/32 -j MASQUERADE. Commit 9dbd829, canonical copy servers/nh3-pve/mesh-exit-masq.sh.

⚠ Do NOT instead advertise the /32 from nh3-dev

Tried the same day and it black-holed nh3-dev from ESH, Anaheim, FV and Irvine while leaving its own LAN and the internet up. ip rule there puts lookup 52 at priority 5270, ahead of main at 32766; becoming a subnet router let table 52 capture cross-site traffic a RouteAll: false node has no accepted route for. ⚠ A one-host check against its own LAN passes cleanly — test all four sites. Same family as the 2026-09-06 accept-routes incident.

Related: 2026-09-15-fv-cross-site-snat