resolver: a reply marked recursion available from a root server's address stops the lookup (closes #300)
check / check (push) Canceled after 0s

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 the
existing "this network intercepts DNS queries", naming the address,
and no other root server is asked, whether or not that resolver had
the name cached. queryDNS now returns a refused reply along with
ErrRefused, so the mark on a refusal can be seen. A refusal without
the mark is passed over and counted as before.

On such a network dnswatcher and its tests fail with that error, by
design. A live test passes public resolvers as the root servers and
expects it.

Model: opus-5-5
This commit is contained in:
2026-10-16 09:53:00 +00:00
committed by sneak
parent adc8131191
commit 4a4a966eb5
5 changed files with 113 additions and 9 deletions
+12
View File
@@ -561,6 +561,18 @@ This approach ensures:
- Ability to detect split-horizon or inconsistent responses across authoritative
servers.
A root server never offers recursion, so a reply marked "recursion available"
from a root server's address came from a recursive resolver on the network
answering in its place, as on a network where a router rule, a VPN or a DNS
filter sends all DNS to one resolver. The first such reply from a root server's
address, a refusal included, stops the lookup at once with the error "this
network intercepts DNS queries", naming that address, and no other root server
is asked. A lookup that every root server refuses without that mark fails with
the same error. Every lookup starts at the root servers, so on such a network
every lookup fails with that error, whether or not that resolver has the name
cached, and dnswatcher's tests fail there too. That is by design: nothing asks
again another way or otherwise works around the interception.
A watched name's records are stored as its nameservers return them, CNAME
included. When they return a CNAME and no address, the chain of every CNAME
target they gave is followed (with a depth limit to prevent loops) to the A and