Fixing BIND9 TSIG Zone Transfer Failures & REFUSED Errors Published: 02 Sep, 2026
The Anatomy of TSIG Verification Failures in BIND9
When operating a multi-tier authoritative DNS infrastructure, zone synchronisation between primary and secondary name servers relies on AXFR (full zone transfer) or IXFR (incremental zone transfer) over TCP port 53. To prevent unauthorised zone snooping and spoofing, transaction signatures (TSIG) cryptographically authenticate communication using shared secret keys.
When TSIG negotiation fails, BIND9 immediately rejects the zone transfer request, returning a REFUSED status or logging a cryptic tsig verify failure. The primary server refuses to send zone serial increments, leaving secondary servers serving stale data until the zone expires entirely according to the SOA EXPIRY timer.
Diagnosing Transfer Refusals with System Logs and Dig
To pinpoint why named is aborting transfers, inspect the operational logs on both primary and secondary nodes. If transfer logging is not explicitly isolated into dedicated channels, the error often masks itself behind generic network timeout messages.
Inspect the systemd journal on the secondary server for the transfer attempt:
journalctl -u named -n 50 -e --no-pager | grep -E "transfer|zone|tsig"A misconfigured secret or algorithm mismatch emits the following operational failure in the secondary node log:
named[41280]: transfer of 'example.com/IN' from 192.0.2.10#53: failed to connect: tsig verify failure
named[41280]: transfer of 'example.com/IN' from 192.0.2.10#53: Transfer status: REFUSEDOn the primary server, the corresponding log message confirms the authorization rejection:
named[10412]: client @0x7f8a1c000c80 198.51.100.25#49152: request has invalid signature: TSIG transfer-key.example.com: tsig verify failure (BADKEY)You can simulate and isolate the transaction directly using dig by providing the TSIG algorithm and key inline:
dig @192.0.2.10 example.com AXFR -y hmac-sha256:transfer-key.example.com:c2VjcmV0a2V5ZGF0YTEyMzQ1Njc4OTA=Root Causes and Production Resolutions
| Failure Flag / Code | Underlying Root Cause | Targeted Fix |
|---|---|---|
| BADKEY | Name mismatch or key not declared in primary's named.conf | Verify matching key identifier strings across both nodes. |
| BADSIG | Cryptographic mismatch or secret hash corruption | Regenerate shared secret with tsig-keygen. |
| BADTIME | NTP drift exceeding the TSIG fudge window (±300s) | Synchronise system clocks using chronyd. |
| REFUSED (No TSIG err) | IP omitted from allow-transfer or missing server block | Map remote IP to the key inside the server directive. |
1. Resolving Cryptographic and Secret Formatting Mismatches
A frequent error is manually base64-encoding keys or using deprecated hash algorithms like HMAC-MD5 or HMAC-SHA1. Generate a clean HMAC-SHA256 key block using native BIND9 tooling:
tsig-keygen -a hmac-sha256 transfer-key.example.comThis outputs the standardized configuration block:
key "transfer-key.example.com" {
algorithm hmac-sha256;
secret "Wz7j1xT8ZgP3M8aLk5Y9dE2Q1vB4N6m8K0jX7sL2rA4=";
};2. Binding Keys to Remote Nameservers via Server Directives
Simply declaring the key block inside named.conf.local is insufficient. The secondary resolver must be explicitly instructed to sign outgoing requests directed at the primary's IP address. Without a server directive, the secondary sends an unsigned AXFR request, which triggers an access denial.
Secondary server configuration (/etc/bind/named.conf.local):
key "transfer-key.example.com" {
algorithm hmac-sha256;
secret "Wz7j1xT8ZgP3M8aLk5Y9dE2Q1vB4N6m8K0jX7sL2rA4=";
};
server 192.0.2.10 {
keys { "transfer-key.example.com"; };
};
zone "example.com" {
type secondary;
file "/var/cache/bind/db.example.com";
primaries { 192.0.2.10; };
};Primary server configuration (/etc/bind/named.conf.local):
key "transfer-key.example.com" {
algorithm hmac-sha256;
secret "Wz7j1xT8ZgP3M8aLk5Y9dE2Q1vB4N6m8K0jX7sL2rA4=";
};
zone "example.com" {
type primary;
file "/var/lib/bind/db.example.com";
allow-transfer { key "transfer-key.example.com"; };
notify yes;
also-notify { 198.51.100.25 key "transfer-key.example.com"; };
};3. Correcting Clock Skew (BADTIME Failures)
TSIG timestamps carry a default validity window (fudge) of 300 seconds. If virtual machine clocks drift beyond 5 minutes, signatures fail immediately with BADTIME.
Check system synchronization status on both servers:
timedatectl statusEnsure chronyd or systemd-timesyncd is active and enforcing NTP sync:
sudo systemctl enable --now chrony
sudo chronyc trackingApplying Configuration and Verifying Transfer
Validate the syntax of your configuration files before restarting the daemon:
named-checkconf /etc/bind/named.confReload the configuration dynamically using rndc without dropping active recursive queries or cache state:
rndc reconfig
rndc reloadTo force an immediate synchronization check and inspect the zone transfer transaction in real-time, execute:
rndc retransfer example.comVerify that the raw zone file has landed in the secondary cache path (e.g., /var/cache/bind/db.example.com) and check that the authoritative SOA serial matches across both endpoints.