diff --git a/control/controlclient/direct.go b/control/controlclient/direct.go index 30a81c5de..e3ca270e2 100644 --- a/control/controlclient/direct.go +++ b/control/controlclient/direct.go @@ -1302,6 +1302,7 @@ func (ms *mapSession) setControlKnobsFromNodeAttrs(selfNodeAttrs []string) { disableUPnP bool randomizeClientPort bool oneCGNAT opt.Bool + forceBackgroundSTUN bool ) for _, attr := range selfNodeAttrs { switch attr { @@ -1317,6 +1318,8 @@ func (ms *mapSession) setControlKnobsFromNodeAttrs(selfNodeAttrs []string) { oneCGNAT.Set(true) case tailcfg.NodeAttrOneCGNATDisable: oneCGNAT.Set(false) + case tailcfg.NodeAttrDebugForceBackgroundSTUN: + forceBackgroundSTUN = true } } k.KeepFullWGConfig.Store(keepFullWG) @@ -1324,6 +1327,7 @@ func (ms *mapSession) setControlKnobsFromNodeAttrs(selfNodeAttrs []string) { k.DisableUPnP.Store(disableUPnP) k.RandomizeClientPort.Store(randomizeClientPort) k.OneCGNAT.Store(oneCGNAT) + k.ForceBackgroundSTUN.Store(forceBackgroundSTUN) } // ipForwardingBroken reports whether the system's IP forwarding is disabled diff --git a/control/controlknobs/controlknobs.go b/control/controlknobs/controlknobs.go index ead726e90..ace56264c 100644 --- a/control/controlknobs/controlknobs.go +++ b/control/controlknobs/controlknobs.go @@ -34,4 +34,8 @@ type Knobs struct { // OneCGNAT is whether the the node should make one big CGNAT route // in the OS rather than one /32 per peer. OneCGNAT syncs.AtomicValue[opt.Bool] + + // ForceBackgroundSTUN forces netcheck STUN queries to keep + // running in magicsock, even when idle. + ForceBackgroundSTUN atomic.Bool } diff --git a/wgengine/magicsock/magicsock.go b/wgengine/magicsock/magicsock.go index f9244e0fb..ae35cef0d 100644 --- a/wgengine/magicsock/magicsock.go +++ b/wgengine/magicsock/magicsock.go @@ -51,7 +51,6 @@ import ( "tailscale.com/types/logger" "tailscale.com/types/netmap" "tailscale.com/types/nettype" - "tailscale.com/types/views" "tailscale.com/util/clientmetric" "tailscale.com/util/mak" "tailscale.com/util/ringbuffer" @@ -2151,8 +2150,7 @@ func (c *Conn) shouldDoPeriodicReSTUNLocked() bool { c.logf("magicsock: periodicReSTUN: idle for %v", idleFor.Round(time.Second)) } if idleFor > sessionActiveTimeout { - if c.netMap != nil && c.netMap.SelfNode.Valid() && - views.SliceContains(c.netMap.SelfNode.Capabilities(), tailcfg.NodeAttrDebugForceBackgroundSTUN) { + if c.controlKnobs != nil && c.controlKnobs.ForceBackgroundSTUN.Load() { // Overridden by control. return true }