#!/bin/sh # Masquerade mesh clients' INTERNET-bound (exit-node) traffic only; preserve site-to-site source. iptables -t nat -F MESH-EXIT 2>/dev/null || iptables -t nat -N MESH-EXIT # ── Mesh-member hosts on this routed subnet — MUST come before the RFC1918 RETURNs ── # A host that runs Tailscale itself installs an anti-spoof rule: # -A ts-input -s 100.64.0.0/10 ! -i tailscale0 -j DROP # With source preservation, a mesh client's packet reaches that host's ETHERNET # interface still carrying its 100.64.x source, and is dropped there — silently, # before anything can answer. Hosts that do NOT run Tailscale are unaffected, # which is why every other NH3 address worked and only this one did not. # Masquerading just these destinations makes them behave like every other host # while leaving source preservation absolute for the rest of the subnet. # (2026-09-14. Tailscale's own default is --snat-subnet-routes=true, i.e. SNAT # everything; this file is the deliberate departure from that, so the exception # belongs here rather than as a reason to abandon the design.) # # ⚠ Do NOT "fix" this instead by advertising the host's /32 from the host # itself. That was tried on nh3-dev 2026-09-14 and black-holed it from ESH, # Anaheim, FV and Irvine — `ip rule` there puts `lookup 52` at priority 5270, # ahead of main at 32766, and becoming a subnet router let table 52 capture # cross-site traffic the node had no accepted route for. Its own LAN and the # internet kept working, so a narrow check looks clean. Fix it at the router. iptables -t nat -A MESH-EXIT -d 10.100.10.50/32 -j MASQUERADE # nh3-dev iptables -t nat -A MESH-EXIT -d 10.0.0.0/8 -j RETURN iptables -t nat -A MESH-EXIT -d 172.16.0.0/12 -j RETURN iptables -t nat -A MESH-EXIT -d 192.168.0.0/16 -j RETURN iptables -t nat -A MESH-EXIT -d 100.64.0.0/10 -j RETURN iptables -t nat -A MESH-EXIT -j MASQUERADE iptables -t nat -C POSTROUTING -s 100.64.0.0/10 -o eth0 -j MESH-EXIT 2>/dev/null \ || iptables -t nat -A POSTROUTING -s 100.64.0.0/10 -o eth0 -j MESH-EXIT # ── Remote-SITE sources, not just mesh clients ──────────────────────────────── # The jump above matches only 100.64.0.0/10, so traffic from another site's LAN # arriving over the mesh never enters MESH-EXIT and keeps its original source. # An NH3 host then replies via its own LAN router instead of back through this # node, the path is asymmetric, and the reply is lost. Measured 2026-09-15: # fv-ml1 reached 100.64.0.1 and 100.64.0.4 fine while 10.100.50.40 failed # outright, and the FV firewall log showed the outbound passing with # src=10.251.50.54 and nothing ever coming back. # # Masquerading remote-site sources onto this node's LAN address makes the reply # return here, where the conntrack state lives. It costs source visibility for # cross-site traffic on the NH3 LAN — the same trade as the nh3-dev rule above, # and the alternative is no connectivity at all. # # ⚠ Sites are listed explicitly rather than using 10.0.0.0/8: a blanket rule # would also masquerade NH3-local traffic that has no business being rewritten. for site_net in 10.251.0.0/16 10.0.0.0/16 10.250.0.0/16 10.6.110.0/24; do iptables -t nat -C POSTROUTING -s "$site_net" -o eth0 -j MASQUERADE 2>/dev/null \ || iptables -t nat -A POSTROUTING -s "$site_net" -o eth0 -j MASQUERADE done