Zone transfers are BIND’s way of keeping DNS zones synchronized between authoritative servers. Reloading a zone tells BIND to re-read its zone file, while forcing a zone transfer makes a secondary server actively pull the latest version from its master.
Here’s BIND in action, demonstrating a zone transfer. Imagine we have a primary server (ns1.example.com) and a secondary server (ns2.example.com) for the example.com zone.
Primary Server (ns1.example.com) Configuration (named.conf):
zone "example.com" {
type master;
file "/var/named/zones/db.example.com";
allow-transfer { 192.168.1.2; }; // IP of ns2.example.com
};
Secondary Server (ns2.example.com) Configuration (named.conf):
zone "example.com" {
type slave;
file "/var/named/zones/db.example.com.slave";
masters { 192.168.1.1; }; // IP of ns1.example.com
};
Zone File (/var/named/zones/db.example.com) on ns1.example.com:
$ORIGIN example.com.
@ IN SOA ns1.example.com. admin.example.com. (
2023102701 ; Serial
3600 ; Refresh
1800 ; Retry
604800 ; Expire
86400 ) ; Minimum TTL
;
@ IN NS ns1.example.com.
@ IN NS ns2.example.com.
@ IN A 192.0.2.1
ns1 IN A 192.168.1.1
ns2 IN A 192.168.1.2
www IN A 192.0.2.10
Now, let’s say we need to add a new record to example.com. On ns1.example.com, we edit /var/named/zones/db.example.com:
$ORIGIN example.com.
@ IN SOA ns1.example.com. admin.example.com. (
2023102702 ; Serial (Incremented!)
3600 ; Refresh
1800 ; Retry
604800 ; Expire
86400 ) ; Minimum TTL
;
@ IN NS ns1.example.com.
@ IN NS ns2.example.com.
@ IN A 192.0.2.1
ns1 IN A 192.168.1.1
ns2 IN A 192.168.1.2
www IN A 192.0.2.10
mail IN A 192.0.2.20 ; New record
Notice the serial number is incremented to 2023102702. This is crucial.
Reloading the Primary:
To make ns1.example.com aware of this change, we reload its zone:
sudo rndc reload example.com
BIND will re-read the db.example.com file. The serial number change is the signal that the zone has been updated.
Triggering the Transfer on the Secondary:
Now, ns2.example.com needs to get this updated zone. By default, it will wait for the Refresh interval (3600 seconds, or 1 hour) to check. To force it to sync now, we use rndc:
sudo rndc retransfer example.com
This command tells ns2.example.com to immediately initiate a zone transfer from its configured masters. It will query ns1.example.com for the zone’s SOA record, see the new serial number 2023102702, and pull the entire zone file.
Verifying the Transfer:
On ns2.example.com, you can check the BIND logs (often /var/log/messages or /var/log/syslog) for messages indicating a successful zone transfer. You can also inspect the slave zone file:
cat /var/named/zones/db.example.com.slave
You should see the mail IN A 192.0.2.20 record.
The most surprising true thing about zone transfers is that BIND doesn’t actually compare the content of the zone files directly when deciding whether to transfer. It relies solely on the serial number in the SOA record. If the serial number on the master is higher than what the slave last recorded, the slave will request a transfer. This makes serial number management absolutely critical.
BIND operates on a master-slave (now primary-secondary) model for zone data distribution. The primary server holds the authoritative, master copy of the zone data. Secondary servers are configured to periodically poll the primary for updates. This polling is driven by the Refresh interval in the SOA record. When a secondary server polls and finds that the primary’s SOA serial number is higher than its own, it initiates a full zone transfer (AXFR or IXFR). AXFR (Authoritative Transfer) sends the entire zone file. IXFR (Incremental Zone Transfer) sends only the changes since the last successful transfer, which is more efficient but requires the primary to keep track of changes.
The allow-transfer directive on the primary controls which IP addresses are permitted to request zone transfers. This is a fundamental security measure to prevent unauthorized replication of your DNS zone data. The masters directive on the secondary specifies the IP addresses of the primary servers from which it should fetch zone data.
Reloading a zone (rndc reload zone_name) on the primary server is a user-initiated action. It tells the BIND process to re-read the zone file from disk. This is necessary after making manual edits to the zone file. If you don’t reload, the primary server will continue to serve the old data from memory until it’s restarted or the zone is reloaded.
Forcing a transfer (rndc retransfer zone_name) on the secondary server bypasses the Refresh timer. It immediately triggers the secondary to check the master’s SOA serial number and initiate a transfer if it’s newer. This is useful for ensuring that changes are propagated as quickly as possible without waiting for the next scheduled refresh.
A common pitfall is forgetting to increment the serial number in the SOA record on the primary server after editing the zone file. If the serial number isn’t incremented, the secondary server will not detect any changes and will not perform a zone transfer, even if you reload the primary and force a transfer on the secondary. The serial number format is typically YYYYMMDDnn, where YYYY is the year, MM is the month, DD is the day, and nn is a two-digit sequence number for changes made on the same day.
Beyond the serial number, the Retry and Expire timers in the SOA record are also important. Retry specifies how long the secondary should wait before retrying a failed transfer. Expire determines how long a secondary server will continue to serve zone data if it can no longer contact the primary. If the Expire time is reached and the secondary hasn’t successfully transferred the zone, it will typically stop serving the zone data to prevent serving stale information.
The next concept you’ll run into is understanding DNSSEC validation and how it interacts with zone transfers, particularly when dealing with signed zones and key rollovers.