@ -2175,7 +2175,6 @@ func (b *LocalBackend) authReconfig() {
nm := b . netMap
hasPAC := b . prevIfState . HasPAC ( )
disableSubnetsIfPAC := nm != nil && nm . Debug != nil && nm . Debug . DisableSubnetsIfPAC . EqualBool ( true )
oneCGNATRoute := nm != nil && nm . Debug != nil && nm . Debug . OneCGNATRoute . EqualBool ( true )
b . mu . Unlock ( )
if blocked {
@ -2220,6 +2219,7 @@ func (b *LocalBackend) authReconfig() {
return
}
oneCGNATRoute := shouldUseOneCGNATRoute ( nm , b . logf , version . OS ( ) )
rcfg := b . routerConfig ( cfg , prefs , oneCGNATRoute )
dcfg := dnsConfigForNetmap ( nm , prefs , b . logf , version . OS ( ) )
@ -2232,6 +2232,38 @@ func (b *LocalBackend) authReconfig() {
b . initPeerAPIListener ( )
}
// shouldUseOneCGNATRoute reports whether we should prefer to make one big
// CGNAT /10 route rather than a /32 per peer.
//
// The versionOS is a Tailscale-style version ("iOS", "macOS") and not
// a runtime.GOOS.
func shouldUseOneCGNATRoute ( nm * netmap . NetworkMap , logf logger . Logf , versionOS string ) bool {
// Explicit enabling or disabling always take precedence.
if nm . Debug != nil {
if v , ok := nm . Debug . OneCGNATRoute . Get ( ) ; ok {
logf ( "[v1] shouldUseOneCGNATRoute: explicit=%v" , v )
return v
}
}
// Also prefer to do this on the Mac, so that we don't need to constantly
// update the network extension configuration (which is disruptive to
// Chrome, see https://github.com/tailscale/tailscale/issues/3102). Only
// use fine-grained routes if another interfaces is also using the CGNAT
// IP range.
if versionOS == "macOS" {
hasCGNATInterface , err := interfaces . HasCGNATInterface ( )
if err != nil {
logf ( "shouldUseOneCGNATRoute: Could not determine if any interfaces use CGNAT: %v" , err )
return false
}
logf ( "[v1] shouldUseOneCGNATRoute: macOS automatic=%v" , ! hasCGNATInterface )
if ! hasCGNATInterface {
return true
}
}
return false
}
// dnsConfigForNetmap returns a *dns.Config for the given netmap,
// prefs, client OS version, and cloud hosting environment.
//