docs / guides

Zone transfers fail with NOTAUTH or REFUSED: fixing BIND and PowerDNS AXFR

A zone exists on the primary and the secondary knows about it, yet the zone never arrives. On the secondary (a ZoneCloud Node, or any BIND slave) the log shows:

transfer of 'example.com/IN' from 203.0.113.10#53: connected using 198.51.100.20#33439
transfer of 'example.com/IN' from 203.0.113.10#53: failed while receiving responses: NOTAUTH
transfer of 'example.com/IN' from 203.0.113.10#53: Transfer status: NOTAUTH
transfer of 'example.com/IN' from 203.0.113.10#53: Transfer completed: 0 messages, 0 records, 0 bytes

NOTAUTH or REFUSED means the connection worked, but the primary (203.0.113.10) won’t hand the zone to the secondary (198.51.100.20). This is the most common zone-transfer failure we see in support, and it’s almost always configuration on the primary.

How a secondary gets a zone

Three things have to line up:

  1. The secondary has an entry for the zone, pointing at the primary. On a ZoneCloud Node, the Node writes it into its zones file (ZONES_FILE in /etc/zcloudnode.conf, by default /var/named/zones.conf):
    zone "example.com" {
        type slave;
        file "slaves/example.com.db";
        masters { 203.0.113.10; };
        allow-notify { 203.0.113.10; };
    };
  2. The primary allows the secondary to transfer the zone, and notifies it when the zone changes.
  3. The network lets the transfer through. Zone transfers use TCP port 53, so a firewall that allows only UDP 53 lets queries through but stops transfers.

NOTAUTH and REFUSED are failures of step 2.

Test it in one command

From the secondary, ask the primary for the zone yourself:

dig @203.0.113.10 example.com AXFR
  • The whole zone scrolls by: the primary allows this secondary. Look at the secondary’s entry and its logs instead.
  • ; Transfer failed. The primary refuses this secondary’s address. Read on.
  • A timeout or connection refused: nothing reached a DNS server over TCP 53. Check the firewall between the two machines, and that the primary’s DNS server listens on TCP (ss -lntu | grep ':53 ').

Run it from the secondary itself, so the primary sees the same source address it sees in a real transfer. On a host with several IPs, that’s the address the secondary uses towards the primary.

Fix it on a BIND primary

The secondaries’ IPs must be in allow-transfer, and in also-notify so that changes are announced:

options {
    notify yes;
    allow-transfer { 198.51.100.20; 198.51.100.21; };
    also-notify   { 198.51.100.20; 198.51.100.21; };
};

Two traps:

  • A zone-level allow-transfer overrides the global one. If a zone’s own block in named.conf has allow-transfer { … };, the list in options {} doesn’t apply to that zone. Some panels write a per-zone list or an ACL there. Add the secondaries to it, or to the ACL it names.
  • ACLs must contain the addresses you think they do. allow-transfer { nodes; }; only works if the acl nodes { … }; it points to lists the secondaries’ current IPs.

Reload BIND (rndc reconfig, or rndc reload after editing zone files) and test again with dig.

On a ZoneCloud Agent with BIND, the Agent keeps notify, allow-transfer and also-notify in options {} up to date itself, in a block marked // --- zcloud managed begin ---. Existing entries and ACL names are kept. A zone-level list still overrides it, as above.

Fix it on a PowerDNS primary

PowerDNS refuses all transfers until it is told otherwise. In pdns.conf:

primary=yes
disable-axfr=no
allow-axfr-ips=127.0.0.0/8, 198.51.100.20, 198.51.100.21
also-notify=198.51.100.20, 198.51.100.21
allow-unsigned-notify=yes

primary is the PowerDNS 4.5+ name; older releases call it master. Restart PowerDNS. When PowerDNS’s own NOTIFY is turned away, its log shows:

Received unsuccessful notification report for 'example.com' from 198.51.100.20:53, error: Query Refused

That one is the other way round: the secondary refuses the NOTIFY. Check the secondary’s allow-notify for the primary’s address.

A ZoneCloud Agent on PowerDNS writes these settings into pdns.conf itself: see PowerDNS with the BIND backend. On cPanel, also see Agent on cPanel PowerDNS.

Which DNS server is the primary really running?

A common surprise: the config you edit isn’t the server that answers. A cPanel or Enhance server may run PowerDNS while /etc/named.conf still exists, or the other way round. Check what is listening on port 53:

ss -lntup | grep ':53 '

The process name (pdns_server or named) tells you which config matters.

After the fix

On the secondary, ask for the zone again and watch the log:

rndc retransfer example.com
journalctl -u named -f        # named-chroot on some EL systems

Then compare serials. The secondary should report the same SOA serial as the primary:

dig +short @203.0.113.10 example.com SOA
dig +short @198.51.100.20 example.com SOA

If the serials match but the records differ, the primary changed the zone without raising its serial, so the secondary has nothing to fetch. Raise the serial on the primary.

Still failing?