tailscale/wgengine
James Tucker 1b40911611 wgengine/netstack: absorb all quad-100 traffic locally, never leak to peers
Previously, handleLocalPackets intercepted traffic to the Tailscale
service IP (100.100.100.100 / fd7a:115c:a1e0::53) only for an allow-list
of ports: TCP 53/80/8080 and UDP 53. Any other port returned
filter.Accept, letting the packet fall through to the ACL filter and
wireguard-go, which would attempt a peer lookup. No peer owns the
quad-100 AllowedIP, so after ~5s pendopen.go would log:

    open-conn-track: timeout opening ...; no associated peer node

This is the common "conntrack error no peer found for 100.100.100.100:853"
log spam seen in the wild (e.g. from systemd-resolved or another
resolver speculatively trying DoT on quad-100). It also leaks quad-100
packets onto the tailnet.

Remove the port allow-list so handleLocalPackets absorbs every quad-100
packet into netstack regardless of IP protocol or port. Traffic never
reaches the conntrack / peer-routing layers.

With the allow-list gone, acceptTCP needs a corresponding guard: on a
quad-100 TCP port we don't serve, execution used to fall through to the
isTailscaleIP case (quad-100 is in the tailscale IP range), which
rewrote the dial target to 127.0.0.1:<port> and forwardTCP'd the
connection to whatever happened to be listening on the host's loopback
at that port. Add a hittingServiceIP case that RSTs cleanly instead,
placed before the isTailscaleIP fallthrough.

TestQuad100UnservedTCPPortDoesNotForward is a new integration test that
injects a TCP SYN to 100.100.100.100:853 via handleLocalPackets, stubs
forwardDialFunc, and asserts the dialer is not invoked; it catches
regressions of the acceptTCP recursion/loopback-redirection case.

Fixes #15796
Fixes #19421
Updates #3261
Updates #11305

Signed-off-by: James Tucker <james@tailscale.com>
2026-04-24 12:42:16 -07:00
..
bench all: remove AUTHORS file and references to it 2026-01-23 15:49:45 -08:00
filter all: use Go 1.26 things, run most gofix modernizers 2026-03-06 13:32:03 -08:00
magicsock wgengine/magicsock: do not send TSMP disco when connected (#19497) 2026-04-23 12:23:57 -04:00
netlog all: remove AUTHORS file and references to it 2026-01-23 15:49:45 -08:00
netstack wgengine/netstack: absorb all quad-100 traffic locally, never leak to peers 2026-04-24 12:42:16 -07:00
router util/linuxfw,wgengine/router: allow incoming CGNAT range traffic with nodeattr 2026-04-14 16:45:06 -04:00
wgcfg cmd/vet: add subtestnames analyzer; fix all existing violations 2026-04-05 15:52:51 -07:00
wgint all: remove AUTHORS file and references to it 2026-01-23 15:49:45 -08:00
wglog all: remove AUTHORS file and references to it 2026-01-23 15:49:45 -08:00
winnet all: remove AUTHORS file and references to it 2026-01-23 15:49:45 -08:00
mem_ios.go all: remove AUTHORS file and references to it 2026-01-23 15:49:45 -08:00
pendopen_omit.go all: remove AUTHORS file and references to it 2026-01-23 15:49:45 -08:00
pendopen.go all: use bart.Lite instead of bart.Table where appropriate 2026-03-24 14:45:23 +00:00
userspace_ext_test.go all: remove AUTHORS file and references to it 2026-01-23 15:49:45 -08:00
userspace_test.go wgengine: replace reflect.DeepEqual with typed Equal for maybeReconfigInputs (#19365) 2026-04-14 13:16:21 -04:00
userspace.go wgengine: replace reflect.DeepEqual with typed Equal for maybeReconfigInputs (#19365) 2026-04-14 13:16:21 -04:00
watchdog_omit.go all: remove AUTHORS file and references to it 2026-01-23 15:49:45 -08:00
watchdog_test.go cmd/vet: add subtestnames analyzer; fix all existing violations 2026-04-05 15:52:51 -07:00
watchdog.go control/controlclient,ipn/ipnlocal,wgengine: avoid restarting wireguard when key is learned via tsmp (#19142) 2026-03-30 14:26:08 -04:00
wgengine.go all: remove AUTHORS file and references to it 2026-01-23 15:49:45 -08:00