From b8d9c3bc8883cd71190923e268d61cce76c6034e Mon Sep 17 00:00:00 2001 From: Brad Fitzpatrick Date: Sun, 3 Nov 2024 14:21:57 -0800 Subject: [PATCH] cmd/lopower: set ultimate fallback DNS servers Change-Id: I044d6c7b9dc4b874f3c60d2c6ce2105bafc00639 Signed-off-by: Brad Fitzpatrick --- cmd/lopower/lopower.go | 18 +++++++++++++++++- net/dns/manager.go | 19 +++++++++++++++++-- 2 files changed, 34 insertions(+), 3 deletions(-) diff --git a/cmd/lopower/lopower.go b/cmd/lopower/lopower.go index 0d4da7232..a8599a5f6 100644 --- a/cmd/lopower/lopower.go +++ b/cmd/lopower/lopower.go @@ -50,6 +50,7 @@ import ( "tailscale.com/net/tsaddr" "tailscale.com/syncs" "tailscale.com/tsnet" + "tailscale.com/types/dnstype" "tailscale.com/types/ipproto" "tailscale.com/types/key" "tailscale.com/types/logger" @@ -638,7 +639,22 @@ func (lp *lpServer) startTSNet(ctx context.Context) { } lp.tsnet = ts ts.PreStart = func() error { - ts.Sys().DNSManager.Get().SetForceAAAA(true) + dnsMgr := ts.Sys().DNSManager.Get() + dnsMgr.SetForceAAAA(true) + + // Force fallback resolvers to Google and Cloudflare as an ultimate + // fallback in case the Tailnet DNS servers are not set/forced. Normally + // tailscaled would resort to using the OS DNS resolvers, but + // tsnet/userspace binaries don't do that (yet?), so this is the + // "Opionated" part of the "LOPOWER" name. The opinion is just using + // big providers known to work. (Normally stock tailscaled never + // makes such opinions and never defaults to any big provider, unless + // you're already running on that big provider's network so have + // already indicated you're fine with them.)) + dnsMgr.SetForceFallbackResolvers([]*dnstype.Resolver{ + {Addr: "8.8.8.8"}, + {Addr: "1.1.1.1"}, + }) return nil } diff --git a/net/dns/manager.go b/net/dns/manager.go index f170d523c..756816611 100644 --- a/net/dns/manager.go +++ b/net/dns/manager.go @@ -66,8 +66,9 @@ type Manager struct { mu sync.Mutex // guards following // config is the last configuration we successfully compiled or nil if there // was any failure applying the last configuration. - config *Config - forceAAAA bool // whether client wants MagicDNS AAAA even if unsure of host's IPv6 status + config *Config + forceAAAA bool // whether client wants MagicDNS AAAA even if unsure of host's IPv6 status + forceFallbackResolvers []*dnstype.Resolver } // NewManagers created a new manager from the given config. @@ -161,6 +162,16 @@ func (m *Manager) SetForceAAAA(v bool) { m.forceAAAA = v } +// SetForceFallbackResolvers sets the resolvers to use to override +// the fallback resolvers if the control plane doesn't send any. +// +// It takes ownership of the provided slice. +func (m *Manager) SetForceFallbackResolvers(resolvers []*dnstype.Resolver) { + m.mu.Lock() + defer m.mu.Unlock() + m.forceFallbackResolvers = resolvers +} + // setLocked sets the DNS configuration. // // m.mu must be held. @@ -179,6 +190,10 @@ func (m *Manager) setLocked(cfg Config) error { return err } + if _, ok := rcfg.Routes["."]; !ok && len(m.forceFallbackResolvers) > 0 { + rcfg.Routes["."] = m.forceFallbackResolvers + } + m.logf("Resolvercfg: %v", logger.ArgWriter(func(w *bufio.Writer) { rcfg.WriteToBufioWriter(w) }))