resolver: a reply marked recursion available from a root server's address stops the lookup (closes #300)
check / check (push) Waiting to run
check / check (push) Waiting to run
dnswatcher never asks for recursion and a root server never offers it, so a reply marked recursion available from a root server's address came from a resolver on the network answering in its place. The first such reply, a refusal included, now stops the lookup at once with "this network intercepts DNS queries", naming the address, whether or not that resolver had the name cached. queryDNS returns a refused reply along with ErrRefused so the mark can be seen; a refusal without the mark is handled as before. On such a network dnswatcher and its tests fail with that error, by design, as the owner ruled on the issue. Model: opus-5-5
This commit was merged in pull request #301.
This commit is contained in:
@@ -115,7 +115,8 @@ func (r *Resolver) retryTCP(
|
||||
}
|
||||
|
||||
// queryDNS sends a DNS query to a specific server IP, never asking it
|
||||
// for recursion. A reply of REFUSED is returned as ErrRefused.
|
||||
// for recursion. A reply of REFUSED is returned together with
|
||||
// ErrRefused, so that the caller can still read the reply's flags.
|
||||
func (r *Resolver) queryDNS(
|
||||
ctx context.Context,
|
||||
serverIP string,
|
||||
@@ -139,7 +140,7 @@ func (r *Resolver) queryDNS(
|
||||
}
|
||||
|
||||
if resp.Rcode == dns.RcodeRefused {
|
||||
return nil, fmt.Errorf(
|
||||
return resp, fmt.Errorf(
|
||||
"query %s @%s: %w", name, serverIP, ErrRefused,
|
||||
)
|
||||
}
|
||||
@@ -284,10 +285,15 @@ func shuffled(
|
||||
}
|
||||
|
||||
// queryServers asks servers, the servers of zone, about name in a random
|
||||
// order until one gives a usable reply. A server that times out, refuses
|
||||
// or gives a reply that is not usable is passed over for the next. When
|
||||
// every server refused, the error says so, and when they are the root
|
||||
// servers it is ErrIntercepted.
|
||||
// order until one gives a usable reply. When they are the root servers,
|
||||
// the first reply marked recursion available, a refusal included, ends
|
||||
// the lookup with ErrIntercepted, naming the address it came from, and
|
||||
// no other root server is asked: root servers offer no recursion, so
|
||||
// that reply came from something on the network answering in their
|
||||
// place. Otherwise a server that times out, refuses or gives a reply
|
||||
// that is not usable is passed over for the next. When every server
|
||||
// refused, the error says so, and when they are the root servers it is
|
||||
// ErrIntercepted.
|
||||
func (r *Resolver) queryServers(
|
||||
ctx context.Context,
|
||||
servers []string,
|
||||
@@ -304,7 +310,17 @@ func (r *Resolver) queryServers(
|
||||
return nil, ErrContextCanceled
|
||||
}
|
||||
|
||||
// queryDNS returns a refusal together with its reply, so a
|
||||
// refusal's mark is checked here too.
|
||||
resp, err := r.queryDNS(ctx, ip, name, qtype)
|
||||
if resp != nil && zone == "." && resp.RecursionAvailable {
|
||||
return nil, fmt.Errorf(
|
||||
"query %s @%s: reply marked recursion available, "+
|
||||
"so not from a root server: %w",
|
||||
name, ip, ErrIntercepted,
|
||||
)
|
||||
}
|
||||
|
||||
if err == nil && !usableReply(resp, zone, name) {
|
||||
err = fmt.Errorf(
|
||||
"query %s @%s: %w", name, ip, ErrUnusableReply,
|
||||
|
||||
Reference in New Issue
Block a user