From 9cedc555709268e84489d08ac11b60992c9be9b9 Mon Sep 17 00:00:00 2001 From: Brad Fitzpatrick Date: Mon, 16 Oct 2023 09:16:01 -0700 Subject: [PATCH] net/dnsfallback, control/controlknobs: add knob to disable recursive resolver Updates tailscale/corp#15261 Change-Id: I099860c400c82617382723b96fd3a5193c45f0d7 Signed-off-by: Brad Fitzpatrick --- control/controlclient/direct.go | 2 +- control/controlhttp/client.go | 2 +- control/controlknobs/controlknobs.go | 15 +++++++++++++++ logpolicy/logpolicy.go | 2 +- net/dnsfallback/dnsfallback.go | 4 ++-- tailcfg/tailcfg.go | 3 +++ 6 files changed, 23 insertions(+), 5 deletions(-) diff --git a/control/controlclient/direct.go b/control/controlclient/direct.go index 80f6e919b..2f4c40c03 100644 --- a/control/controlclient/direct.go +++ b/control/controlclient/direct.go @@ -235,7 +235,7 @@ func NewDirect(opts Options) (*Direct, error) { dnsCache := &dnscache.Resolver{ Forward: dnscache.Get().Forward, // use default cache's forwarder UseLastGood: true, - LookupIPFallback: dnsfallback.MakeLookupFunc(opts.Logf, opts.NetMon), + LookupIPFallback: dnsfallback.MakeLookupFunc(opts.Logf, opts.NetMon, opts.ControlKnobs.EnableRecursiveResolver), Logf: opts.Logf, NetMon: opts.NetMon, } diff --git a/control/controlhttp/client.go b/control/controlhttp/client.go index fb220fd0b..d622aca40 100644 --- a/control/controlhttp/client.go +++ b/control/controlhttp/client.go @@ -390,7 +390,7 @@ func (a *Dialer) resolver() *dnscache.Resolver { return &dnscache.Resolver{ Forward: dnscache.Get().Forward, - LookupIPFallback: dnsfallback.MakeLookupFunc(a.logf, a.NetMon), + LookupIPFallback: dnsfallback.MakeLookupFunc(a.logf, a.NetMon, func() bool { return false }), UseLastGood: true, Logf: a.Logf, // not a.logf method; we want to propagate nil-ness NetMon: a.NetMon, diff --git a/control/controlknobs/controlknobs.go b/control/controlknobs/controlknobs.go index e64bc8011..2678ba494 100644 --- a/control/controlknobs/controlknobs.go +++ b/control/controlknobs/controlknobs.go @@ -52,6 +52,10 @@ type Knobs struct { // DisableDNSForwarderTCPRetries is whether the DNS forwarder should // skip retrying truncated queries over TCP. DisableDNSForwarderTCPRetries atomic.Bool + + // DisableRecursiveResolver is whether the node should disable the + // dnsfallback recursive resolver. + DisableRecursiveResolver atomic.Bool } // UpdateFromNodeAttributes updates k (if non-nil) based on the provided self @@ -74,6 +78,7 @@ func (k *Knobs) UpdateFromNodeAttributes(selfNodeAttrs []tailcfg.NodeCapability, forceBackgroundSTUN = has(tailcfg.NodeAttrDebugForceBackgroundSTUN) peerMTUEnable = has(tailcfg.NodeAttrPeerMTUEnable) dnsForwarderDisableTCPRetries = has(tailcfg.NodeAttrDNSForwarderDisableTCPRetries) + dnsDisableRecursiveResolver = has(tailcfg.NodeAttrDisableRecursiveResolver) ) if has(tailcfg.NodeAttrOneCGNATEnable) { @@ -91,6 +96,7 @@ func (k *Knobs) UpdateFromNodeAttributes(selfNodeAttrs []tailcfg.NodeCapability, k.DisableDeltaUpdates.Store(disableDeltaUpdates) k.PeerMTUEnable.Store(peerMTUEnable) k.DisableDNSForwarderTCPRetries.Store(dnsForwarderDisableTCPRetries) + k.DisableRecursiveResolver.Store(dnsDisableRecursiveResolver) } // AsDebugJSON returns k as something that can be marshalled with json.Marshal @@ -111,3 +117,12 @@ func (k *Knobs) AsDebugJSON() map[string]any { "DisableDNSForwarderTCPRetries": k.DisableDNSForwarderTCPRetries.Load(), } } + +// EnableRecursiveResolver is whether the node should use its DNS recursive resolver +// as a fallback. It defaults to enabled unless disabled by the control plane. +func (k *Knobs) EnableRecursiveResolver() bool { + if k == nil { + return true + } + return !k.DisableRecursiveResolver.Load() +} diff --git a/logpolicy/logpolicy.go b/logpolicy/logpolicy.go index 7d22362ae..814809188 100644 --- a/logpolicy/logpolicy.go +++ b/logpolicy/logpolicy.go @@ -736,7 +736,7 @@ func dialContext(ctx context.Context, netw, addr string, netMon *netmon.Monitor, dnsCache := &dnscache.Resolver{ Forward: dnscache.Get().Forward, // use default cache's forwarder UseLastGood: true, - LookupIPFallback: dnsfallback.MakeLookupFunc(logf, netMon), + LookupIPFallback: dnsfallback.MakeLookupFunc(logf, netMon, func() bool { return false }), NetMon: netMon, } dialer := dnscache.Dialer(nd.DialContext, dnsCache) diff --git a/net/dnsfallback/dnsfallback.go b/net/dnsfallback/dnsfallback.go index d60404ddc..2aba97dff 100644 --- a/net/dnsfallback/dnsfallback.go +++ b/net/dnsfallback/dnsfallback.go @@ -44,9 +44,9 @@ var disableRecursiveResolver = envknob.RegisterBool("TS_DNSFALLBACK_DISABLE_RECU // MakeLookupFunc creates a function that can be used to resolve hostnames // (e.g. as a LookupIPFallback from dnscache.Resolver). // The netMon parameter is optional; if non-nil it's used to do faster interface lookups. -func MakeLookupFunc(logf logger.Logf, netMon *netmon.Monitor) func(ctx context.Context, host string) ([]netip.Addr, error) { +func MakeLookupFunc(logf logger.Logf, netMon *netmon.Monitor, enableRecursive func() bool) func(ctx context.Context, host string) ([]netip.Addr, error) { return func(ctx context.Context, host string) ([]netip.Addr, error) { - if disableRecursiveResolver() { + if disableRecursiveResolver() || !enableRecursive() { return lookup(ctx, host, logf, netMon) } diff --git a/tailcfg/tailcfg.go b/tailcfg/tailcfg.go index e7eac4a25..bd2b9c0f7 100644 --- a/tailcfg/tailcfg.go +++ b/tailcfg/tailcfg.go @@ -2096,6 +2096,9 @@ const ( // See Issue 150. NodeAttrDebugDisableDRPO NodeCapability = "debug-disable-drpo" + // NodeAttrDisableRecursiveResolver disables the recursive resolver. + NodeAttrDisableRecursiveResolver NodeCapability = "disable-recursive-resolver" + // NodeAttrDisableSubnetsIfPAC controls whether subnet routers should be // disabled if WPAD is present on the network. NodeAttrDisableSubnetsIfPAC NodeCapability = "debug-disable-subnets-if-pac"