Zone transfers are how BIND, the venerable DNS server software, keeps DNS records synchronized between different authoritative servers. Specifically, a primary (or master) server holds the definitive copy of a zone’s records, and secondary (or slave) servers request copies of this zone data from the primary. This ensures redundancy and distributes the load of answering DNS queries.
Imagine you have a zone called example.com. Your primary server, ns1.example.com, has the master copy of example.com’s DNS records. You want ns2.example.com to also be authoritative for example.com, but you don’t want to manually edit its zone file. This is where zone transfers come in. ns2 will periodically ask ns1 for the entire example.com zone file.
Here’s a simplified view of the BIND configuration for this. On your primary server (ns1.example.com), you need to tell BIND which secondary servers are allowed to request zone transfers. This is done in the named.conf file, typically within the zone definition for example.com:
zone "example.com" IN {
type master;
file "zones/db.example.com";
allow-transfer { 192.168.1.2; }; // IP of ns2.example.com
};
The allow-transfer directive is crucial. It specifies the IP addresses of the secondary servers that are permitted to initiate a zone transfer. In this case, only 192.168.1.2 (which we assume is ns2.example.com) can request the example.com zone data from ns1.
On the secondary server (ns2.example.com), you configure it to be a slave of the primary. Again, this goes into named.conf:
zone "example.com" IN {
type slave;
file "slaves/db.example.com";
masters { 192.168.1.1; }; // IP of ns1.example.com
};
Here, type slave declares this server as a secondary. The masters directive lists the IP addresses of the primary servers from which it should request zone data. ns2 will periodically query ns1 (at 192.168.1.1) for updates to the example.com zone. BIND typically checks for updates every 15 minutes by default, but this interval is controlled by the refresh parameter in the SOA record of the zone file.
The actual zone transfer happens using the AXFR (Authoritative Transfer) or IXFR (Incremental Zone Transfer) protocol. AXFR is a full zone transfer, sending the entire zone file. IXFR is more efficient, sending only the changes since the last transfer. BIND prefers IXFR if available and supported by both servers.
To see zone transfers in action, you can use dig or nslookup to query for zone transfer information, though this is more for debugging than direct observation of the transfer process itself. A more direct way is to monitor BIND’s logs. When a secondary server initiates a transfer, you’ll see messages like:
client @0x7f8d6c001000 192.168.1.2#54321: Transfer of 'example.com/IN' from 192.168.1.1#53: Transfer completed: 5 records transferred.
This log entry indicates that ns2 (at 192.168.1.2) successfully received 5 records for the example.com zone from ns1 (at 192.168.1.1).
The SOA (Start of Authority) record in the zone file plays a critical role in managing zone transfers. It contains several fields that dictate transfer behavior:
- Serial Number: A monotonically increasing number that changes every time the zone file is updated. The secondary server compares this serial number with the one it has. If the primary’s serial is higher, a transfer is initiated.
- Refresh: The interval (in seconds) at which the secondary server should check the primary for updates.
- Retry: The interval (in seconds) at which the secondary server should retry a failed transfer.
- Expire: The time (in seconds) after which the secondary server will stop serving zone data if it cannot contact the primary.
- Minimum TTL: The default Time To Live for records in the zone.
For example, a typical SOA record for example.com might look like this:
$TTL 86400
@ IN SOA ns1.example.com. admin.example.com. (
2023102701 ; Serial
3600 ; Refresh (1 hour)
1800 ; Retry (30 minutes)
604800 ; Expire (1 week)
86400 ) ; Minimum TTL (1 day)
When you make a change to db.example.com on ns1, you must increment the serial number. Failing to do so will prevent secondary servers from picking up the changes, as their SOA serial will remain higher or equal. A common practice is to use a date-based serial, like YYYYMMDDnn, where nn is a sequence number for that day, making it easy to track and ensure monotonicity.
The allow-transfer directive on the primary is not the only security measure. You can also use TSIG (Transaction Signature) to authenticate zone transfers, ensuring that only authorized servers can perform them and that the data hasn’t been tampered with in transit. This involves generating shared secret keys and configuring both primary and secondary servers to use them for specific zone transfers.
One subtle aspect of zone transfers is how BIND handles NOTIFY messages. When a primary server detects a change in a zone (e.g., by seeing its serial number increment), it can send a NOTIFY message to its configured secondaries. This proactively tells the secondary servers that an update is available, prompting them to initiate a transfer sooner than their scheduled refresh interval would dictate. To enable this, you need also-notify in your BIND configuration, specifying the IP addresses of the servers to notify:
zone "example.com" IN {
type master;
file "zones/db.example.com";
allow-transfer { 192.168.1.2; };
also-notify { 192.168.1.2; }; // Notify ns2.example.com
};
This makes your DNS infrastructure much more responsive to changes.
After successfully configuring zone transfers, the next immediate hurdle you’ll likely encounter is ensuring that firewalls between your primary and secondary servers permit UDP and TCP traffic on port 53, as these are the ports BIND uses for DNS queries and zone transfers, respectively.