فهرست منبع

net/dnsfallback: run recursive resolver and compare results

When performing a fallback DNS query, run the recursive resolver in a
separate goroutine and compare the results returned by the recursive
resolver with the results we get from "regular" bootstrap DNS. This will
allow us to gather data about whether the recursive DNS resolver works
better, worse, or about the same as "regular" bootstrap DNS.

Updates #5853

Signed-off-by: Andrew Dunham <[email protected]>
Change-Id: Ifa0b0cc9eeb0dccd6f7a3d91675fe44b3b34bd48
Andrew Dunham 2 سال پیش
والد
کامیت
a7648a6723
3فایلهای تغییر یافته به همراه77 افزوده شده و 4 حذف شده
  1. 4 2
      cmd/tailscale/depaware.txt
  2. 3 1
      cmd/tailscaled/depaware.txt
  3. 70 1
      net/dnsfallback/dnsfallback.go

+ 4 - 2
cmd/tailscale/depaware.txt

@@ -32,6 +32,7 @@ tailscale.com/cmd/tailscale dependencies: (generated by github.com/tailscale/dep
    L 💣 github.com/mdlayher/netlink/nlenc                            from github.com/jsimonetti/rtnetlink+
    L    github.com/mdlayher/netlink/nltest                           from github.com/google/nftables
    L 💣 github.com/mdlayher/socket                                   from github.com/mdlayher/netlink
+        github.com/miekg/dns                                         from tailscale.com/net/dns/recursive
      💣 github.com/mitchellh/go-ps                                   from tailscale.com/cmd/tailscale/cli+
         github.com/peterbourgon/ff/v3                                from github.com/peterbourgon/ff/v3/ffcli
         github.com/peterbourgon/ff/v3/ffcli                          from tailscale.com/cmd/tailscale/cli
@@ -93,6 +94,7 @@ tailscale.com/cmd/tailscale dependencies: (generated by github.com/tailscale/dep
         tailscale.com/ipn                                            from tailscale.com/cmd/tailscale/cli+
         tailscale.com/ipn/ipnstate                                   from tailscale.com/cmd/tailscale/cli+
         tailscale.com/metrics                                        from tailscale.com/derp
+        tailscale.com/net/dns/recursive                              from tailscale.com/net/dnsfallback
         tailscale.com/net/dnscache                                   from tailscale.com/derp/derphttp+
         tailscale.com/net/dnsfallback                                from tailscale.com/control/controlhttp
         tailscale.com/net/flowtrack                                  from tailscale.com/wgengine/filter+
@@ -172,7 +174,7 @@ tailscale.com/cmd/tailscale dependencies: (generated by github.com/tailscale/dep
         golang.org/x/crypto/nacl/secretbox                           from golang.org/x/crypto/nacl/box
         golang.org/x/crypto/pbkdf2                                   from software.sslmate.com/src/go-pkcs12
         golang.org/x/crypto/salsa20/salsa                            from golang.org/x/crypto/nacl/box+
-        golang.org/x/exp/constraints                                 from golang.org/x/exp/slices
+        golang.org/x/exp/constraints                                 from golang.org/x/exp/slices+
         golang.org/x/exp/maps                                        from tailscale.com/types/views
         golang.org/x/exp/slices                                      from tailscale.com/net/tsaddr+
         golang.org/x/net/bpf                                         from github.com/mdlayher/netlink+
@@ -235,7 +237,7 @@ tailscale.com/cmd/tailscale dependencies: (generated by github.com/tailscale/dep
         embed                                                        from tailscale.com/cmd/tailscale/cli+
         encoding                                                     from encoding/json+
         encoding/asn1                                                from crypto/x509+
-        encoding/base32                                              from tailscale.com/tka
+        encoding/base32                                              from tailscale.com/tka+
         encoding/base64                                              from encoding/json+
         encoding/binary                                              from compress/gzip+
         encoding/hex                                                 from crypto/x509+

+ 3 - 1
cmd/tailscaled/depaware.txt

@@ -118,6 +118,7 @@ tailscale.com/cmd/tailscaled dependencies: (generated by github.com/tailscale/de
    L    github.com/mdlayher/netlink/nltest                           from github.com/google/nftables
    L    github.com/mdlayher/sdnotify                                 from tailscale.com/util/systemd
    L 💣 github.com/mdlayher/socket                                   from github.com/mdlayher/netlink
+        github.com/miekg/dns                                         from tailscale.com/net/dns/recursive
      💣 github.com/mitchellh/go-ps                                   from tailscale.com/safesocket
    L    github.com/pierrec/lz4/v4                                    from github.com/u-root/uio/uio
    L    github.com/pierrec/lz4/v4/internal/lz4block                  from github.com/pierrec/lz4/v4+
@@ -254,6 +255,7 @@ tailscale.com/cmd/tailscaled dependencies: (generated by github.com/tailscale/de
         tailscale.com/net/connstats                                  from tailscale.com/net/tstun+
         tailscale.com/net/dns                                        from tailscale.com/ipn/ipnlocal+
         tailscale.com/net/dns/publicdns                              from tailscale.com/net/dns/resolver+
+        tailscale.com/net/dns/recursive                              from tailscale.com/net/dnsfallback
         tailscale.com/net/dns/resolvconffile                         from tailscale.com/net/dns+
         tailscale.com/net/dns/resolver                               from tailscale.com/ipn/ipnlocal+
         tailscale.com/net/dnscache                                   from tailscale.com/control/controlclient+
@@ -442,7 +444,7 @@ tailscale.com/cmd/tailscaled dependencies: (generated by github.com/tailscale/de
         embed                                                        from tailscale.com+
         encoding                                                     from encoding/json+
         encoding/asn1                                                from crypto/x509+
-        encoding/base32                                              from tailscale.com/tka
+        encoding/base32                                              from tailscale.com/tka+
         encoding/base64                                              from encoding/json+
         encoding/binary                                              from compress/gzip+
         encoding/hex                                                 from crypto/x509+

+ 70 - 1
net/dnsfallback/dnsfallback.go

@@ -22,22 +22,85 @@ import (
 	"sync/atomic"
 	"time"
 
+	"golang.org/x/exp/slices"
 	"tailscale.com/atomicfile"
+	"tailscale.com/envknob"
+	"tailscale.com/net/dns/recursive"
 	"tailscale.com/net/netmon"
 	"tailscale.com/net/netns"
 	"tailscale.com/net/tlsdial"
 	"tailscale.com/net/tshttpproxy"
 	"tailscale.com/tailcfg"
 	"tailscale.com/types/logger"
+	"tailscale.com/util/clientmetric"
 	"tailscale.com/util/slicesx"
 )
 
+var disableRecursiveResolver = envknob.RegisterBool("TS_DNSFALLBACK_DISABLE_RECURSIVE_RESOLVER")
+
 // 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) {
 	return func(ctx context.Context, host string) ([]netip.Addr, error) {
-		return lookup(ctx, host, logf, netMon)
+		if disableRecursiveResolver() {
+			return lookup(ctx, host, logf, netMon)
+		}
+
+		addrsCh := make(chan []netip.Addr, 1)
+
+		// Run the recursive resolver in the background so we can
+		// compare the results.
+		go func() {
+			logf := logger.WithPrefix(logf, "recursive: ")
+
+			// Ensure that we catch panics while we're testing this
+			// code path; this should never panic, but we don't
+			// want to take down the process by having the panic
+			// propagate to the top of the goroutine's stack and
+			// then terminate.
+			defer func() {
+				if r := recover(); r != nil {
+					logf("bootstrap DNS: recovered panic: %v", r)
+					metricRecursiveErrors.Add(1)
+				}
+			}()
+
+			resolver := recursive.Resolver{
+				Dialer: netns.NewDialer(logf, netMon),
+				Logf:   logf,
+			}
+			addrs, minTTL, err := resolver.Resolve(ctx, host)
+			if err != nil {
+				logf("error using recursive resolver: %v", err)
+				metricRecursiveErrors.Add(1)
+				return
+			}
+			slices.SortFunc(addrs, func(a, b netip.Addr) bool { return a.Less(b) })
+
+			// Wait for a response from the main function
+			oldAddrs := <-addrsCh
+			slices.SortFunc(oldAddrs, func(a, b netip.Addr) bool { return a.Less(b) })
+
+			matches := slices.Equal(addrs, oldAddrs)
+
+			logf("bootstrap DNS comparison: matches=%v oldAddrs=%v addrs=%v minTTL=%v", matches, oldAddrs, addrs, minTTL)
+
+			if matches {
+				metricRecursiveMatches.Add(1)
+			} else {
+				metricRecursiveMismatches.Add(1)
+			}
+		}()
+
+		addrs, err := lookup(ctx, host, logf, netMon)
+		if err != nil {
+			addrsCh <- nil
+			return nil, err
+		}
+
+		addrsCh <- slices.Clone(addrs)
+		return addrs, nil
 	}
 }
 
@@ -254,3 +317,9 @@ func SetCachePath(path string, logf logger.Logf) {
 	cachedDERPMap.Store(dm)
 	logf("[v2] dnsfallback: SetCachePath loaded cached DERP map")
 }
+
+var (
+	metricRecursiveMatches    = clientmetric.NewCounter("dnsfallback_recursive_matches")
+	metricRecursiveMismatches = clientmetric.NewCounter("dnsfallback_recursive_mismatches")
+	metricRecursiveErrors     = clientmetric.NewCounter("dnsfallback_recursive_errors")
+)