diff --git a/tailcfg/tailcfg.go b/tailcfg/tailcfg.go index 9276cebc2..24af5137c 100644 --- a/tailcfg/tailcfg.go +++ b/tailcfg/tailcfg.go @@ -1184,6 +1184,7 @@ const ( EndpointSTUN = EndpointType(2) EndpointPortmapped = EndpointType(3) EndpointSTUN4LocalPort = EndpointType(4) // hard NAT: STUN'ed IPv4 address + local fixed port + EndpointExplicitConf = EndpointType(5) // explicitly configured (routing to be done by client) ) func (et EndpointType) String() string { @@ -1198,6 +1199,8 @@ func (et EndpointType) String() string { return "portmap" case EndpointSTUN4LocalPort: return "stun4localport" + case EndpointExplicitConf: + return "explicitconf" } return "other" } diff --git a/wgengine/magicsock/debugknobs.go b/wgengine/magicsock/debugknobs.go index 867109a42..90b49d86f 100644 --- a/wgengine/magicsock/debugknobs.go +++ b/wgengine/magicsock/debugknobs.go @@ -6,6 +6,10 @@ package magicsock import ( + "log" + "net/netip" + "sync" + "tailscale.com/envknob" ) @@ -68,3 +72,18 @@ var ( // checked every time at runtime, because tests set this after program // startup. func inTest() bool { return envknob.Bool("IN_TS_TEST") } + +// pretendpoint returns TS_DEBUG_PRETENDPOINT as an AddrPort, if set. +// See https://github.com/tailscale/tailscale/issues/12578 and +// https://github.com/tailscale/tailscale/pull/12735. +var pretendpoint = sync.OnceValue(func() (ap netip.AddrPort) { + s := envknob.String("TS_DEBUG_PRETENDPOINT") + if s == "" { + return + } + ap, err := netip.ParseAddrPort(s) + if err != nil { + log.Printf("ignoring invalid TS_DEBUG_PRETENDPOINT %q: %v", s, err) + } + return ap +}) diff --git a/wgengine/magicsock/debugknobs_stubs.go b/wgengine/magicsock/debugknobs_stubs.go index 7ee316e0f..7a2f60f6b 100644 --- a/wgengine/magicsock/debugknobs_stubs.go +++ b/wgengine/magicsock/debugknobs_stubs.go @@ -5,7 +5,11 @@ package magicsock -import "tailscale.com/types/opt" +import ( + "net/netip" + + "tailscale.com/types/opt" +) // All knobs are disabled on iOS and Wasm. // @@ -26,3 +30,4 @@ func debugEnablePMTUD() opt.Bool { return "" } func debugRingBufferMaxSizeBytes() int { return 0 } func inTest() bool { return false } func debugPeerMap() bool { return false } +func pretendpoint() netip.AddrPort { return netip.AddrPort{} } diff --git a/wgengine/magicsock/magicsock.go b/wgengine/magicsock/magicsock.go index 30181f8e1..3ccf30c5e 100644 --- a/wgengine/magicsock/magicsock.go +++ b/wgengine/magicsock/magicsock.go @@ -919,6 +919,12 @@ func (c *Conn) determineEndpoints(ctx context.Context) ([]tailcfg.Endpoint, erro } } + // Temporarily (2024-07-08) during investigations, allow setting + // a pretend endpoint for testing NAT traversal scenarios. + // TODO(bradfitz): probably promote this to the config file. + // https://github.com/tailscale/tailscale/issues/12578 + addAddr(pretendpoint(), tailcfg.EndpointExplicitConf) + // Update our set of endpoints by adding any endpoints that we // previously found but haven't expired yet. This also updates the // cache with the set of endpoints discovered in this function.