Zone Transfers (AXFR / IXFR)
Nexus GSLB implements RFC 5936 full zone transfer (AXFR) and RFC 1995 incremental zone transfer (IXFR, served as AXFR fallback). This allows secondary nameservers, CDN providers, and monitoring tools to pull a consistent snapshot of the zone.
Overview
Property | Value |
|---|---|
Protocol | DNS QUERY, qtype AXFR (252) or IXFR (251) |
Standards | RFC 5936 (AXFR), RFC 1995 (IXFR) |
Transport | TCP/53 only — UDP AXFR requests receive |
TSIG | Optional by default; can be required via |
IXFR handling | Full AXFR is returned — Nexus does not track per-serial deltas |
Default state | Disabled — must opt in via |
Configuration
dns: domain: "gslb.cc" nsNames: - "ns1.gslb.cc" - "ns2.gslb.cc" axfr: enabled: true # required — AXFR is disabled by default requireTsig: true # recommended for public-facing zones
Fields
Field | Type | Default | Description |
|---|---|---|---|
| bool |
| Allow AXFR/IXFR responses. Must be |
| bool |
| Reject unsigned transfer requests with |
Zone contents
Each transfer response contains the following record sets, in order:
Records | Source |
|---|---|
SOA (opening) | Synthesised from |
NS | All hostnames in |
A / AAAA | All pool members with |
TXT | All TXT records managed via the API or RFC 2136 dynamic updates |
SOA (closing) | Identical to the opening SOA — required bookend per RFC 5936 §2.2 |
GSLB note on A/AAAA records
In a standard authoritative zone, a domain name resolves to a fixed set of IPs. In a GSLB zone, the DNS server returns a single IP selected by the load-balancing algorithm on each query. Zone transfers expose the full member set rather than a single selected answer, because secondary servers have no health state.
This is intentional — secondaries should have all IPs available so that if the primary becomes unreachable, the secondary serves some answer rather than NXDOMAIN. Combine secondary serving with short TTLs (10–60s) to minimise stale-cache effects when members fail.
TSIG authentication
If the client request includes a TSIG record, Nexus validates it against the TSIG key store (the same store used for RFC 2136 dynamic updates). If validation fails, the server responds with NOTAUTH.
If the client request has no TSIG and requireTsig: true is set, the server responds with REFUSED.
To create a TSIG key for a secondary DNS server:
curl -X POST https://nexus-api.example.com/api/v1/dns/tsig-keys \ -H "Authorization: Bearer $GSLB_API_KEY" \ -H "Content-Type: application/json" \ -d '{"name": "secondary-bind9.gslb.cc.", "algorithm": "hmac-sha256."}'
Save the returned secret — it is shown once and not retrievable later. See RFC 2136 reference for full TSIG key management API.
Message framing
Records are streamed in multiple TCP messages rather than one large frame. Each message carries at most 100 RRs, keeping frames well under 16 KB. The SOA bookend is always in the final message. All messages in a single transfer share the same SOA serial, so receivers see a consistent snapshot even if DB state changes mid-transfer.
IXFR fallback
Nexus does not maintain per-serial zone diffs. When a secondary requests IXFR, Nexus responds with a full AXFR transfer. This is valid per RFC 1995 §4:
"If an IXFR query with the same or newer serial number is received, it MUST be treated as an AXFR query."
All major secondary DNS implementations (BIND 9, Knot DNS, NSD, CoreDNS, PowerDNS) accept AXFR in response to IXFR and handle it transparently.
Permissions
Zone transfers are served by the DNS server directly and do not go through the REST API permission layer. Access control is via:
dns.axfr.enabled— global on/off switchdns.axfr.requireTsig— require a valid TSIG signatureFirewall rules on port 53/TCP — restrict by source IP at the network level
There is no per-tenant access control for AXFR. Any client with a valid TSIG key (from any tenant) can transfer the zone when requireTsig: true. Use firewall rules when tighter control is needed.
Troubleshooting
REFUSED on AXFR request
dns.axfr.enabledisfalse— set it totrueand restart.The request came over UDP — AXFR requires TCP. Verify your secondary is configured for TCP transfer.
requireTsig: trueis set but the request has no TSIG key — add a TSIG key to the secondary configuration.
NOTAUTH on AXFR request
TSIG signature validation failed. Common causes:
Wrong key name (must match exactly, including trailing dot)
Wrong secret value
Clock skew greater than 5 minutes between secondary and primary
Empty zone (SOA only, no A records)
No services are configured, or all configured services have no pool assigned (
pool_id IS NULL)All pool members are disabled (
enabled: false)Database is nil (DNS server started without a DB path)
Test the transfer manually
# Unsigneddig AXFR gslb.cc @<nexus-ip> -p 53# With TSIG (requires bind-utils / dig with TSIG support)dig AXFR gslb.cc @<nexus-ip> -p 53 \ -y "hmac-sha256:secondary-bind9.gslb.cc.:<base64-secret>"
Code references
internal/dns/axfr.go:handleAXFR,buildZoneRRsinternal/dns/server.go:AXFRConfig, routing inhandleDNSRequestinternal/storage (rqlite.go + storage_*.go):ListServices,ListAllTXTRecords