mirror of
https://github.com/tailscale/tailscale.git
synced 2025-08-15 07:27:30 +00:00
tailcfg,wgengine/magicsock: set peer relay CapVer (#16531)
Updates tailscale/corp#27502 Updates tailscale/corp#30051 Signed-off-by: Jordan Whited <jordan@tailscale.com>
This commit is contained in:
@@ -164,7 +164,8 @@ type CapabilityVersion int
|
|||||||
// - 117: 2025-05-28: Client understands DisplayMessages (structured health messages), but not necessarily PrimaryAction.
|
// - 117: 2025-05-28: Client understands DisplayMessages (structured health messages), but not necessarily PrimaryAction.
|
||||||
// - 118: 2025-07-01: Client sends Hostinfo.StateEncrypted to report whether the state file is encrypted at rest (#15830)
|
// - 118: 2025-07-01: Client sends Hostinfo.StateEncrypted to report whether the state file is encrypted at rest (#15830)
|
||||||
// - 119: 2025-07-10: Client uses Hostinfo.Location.Priority to prioritize one route over another.
|
// - 119: 2025-07-10: Client uses Hostinfo.Location.Priority to prioritize one route over another.
|
||||||
const CurrentCapabilityVersion CapabilityVersion = 119
|
// - 120: 2025-07-15: Client understands peer relay disco messages, and implements peer client and relay server functions
|
||||||
|
const CurrentCapabilityVersion CapabilityVersion = 120
|
||||||
|
|
||||||
// ID is an integer ID for a user, node, or login allocated by the
|
// ID is an integer ID for a user, node, or login allocated by the
|
||||||
// control plane.
|
// control plane.
|
||||||
|
@@ -62,12 +62,6 @@ var (
|
|||||||
//
|
//
|
||||||
//lint:ignore U1000 used on Linux/Darwin only
|
//lint:ignore U1000 used on Linux/Darwin only
|
||||||
debugPMTUD = envknob.RegisterBool("TS_DEBUG_PMTUD")
|
debugPMTUD = envknob.RegisterBool("TS_DEBUG_PMTUD")
|
||||||
// debugAssumeUDPRelayCapable forces magicsock to assume that all peers are
|
|
||||||
// UDP relay capable clients and servers. This will eventually be replaced
|
|
||||||
// by a [tailcfg.CapabilityVersion] comparison. It enables early testing of
|
|
||||||
// the UDP relay feature before we have established related
|
|
||||||
// [tailcfg.CapabilityVersion]'s.
|
|
||||||
debugAssumeUDPRelayCapable = envknob.RegisterBool("TS_DEBUG_ASSUME_UDP_RELAY_CAPABLE")
|
|
||||||
// Hey you! Adding a new debugknob? Make sure to stub it out in the
|
// Hey you! Adding a new debugknob? Make sure to stub it out in the
|
||||||
// debugknobs_stubs.go file too.
|
// debugknobs_stubs.go file too.
|
||||||
)
|
)
|
||||||
|
@@ -31,4 +31,3 @@ func debugRingBufferMaxSizeBytes() int { return 0 }
|
|||||||
func inTest() bool { return false }
|
func inTest() bool { return false }
|
||||||
func debugPeerMap() bool { return false }
|
func debugPeerMap() bool { return false }
|
||||||
func pretendpoints() []netip.AddrPort { return []netip.AddrPort{} }
|
func pretendpoints() []netip.AddrPort { return []netip.AddrPort{} }
|
||||||
func debugAssumeUDPRelayCapable() bool { return false }
|
|
||||||
|
@@ -14,7 +14,6 @@ import (
|
|||||||
"expvar"
|
"expvar"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"math"
|
|
||||||
"net"
|
"net"
|
||||||
"net/netip"
|
"net/netip"
|
||||||
"reflect"
|
"reflect"
|
||||||
@@ -2616,14 +2615,10 @@ func (c *Conn) SetProbeUDPLifetime(v bool) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// capVerIsRelayCapable returns true if version is relay client and server
|
||||||
|
// capable, otherwise it returns false.
|
||||||
func capVerIsRelayCapable(version tailcfg.CapabilityVersion) bool {
|
func capVerIsRelayCapable(version tailcfg.CapabilityVersion) bool {
|
||||||
// TODO(jwhited): implement once capVer is bumped
|
return version >= 120
|
||||||
return version == math.MinInt32 || debugAssumeUDPRelayCapable()
|
|
||||||
}
|
|
||||||
|
|
||||||
func capVerIsRelayServerCapable(version tailcfg.CapabilityVersion) bool {
|
|
||||||
// TODO(jwhited): implement once capVer is bumped & update Test_peerAPIIfCandidateRelayServer
|
|
||||||
return version == math.MinInt32 || debugAssumeUDPRelayCapable()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// onFilterUpdate is called when a [FilterUpdate] is received over the
|
// onFilterUpdate is called when a [FilterUpdate] is received over the
|
||||||
@@ -2677,10 +2672,16 @@ func peerAPIIfCandidateRelayServer(filt *filter.Filter, self, maybeCandidate tai
|
|||||||
if filt == nil ||
|
if filt == nil ||
|
||||||
!self.Valid() ||
|
!self.Valid() ||
|
||||||
!maybeCandidate.Valid() ||
|
!maybeCandidate.Valid() ||
|
||||||
!capVerIsRelayServerCapable(maybeCandidate.Cap()) ||
|
|
||||||
!maybeCandidate.Hostinfo().Valid() {
|
!maybeCandidate.Hostinfo().Valid() {
|
||||||
return netip.AddrPort{}
|
return netip.AddrPort{}
|
||||||
}
|
}
|
||||||
|
if maybeCandidate.ID() != self.ID() && !capVerIsRelayCapable(maybeCandidate.Cap()) {
|
||||||
|
// If maybeCandidate's [tailcfg.CapabilityVersion] is not relay-capable,
|
||||||
|
// we skip it. If maybeCandidate happens to be self, then this check is
|
||||||
|
// unnecessary as self is always capable from this point (the statically
|
||||||
|
// compiled [tailcfg.CurrentCapabilityVersion]) forward.
|
||||||
|
return netip.AddrPort{}
|
||||||
|
}
|
||||||
for _, maybeCandidatePrefix := range maybeCandidate.Addresses().All() {
|
for _, maybeCandidatePrefix := range maybeCandidate.Addresses().All() {
|
||||||
if !maybeCandidatePrefix.IsSingleIP() {
|
if !maybeCandidatePrefix.IsSingleIP() {
|
||||||
continue
|
continue
|
||||||
|
@@ -3399,7 +3399,11 @@ func Test_peerAPIIfCandidateRelayServer(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
selfOnlyIPv4 := &tailcfg.Node{
|
selfOnlyIPv4 := &tailcfg.Node{
|
||||||
Cap: math.MinInt32,
|
ID: 1,
|
||||||
|
// Intentionally set a value < 120 to verify the statically compiled
|
||||||
|
// [tailcfg.CurrentCapabilityVersion] is used when self is
|
||||||
|
// maybeCandidate.
|
||||||
|
Cap: 119,
|
||||||
Addresses: []netip.Prefix{
|
Addresses: []netip.Prefix{
|
||||||
netip.MustParsePrefix("1.1.1.1/32"),
|
netip.MustParsePrefix("1.1.1.1/32"),
|
||||||
},
|
},
|
||||||
@@ -3409,13 +3413,17 @@ func Test_peerAPIIfCandidateRelayServer(t *testing.T) {
|
|||||||
selfOnlyIPv6.Addresses[0] = netip.MustParsePrefix("::1/128")
|
selfOnlyIPv6.Addresses[0] = netip.MustParsePrefix("::1/128")
|
||||||
|
|
||||||
peerOnlyIPv4 := &tailcfg.Node{
|
peerOnlyIPv4 := &tailcfg.Node{
|
||||||
Cap: math.MinInt32,
|
ID: 2,
|
||||||
|
Cap: 120,
|
||||||
Addresses: []netip.Prefix{
|
Addresses: []netip.Prefix{
|
||||||
netip.MustParsePrefix("2.2.2.2/32"),
|
netip.MustParsePrefix("2.2.2.2/32"),
|
||||||
},
|
},
|
||||||
Hostinfo: hostInfo.View(),
|
Hostinfo: hostInfo.View(),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
peerOnlyIPv4NotCapable := peerOnlyIPv4.Clone()
|
||||||
|
peerOnlyIPv4NotCapable.Cap = 119
|
||||||
|
|
||||||
peerOnlyIPv6 := peerOnlyIPv4.Clone()
|
peerOnlyIPv6 := peerOnlyIPv4.Clone()
|
||||||
peerOnlyIPv6.Addresses[0] = netip.MustParsePrefix("::2/128")
|
peerOnlyIPv6.Addresses[0] = netip.MustParsePrefix("::2/128")
|
||||||
|
|
||||||
@@ -3500,6 +3508,22 @@ func Test_peerAPIIfCandidateRelayServer(t *testing.T) {
|
|||||||
maybeCandidate: selfOnlyIPv6.View(),
|
maybeCandidate: selfOnlyIPv6.View(),
|
||||||
want: netip.AddrPortFrom(selfOnlyIPv6.Addresses[0].Addr(), 6),
|
want: netip.AddrPortFrom(selfOnlyIPv6.Addresses[0].Addr(), 6),
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "peer incapable",
|
||||||
|
filt: filter.New([]filtertype.Match{
|
||||||
|
{
|
||||||
|
Srcs: []netip.Prefix{netip.MustParsePrefix("2.2.2.2/32")},
|
||||||
|
Caps: []filtertype.CapMatch{
|
||||||
|
{
|
||||||
|
Dst: netip.MustParsePrefix("1.1.1.1/32"),
|
||||||
|
Cap: tailcfg.PeerCapabilityRelayTarget,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}, nil, nil, nil, nil, nil),
|
||||||
|
self: selfOnlyIPv4.View(),
|
||||||
|
maybeCandidate: peerOnlyIPv4NotCapable.View(),
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: "no match dst",
|
name: "no match dst",
|
||||||
filt: filter.New([]filtertype.Match{
|
filt: filter.New([]filtertype.Match{
|
||||||
|
Reference in New Issue
Block a user