summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorDylan Bargatze <dylan@tailscale.com>2025-07-09 18:06:58 -0400
committerGitHub <noreply@github.com>2025-07-09 18:06:58 -0400
commitd40b25326ccdb111ce4e99893164dd6742328a52 (patch)
treeb8e8e63e8d0789e85ede62afa077e938a61c90a9
parentff1803158a60c37128557f40c643f3839bc5609a (diff)
downloadtailscale-d40b25326ccdb111ce4e99893164dd6742328a52.tar.xz
tailscale-d40b25326ccdb111ce4e99893164dd6742328a52.zip
tailcfg, wgengine/magicsock: disable all UDP relay usage if disable-relay-client is set (#16492)
If the NodeAttrDisableRelayClient node attribute is set, ensures that a node cannot allocate endpoints on a UDP relay server itself, and cannot use newly-discovered paths (via disco/CallMeMaybeVia) that traverse a UDP relay server. Fixes tailscale/corp#30180 Signed-off-by: Dylan Bargatze <dylan@tailscale.com>
-rw-r--r--tailcfg/tailcfg.go18
-rw-r--r--wgengine/magicsock/magicsock.go10
2 files changed, 19 insertions, 9 deletions
diff --git a/tailcfg/tailcfg.go b/tailcfg/tailcfg.go
index d97f60a8a..6c88217de 100644
--- a/tailcfg/tailcfg.go
+++ b/tailcfg/tailcfg.go
@@ -2607,14 +2607,16 @@ const (
// only needs to be present in [NodeCapMap] to take effect.
NodeAttrDisableRelayServer NodeCapability = "disable-relay-server"
- // NodeAttrDisableRelayClient prevents the node from allocating UDP relay
- // server endpoints itself; the node may still bind into and relay traffic
- // using endpoints allocated by its peers. This attribute can be added to
- // the node dynamically; if added while the node is already running, the
- // node will be unable to allocate UDP relay server endpoints after it next
- // updates its network map. There are no expected values for this key in
- // [NodeCapMap]; the key only needs to be present in [NodeCapMap] to take
- // effect.
+ // NodeAttrDisableRelayClient prevents the node from both allocating UDP
+ // relay server endpoints itself, and from using endpoints allocated by
+ // its peers. This attribute can be added to the node dynamically; if added
+ // while the node is already running, the node will be unable to allocate
+ // endpoints after it next updates its network map, and will be immediately
+ // unable to use new paths via a UDP relay server. Setting this attribute
+ // dynamically does not remove any existing paths, including paths that
+ // traverse a UDP relay server. There are no expected values for this key
+ // in [NodeCapMap]; the key only needs to be present in [NodeCapMap] to
+ // take effect.
NodeAttrDisableRelayClient NodeCapability = "disable-relay-client"
// NodeAttrMagicDNSPeerAAAA is a capability that tells the node's MagicDNS
diff --git a/wgengine/magicsock/magicsock.go b/wgengine/magicsock/magicsock.go
index 1978867fa..582e74c8b 100644
--- a/wgengine/magicsock/magicsock.go
+++ b/wgengine/magicsock/magicsock.go
@@ -355,7 +355,7 @@ type Conn struct {
self tailcfg.NodeView // from last onNodeViewsUpdate
peers views.Slice[tailcfg.NodeView] // from last onNodeViewsUpdate, sorted by Node.ID; Note: [netmap.NodeMutation]'s rx'd in onNodeMutationsUpdate are never applied
filt *filter.Filter // from last onFilterUpdate
- relayClientEnabled bool // whether we can allocate UDP relay endpoints on UDP relay servers
+ relayClientEnabled bool // whether we can allocate UDP relay endpoints on UDP relay servers or receive CallMeMaybeVia messages from peers
lastFlags debugFlags // at time of last onNodeViewsUpdate
privateKey key.NodePrivate // WireGuard private key for this node
everHadKey bool // whether we ever had a non-zero private key
@@ -2149,6 +2149,14 @@ func (c *Conn) handleDiscoMessage(msg []byte, src epAddr, shouldBeRelayHandshake
c.logf("magicsock: disco: ignoring %s from %v; %v is unknown", msgType, sender.ShortString(), derpNodeSrc.ShortString())
return
}
+ // If the "disable-relay-client" node attr is set for this node, it
+ // can't be a UDP relay client, so drop any CallMeMaybeVia messages it
+ // receives.
+ if isVia && !c.relayClientEnabled {
+ c.logf("magicsock: disco: ignoring %s from %v; disable-relay-client node attr is set", msgType, sender.ShortString())
+ return
+ }
+
ep.mu.Lock()
relayCapable := ep.relayCapable
lastBest := ep.bestAddr