net/dns/resolver: return SERVFAIL when no upstream resolvers set
Otherwise we just keep looping over the same thing again and again.
```
dns udp query: upstream nameservers not set
dns udp query: upstream nameservers not set
dns udp query: upstream nameservers not set
```
@@ -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
+ }
}
}
