diff --git a/control/controlclient/direct.go b/control/controlclient/direct.go index 80401f4dd..59cd4631b 100644 --- a/control/controlclient/direct.go +++ b/control/controlclient/direct.go @@ -133,6 +133,12 @@ type Options struct { // MapResponse.PingRequest queries from the control plane. // If nil, PingRequest queries are not answered. Pinger Pinger + + // GetTailscaleRoutes is a function that should return any Tailscale + // routes that are currently known; if any are returned, we test the IP + // address of the control server against these routes and use our + // fallback DNS server in those cases. + GetTailscaleRoutes func() []netip.Prefix } // Pinger is the LocalBackend.Ping method. diff --git a/ipn/ipnlocal/local.go b/ipn/ipnlocal/local.go index 4639fce66..1b3af11e4 100644 --- a/ipn/ipnlocal/local.go +++ b/ipn/ipnlocal/local.go @@ -132,6 +132,7 @@ type LocalBackend struct { filterAtomic atomic.Pointer[filter.Filter] containsViaIPFuncAtomic syncs.AtomicValue[func(netip.Addr) bool] + tailscaleRoutesAtomic syncs.AtomicValue[[]netip.Prefix] // The mutex protects the following elements. mu sync.Mutex @@ -884,6 +885,10 @@ func (b *LocalBackend) getNewControlClientFunc() clientGen { return b.ccGen } +func (b *LocalBackend) getTailscaleRoutes() []netip.Prefix { + return b.tailscaleRoutesAtomic.Load() +} + // startIsNoopLocked reports whether a Start call on this LocalBackend // with the provided Start Options would be a useless no-op. // @@ -1078,6 +1083,7 @@ func (b *LocalBackend) Start(opts ipn.Options) error { Dialer: b.Dialer(), Status: b.setClientStatus, C2NHandler: http.HandlerFunc(b.handleC2N), + GetTailscaleRoutes: b.getTailscaleRoutes, // Don't warn about broken Linux IP forwarding when // netstack is being used. @@ -2315,6 +2321,7 @@ func (b *LocalBackend) authReconfig() { } b.logf("[v1] authReconfig: ra=%v dns=%v 0x%02x: %v", prefs.RouteAll, prefs.CorpDNS, flags, err) + b.tailscaleRoutesAtomic.Store(rcfg.Routes) b.initPeerAPIListener() }