From b85c2b231305be1f76bbaeff16c5ea8da630ef16 Mon Sep 17 00:00:00 2001 From: Andrew Dunham Date: Thu, 11 Apr 2024 14:47:30 -0400 Subject: [PATCH] net/dns/resolver: use SystemDial in DoH forwarder This ensures that we close the underlying connection(s) when a major link change happens. If we don't do this, on mobile platforms switching between WiFi and cellular can result in leftover connections in the http.Client's connection pool which are bound to the "wrong" interface. Updates #10821 Updates tailscale/corp#19124 Signed-off-by: Andrew Dunham Change-Id: Ibd51ce2efcaf4bd68e14f6fdeded61d4e99f9a01 --- net/dns/resolver/forwarder.go | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/net/dns/resolver/forwarder.go b/net/dns/resolver/forwarder.go index 26bc6148c..884e53321 100644 --- a/net/dns/resolver/forwarder.go +++ b/net/dns/resolver/forwarder.go @@ -28,7 +28,6 @@ import ( "tailscale.com/net/dnscache" "tailscale.com/net/neterror" "tailscale.com/net/netmon" - "tailscale.com/net/netns" "tailscale.com/net/sockstats" "tailscale.com/net/tsdial" "tailscale.com/types/dnstype" @@ -394,8 +393,20 @@ func (f *forwarder) getKnownDoHClientForProvider(urlBase string) (c *http.Client if err != nil { return nil, false } - nsDialer := netns.NewDialer(f.logf, f.netMon) - dialer := dnscache.Dialer(nsDialer.DialContext, &dnscache.Resolver{ + // NOTE: use f.dialer.SystemDial so we close connections on a link + // change; on mobile devices when switching between WiFi and cellular, + // we need to ensure we don't retain a connection on the old interface + // or we can block DNS resolution. + // + // NOTE: if we ever support arbitrary user-defined DoH providers, this + // isn't sufficient; we'd need a dialer that dial a DoH server on the + // internet, without going through Tailscale (as SystemDial does), but + // also can dial a node on the tailnet (e.g. a PiHole). + // + // As of the time of writing (2024-02-11), this isn't a problem because + // we only support a restricted set of public DoH providers that aren't + // on a user's tailnet. + dialer := dnscache.Dialer(f.dialer.SystemDial, &dnscache.Resolver{ SingleHost: dohURL.Hostname(), SingleHostStaticResult: allIPs, Logf: f.logf,