A DNS zone transfer is one of those foundational mechanisms that keeps the internet's naming system from falling apart — yet it's frequently misunderstood, poorly secured, and occasionally exploited. Whether you're setting up a secondary nameserver, troubleshooting why your secondary DNS isn't reflecting changes, or trying to understand why a security scanner flagged your nameserver, you're in the right place. This article covers exactly how zone transfers work at a protocol level, how to configure them correctly on common DNS software, how to lock them down against unauthorized reconnaissance, and how to verify everything is functioning as expected.

What Is a DNS Zone Transfer?

A DNS zone is a portion of the DNS namespace managed by a specific organization or administrator. It's stored in a zone file that contains all the resource records (A, AAAA, MX, CNAME, TXT, NS, SOA, etc.) for a domain. A zone transfer is the mechanism by which a secondary (slave) nameserver obtains a copy of that zone file from the primary (master) nameserver.

The purpose is simple: redundancy and availability. If your primary nameserver goes down, secondary nameservers can continue answering queries. But for secondaries to be useful, they need current data — and zone transfers are how that data gets replicated.

Zone transfers use TCP port 53, not UDP. This is because zone transfer payloads can be large, exceeding the 512-byte UDP limit (even with EDNS0 extensions). The TCP connection provides reliable, ordered delivery of the full zone data.

The Two Types of Zone Transfer: AXFR and IXFR

There are two distinct transfer mechanisms defined in DNS standards:

  • AXFR (Authoritative Transfer) — A full zone transfer. The secondary requests the entire zone from the primary, regardless of what it already has. Defined in RFC 1035 and later refined in RFC 5936. AXFR is used for initial replication and as a fallback.
  • IXFR (Incremental Transfer) — An incremental zone transfer, defined in RFC 1995. The secondary sends its current SOA serial number to the primary, and the primary responds with only the changes since that serial. This is far more efficient for large zones with frequent updates.

Modern DNS software (BIND, PowerDNS, Knot DNS) supports both. IXFR falls back to AXFR automatically if the primary doesn't have the incremental history needed to satisfy the request.

The SOA Record and Serial Numbers: The Heartbeat of Zone Sync

The SOA (Start of Authority) record is the control record for zone transfers. It contains several critical fields:

  • Serial — An integer that increments with each zone change. Secondaries compare their serial to the primary's to decide if a transfer is needed.
  • Refresh — How often (in seconds) the secondary polls the primary's SOA to check for changes.
  • Retry — How long the secondary waits before retrying after a failed refresh.
  • Expire — How long the secondary continues serving the zone if it can't reach the primary. After this, it stops answering as authoritative.
  • Minimum TTL — The default TTL applied to negative responses (NXDOMAIN).

The transfer process works like this: the secondary periodically sends a SOA query to the primary. If the primary's serial is higher than the secondary's, the secondary initiates an AXFR or IXFR. If serials match, no transfer occurs. This is why forgetting to increment the SOA serial after a zone change is one of the most common reasons a secondary nameserver stays out of date.

💡 After making zone changes, use the DNS Propagation Checker to confirm your secondary nameservers are serving the updated records — not just the primary.

How Zone Transfers Work Step by Step

  1. The secondary nameserver's refresh timer fires (based on the SOA Refresh value).
  2. The secondary sends a SOA query (UDP or TCP) to the primary nameserver's IP address.
  3. The primary responds with its current SOA record, including the serial number.
  4. The secondary compares the primary's serial to its own. If the primary's serial is higher, proceed. If equal or lower, stop — no transfer needed.
  5. The secondary opens a TCP connection to port 53 on the primary and sends an IXFR or AXFR request.
  6. The primary checks its allow-transfer ACL. If the secondary's IP is not permitted, the primary sends a REFUSED response.
  7. If permitted, the primary streams the zone data. For AXFR, this is the full zone bounded by two SOA records (one at start, one at end). For IXFR, it's a sequence of deleted and added records between serials.
  8. The secondary writes the received data to its local zone storage and begins serving it.

NOTIFY messages (RFC 1996) optimize this process. Instead of waiting for the refresh timer, the primary actively notifies secondaries immediately after a zone change. Secondaries receiving a NOTIFY immediately trigger a SOA check and transfer if needed, dramatically reducing propagation lag.

Configuring Zone Transfers in BIND (Named)

BIND is still the most widely deployed authoritative DNS software. Here's how to configure zone transfers correctly.

On the primary (master) server, in named.conf:

zone "example.com" IN { type master; file "/var/named/example.com.zone"; allow-transfer { 203.0.113.10; 203.0.113.11; }; // Secondary IPs only also-notify { 203.0.113.10; 203.0.113.11; }; notify yes; };

On the secondary (slave) server, in named.conf:

zone "example.com" IN { type slave; masters { 203.0.113.1; }; // Primary server IP file "/var/named/slaves/example.com.zone"; };

After editing, reload BIND without a full restart:

rndc reload # Or for a specific zone: rndc reload example.com

To manually trigger a zone transfer from the secondary:

rndc retransfer example.com

Configuring Zone Transfers in PowerDNS

PowerDNS Authoritative Server uses a database backend, so zone transfers involve its API and configuration file (/etc/powerdns/pdns.conf):

# Allow transfer to specific secondaries allow-axfr-ips=203.0.113.10,203.0.113.11 # Enable NOTIFY also-notify=203.0.113.10,203.0.113.11

For TSIG-secured transfers in PowerDNS:

# Generate a TSIG key pdnsutil generate-tsig-key mykey hmac-sha256 # Assign it to the zone pdnsutil set-meta example.com TSIG-ALLOW-AXFR mykey pdnsutil set-meta example.com SLAVE-RENOTIFY mykey

Securing Zone Transfers: The Critical Part Most People Get Wrong

An open zone transfer — one that allows any IP to request your full zone — is a significant security exposure. An attacker can enumerate every hostname, IP, mail server, and internal service name in your DNS zone in seconds. This is called zone enumeration and is a standard first step in reconnaissance.

There are three layers of protection you should implement:

1. IP-Based ACLs (Minimum Requirement)

Restrict allow-transfer to only the IP addresses of your legitimate secondary nameservers. Never use allow-transfer { any; }; in production. This is the baseline — it's not sufficient on its own because IP spoofing is possible in some network configurations.

2. TSIG (Transaction Signature) Keys

TSIG uses a shared HMAC secret to cryptographically sign DNS messages between primary and secondary. Even if an attacker spoofs the secondary's IP, they cannot forge a valid TSIG signature without the shared key. TSIG is defined in RFC 2845 and is supported by all major DNS servers.

Generating a TSIG key in BIND:

# Generate key material tsig-keygen -a hmac-sha256 transfer-key # Output looks like: key "transfer-key" { algorithm hmac-sha256; secret "base64encodedkeyhere=="; };

Place this key block in named.conf on both servers, then reference it in the zone configuration:

// On primary: allow-transfer { key transfer-key; }; // On secondary: masters { 203.0.113.1 key transfer-key; };

3. Firewall Rules

Block TCP port 53 inbound at your firewall for all sources except your known secondary nameserver IPs. DNS resolvers and clients only need UDP 53 (and TCP 53 for large responses). Zone transfers are the only reason you need inbound TCP 53 from external addresses.

# iptables example: allow TCP 53 only from secondaries iptables -A INPUT -p tcp --dport 53 -s 203.0.113.10 -j ACCEPT iptables -A INPUT -p tcp --dport 53 -s 203.0.113.11 -j ACCEPT iptables -A INPUT -p tcp --dport 53 -j DROP

Testing and Verifying Zone Transfers with dig

The dig command is the right tool to test zone transfers directly. Use it to audit whether your server is properly restricting transfers:

Attempt an AXFR (should be REFUSED from unauthorized IPs):

dig @ns1.example.com example.com AXFR

A properly secured server returns:

; Transfer failed. ;; Connection to 203.0.113.1#53(203.0.113.1) for example.com failed: REFUSED

From an authorized secondary, a successful AXFR looks like a stream of all records followed by a closing SOA:

example.com. 3600 IN SOA ns1.example.com. admin.example.com. 2026072901 3600 900 604800 300 example.com. 3600 IN NS ns1.example.com. example.com. 3600 IN NS ns2.example.com. example.com. 3600 IN A 93.184.216.34 mail.example.com. 3600 IN A 93.184.216.35 example.com. 3600 IN SOA ns1.example.com. admin.example.com. 2026072901 3600 900 604800 300

Check what serial number your secondary is currently serving:

dig @ns2.example.com example.com SOA +short

Compare it to the primary:

dig @ns1.example.com example.com SOA +short

If the serials differ, the secondary hasn't successfully transferred yet. Use our DNS Lookup tool to check SOA records across multiple nameservers simultaneously without needing a terminal.

Common Reasons Zone Transfers Fail

When your secondary isn't picking up changes, these are the most frequent causes, ranked by how often they appear in practice:

  1. SOA serial not incremented — The most common mistake. If the primary's serial equals the secondary's, no transfer is initiated. Always increment the serial after any zone change. Use the date-based format YYYYMMDDNN (e.g., 2026072901) to make this obvious.
  2. IP not in allow-transfer ACL — The secondary's IP isn't whitelisted on the primary. Check both the zone-level and any global options block in named.conf.
  3. Firewall blocking TCP 53 — A firewall between primary and secondary is dropping TCP connections. Test with nc -zv 203.0.113.1 53 from the secondary.
  4. TSIG key mismatch — The key name, algorithm, or secret doesn't match between primary and secondary. BIND logs will show BADSIG errors in this case.
  5. masters directive points to wrong IP — The secondary is configured to transfer from the wrong server, or the primary's IP changed.
  6. Zone file permissions — The named process on the secondary can't write the transferred zone to disk. Check /var/named/slaves/ ownership.
  7. Refresh interval too long — With a 24-hour refresh and no NOTIFY, changes can take a full day to propagate. Ensure NOTIFY is enabled.

Checking Logs for Transfer Errors

BIND logs zone transfer activity to syslog. On most Linux systems:

# Real-time BIND log monitoring journalctl -u named -f # Or check syslog directly grep named /var/log/syslog | grep -E 'transfer|AXFR|IXFR|refused' # On RHEL/CentOS: grep named /var/log/messages

Successful transfer log line looks like:

named[1234]: transfer of 'example.com/IN' from 203.0.113.1#53: Transfer completed: 1 messages, 47 records, 1842 bytes, 0.023 secs (80087 bytes/sec)

Failed transfer (REFUSED):

named[1234]: transfer of 'example.com/IN' from 203.0.113.1#53: failed while receiving responses: REFUSED

Zone Transfers and DNSSEC

When DNSSEC is enabled, zone transfers include RRSIG, DNSKEY, NSEC/NSEC3, and DS records. The zone is larger, but the transfer mechanism is identical — AXFR/IXFR still applies. One important consideration: if you're using inline signing in BIND (where BIND signs the zone automatically), the signed version of the zone is what gets transferred. Secondaries receive the signed zone and serve it directly without needing access to private signing keys — which is the correct architecture.

For TSIG-secured transfers with DNSSEC, the TSIG signature applies at the transaction level (authenticating the transfer itself), while DNSSEC signatures apply at the record level (authenticating the data). They serve complementary roles and should both be used.

Zone Transfers in 2026: Hidden and Catalog Zones

Modern DNS deployments are moving away from manually configuring each zone on each secondary. Two mechanisms address this at scale:

  • Catalog Zones (RFC 9432) — A special zone that lists other zones. When a zone is added to the catalog on the primary, secondaries automatically discover and begin transferring it. BIND 9.18+ and Knot DNS support this. It eliminates the per-zone configuration on secondaries entirely.
  • DNS-over-TLS for zone transfers — XFR-over-TLS (RFC 9103) encrypts zone transfer traffic, preventing eavesdropping on zone contents in transit. This is increasingly important as TSIG alone doesn't provide confidentiality, only authentication.

If you're running a hosting provider or managing hundreds of zones, catalog zones and XFR-over-TLS represent the current best practice for 2026 deployments.

Misdiagnoses to Watch For

A few situations that look like zone transfer problems but aren't:

  • Resolver caching, not secondary lag — If dig queries to a resolver (not directly to the nameserver) show stale data, the resolver's cache TTL may not have expired yet. Always query nameservers directly with dig @ns1.example.com to bypass resolver caches.
  • Wrong nameserver in registrar delegation — If your domain's NS records at the registrar still point to an old nameserver, clients will query the wrong server regardless of whether your transfer is working perfectly.
  • Hidden primary architecture — Some setups use a hidden primary (not listed in public NS records) that pushes to public-facing secondaries. If you're querying the primary directly and wondering why dig AXFR returns records, that's expected — restrict transfers from the public-facing secondaries, not necessarily the hidden primary.
⚠️ Run a security audit: use dig @your-nameserver yourdomain.com AXFR from a machine that is NOT your secondary. If you receive zone data instead of REFUSED, your zone transfer is open to the world and needs to be locked down immediately.

How to Confirm the Fix Worked

  1. Increment the SOA serial on the primary and reload the zone.
  2. Wait for the NOTIFY to reach the secondary (usually within seconds) or manually trigger with rndc notify example.com on the primary.
  3. On the secondary, run dig @localhost example.com SOA +short and confirm the serial matches the primary.
  4. From an unauthorized IP, confirm dig @ns1.example.com example.com AXFR returns REFUSED.
  5. Check BIND logs for a successful transfer completion message.