Type something to search...
What Is a DNS Zone Transfer (AXFR vs IXFR)?

What Is a DNS Zone Transfer (AXFR vs IXFR)?

Every domain should be served by at least two authoritative nameservers, ideally on different networks, so that one failure does not take your site and email offline. But if you edit a record on one server, how does the other one find out? In most traditional setups, the answer is a zone transfer: the secondary server pulls a copy of the zone from the primary, either in full (AXFR) or as a set of changes (IXFR). Zone transfers are also what makes using multiple DNS providers for redundancy practical, and, when left open to the world, a well-known way of leaking your entire DNS inventory. This article explains how both transfer types work, how NOTIFY and the SOA timers drive them, how to configure and test them in BIND, and how to lock them down.

What Is a DNS Zone Transfer?

A zone transfer is the DNS mechanism for replicating a zone's contents from one authoritative server to another. The server holding the editable master copy is the primary (historically "master"), and the servers that receive copies are secondaries (historically "slaves"). Clients never see transfers; they simply get the same answers from any of the zone's nameservers.

There are two kinds:

  • AXFR (Authoritative Transfer), defined in RFC 1034 and fully specified in RFC 5936, sends the complete zone.
  • IXFR (Incremental Transfer), defined in RFC 1995, sends only the records added and removed between two versions of the zone.

Both rely on the zone's SOA record, specifically its serial number, to decide whether a transfer is needed at all.

AXFR vs IXFR at a Glance

FeatureAXFR (full)IXFR (incremental)
What is sentEvery record in the zoneOnly the differences since the secondary's serial
Defined inRFC 1034, RFC 5936RFC 1995
TransportTCPUsually TCP (UDP allowed for small responses)
Needs change historyNoYes, the primary must keep a journal of changes
Bandwidth for a small changeSize of the entire zoneSize of the change
Fallback—Falls back to AXFR if history is unavailable
Best forSmall zones, initial sync, recoveryLarge or frequently changing zones

How a Transfer Is Triggered

Secondaries learn about changes in two ways.

1. SOA polling with refresh and retry

Every secondary periodically asks the primary for the zone's SOA record. The interval comes from the SOA refresh field. If the primary's serial is higher than the secondary's copy, the secondary starts a transfer. If the primary cannot be reached, the secondary tries again after the retry interval. If it still cannot refresh by the time the expire interval runs out, the secondary stops answering for the zone rather than serve dangerously stale data.

example.com.  3600  IN  SOA  ns1.example.com. hostmaster.example.com. (
                    2026100103 ; serial
                    7200       ; refresh: check every 2 hours
                    900        ; retry: 15 minutes after a failed check
                    1209600    ; expire: stop serving after 2 weeks without contact
                    300 )      ; negative caching TTL

This is why the serial must increase on every change. If you edit a zone and forget to bump it, secondaries will never fetch your edit. The full layout of a zone file like this is explained in What Is a DNS Zone File?

2. NOTIFY

Waiting up to two hours for a refresh is too slow for most changes, so RFC 1996 added NOTIFY. When the zone changes, the primary sends a NOTIFY message to each secondary. The secondary immediately checks the SOA, sees the higher serial, and requests a transfer. In practice, NOTIFY means changes reach secondaries within seconds, and the refresh timer is only a safety net.

How AXFR Works

  1. The secondary opens a TCP connection to the primary on port 53. Transfers use TCP because zones are far larger than a single UDP response. More on why is in Why Does DNS Use Port 53?
  2. It sends a query of type AXFR for the zone name.
  3. The primary streams back every record, starting and ending with the SOA record. The repeated SOA marks the end of the transfer.
  4. The secondary replaces its copy of the zone with the new one.

You can watch this with dig, if the server permits it:

dig @ns1.example.com example.com AXFR
example.com.        3600  IN  SOA   ns1.example.com. hostmaster.example.com. 2026100103 7200 900 1209600 300
example.com.        3600  IN  NS    ns1.example.com.
example.com.        3600  IN  NS    ns2.example-dns.net.
example.com.        3600  IN  A     203.0.113.10
example.com.        3600  IN  MX    10 mail.example.com.
mail.example.com.   3600  IN  A     203.0.113.25
www.example.com.    300   IN  CNAME example.com.
example.com.        3600  IN  SOA   ns1.example.com. hostmaster.example.com. 2026100103 7200 900 1209600 300
;; XFR size: 8 records (messages 1, bytes 312)

Notice the SOA at both ends. If the server refuses, you will see ; Transfer failed., which is what you want to see from any machine that is not an authorised secondary.

How IXFR Works

  1. The secondary sends an IXFR query that includes its current SOA serial.
  2. The primary looks up its change history from that serial to the current one.
  3. If it has the history, it sends a sequence of difference blocks. Each block starts with the old SOA, lists the records deleted, then the new SOA, then the records added.
  4. If it does not have the history, or the difference would be larger than the zone itself, it may respond with a full AXFR-style answer instead.
  5. If the secondary is already current, the primary replies with just its SOA.

You can request an incremental transfer from a given serial with dig:

dig @ns1.example.com example.com IXFR=2026100101
example.com.  3600  IN  SOA  ns1.example.com. hostmaster.example.com. 2026100103 7200 900 1209600 300
example.com.  3600  IN  SOA  ns1.example.com. hostmaster.example.com. 2026100101 7200 900 1209600 300
www.example.com.  300  IN  A      203.0.113.10
example.com.  3600  IN  SOA  ns1.example.com. hostmaster.example.com. 2026100102 7200 900 1209600 300
www.example.com.  300  IN  CNAME  example.com.
example.com.  3600  IN  SOA  ns1.example.com. hostmaster.example.com. 2026100102 7200 900 1209600 300
example.com.  3600  IN  SOA  ns1.example.com. hostmaster.example.com. 2026100103 7200 900 1209600 300
api.example.com.  3600  IN  A    203.0.113.20
example.com.  3600  IN  SOA  ns1.example.com. hostmaster.example.com. 2026100103 7200 900 1209600 300

Read it as: current serial 2026100103; from 2026100101 to 2026100102, delete the www A record and add a www CNAME; from 2026100102 to 2026100103, delete nothing and add an api A record; final SOA closes the response. Each change set is only a few records, regardless of how big the zone is.

Where the change history comes from

IXFR only works if the primary keeps a journal of changes. In BIND, zones updated through dynamic DNS (RFC 2136, for example with nsupdate) get a journal automatically. If you edit zone files by hand and reload, BIND can build a journal by comparing the old and new versions when you set ixfr-from-differences yes;. Without either, BIND falls back to AXFR.

Configuring Zone Transfers in BIND

Here is a minimal primary and secondary configuration with transfers authenticated by a TSIG key, a shared secret that signs each transfer message (RFC 8945). First, generate the key on the primary:

tsig-keygen -a hmac-sha256 transfer-key > /etc/bind/transfer.key

This writes a key statement with a random base64 secret to /etc/bind/transfer.key. Copy that file securely to the secondary.

On the primary (named.conf):

include "/etc/bind/transfer.key";

zone "example.com" {
    type primary;
    file "/etc/bind/db.example.com";
    notify yes;
    also-notify { 198.51.100.53 key transfer-key; };
    allow-transfer { key transfer-key; };
    ixfr-from-differences yes;
};

This loads the key, sends NOTIFY messages to the secondary at 198.51.100.53, permits transfers only to clients that sign their requests with transfer-key, and builds IXFR history from manual edits.

On the secondary:

include "/etc/bind/transfer.key";

zone "example.com" {
    type secondary;
    file "/var/cache/bind/db.example.com";
    primaries { 203.0.113.53 key transfer-key; };
    allow-notify { 203.0.113.53; };
};

This tells the secondary to fetch the zone from 203.0.113.53, signing requests with the shared key, and to accept NOTIFY messages only from the primary. Check both configurations before reloading:

sudo named-checkconf
sudo rndc reload

named-checkconf validates the configuration files and prints nothing if they are correct. On the secondary, you can force or inspect transfers with rndc:

sudo rndc refresh example.com     # check the SOA now, transfer if needed
sudo rndc retransfer example.com  # force a full transfer regardless of serial
sudo rndc zonestatus example.com  # show serial, last refresh and expiry

These commands are useful when testing a new secondary or recovering from a corrupted copy. A complete server setup is covered in How to Run Your Own DNS Server with BIND.

To test a TSIG-protected transfer from the command line, pass the key file to dig:

dig @203.0.113.53 example.com AXFR -k /etc/bind/transfer.key

Without -k, the same query should fail; with it, the zone should stream back.

Transfers with Managed DNS Providers

Many managed DNS providers can act as a secondary to your primary, or as a primary that allows transfers to your own secondaries. Typically you enter the primary's IP address and a TSIG key in their dashboard, and they handle NOTIFY and IXFR for you. Remember that provider-specific features, such as ALIAS records, geo-routing and health-checked records, are not part of standard zone data and do not survive a transfer. If you rely on them, you will need to configure them separately at each provider, or use API-based synchronisation instead of AXFR.

Securing Zone Transfers

An open zone transfer hands anyone your complete list of hostnames, including internal-sounding ones like vpn, staging or jenkins. That is free reconnaissance for an attacker. Lock transfers down as follows:

  1. Never allow transfers to any. In BIND, set allow-transfer explicitly on every zone, and consider a global default of allow-transfer { none; }; in the options block.
  2. Authenticate with TSIG rather than relying only on IP addresses, which can be spoofed or reassigned.
  3. Restrict at the network level. Allow inbound TCP 53 from secondaries for transfers, while still allowing TCP 53 for normal queries that fall back from UDP.
  4. Consider encrypting transfers. RFC 9103 defines XFR over TLS (XoT), which protects zone contents in transit. Support is available in recent BIND, NSD and Knot versions.
  5. Test from outside. Periodically run dig @your-nameserver example.com AXFR from a machine that is not a secondary and confirm it fails.
  6. Monitor serials. Compare SOA serials across all nameservers so a stuck secondary is noticed before the expire timer runs out.
for ns in $(dig +short example.com NS); do
  printf '%-30s %s\n' "$ns" "$(dig +short @"$ns" example.com SOA | awk '{print $3}')"
done

This loop lists each nameserver for the zone and the serial it is serving. Every line should show the same number. A mismatch that lasts more than a few minutes means transfers are failing. For broader security hardening, see How to Secure DNS Against Attacks.

Pulling a Zone Programmatically

dnspython can perform a transfer and give you a parsed zone, which is handy for audits and backups:

import dns.query
import dns.zone

zone = dns.zone.from_xfr(dns.query.xfr("203.0.113.53", "example.com"))

for name, ttl, rdata in zone.iterate_rdatas():
    print(name.derelativize(zone.origin), ttl, rdata.to_text())

dns.query.xfr performs an AXFR against the given server, and dns.zone.from_xfr assembles the streamed records into a zone object; the loop prints every record with its fully qualified name and TTL. For TSIG-protected servers, pass keyring and keyname arguments to dns.query.xfr.


DNS Zone Transfer FAQ

AXFR transfers the entire zone every time. IXFR transfers only the records that changed since the secondary's current serial, which is far more efficient for large or frequently updated zones.

AXFR always uses TCP. IXFR normally uses TCP too, though the standard allows UDP when the response is small enough. Either way, port 53 is used unless the transfer is encrypted with XoT, which runs over TLS on port 853.

The most common cause is forgetting to increase the SOA serial. Others include blocked TCP 53, a mismatched TSIG key, NOTIFY messages being rejected, or the primary's allow-transfer rule not including the secondary.

Allowing them to anyone is. An open AXFR reveals every hostname in your zone. Restrict transfers to known secondaries and authenticate them with TSIG.

NOTIFY is a message the primary sends to secondaries when a zone changes, prompting them to check the serial and transfer immediately instead of waiting for the refresh timer.

It keeps serving its existing copy and retries at the SOA retry interval. If it cannot refresh before the expire interval runs out, it stops answering for the zone.

Only if the primary has change history for the secondary's serial. If not, it falls back to sending the full zone, so a transfer still succeeds.

Yes, many managed providers support acting as a primary or secondary with standard AXFR and IXFR. Provider-specific record types and routing features do not transfer, though.

Conclusion

Zone transfers are the quiet replication layer behind redundant authoritative DNS. AXFR copies the whole zone and is simple and robust, which makes it ideal for small zones and initial synchronisation. IXFR sends only what changed, using the SOA serial and a journal of changes, which keeps large or busy zones in sync with minimal traffic. NOTIFY makes both fast, and the SOA refresh, retry and expire timers act as a safety net when NOTIFY messages are lost.

Getting transfers right comes down to a short checklist: increase the serial on every change, enable NOTIFY, keep a journal if you want IXFR, authenticate with TSIG, restrict allow-transfer to your secondaries, and monitor serials across every nameserver. Do that, and your secondaries will stay in sync without exposing your zone to the rest of the internet.

Here are some useful references for going deeper on DNS zone transfers:

  1. RFC 5936: DNS Zone Transfer Protocol (AXFR) — the current specification for full zone transfers.
  2. RFC 1995: Incremental Zone Transfer in DNS — defines IXFR and its difference-sequence format.
  3. RFC 1996: A Mechanism for Prompt Notification of Zone Changes (DNS NOTIFY) — how primaries alert secondaries to changes.
  4. RFC 8945: Secret Key Transaction Authentication for DNS (TSIG) — the shared-key authentication used to protect transfers.
  5. RFC 9103: DNS Zone Transfer over TLS — encrypting zone transfers with XoT.
  6. BIND 9 Documentation: BIND 9 Administrator Reference Manual — configuring primaries, secondaries, TSIG and rndc.
Tags :
Share :

Related Posts

What Is the Difference Between Authoritative and Recursive DNS Servers?

What Is the Difference Between Authoritative and Recursive DNS Servers?

When someone says "the DNS server," they could mean two completely different machines doing two completely different jobs. One kind of server holds t

Continue Reading
Can DNS settings affect website speed?

Can DNS settings affect website speed?

Yes, DNS settings can significantly affect the speed at which a website loads for its users. DNS, or Domain Name System, is often likened to the inte

Continue Reading
Can You Use a CNAME Record on the Root Domain?

Can You Use a CNAME Record on the Root Domain?

It is one of the most common DNS questions there is. Your hosting platform says "add a CNAME pointing to myapp.example-cdn.net," it works perfectly

Continue Reading