DNSSEC "Enabled" But Never Validates: The DS Record Has to Go to the Registrar, Not the DNS Host¶
A zone can have DNSSEC fully configured at the DNS host — DNSKEY published, records signed, everything looking correct in the dashboard — and still never actually validate for a single visitor. The AD (Authenticated Data) flag just never sets, silently, with no error anywhere. The cause is almost always the same: the DS record was never submitted to the registrar, so the chain of trust from the root has a gap that nothing on the DNS-hosting side can fix.
Symptom¶
dig shows what looks like a healthy signed zone:
But a resolver that actually validates never sets the AD flag on any answer:
No error, no warning, nothing in the DNS host's dashboard flags it as broken. The zone just quietly never validates — for that record, or for any other record on the domain, past or future.
Cause¶
DNSSEC's chain of trust has three pieces, and only the DNS host controls two of them:
- DNSKEY — the zone's public signing key, published by the DNS host. This is the part every provider's "Enable DNSSEC" toggle actually does.
- RRSIG — signatures over each record, generated automatically once DNSKEY exists.
- DS (Delegation Signer) — a hash of the DNSKEY that has to live in the parent zone, i.e. at the registrar (for a top-level domain, that's whoever sells the
.com/.house/etc. registration — Namecheap, GoDaddy, etc.), not the DNS host.
A resolver validates by walking down from the root: root → TLD → your domain, checking a DS-to-DNSKEY match at every hop. If the registrar never received the DS record, the TLD servers have no DS for your domain at all — confirmable directly:
dig +short DS yourdomain.com @a.gtld-servers.net
# empty = no DS at the registry, chain is broken here
An empty answer here (sometimes returned with an NSEC3 non-existence proof rather than just nothing) means the trust chain stops dead at the TLD level, regardless of how correctly everything is configured downstream. Publishing a DNSKEY and submitting a DS record are two separate manual actions, on two separate platforms (DNS host vs. registrar), and it's entirely possible to do the first and forget the second — especially since nothing about the zone looks broken from the DNS host's side.
This is exactly what happened on a majorshouse.com-style setup: Cloudflare had DNSSEC signing on, the DNSKEY was live and correctly formed, but the DS had never been pushed to the registrar (Namecheap). The domain had effectively never had working DNSSEC, on any record, the entire time it looked "enabled."
How this was caught — a safe way to test without touching production¶
Don't debug DNSSEC on a live, in-use zone. Test it on a throwaway delegated subzone instead — it exercises the exact same trust-chain mechanics without any risk to real traffic:
- Create a subzone at a new/candidate DNS provider (e.g.
canary.yourdomain.comat deSEC, Route53, PowerDNS, whatever you're evaluating). The provider gives you NS records and a DS record for that subzone. - At your existing DNS host (the one hosting the parent
yourdomain.com), add: - NS records delegating
canary.yourdomain.comto the new provider's nameservers - a DS record for
canary.yourdomain.comcontaining the hash the new provider gave you - Add a few test records at the new provider and query them from a validating public resolver (
8.8.8.8,1.1.1.1): - Check for the
adflag. If it's missing, check whether the parent domain itself has a working chain first —dig +short DS yourdomain.com @<a-tld-server>— before assuming the new provider or the subzone is at fault. A subzone can be signed perfectly and still fail to validate end-to-end if the zone it's delegated under was never DNSSEC-complete in the first place.
This delegation approach is genuinely free of risk: the parent zone's own records are completely untouched, nothing resolves any differently for real traffic, and the whole thing (NS + DS records at the parent, zone at the new provider) is a two-minute teardown when you're done — delete the child zone at the new provider, delete the three delegation records at the parent.
Fix¶
- If the DS record was simply never submitted: get it from the DNS host's dashboard (or API — most expose it alongside the DNSKEY) and add it at the registrar's DNSSEC/DS-record settings.
- If you're migrating DNS providers entirely (not just testing), remember the DS record is provider-specific — every time the authoritative DNS host changes, a new DS record has to be generated and re-submitted at the registrar. This is a distinct step from updating nameservers, and it's easy to complete an NS cutover, watch everything resolve fine (DNSSEC failure is silent, remember), and only notice the gap months later.
- After submitting, re-check with
dig +short DS yourdomain.com @<a-tld-server>— propagation to the registry is usually fast (minutes), but full resolver-side pickup can take up to your old DS record's TTL if one existed previously.
Related¶
- Self-Hosted Recursive DNS with unbound — a different DNS chain-of-trust gotcha: DNSBL lookups silently failing because the resolver itself wasn't trusted, not the zone's signing