Hardening DNS infrastructure
DNS is trusted by everything and verified by almost nothing, which is why a resolver you run carelessly becomes a weapon pointed at other people and an authoritative server you run carelessly becomes a map of your estate and a channel out of it. The threats are familiar, cache poisoning, amplification, tunneling, zone disclosure and the defenses are not exotic. They come down to four decisions: who may ask your resolver to recurse, who may pull your zones, whether your answers can be forged and whether you can see data leaving in your own queries.
Separate the two roles
The first mistake is running one server that both recurses for internal clients and answers authoritatively for public zones. Those are opposite trust postures and they belong on different machines. The authoritative server in the DMZ answers for your public zones and recurses for no one; the resolver inside answers your clients and is unreachable from the internet. Collapsing them is how you end up an open resolver by accident.
Close recursion, or become an amplifier
An open resolver, one that will recurse for any source address, is the raw material of an amplification attack: a 64-byte spoofed query pulls a multi-kilobyte answer toward a victim and your server is the gun. The fix is to recurse only for the networks that are yours:
// named.conf, the resolver
acl internal { 10.0.0.0/8; 192.168.0.0/16; 127.0.0.1; };
options {
allow-query { internal; };
allow-recursion { internal; };
recursion yes; // a resolver recurses, but only for 'internal'
};
The authoritative server takes the opposite stance, recursion off entirely, because an authoritative server has no business resolving anything:
options {
recursion no;
allow-query { any; }; // it answers for its own zones, to anyone
};
Response Rate Limiting blunts amplification even for the legitimately-public authoritative server, by capping how often an identical answer is sent to a spoofed flood:
options {
rate-limit { responses-per-second 10; window 5; };
};
Lock down zone transfers
A zone transfer hands over every record you have, which to an attacker is a finished inventory: every host, every service, the whole shape of the network in one AXFR. By default far too many servers answer it to anyone. Transfers go to your secondaries and nobody else, authenticated with a TSIG key rather than trusted by IP, which a spoofer can forge:
key "xfr-key" { algorithm hmac-sha256; secret "..."; };
zone "company.com" {
type primary;
allow-transfer { key "xfr-key"; }; // secondaries hold the same key
notify yes;
};
Everyone else attempting an AXFR gets refused and the inventory stays yours.
DNSSEC: make answers unforgeable
Recursion limits and TSIG protect your servers; DNSSEC protects your answers, by signing them so a resolver that validates can tell a forged record from a real one and defeat cache poisoning at the source. It signs, it does not encrypt, so it is about integrity and authenticity, not confidentiality and it is worth being clear about that because people reach for it expecting privacy it never offered. Modern BIND automates most of the key handling:
zone "company.com" {
type primary;
dnssec-policy default; // automatic ZSK/KSK, signing, rollover
inline-signing yes;
};
The one manual step that cannot be skipped is publishing the DS record in the parent zone, because that is the link that ties your signatures into the chain of trust from the root. Sign the zone and forget the DS and you have done the work and gained none of the protection.
See what leaves in your own queries
DNS is the exfiltration channel of choice precisely because it is allowed out everywhere a firewall otherwise says no and because a request for <base64-chunk>.exfil.attacker.com looks like any other lookup. I have built the benign version of this, IP tunneled over DNS, so I have no illusions about how quietly it moves: the data rides in the labels going out, the answers ride back in TXT or NULL records and the volume can be kept under any rate threshold. You will not block it with a signature. What you can do is watch your own resolver logs for the shape of it, abnormally long or high-entropy labels, a single client generating a steady stream of unique subdomains under one parent, a sustained run of TXT queries and treat that pattern as the signal it is. Query logging on the resolver is the precondition; without it the channel is simply invisible.
Response Policy Zones are the enforcement side of the same coin, turning a threat-intelligence feed of known-bad domains into NXDOMAIN or a sinkhole at resolution time:
response-policy { zone "rpz.local"; };
// in rpz.local: malware.example. CNAME . (forces NXDOMAIN)
On encrypted transport
DoT and DoH encrypt the client-to-resolver hop, which is a real gain against eavesdropping and on-path tampering and a real complication for an enterprise that relies on seeing DNS to defend it. The tension is honest: the same encryption that stops an ISP reading your lookups stops your own monitoring reading them and DoH in particular lets an endpoint bypass the corporate resolver entirely and talk to a public one over 443. The defensible posture is to run your own DoT/DoH resolver, point clients at it and block outbound DNS, plaintext and encrypted both, to everything else, so queries are protected on the wire and still pass through the resolver you can see.
Where to land
Split authoritative from recursive and never let one be the other. Recurse only for your own networks so you are not an amplifier, rate-limit the authoritative server and restrict zone transfers to TSIG-authenticated secondaries so your inventory stays private. Sign your zones with DNSSEC and publish the DS record so the signatures mean something. Log queries on the resolver, because tunneling is invisible without the logs and obvious with them and enforce known-bad domains through RPZ. Encrypt the client hop with your own resolver rather than letting endpoints wander off to public DoH. None of it is new and all of it is still undone on more networks than not.
[edit: 2026] The Ansible implementation of all this: the unbound role .