Mike O'Driscoll a058d04afb cmd,ipn,util,wgengine: add --exit-node-allow-wan-ports flag for incoming WAN connections
Add a new `tailscale set` flag that allows incoming WAN connections on
specified proto:port pairs to bypass exit node routing. When a node uses
an exit node, reply traffic for externally-initiated connections gets
captured by the exit node's default route, breaking any service the
machine hosts on its public IP but preserving privacy. This flag
installs port-specific conntrack-based firewall rules that marks
replies to matching inbound connections with the Tailscale bypass
fwmark (0x80000), causing them to route through the main table instead
of the exit node tunnel.

Usage: tailscale set --exit-node-allow-wan-ports=tcp:22,tcp:443 --accept-risk=wan-bypass

For each proto:port entry, two firewall rules are created:
- mangle/PREROUTING: tags connections on non-tailscale interfaces for
  the specified destination port with the bypass conntrack mark. Matches
  all connection states (not just NEW) so existing connections get
  tagged when rules are installed after an exit node is activated.
- mangle/OUTPUT: sets the bypass fwmark on ESTABLISHED/RELATED replies
  (matched by source port) so they route via the physical interface

WAN bypass rules are installed before routes in the router's Set()
method to avoid a window where the exit node route is active but no
bypass rules exist, which would drop existing connections.

Implements both iptables and nftables backends. The nftables OUTPUT
rules use a separate chain (ts-wan-bypass) with ChainTypeRoute to
trigger re-routing when the packet mark changes.

Also fixes a pre-existing byte-order bug in the nftables backend where
mark-related helper functions (getTailscaleFwmarkMask, etc.) used
hardcoded big-endian byte arrays instead of native byte order. On
little-endian systems (all x86), the nftables Bitwise expressions
operated on the wrong bits, making the connmark save/restore rules
(rp_filter workaround) silently ineffective. Changed all mark byte
helpers to use binary.NativeEndian.

Updates #10940

Signed-off-by: Mike O'Driscoll <mikeo@tailscale.com>
2026-05-01 16:52:26 +00:00
..