DNS has one quiet mercy built into how you query it: you have to know a name before you can ask about it. There’s no LIST command. You can look up mail.example.com if you already suspect it exists, but you can’t say “show me every name in this zone” — the protocol answers questions, it doesn’t hand out the index. That property is the reason internal-jenkins.example.com and vpn-old.example.com and staging-db.example.com can sit in public DNS for years without anyone stumbling onto them. They resolve fine if you know to ask; nobody knows to ask. (DNSSEC zones signed with plain NSEC are the exception — their denial records chain from one name to the next and can be walked, which is why NSEC3 exists. That’s a different leak.)

Except for one operation that does exactly the thing the rest of DNS refuses to do. It lists the whole zone. Every record, in order, in a single conversation. It’s called a zone transfer, it’s a core feature the system can’t work without — and when it’s left open, it’s the fastest reconnaissance win on the internet: you point a tool at a nameserver and ask it to mail you the phone book, and sometimes it does.

Why the feature has to exist

Zone transfers aren’t a bug or a backdoor. They’re how DNS stays up.

A zone — the set of records for a domain — is served by more than one nameserver on purpose. If example.com had a single authoritative server and it fell over, the domain would vanish from the internet: no website, no email, nothing resolves. So you run a primary that holds the master copy and one or more secondaries that serve identical answers, ideally on different networks. When a resolver asks any of them, it gets the same zone.

Which raises the obvious question: how do the secondaries get the data? They copy it from the primary, and the mechanism for that copy is the zone transfer. The full version, AXFR, is standardized in RFC 5936: it runs over TCP on port 53 and streams every record in the zone — the SOA, the NS records, every A and AAAA and MX and TXT and CNAME. Its efficient sibling, IXFR (RFC 1995), transfers only what changed since the secondary’s last copy, so a zone with thousands of records and one edit doesn’t re-ship the whole thing. A third message, NOTIFY, lets the primary poke the secondaries when something changes so they don’t have to wait for a timer.

This is genuinely good engineering. Zone transfers are why DNS survives a dead server, a datacenter outage, a botched deploy on one node. The redundancy the entire internet leans on is built out of one server copying its zone to another.

The part that goes wrong

The problem is the same one that shows up everywhere in infrastructure: a mechanism built for a trusted party, exposed to an untrusted one.

AXFR was designed for your secondaries to call. The primary is supposed to answer transfer requests only from the specific servers you’ve told it about. But nothing in the protocol enforces that by itself — the access control is configuration you have to add. Leave it off, or write the catch-all allow-transfer { any; }, and the primary will happily stream the entire zone to anyone on the internet who asks. Not one record. All of them.

And “all of them” is the whole game, because it defeats the mercy I opened with. Normally an attacker has to guess your names — brute-force a wordlist against your DNS, hoping dev, vpn, git, backup happen to be live, learning nothing about the names they didn’t think to try. An open AXFR skips all of that. It doesn’t return the names you guessed; it returns the names you’d never guess. The oddly-specific internal hostname. The staging environment nobody remembered was still pointed somewhere. The old VPN concentrator. The mail gateway, the monitoring box, the four regional load balancers with a naming scheme that tells you exactly how the rest of the infrastructure is laid out. One request, and the shape of your network is on someone else’s screen.

The command to try it is not exotic. It’s one line of a tool that ships with, or is one package away on, every operating system:

dig axfr @ns1.example.com example.com

If transfers are locked down, you get a curt refusal. If they’re open, your terminal fills with the zone. This is not a sophisticated exploit — it’s dig doing exactly what it’s documented to do. Which is why it’s step one of essentially every external reconnaissance methodology: before anyone runs a fancy scanner, they ask each of your nameservers, politely, for the whole map. It costs nothing to try and occasionally it just works.

Scans of the internet keep finding open transfers in numbers that should be embarrassing — not on obscure hobby domains but across nameservers that ought to know better. It stays common because it fails silently: an open AXFR breaks nothing, degrades nothing, throws no error. Everything works perfectly right up until the moment someone who isn’t your secondary asks the question.

Locking it down (and why that’s not quite enough)

The fix has two layers, and most people stop after the first.

The first layer is access control by address: configure the primary to answer transfers only from the IPs of your known secondaries, and refuse everyone else. This is the baseline, it’s simple, and allow-transfer { any; } should never appear in a config file. But IP allowlists have the weakness every IP-based control has — addresses get shared and reassigned, secondaries move, and a rule that’s right today rots as the infrastructure changes.

The second layer is TSIG, the DNS transaction signature mechanism (RFC 8945). Primary and secondary share a secret key and sign their transfer requests and responses with it, typically using HMAC-SHA256. Now the primary isn’t trusting a source IP — it’s checking that the requester holds the shared secret and that the message wasn’t tampered with in flight. TSIG is what turns “probably my secondary” into “provably my secondary.” If your nameservers support it, use it; it’s strictly better than an ACL alone.

Here’s the part almost nobody accounts for, though: even a perfectly locked-down AXFR is sent in cleartext. TSIG authenticates the transfer and guarantees integrity, but it does not encrypt anything. Which means the entire zone still crosses the network in the clear on its way from primary to secondary, and anyone positioned to watch that traffic — a compromised link, a passive tap between your datacenters — can harvest the whole zone by eavesdropping, without ever sending a request the ACL could reject. You didn’t hand out the phone book; someone read it over your shoulder.

That gap is why the IETF eventually published XFR-over-TLS (XoT) in RFC 9103 in 2021: run the zone transfer inside a TLS tunnel so the copy is confidential in transit, not just authenticated. It’s the same move the rest of DNS has been making — DNS-over-TLS, DNS-over-HTTPS — finally applied to the bulk-copy path that had been quietly shipping your whole namespace as plaintext for decades.

What it says about the protocol

Zone transfers are a small, clean example of a pattern worth recognizing, because it repeats all over infrastructure. A mechanism gets designed for cooperation between parties who trust each other — a primary and its secondaries, replicating a zone. The design is correct for that relationship. Then the same endpoint gets left reachable by parties the design never contemplated, the trust assumption quietly stops holding, and a feature becomes a disclosure.

The defense isn’t to distrust the feature; DNS needs zone transfers and always will. It’s to be precise about who the feature is for — name the secondaries, prove them with a key, encrypt the copy — and to remember that the internet’s default posture toward anything reachable is to ask it a question and see what falls out. DNS spends most of its design making you know a name before you can ask about it. It would be a shame to undo all of that with one line of config that mails the list to whoever knocks.