Four record types do the work. Each has one job, and once you can name the job you can read a DNSSEC failure without a tool.
First: DNSSEC signs sets, not records
An RRset is every record of the same name, class and type taken together. If a name has three A records, that is one RRset and it gets one signature covering all three.
Why this matters operationally
Adding a fourth A record invalidates the signature over the whole set, so the set has to be re-signed. This is why a signed zone cannot simply have records inserted into it — it has to go through a signing step. It is also why a change made through a provider API must trigger re-signing, or the zone serves a set whose signature no longer matches.
The four types
| Type | Lives in | Job |
|---|---|---|
| DNSKEY | The zone | Publishes the zone’s public keys. |
| RRSIG | The zone, beside every signed RRset | The signature over that RRset, with an explicit validity window. |
| DS | The parent zone | A digest of the child’s key-signing key. The single link joining child to parent. |
| NSEC / NSEC3 | The zone | Proves that a name does not exist, without an online signing key. |
Two keys, usually
Convention splits the keys by role, and the DNSKEY flags field tells them apart:
- KSK, flag 257. Signs only the DNSKEY RRset. This is the key the parent commits to via the DS record, so rolling it requires a change at the registrar.
- ZSK, flag 256. Signs everything else. Can be rolled entirely within the zone, with no parent involvement.
The split exists so the frequently-rotated key is the one that does not need the registrar. It is a convention, not a requirement — a single combined key is valid, and some operators use one:
257 3 13 00uWWtb/MvPAHwXTy6vzCvBJEvM++9AK...
RRSIG, and the field that causes outages
certadns.com. 3600 IN SOA ns1.certadns.com. hostmaster.certadns.com. 2026091002 ... certadns.com. 3600 IN RRSIG SOA 13 2 3600 20260924000000 20260903000000 29357 certadns.com. <signature>
SOA— the type this signature covers.13— the algorithm.2— labels in the signed name.3600— the original TTL.20260924000000— expiration. After this instant the signature is invalid and validating resolvers return SERVFAIL.20260903000000— inception.29357— the key tag identifying which DNSKEY to use.
That expiration is a wall-clock date, and it is why DNSSEC needs ongoing operation rather than one-time setup. This zone’s signatures were valid for 21 days at the time of checking, with about 12 remaining — comfortable, and only because something re-signs it regularly.
Proving a name does not exist
Signing answers is straightforward. Signing a denial is harder: the zone cannot pre-sign a statement for every name that does not exist, because there are infinitely many.
- NSEC signs the gaps: each record says "between this name and the next existing name, there is nothing". Correct, and it lets anyone walk the chain and enumerate the entire zone.
- NSEC3 (RFC 5155) does the same over hashed names, so walking yields hashes rather than names. Defeats casual enumeration; the hashes remain subject to offline guessing.
- NSEC3 opt-out allows unsigned delegations to be skipped when building the chain. It makes signing a very large zone with mostly unsigned children far cheaper, and the cost is that it no longer proves those delegations are absent. TLD registries use it; ordinary zones have no reason to.
Some providers instead synthesise a minimal signed denial on the fly for each query. It needs an online key, and it proves less about the zone’s contents — which is the point.