ci/docs: Fall back to discovered servers for AXFR
The DNS reference generator transfers each zone from the nameservers public NS discovery returns. The home IPv6 reverse zone (0.d.4.0.0.c.7.9.e.0.a.2.ip6.arpa) is delegated only to Hurricane Electric, which refuses AXFR, so generation aborted before committing any zone. Our own authoritative servers (ns1/ns2.h.nul.ie) serve that zone and permit transfers but aren't in its public delegation, as their addresses are dynamic. When a zone's delegated servers all refuse, retry against the union of nameservers discovered for every other zone. That pool includes ns1/ns2.h.nul.ie via the h.nul.ie NS records, resolved to their current addresses at query time, so the reverse zone transfers from the same reachable servers h.nul.ie already uses. Zones whose own servers work are unaffected; the fallback only runs after their transfers fail. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
+18
-3
@@ -144,9 +144,19 @@ def discover_nameservers(domains: list[str], port: int) -> dict[str, list[str]]:
|
||||
return discovered
|
||||
|
||||
|
||||
def transfer_domain(port: int, domain: str, servers: list[str]) -> list[Record]:
|
||||
def transfer_domain(
|
||||
port: int, domain: str, servers: list[str], fallback: list[str] = ()
|
||||
) -> list[Record]:
|
||||
# A zone may be delegated publicly to servers that refuse AXFR (e.g. HE serving
|
||||
# reverse DNS) while our own authoritative servers, discovered for other zones,
|
||||
# will transfer it. Try the delegated servers first, then fall back to those.
|
||||
ordered = list(servers)
|
||||
for server in fallback:
|
||||
if server not in ordered:
|
||||
ordered.append(server)
|
||||
|
||||
errors = []
|
||||
for server in servers:
|
||||
for server in ordered:
|
||||
try:
|
||||
return transfer(server, port, domain)
|
||||
except RuntimeError as error:
|
||||
@@ -325,8 +335,13 @@ def main() -> int:
|
||||
|
||||
try:
|
||||
nameservers = discover_nameservers(args.domain, args.port)
|
||||
fallback = []
|
||||
for servers in nameservers.values():
|
||||
for server in servers:
|
||||
if server not in fallback:
|
||||
fallback.append(server)
|
||||
transferred = [
|
||||
(domain, transfer_domain(args.port, domain, nameservers[domain]))
|
||||
(domain, transfer_domain(args.port, domain, nameservers[domain], fallback))
|
||||
for domain in args.domain
|
||||
]
|
||||
except RuntimeError as error:
|
||||
|
||||
Reference in New Issue
Block a user