Portal | Level: L2: Operations | Topics: DNSSEC & DNS Security | Domain: Networking
DNSSEC & DNS Security — Primer¶
Why This Matters¶
DNS is the phone book of the internet, and it was designed in 1983 with no authentication. A resolver asking "what is the IP of bank.example.com?" has no way to verify that the answer came from the authoritative server and was not modified in transit. The Kaminsky attack (2008) demonstrated that an attacker could poison a resolver's cache with a forged answer in seconds using parallel queries, redirecting millions of users to malicious IPs. Any application that relies on DNS — which is every networked application — is exposed.
Who made it: The Kaminsky attack was discovered by Dan Kaminsky in 2008, when he was a 29-year-old penetration tester in Seattle. He coordinated with every major DNS vendor in secret for months before disclosure -- one of the largest coordinated vulnerability patches in internet history. He presented the findings at Black Hat wearing a suit and rollerskates. Kaminsky passed away in 2021 and was inducted into the Internet Hall of Fame.
DNSSEC (DNS Security Extensions, RFC 4033-4035) adds a chain of cryptographic signatures to DNS. Each zone signs its records, and the signing key is authenticated by the parent zone, all the way up to the root. A validating resolver can verify the entire chain and detect forged or tampered responses. DNSSEC does not encrypt DNS traffic — it authenticates it. For privacy (hiding what you're looking up), DNS-over-TLS (DoT) and DNS-over-HTTPS (DoH) are the relevant technologies.
Understanding the DNS attack surface and the defenses against it is essential for anyone responsible for production infrastructure. A misconfigured DNSSEC rollover or an expired DS record can make your entire domain unreachable, which is worse than having no DNSSEC at all.
Core Concepts¶
1. DNS Attack Surface¶
Cache Poisoning (Kaminsky Attack):
An attacker sends a flood of forged DNS responses to a resolver before the legitimate authoritative response arrives. The forged response claims to be authoritative for bank.example.com and redirects to an attacker-controlled IP. Since the resolver caches the response, all subsequent users of that resolver are redirected.
Mitigations: - Source port randomization (RFC 5452) — resolver uses random source port, raises bar from 1-in-65535 to 1-in-4-billion - DNS transaction ID randomization — 16-bit TXN ID plus random port - DNSSEC validation — the only complete fix
DNS Rebinding: An attacker registers a domain with a very short TTL. Initial DNS resolution points to a public IP (passes browser same-origin checks). Immediately after, the DNS record changes to an internal IP (e.g., 192.168.1.1). The attacker's JavaScript now has same-origin access to internal services.
Mitigation: DNS rebinding protection in resolvers (reject external names resolving to RFC 1918 addresses), firewall rules blocking inbound queries to internal IPs.
DNS Amplification (DDoS): Attacker sends a small DNS query with a spoofed source IP (victim's IP) to open resolvers. The resolver sends a large response (e.g., a DNSKEY or ANY response) to the victim. Amplification factor can exceed 100x.
Mitigation: Rate limiting (Response Rate Limiting, RRL), disable open recursion.
2. DNSSEC Chain of Trust¶
The chain starts at the root zone (.) and works down through TLDs to your zone:
Root Zone (.)
↓ DS record + RRSIG
.com
↓ DS record + RRSIG
example.com
↓ DNSKEY (ZSK + KSK) + RRSIG on all records
www.example.com A 93.184.216.34 ← RRSIG proves this is authentic
Key types: - KSK (Key Signing Key): Signs the DNSKEY record set. High-value key; changed infrequently. Its hash (DS record) is published in the parent zone. - ZSK (Zone Signing Key): Signs all other records in the zone. Rotated more frequently (monthly to yearly). Does not require parent zone update on rollover.
Remember: Mnemonic for KSK vs ZSK: "KSK = King Signs Keys, ZSK = Zone Signs Everything." The KSK only signs the DNSKEY record set (the keys themselves). The ZSK signs all the actual data records. The KSK's hash (DS record) lives in the parent zone, which is why KSK rollovers are painful -- they require coordinating with the parent.
Record types added by DNSSEC: | Record | Purpose | |--------|---------| | DNSKEY | Holds the public key for the zone | | RRSIG | Cryptographic signature over an RRset | | DS | Delegation Signer — hash of child zone's KSK, published in parent | | NSEC | Authenticated denial of existence (reveals zone enumeration) | | NSEC3 | Hashed authenticated denial (prevents zone enumeration) |
3. RRSIG — How Signatures Work¶
Every RRset (a set of records of the same type and name) gets an RRSIG record:
$ dig +dnssec www.example.com A
;; ANSWER SECTION:
www.example.com. 3600 IN A 93.184.216.34
www.example.com. 3600 IN RRSIG A 13 3 3600 (
20260415000000 20260401000000 12345 example.com.
ABC123...base64-encoded-signature... )
# Fields: covered-type algorithm labels original-ttl sig-expiry sig-inception key-tag signer signature
Algorithm 13 = ECDSA P-256 with SHA-256 (modern default). Algorithm 8 = RSA/SHA-256 (still common, larger keys).
A resolver validates by: 1. Fetching the DNSKEY for example.com 2. Verifying the DNSKEY against the DS record in .com (parent) 3. Verifying the DS record in .com against the DS in root 4. Using the DNSKEY to verify the RRSIG on the answer
4. Signing a Zone¶
Using BIND (named) with dnssec-policy:
# named.conf - modern auto-signing with dnssec-policy
zone "example.com" {
type primary;
file "zones/example.com.zone";
dnssec-policy default; # auto-manage keys and signing
key-directory "/etc/bind/keys/example.com";
inline-signing yes;
};
# Check signing status
rndc dnssec -status example.com
# Force re-sign
rndc sign example.com
Manual signing with dnssec-signzone (legacy):
# Generate ZSK
dnssec-keygen -a ECDSAP256SHA256 -n ZONE example.com
# Creates Kexample.com.+013+12345.key and .private
# Generate KSK
dnssec-keygen -a ECDSAP256SHA256 -f KSK -n ZONE example.com
# Creates Kexample.com.+013+67890.key and .private
# Sign the zone
dnssec-signzone -o example.com -N INCREMENT \
-k Kexample.com.+013+67890.key \
zones/example.com.zone \
Kexample.com.+013+12345.key
# Output: example.com.zone.signed
# Also creates dsset-example.com. with DS records for parent
Publish DS record to registrar:
cat dsset-example.com.
# example.com. IN DS 67890 13 2 AABC...long-hash...
# Submit this to your domain registrar or parent zone operator
5. Validation at Resolvers¶
BIND resolver validation:
# named.conf
options {
dnssec-validation auto; # use built-in root trust anchor
# dnssec-validation yes; # use manually specified trust anchor
};
# Check if validation is working
dig +dnssec +cd A www.dnssec-failed.org
# +cd = checking disabled, bypasses validation so you can see poisoned response
dig A www.dnssec-failed.org
# Should SERVFAIL if validation is on (this domain intentionally fails validation)
Checking validation result:
$ dig +dnssec A www.example.com | grep -E "AD|SERVFAIL"
# AD flag (Authenticated Data) means the resolver validated the response
;; flags: qr rd ra ad; QUERY: 1, ANSWER: 2
# Test DNSSEC validation
dig +dnssec SOA sigok.verteiltesysteme.net
# Should return AD flag (good signature)
dig +dnssec SOA sigfail.verteiltesysteme.net
# Should SERVFAIL (broken signature)
Unbound resolver config:
# /etc/unbound/unbound.conf
server:
auto-trust-anchor-file: "/var/lib/unbound/root.key"
val-log-level: 2 # log validation failures
# Update root trust anchor
unbound-anchor -a /var/lib/unbound/root.key
6. Key Rollover Procedures¶
ZSK rollover (pre-publish method):
Week 1: Publish new ZSK in DNSKEY (alongside old ZSK)
Wait for TTL of DNSKEY to expire everywhere
Week 2: Start signing with new ZSK (keep old ZSK in DNSKEY)
Wait for TTL of signed records to expire
Week 3: Remove old ZSK from DNSKEY
KSK rollover (double-sign method) — requires parent DS update:
Phase 1: Generate new KSK, add to DNSKEY RRset, sign DNSKEY with both KSKs
Phase 2: Submit new KSK's DS hash to parent registrar
Phase 3: Wait for parent DS TTL to expire (can be 24-48 hours)
Phase 4: Remove old KSK from DNSKEY, remove old DS from parent
This is why KSK rollovers are operationally painful. ICANN's 2018 root KSK rollover was delayed years due to concerns about resolver readiness.
War story: ICANN's root KSK rollover (KSK-2017 to KSK-2017, finally executed October 11, 2018) was the first-ever root key rollover. It was originally scheduled for 2017 but delayed a full year because ICANN couldn't confirm that enough resolvers had the new trust anchor. The stakes: a failed rollover would break DNSSEC validation for every resolver that hadn't updated, potentially knocking millions of users offline.
BIND automated rollover:
# With dnssec-policy, BIND handles this automatically
# Check scheduled rollovers
rndc dnssec -status example.com
# Force a key rollover
rndc dnssec -rollover -key 12345 example.com
7. NSEC vs NSEC3¶
NSEC proves non-existence by pointing from one record to the next in alphabetical order. An attacker can walk the zone and enumerate all records:
dig +dnssec NSEC example.com
# example.com. NSEC www.example.com. A NS SOA MX RRSIG NSEC DNSKEY
# Reveals: next name is www.example.com
NSEC3 hashes the record names with a salt before creating the chain. The hash cannot be reversed (without a rainbow table attack on common labels):
# Zone signing with NSEC3
dnssec-signzone -3 aabbccdd -H 10 -o example.com example.com.zone
# -3 enables NSEC3, aabbccdd is the salt, -H 10 is hash iterations
$ dig +dnssec NSEC3PARAM example.com
# example.com. NSEC3PARAM 1 0 10 AABBCCDD
NSEC3 is the default for new deployments. NSEC3 with opt-out (-O flag) reduces overhead in large delegated zones by allowing unsigned delegations.
8. DNS-over-HTTPS (DoH) and DNS-over-TLS (DoT)¶
Both encrypt DNS traffic to prevent eavesdropping and on-path tampering. Neither replaces DNSSEC — they are complementary.
| Protocol | Port | Transport | Use case |
|---|---|---|---|
| DNS (plain) | 53 | UDP/TCP | Legacy, unauthenticated |
| DoT | 853 | TCP+TLS | Resolver-to-forwarder, stub-to-resolver |
| DoH | 443 | HTTPS | Browser-to-resolver, hard to block |
Configure DoT on BIND resolver:
# named.conf
options {
tls local-tls {
key-file "/etc/ssl/private/named.key";
cert-file "/etc/ssl/certs/named.crt";
};
listen-on-v6 port 853 tls local-tls { ::1; };
listen-on port 853 tls local-tls { 127.0.0.1; };
};
Test DoT with kdig:
Test DoH:
curl -s -H 'accept: application/dns-json' \
'https://cloudflare-dns.com/dns-query?name=example.com&type=A' | jq
9. Split-Horizon DNS Security¶
Split-horizon (split-brain) DNS serves different answers to internal vs external clients. Security implications:
- Internal zone must be firewalled — internal records must never leak to the public internet
- DNSSEC is typically only applied to the external zone
- DNSSEC on internal zones is possible but requires managing an internal trust anchor
- Common mistake: zone transfer (AXFR) of internal zone to unauthorized server leaks topology
# Restrict zone transfers
zone "internal.example.com" {
type primary;
file "zones/internal.example.com.zone";
allow-transfer { 10.0.0.0/8; }; # Only allow internal secondary
allow-query { 10.0.0.0/8; }; # Only internal clients can query
};
10. Monitoring DNSSEC Validity¶
# Check DNSSEC chain from resolver perspective
dig +trace +dnssec A example.com
# Check DS records at parent
dig DS example.com @a.gtld-servers.net.
# Check DNSKEY at zone
dig DNSKEY example.com
# Verify signatures are not expired
dig +dnssec RRSIG SOA example.com | grep "sig-expiry"
# Online tools: dnsviz.net, dnssec-analyzer.verisignlabs.com
# Monitor expiry with Nagios/icinga check
check_dns_expiry --zone example.com --warn 30 --crit 7
Quick Reference¶
# Check if domain uses DNSSEC
dig DS example.com
dig DNSKEY example.com
# Validate resolution (AD flag = authenticated)
dig +dnssec A www.example.com | grep "flags:"
# Test intentionally broken DNSSEC (should SERVFAIL)
dig A www.dnssec-failed.org
# Walk NSEC chain (zone enumeration — why to use NSEC3)
ldns-walk example.com
# Check NSEC3 parameters
dig NSEC3PARAM example.com
# Get DS record for submission to parent
dig CDS example.com # RFC 7344 — child-published DS
dnssec-dsfromkey Kexample.com.+013+67890.key
# Kaminsky attack mitigation check
dig +short chaos version.bind @resolver.ip # Check resolver software version
# Look for randomized source ports in pcap
tcpdump -i eth0 udp port 53 -n | awk '{print $5}' | sort | uniq -c | sort -rn | head
DNSSEC algorithm numbers: | Algorithm | Number | Status | |-----------|--------|--------| | RSA/SHA-1 | 5 | Deprecated | | RSA/SHA-256 | 8 | Supported | | ECDSA P-256/SHA-256 | 13 | Recommended | | ECDSA P-384/SHA-384 | 14 | Supported | | Ed25519 | 15 | Recommended (modern) |
Interview tip: If asked about DNSSEC vs DoH/DoT, the key distinction is: DNSSEC provides authentication (the answer is genuine and untampered), while DoH/DoT provide privacy (nobody can see what you looked up). They are complementary, not competing. A complete DNS security strategy uses both.
Wiki Navigation¶
Prerequisites¶
- DNS Operations (Topic Pack, L2)
Related Content¶
- Dnssec Flashcards (CLI) (flashcard_deck, L1) — DNSSEC & DNS Security