Zone transfer: AXFR / IXFR / SOA
Zone transfer copies zone data from a primary to its secondaries; the SOA serial tells a secondary whether it needs to pull.
Asks for the serial and the timers every secondary follows.
dig @1.1.1.1 isitdns.net SOA +multilineGO one SOA with the serial, refresh, retry, expire and minimum labelled
NO GO one SOA TTL after you publish, a serial older than the primary's
What it is#
Zone transfer is server-to-server replication of an authoritative zone. AXFR (RFC 5936) copies the whole zone, always over TCP. IXFR (RFC 1995) copies only what changed since a given serial, over UDP when the reply fits one packet or TCP otherwise (RFC 1995 section 2). NOTIFY (RFC 1996) is the primary's push telling secondaries a new serial exists, so they don't wait for the next refresh poll. The SOA serial drives all three: a secondary pulls when the primary's serial is newer than its own.
When to use it#
- You run your own secondaries and need them serving the same data as the primary.
- An external party (a partner, a secondary DNS service) serves your zone from their servers.
- You are migrating a zone to a new provider: they pull it once by AXFR, then you cut the NS records over.
- You are authorized to inspect a full zone you don't operate, from an IP the primary allows.
When not to use it#
- Inside a managed provider or appliance cluster. Cluster replication moves zone data over the vendor's own channel; you do not expose AXFR between the nodes.
- To get data into resolvers. Resolvers learn records by querying and caching, governed by TTL. Transfer is authoritative-to-authoritative only.
- To fetch a zone without authorization. A primary that answers your AXFR is misconfigured (see the
allow-transfergotcha below), and the transfer hands over the zone's full contents. - A stub zone is not a transfer consumer. Stubs copy NS + SOA (plus glue) only.
dig for transfers: AXFR and IXFR#
Replace PRIMARY_IP with the primary nameserver's IP address and ZONE_NAME with the zone you are transferring.
dig @PRIMARY_IP ZONE_NAME AXFRThe primary must allow the transfer from your IP. dig's AXFR output is one record per line, ending with the SOA repeated: RFC 5936 section 2.2 requires the transfer to open and close with the same SOA record, which is the end-of-zone marker.
dig @PRIMARY_IP ZONE_NAME IXFR=SERIALReplace SERIAL with the serial your secondary currently holds. If the primary can't satisfy the incremental gap, it responds with a full AXFR instead.
nslookup has no portable IXFR capability and no reliable cross-platform AXFR support. Use dig for transfers.
SOA timers: the knobs that govern transfer behavior#
The SOA RDATA holds four timers plus the serial; they control transfer cadence and freshness:
| Field | What it does | Example |
|---|---|---|
refresh | How often a secondary checks the primary's SOA (when NOTIFY is not trusted) | 3600 (1h) |
retry | If a refresh failed, when to retry | 900 (15m) |
expire | If the primary stays unreachable this long, the secondary stops serving the zone | 604800 (1w) |
minimum (negative TTL) | One of the two inputs to how long resolvers cache NXDOMAIN answers | 1800 (30m) |
The SOA record itself also has a TTL (set at the zone level, outside the RDATA), which governs how long other resolvers cache the SOA record. It is also the other input to the negative TTL: RFC 2308 section 5 takes the negative TTL from the lower of
SOA.MINIMUMand the SOA record's own TTL.
Pulling minimum down before adding a record that previously didn't exist avoids long NXDOMAIN-caching pain, because the negative TTL is the smaller of the two (RFC 2308 section 5). See soa for the full timer walkthrough.
Gotchas#
- AXFR is TCP-only. A firewall that blocks TCP/53 (only allows UDP/53) breaks transfers silently. See anatomy-of-a-query for the TCP vs UDP decision logic.
- NOTIFY without authentication is spoofable. NOTIFY rides UDP with no handshake, so well-configured secondaries accept it only from their configured masters; check
also-notify/masterson each side. - Set
allow-transferexplicitly, and prefer TSIG over an IP-only ACL. TSIG (RFC 8945) authenticates the request with a shared secret; an IP-only ACL only checks the TCP source address. BIND 9.18 and earlier default to allowing transfers to any host; BIND 9.20 changed the default to deny, requiring an explicitallow-transferACL (9.20.0 release notes). NSD denies unlisted or blocked addresses by default (nsd.conf(5)). Knot'sacllist defaults to not set, which denies transfers, updates and NOTIFY alike (Knot reference: acl). PowerDNS'sallow-axfr-ipsdefaults to127.0.0.0/8,::1, localhost only (PowerDNS settings). An open AXFR hands your entire zone to anyone who asks. - TSIG clock skew. TSIG signs requests with a timestamp tolerance ("fudge") of 300 seconds recommended by RFC 8945 section 10. NTP drift beyond that breaks transfers. Bad clocks also break DNSSEC validation, but on a different scale: validation only fails once the clock lands outside the RRSIG validity window, usually hours or days wide, not 300 seconds. See dnssec-troubleshooting.
- A stub zone is not a secondary. Stubs copy NS + SOA (plus glue) only; they do not AXFR/IXFR the full zone. See stub.
- Dynamic update (RFC 2136) is different. DDNS updates the zone in place and bumps the SOA; the update itself is not a transfer, but AXFR/IXFR is how that change then reaches secondaries. See ddns.