Zone transfers need a shared key, not just a source-address rule
- date
- 20260818
- what happened
- Setting up the second DNS secondary during the migration to Technitium, the primary's address-based access control for zone transfers proved not to be durable. The secondary intermittently requested a transfer from a different one of its own addresses than the one the primary's allow list expected, and the primary refused it.
- what it cost
- Intermittent, silent zone-transfer failures that an address-based rule could not explain, since both addresses involved were legitimately the secondary's own.
- what changed
- Zone transfers were switched to authorisation by a shared cryptographic transfer key, which removes the source address from the authorisation decision entirely. A related dependency was documented at the same time: rebuilding the primary from scratch, rather than restoring its data, silently breaks replication to a secondary still configured for the old key, with nothing alerting on the failure.
- the check now
- Authorise zone transfers by a shared key, never by source address alone, particularly on DNS software that manages its own outbound source address selection. After rebuilding a primary, verify the transfer key on every secondary explicitly.
DNS secondaries are supposed to be a solved, boring problem. Point a secondary at a primary, authorise it, and the zone data replicates. The authorisation mechanism that looks obvious is an allow list: permit only the secondary’s own known address to request a transfer, and refuse everyone else.
On 20260818 that turned out not to be reliable on this particular DNS server software, for a reason that has nothing to do with the network. A host with more than one address does not necessarily use the address you expect when it opens an outbound connection, and this software was not consistent about which of its own addresses it sourced a transfer request from. The primary refused the ones it did not recognise. Both addresses were the secondary’s, both were legitimate, and no packet was lost or misrouted. The rule simply could not express the thing it was trying to express.
Transaction signatures fix this properly. Both servers hold the same shared key, the secondary signs its request with it, and the primary authorises on the signature rather than on where the request appears to come from. That removes an entire category of “which address did it actually come from” bugs at essentially no added operational cost once set up.
There is a second-order dependency worth knowing about. Because the key now carries the authorisation, rebuilding a primary from scratch rather than restoring its data leaves every secondary still holding the old key, and replication stops with nothing raising an alarm about it. Verify the key on each secondary explicitly after any rebuild, rather than assuming a restore carried it.
Source: node0 lessons v0.1, lesson 4.12. Sanitized: checklist v0.1, 20260921; transfer key names; voice pass 20260921. Part of oznog.com/node0.
