From 21cfa2a47cfce3627f1957de78a7ebf880df50bc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Claus=20Lensb=C3=B8l?= Date: Fri, 3 Oct 2025 13:59:13 -0400 Subject: [PATCH] wgengine/router: pull out interface method only needed in Linux MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Instead of having userspace do the call into the router, just let the router pick up the change itself. Updates #15160 Signed-off-by: Claus Lensbøl --- wgengine/magicsock/magicsock.go | 4 +++- wgengine/router/callback.go | 7 ------- wgengine/router/osrouter/router_linux.go | 11 +++++++++-- wgengine/router/osrouter/router_openbsd.go | 7 ------- wgengine/router/osrouter/router_plan9.go | 7 ------- wgengine/router/osrouter/router_userspace_bsd.go | 7 ------- wgengine/router/osrouter/router_windows.go | 7 ------- wgengine/router/router.go | 8 -------- wgengine/router/router_fake.go | 5 ----- wgengine/userspace.go | 6 ------ 10 files changed, 12 insertions(+), 57 deletions(-) diff --git a/wgengine/magicsock/magicsock.go b/wgengine/magicsock/magicsock.go index bf5c4240a..384f310a0 100644 --- a/wgengine/magicsock/magicsock.go +++ b/wgengine/magicsock/magicsock.go @@ -3464,7 +3464,9 @@ func (c *Conn) listenPacket(network string, port uint16) (nettype.PacketConn, er return nettype.MakePacketListenerWithNetIP(netns.Listener(c.logf, c.netMon)).ListenPacket(ctx, network, addr) } -// PortUpdate is an eventbus value, reporting the port and address family of a magicsock connection. +// PortUpdate is an eventbus value, reporting the port and address family +// magicsock is currently listening on, so it can be threaded through firewalls +// and such. type PortUpdate struct { UDPPort uint16 EndpointNetwork string // either "udp4" or "udp6". diff --git a/wgengine/router/callback.go b/wgengine/router/callback.go index 1d9091277..c1838539b 100644 --- a/wgengine/router/callback.go +++ b/wgengine/router/callback.go @@ -56,13 +56,6 @@ func (r *CallbackRouter) Set(rcfg *Config) error { return r.SetBoth(r.rcfg, r.dcfg) } -// UpdateMagicsockPort implements the Router interface. This implementation -// does nothing and returns nil because this router does not currently need -// to know what the magicsock UDP port is. -func (r *CallbackRouter) UpdateMagicsockPort(_ uint16, _ string) error { - return nil -} - // SetDNS implements dns.OSConfigurator. func (r *CallbackRouter) SetDNS(dcfg dns.OSConfig) error { r.mu.Lock() diff --git a/wgengine/router/osrouter/router_linux.go b/wgengine/router/osrouter/router_linux.go index 47a1d8246..183aa70ec 100644 --- a/wgengine/router/osrouter/router_linux.go +++ b/wgengine/router/osrouter/router_linux.go @@ -34,6 +34,7 @@ import ( "tailscale.com/util/eventbus" "tailscale.com/util/linuxfw" "tailscale.com/version/distro" + "tailscale.com/wgengine/magicsock" "tailscale.com/wgengine/router" ) @@ -171,6 +172,7 @@ func newUserspaceRouterAdvanced(logf logger.Logf, tunname string, netMon *netmon // [eventbus.Client] is closed. func (r *linuxRouter) consumeEventbusTopics(ec *eventbus.Client) func(*eventbus.Client) { ruleDeletedSub := eventbus.Subscribe[netmon.RuleDeleted](ec) + portUpdateSub := eventbus.Subscribe[magicsock.PortUpdate](ec) return func(ec *eventbus.Client) { for { select { @@ -178,6 +180,11 @@ func (r *linuxRouter) consumeEventbusTopics(ec *eventbus.Client) func(*eventbus. return case rs := <-ruleDeletedSub.Events(): r.onIPRuleDeleted(rs.Table, rs.Priority) + case pu := <-portUpdateSub.Events(): + r.logf("portUpdate(port=%v, network=%s)", pu.UDPPort, pu.EndpointNetwork) + if err := r.updateMagicsockPort(pu.UDPPort, pu.EndpointNetwork); err != nil { + r.logf("updateMagicsockPort(port=%v, network=%s) failed: %v", pu.UDPPort, pu.EndpointNetwork, err) + } } } } @@ -540,8 +547,8 @@ func (r *linuxRouter) updateStatefulFilteringWithDockerWarning(cfg *router.Confi r.health.SetHealthy(dockerStatefulFilteringWarnable) } -// UpdateMagicsockPort implements the Router interface. -func (r *linuxRouter) UpdateMagicsockPort(port uint16, network string) error { +// updateMagicsockPort implements the Router interface. +func (r *linuxRouter) updateMagicsockPort(port uint16, network string) error { r.mu.Lock() defer r.mu.Unlock() if r.nfr == nil { diff --git a/wgengine/router/osrouter/router_openbsd.go b/wgengine/router/osrouter/router_openbsd.go index 8f3599309..55b485f0e 100644 --- a/wgengine/router/osrouter/router_openbsd.go +++ b/wgengine/router/osrouter/router_openbsd.go @@ -238,13 +238,6 @@ func (r *openbsdRouter) Set(cfg *router.Config) error { return errq } -// UpdateMagicsockPort implements the Router interface. This implementation -// does nothing and returns nil because this router does not currently need -// to know what the magicsock UDP port is. -func (r *openbsdRouter) UpdateMagicsockPort(_ uint16, _ string) error { - return nil -} - func (r *openbsdRouter) Close() error { cleanUp(r.logf, r.tunname) return nil diff --git a/wgengine/router/osrouter/router_plan9.go b/wgengine/router/osrouter/router_plan9.go index 5872aa7fc..a5b461a6f 100644 --- a/wgengine/router/osrouter/router_plan9.go +++ b/wgengine/router/osrouter/router_plan9.go @@ -115,13 +115,6 @@ func (r *plan9Router) Set(cfg *router.Config) error { return nil } -// UpdateMagicsockPort implements the Router interface. This implementation -// does nothing and returns nil because this router does not currently need -// to know what the magicsock UDP port is. -func (r *plan9Router) UpdateMagicsockPort(_ uint16, _ string) error { - return nil -} - func (r *plan9Router) Close() error { // TODO(bradfitz): unbind return nil diff --git a/wgengine/router/osrouter/router_userspace_bsd.go b/wgengine/router/osrouter/router_userspace_bsd.go index cdaf3adea..70ef2b6bf 100644 --- a/wgengine/router/osrouter/router_userspace_bsd.go +++ b/wgengine/router/osrouter/router_userspace_bsd.go @@ -206,13 +206,6 @@ func (r *userspaceBSDRouter) Set(cfg *router.Config) (reterr error) { return reterr } -// UpdateMagicsockPort implements the Router interface. This implementation -// does nothing and returns nil because this router does not currently need -// to know what the magicsock UDP port is. -func (r *userspaceBSDRouter) UpdateMagicsockPort(_ uint16, _ string) error { - return nil -} - func (r *userspaceBSDRouter) Close() error { return nil } diff --git a/wgengine/router/osrouter/router_windows.go b/wgengine/router/osrouter/router_windows.go index 05bf210e8..a1acbe3b6 100644 --- a/wgengine/router/osrouter/router_windows.go +++ b/wgengine/router/osrouter/router_windows.go @@ -114,13 +114,6 @@ func hasDefaultRoute(routes []netip.Prefix) bool { return false } -// UpdateMagicsockPort implements the Router interface. This implementation -// does nothing and returns nil because this router does not currently need -// to know what the magicsock UDP port is. -func (r *winRouter) UpdateMagicsockPort(_ uint16, _ string) error { - return nil -} - func (r *winRouter) Close() error { r.firewall.clear() diff --git a/wgengine/router/router.go b/wgengine/router/router.go index 7723138f4..0883fbc2f 100644 --- a/wgengine/router/router.go +++ b/wgengine/router/router.go @@ -34,14 +34,6 @@ type Router interface { // implementation should handle gracefully. Set(*Config) error - // UpdateMagicsockPort tells the OS network stack what port magicsock - // is currently listening on, so it can be threaded through firewalls - // and such. This is distinct from Set() since magicsock may rebind - // ports independently from the Config changing. - // - // network should be either "udp4" or "udp6". - UpdateMagicsockPort(port uint16, network string) error - // Close closes the router. Close() error } diff --git a/wgengine/router/router_fake.go b/wgengine/router/router_fake.go index 549867eca..db35fc9ee 100644 --- a/wgengine/router/router_fake.go +++ b/wgengine/router/router_fake.go @@ -27,11 +27,6 @@ func (r fakeRouter) Set(cfg *Config) error { return nil } -func (r fakeRouter) UpdateMagicsockPort(_ uint16, _ string) error { - r.logf("[v1] warning: fakeRouter.UpdateMagicsockPort: not implemented.") - return nil -} - func (r fakeRouter) Close() error { r.logf("[v1] warning: fakeRouter.Close: not implemented.") return nil diff --git a/wgengine/userspace.go b/wgengine/userspace.go index 8730abe1d..edabd532d 100644 --- a/wgengine/userspace.go +++ b/wgengine/userspace.go @@ -549,7 +549,6 @@ func NewUserspaceEngine(logf logger.Logf, conf Config) (_ Engine, reterr error) // [eventbus.Client] is closed. func (e *userspaceEngine) consumeEventbusTopics(cli *eventbus.Client) func(*eventbus.Client) { changeDeltaSub := eventbus.Subscribe[netmon.ChangeDelta](cli) - portUpdateSub := eventbus.Subscribe[magicsock.PortUpdate](cli) return func(cli *eventbus.Client) { for { select { @@ -560,11 +559,6 @@ func (e *userspaceEngine) consumeEventbusTopics(cli *eventbus.Client) func(*even f() } e.linkChange(&changeDelta) - case pu := <-portUpdateSub.Events(): - e.logf("portUpdate(port=%v, network=%s)", pu.UDPPort, pu.EndpointNetwork) - if err := e.router.UpdateMagicsockPort(pu.UDPPort, pu.EndpointNetwork); err != nil { - e.logf("UpdateMagicsockPort(port=%v, network=%s) failed: %v", pu.UDPPort, pu.EndpointNetwork, err) - } } } }