v1.0.20
v1.0.20 — IPv6 enablement + 4.9 reconcile + watchdog fixes
The kill switch now blocks IPv6 leaks alongside IPv4, the masquerade fixes cover both families, and the plugin now closes a silent IPv6 failure mode that hit pre-4.9 fw3 routers acting as Tailscale exit nodes.
IPv6
- Kill switch covers IPv6. Both
iif br-lanandiif br-guestrules at priority 5280 install for IPv4 AND IPv6, withunreachable defaultin table 100 for both families. Verified zero leak ontailscaleddeath on AXT1800 4.8.4 fw4 and MT3000 4.9.0 fw3. masq6on tailscale0. Without IPv6 masquerade on the Tailscale zone, forwarded LAN/guest IPv6 enters the exit-node tunnel with an unrecognized Tailscale ULA source and gets dropped. Now set automatically alongside the existingmasq(IPv4).- Exit-node-server IPv6 SNAT backstop. When advertising as a Tailscale exit node on pre-4.9 firmware, the plugin now ensures
wan.masq6=1as a defense-in-depth safety net. Tailscale's ownts-postroutingIPv6 chain is empty on iptables-based firmware (verified empirically — likely a Tailscale-side iptables-backend gap), so IPv6 egress for tailnet clients using this router as an exit node depends entirely on GL'swan.masq6setting. GL generally sets this on its own; the plugin guarantees it in case GL's defaults vary by model or firmware variant. A sidecar UCI flag (wan_masq6_set_by_plugin) tracks ownership so teardown only undoes what we set — user or GL-set values are never trampled. On firmware 4.9+ the plugin defers entirely; GL owns this surface. - Status reporting fixed.
get_config'skill_switch_fw_activeandmasquerade_activenow report true only when BOTH families are configured — a torn install no longer falsely reports full protection.
Robustness
- Watchdog idempotent teardown. The Tailscale-disabled check now fires on any poll where TS is off AND KS rules are still installed, replacing the prior transition-based check. Catches the fast 1→0→1 sequence (TS disabled and re-enabled inside the same 5-second poll window) that the old logic silently missed, leaving the KS rules orphaned. Verified empirically on AXT1800 4.8.3 2026-04-25.
- GL 4.9 Custom Exit Node reconcile. When firmware 4.9 sets
tailscale.settings.exit_node_ipbut the daemon'sExitNodeIDis still empty (table 52 has no default route, traffic exits the WAN), the plugin now runstailscale set --exit-node=<ip>to reconcile. Gated by a value-snapshot (last_seen_exit_node_ip): only fires when the watched value actually changes since the previous reapply, so unrelated GL UCI commits don't trigger a wrong reconcile on a stale exit-node IP. - Masquerade deferral on 4.9+. GL firmware 4.9 owns the IP Masquerading toggle natively under the Tailscale page's NAT section. The plugin no longer fights GL's setting on 4.9+ —
ensure_masquerade()is gated on pre-4.9, andpkg/prermskips deletingtailscale0.masq/masq6on 4.9+ so we don't trample GL's state during uninstall.
Minor
- Cache-busting on the injected JS. The body filter now stamps
?v=<version>on the<script>tag URL so browsers re-fetchts-fix.jsafter a plugin upgrade. Removes the "stale version badge until a hard refresh" annoyance.
Known limitation on firmware 4.9+
On 4.9+ the plugin no longer overrides GL's masquerade settings. If you have both IP Masquerading and Allow Remote Access LAN turned off on the Tailscale page, GL may leave the tailscale0 zone without IPv6 masquerade, in which case LAN-side IPv6 will not traverse the exit-node tunnel. Enable either setting and IPv6 works. The kill switch still protects on 4.9 regardless of masquerade state.
Closes
- #11 (j0hnsmith) — IPv6 kill switch
Full Changelog: v1.0.19...v1.0.20