From 3624d72e75089b6f48178bd341dffdf8759b7132 Mon Sep 17 00:00:00 2001 From: Jordan Whited Date: Wed, 6 Aug 2025 15:29:45 -0700 Subject: [PATCH] wgengine/magicsock: disable Peer Relay if CryptoRouting is disabled Updates tailscale/corp#31083 Signed-off-by: Jordan Whited --- wgengine/magicsock/magicsock.go | 4 ++++ wgengine/magicsock/magicsock_test.go | 22 ++++++++++++++++++++++ 2 files changed, 26 insertions(+) diff --git a/wgengine/magicsock/magicsock.go b/wgengine/magicsock/magicsock.go index a4ba090ef..e714f895a 100644 --- a/wgengine/magicsock/magicsock.go +++ b/wgengine/magicsock/magicsock.go @@ -2982,6 +2982,10 @@ func (c *Conn) onNodeViewsUpdate(update NodeViewsUpdate) { peersChanged := c.updateNodes(update) relayClientEnabled := update.SelfNode.Valid() && + // Peer Relay depends on CryptoRouting in [Conn.receiveIP]. If + // CryptoRouting is disabled, then Peer Relay MUST also be disabled to + // avoid traffic blackholes. See http://go/corp/31083. + !update.SelfNode.HasCap(tailcfg.NodeAttrDisableMagicSockCryptoRouting) && !update.SelfNode.HasCap(tailcfg.NodeAttrDisableRelayClient) && !update.SelfNode.HasCap(tailcfg.NodeAttrOnlyTCP443) diff --git a/wgengine/magicsock/magicsock_test.go b/wgengine/magicsock/magicsock_test.go index 9399dab32..4b79a17d2 100644 --- a/wgengine/magicsock/magicsock_test.go +++ b/wgengine/magicsock/magicsock_test.go @@ -3625,6 +3625,10 @@ func TestConn_onNodeViewsUpdate_updateRelayServersSet(t *testing.T) { selfNodeNodeAttrOnlyTCP443.CapMap = make(tailcfg.NodeCapMap) selfNodeNodeAttrOnlyTCP443.CapMap[tailcfg.NodeAttrOnlyTCP443] = nil + selfNodeNodeAttrDisableMagicSockCryptoRouting := selfNode.Clone() + selfNodeNodeAttrDisableMagicSockCryptoRouting.CapMap = make(tailcfg.NodeCapMap) + selfNodeNodeAttrDisableMagicSockCryptoRouting.CapMap[tailcfg.NodeAttrDisableMagicSockCryptoRouting] = nil + tests := []struct { name string filt *filter.Filter @@ -3693,6 +3697,24 @@ func TestConn_onNodeViewsUpdate_updateRelayServersSet(t *testing.T) { wantRelayServers: make(set.Set[candidatePeerRelay]), wantRelayClientEnabled: false, }, + { + name: "no candidate relay server because self has tailcfg.NodeAttrDisableMagicSockCryptoRouting", + filt: filter.New([]filtertype.Match{ + { + Srcs: peerNodeCandidateRelay.Addresses, + Caps: []filtertype.CapMatch{ + { + Dst: selfNodeNodeAttrDisableMagicSockCryptoRouting.Addresses[0], + Cap: tailcfg.PeerCapabilityRelayTarget, + }, + }, + }, + }, nil, nil, nil, nil, nil), + self: selfNodeNodeAttrDisableMagicSockCryptoRouting.View(), + peers: []tailcfg.NodeView{peerNodeCandidateRelay.View()}, + wantRelayServers: make(set.Set[candidatePeerRelay]), + wantRelayClientEnabled: false, + }, { name: "self candidate relay server", filt: filter.New([]filtertype.Match{