Zone Transfers
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 REFUSED |
| TSIG | Optional by default; can be required via
requireTsig |
| IXFR handling | Full AXFR is returned — Nexus does not track per-serial deltas |
| Default state | Disabled — must opt in via dns.axfr.enabled: true |
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 zonesFields
| Field | Type | Default | Description |
|---|---|---|---|
enabled |
bool | false |
Allow AXFR/IXFR responses. Must be true to serve any
transfers. |
requireTsig |
bool | false |
Reject unsigned transfer requests with REFUSED.
Recommended for public authoritative zones. When false,
unsigned requests are accepted alongside TSIG-authenticated ones. |
Zone contents
Each transfer response contains the following record sets, in order:
| Records | Source |
|---|---|
| SOA (opening) | Synthesised from dns.nsHostname,
dns.adminEmail, serial = current Unix timestamp |
| NS | All hostnames in dns.nsNames, TTL 3600 |
| A / AAAA | All pool members with enabled: true, using each
service's configured TTL. Disabled members are excluded. Health state is
not considered — all enabled members appear regardless of current
health. |
| 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 signature- Firewall 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
# Unsigned
dig 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