diff --git a/feature/relayserver/relayserver.go b/feature/relayserver/relayserver.go index 5a82a9d11..f4a533193 100644 --- a/feature/relayserver/relayserver.go +++ b/feature/relayserver/relayserver.go @@ -50,11 +50,11 @@ func newExtension(logf logger.Logf, _ ipnext.SafeBackend) (ipnext.Extension, err type extension struct { logf logger.Logf - mu sync.Mutex // guards the following fields - shutdown bool - port *int // ipn.Prefs.RelayServerPort, nil if disabled - hasNodeAttrRelayServer bool // tailcfg.NodeAttrRelayServer - server relayServer // lazily initialized + mu sync.Mutex // guards the following fields + shutdown bool + port *int // ipn.Prefs.RelayServerPort, nil if disabled + hasNodeAttrDisableRelayServer bool // tailcfg.NodeAttrDisableRelayServer + server relayServer // lazily initialized } // relayServer is the interface of [udprelay.Server]. @@ -81,8 +81,8 @@ func (e *extension) Init(host ipnext.Host) error { func (e *extension) selfNodeViewChanged(nodeView tailcfg.NodeView) { e.mu.Lock() defer e.mu.Unlock() - e.hasNodeAttrRelayServer = nodeView.HasCap(tailcfg.NodeAttrRelayServer) - if !e.hasNodeAttrRelayServer && e.server != nil { + e.hasNodeAttrDisableRelayServer = nodeView.HasCap(tailcfg.NodeAttrDisableRelayServer) + if e.hasNodeAttrDisableRelayServer && e.server != nil { e.server.Close() e.server = nil } @@ -130,8 +130,8 @@ func (e *extension) relayServerOrInit() (relayServer, error) { if e.port == nil { return nil, errors.New("relay server is not configured") } - if !e.hasNodeAttrRelayServer { - return nil, errors.New("no relay:server node attribute") + if e.hasNodeAttrDisableRelayServer { + return nil, errors.New("disable-relay-server node attribute is present") } if !envknob.UseWIPCode() { return nil, errors.New("TAILSCALE_USE_WIP_CODE envvar is not set") diff --git a/tailcfg/tailcfg.go b/tailcfg/tailcfg.go index 10b157ac1..d97f60a8a 100644 --- a/tailcfg/tailcfg.go +++ b/tailcfg/tailcfg.go @@ -2602,13 +2602,20 @@ const ( // peer node list. NodeAttrNativeIPV4 NodeCapability = "native-ipv4" - // NodeAttrRelayServer permits the node to act as an underlay UDP relay - // server. There are no expected values for this key in NodeCapMap. - NodeAttrRelayServer NodeCapability = "relay:server" + // NodeAttrDisableRelayServer prevents the node from acting as an underlay + // UDP relay server. There are no expected values for this key; the key + // only needs to be present in [NodeCapMap] to take effect. + NodeAttrDisableRelayServer NodeCapability = "disable-relay-server" - // NodeAttrRelayClient permits the node to act as an underlay UDP relay - // client. There are no expected values for this key in NodeCapMap. - NodeAttrRelayClient NodeCapability = "relay:client" + // 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 NodeCapability = "disable-relay-client" // NodeAttrMagicDNSPeerAAAA is a capability that tells the node's MagicDNS // server to answer AAAA queries about its peers. See tailscale/tailscale#1152. diff --git a/wgengine/magicsock/magicsock.go b/wgengine/magicsock/magicsock.go index 174345a84..5719b20f9 100644 --- a/wgengine/magicsock/magicsock.go +++ b/wgengine/magicsock/magicsock.go @@ -2703,7 +2703,7 @@ func (c *Conn) onNodeViewsUpdate(update NodeViewsUpdate) { peersChanged := c.updateNodes(update) relayClientEnabled := update.SelfNode.Valid() && - update.SelfNode.HasCap(tailcfg.NodeAttrRelayClient) && + !update.SelfNode.HasCap(tailcfg.NodeAttrDisableRelayClient) && envknob.UseWIPCode() c.mu.Lock() diff --git a/wgengine/magicsock/magicsock_test.go b/wgengine/magicsock/magicsock_test.go index 8aa9a09d2..c388e9ed1 100644 --- a/wgengine/magicsock/magicsock_test.go +++ b/wgengine/magicsock/magicsock_test.go @@ -3408,9 +3408,6 @@ func Test_peerAPIIfCandidateRelayServer(t *testing.T) { } peerOnlyIPv4 := &tailcfg.Node{ Cap: math.MinInt32, - CapMap: map[tailcfg.NodeCapability][]tailcfg.RawMessage{ - tailcfg.NodeAttrRelayServer: nil, - }, Addresses: []netip.Prefix{ netip.MustParsePrefix("2.2.2.2/32"), },