diff --git a/net/dns/resolver/forwarder.go b/net/dns/resolver/forwarder.go index 616c8b8c4..6bf7382d1 100644 --- a/net/dns/resolver/forwarder.go +++ b/net/dns/resolver/forwarder.go @@ -76,8 +76,6 @@ func truncatedFlagSet(pkt []byte) bool { wellKnownHostBackupDelay = 200 * time.Millisecond ) -var errNoUpstreams = errors.New("upstream nameservers not set") - // txid identifies a DNS transaction. // // As the standard DNS Request ID is only 16 bits, we extend it: @@ -205,7 +203,7 @@ type forwarder struct { // // That is, if we're running on GCP or AWS where there's always a well-known // IP of a recursive resolver, return that rather than having callers return - // errNoUpstreams. This fixes both normal 100.100.100.100 resolution when + // SERVFAIL. This fixes both normal 100.100.100.100 resolution when // /etc/resolv.conf is missing/corrupt, and the peerapi ExitDNS stub // resolver lookup. cloudHostFallback []resolverAndDelay @@ -698,7 +696,18 @@ func (f *forwarder) forwardWithDestChan(ctx context.Context, query packet, respo resolvers = f.resolvers(domain) if len(resolvers) == 0 { metricDNSFwdErrorNoUpstream.Add(1) - return errNoUpstreams + f.logf("no upstream resolvers set, returning SERVFAIL") + res, err := servfailResponse(query) + if err != nil { + f.logf("building servfail response: %v", err) + return nil + } + select { + case <-ctx.Done(): + return ctx.Err() + case responseChan <- res: + return nil + } } }