On this page
DNSSEC and DNS Security
DNS was not designed with security in mind—DNSSEC adds a "non-repudiable" proof to every DNS record using a chain of digital signatures. It does not encrypt (DNS over HTTPS handles encryption); it prevents tampering—the cost being the maintenance of the signature chain and the amplification effect on related domains.
Overview
Traditional DNS lacks cryptographic protection: any intermediate node can forge responses (DNS spoofing). DNSSEC does not encrypt queries; instead, it signs each DNS record, forming a chain of trust from the root to the target domain. A resolver can verify that "this A record was indeed issued by the authoritative server for example.com." The cost is larger response packets (RRSIG records) and more complex zone management (KSK/ZSK rotation). DNSSEC deployment is approximately 30% (as of 2024), partly because it does not address privacy issues—hence the need for DoH/DoT as supplements.
Problem: DNS Lacks Authentication
Traditional DNS responses have no cryptographic guarantees. Attackers can:
- Cache Poisoning: Send forged referrals/glue records → recursive resolver caches poisoned RRs
- Man-in-the-Middle Attacks: Forge DNS responses along the path → client receives fake IPs
DNSSEC solves this: sign each zone → form a chain of trust from root to leaf → resolver can verify step-by-step.
Note: DNSSEC does not encrypt queries (encryption = DoH/DoT/DoQ). Users are still exposed to: "ISP sees what domain names you queried."
Record Types
RRSIG (type 46):
Signature for a set of RRsets (not signed individually per RR!)
RDATA:
Type Covered (2B): The RR type being signed
Algorithm (1B): 5=RSA/SHA1 (deprecated), 7=RSASHA1-NSEC3-SHA1, 8=RSA/SHA-256,
10=RSA/SHA-512, 13=ECDSA-P256-SHA256, 14=ECDSA-P384-SHA384,
15=ED25519, 16=ED448
Labels (1B): Number of labels in the original owner name
Original TTL (4B): Original TTL (not the RRSIG's own TTL!)
Signature Expiration (4B): Signature expiration time (Unix timestamp)
Signature Inception (4B): Signature inception time
Key Tag (2B): Numeric tag used to identify the DNSKEY
Signer's Name (label format): The zone that produced this signature (usually the zone's apex)
Signature (variable): The actual signature (of the canonical form of the RRset)
DNSKEY (type 48):
Zone public key used to verify RRSIGs
RDATA:
Flags (2B):
bit 7 (Zone Key): 1 → This key is used for DNSSEC
bit 15 (Secure Entry Point): 1 → KSK (Key Signing Key),
0 → ZSK (Zone Signing Key)
Protocol (1B): Always 3
Algorithm (1B): Same as RRSIG Algorithm
Public Key (variable)
DS (type 43):
Hash of the KSK, stored in the parent zone → forms a cross-zone trust chain
RDATA:
Key Tag (2B): Matches the DNSKEY's key tag
Algorithm (1B): Same as DNSKEY
Digest Type (1B): 1=SHA-1 (deprecated), 2=SHA-256, 4=SHA-384
Digest (variable): SHA-256(owner name + DNSKEY RDATA)
NSEC (type 47): Authenticated denial of existence
→ "example.org A? — Not only does it not exist, but it can prove it doesn't exist"
Trust Chain Verification
Resolver starts with: root DNSKEY hash (trust anchor, pre-installed in resolver)
Querying www.example.com A:
1. Receive A record + RRSIG (signer=example.com)
2. Query example.com DNSKEY → Verify RRSIG using DNSKEY → OK (zone-level trust)
3. Query .com zone: DS (example.com) + RRSIG (signer=.com)
4. Query .com DNSKEY → Verify DS's RRSIG → OK → DNSKEY hash matches DS → OK
5. Query root zone: DS (.com) + RRSIG → root DNSKEY → trust anchor match → OK
→ Complete trust chain: root → .com → example.com → www.example.com
Key Signing Key (KSK) vs Zone Signing Key (ZSK):
KSK: Signs only the DNSKEY RRset — Long key (2048-bit RSA), changed infrequently (1-2 years)
ZSK: Signs all RRsets in the zone — Short key (1024-bit RSA or ECDSA), changed frequently (monthly)
→ Reason for separating KSK/ZSK: ZSK rotates frequently (DNSSEC signatures need frequent updates), but changing KSK
requires updating the DS in the parent zone → Parent zone operation + propagation delay
NSEC3 (RFC 5155)
Problem with NSEC: Enumerates all existing names in a zone (traversing the NSEC chain → returns next name)
NSEC3: Hashes the owner name before proving nonexistence:
NSEC3 record:
Hash Algorithm (1): SHA-1
Flags (1): Opt-Out (bit 0)
Iterations (2): Hash iterations (0-65535, high iterations = DoS risk)
Salt Length + Salt: Per-zone salt
Hash Length + Hash (next hashed owner name)
Type Bit Maps: Same as NSEC
→ Traversing the NSEC3 chain only shows "hashed_abc → hashed_def" → Cannot directly enumerate the zone
(Still possible to brute-force offline; NSEC3 only increases the cost)
DANE (RFC 6698)
Replaces CA (Certificate Authority) for providing trust in TLS certificates:
TLSA record (_port._protocol.name):
port: 443, 25, ...
protocol: _tcp, _udp, ...
RDATA:
Cert Usage (1B):
0: CA constraint (PKIX-TA)
1: Service certificate constraint (PKIX-EE)
2: Trust anchor assertion (DANE-TA) — Specifies your own CA
3: Domain-issued certificate (DANE-EE) — Directly specifies the certificate or public key of this endpoint → Maximum security!
Selector (1B): 0=full certificate, 1=SubjectPublicKeyInfo (public key only)
Matching Type (1B): 0=exact, 1=SHA-256, 2=SHA-512
Certificate Association Data: Hash or exact cert/pubkey
Verification: Client receives TLS certificate → Queries TLSA record → Does hash match? → Trust
→ No need for PKI/CA, no need for CT logs; certificate validity depends solely on DNSSEC signatures
→ Problem: Current adoption is nearly zero (browsers do not support it)
References
- RFC: 4033-4035, 5155, 6698, 6840 (DNSSEC algorithm updates)
- Tools:
dig +dnssec,delv @resolver,dnsviz.net
Keywords: DNSSEC, RRSIG, DNSKEY, DS, NSEC, NSEC3, DANE, trust anchor, zone signing, KSK, ZSK