Network Security

DNSSEC: Chain of Trust from Root to This Domain

How DNSSEC builds a cryptographic chain of trust from the DNS root to this zone — with Pulumi setup and live dig verification

Laurent Goudet · February 24, 2026 · 7 min read

DNS was designed in 1983 with no authentication. A resolver asks “where is lepro.dev?” and trusts whatever answer comes back first. That’s a problem: anyone in the network path — or anyone who can poison a resolver’s cache — can forge a response and redirect traffic to a malicious server. DNSSEC fixes this by adding cryptographic signatures to DNS records, but the mechanism is more subtle than “just sign everything.”

The core challenge is bootstrapping trust. If a nameserver signs its records, how does the resolver know it’s using the right public key? DNSSEC solves this with a chain of trust that starts at the DNS root and delegates downward: the root vouches for TLDs, TLDs vouch for domains, and domains sign their own records. Each link in the chain is a DS (Delegation Signer) record published in the parent zone — a cryptographic handshake that says “this child zone’s key is legitimate.”

The diagram below shows the three levels for lepro.dev: root, .dev TLD, and the zone itself — with the specific record types at each level and how trust flows downward.

DNSSEC Chain of Trust

Root → .dev TLD → lepro.dev — each level signs the next
Root (·)
IANA — trust anchor hardcoded in resolvers
DNSKEYRRSIG
Signs child zone
DS record anchors trust
.dev TLD
Google Registry — signs all .dev delegations
DNSKEYDSRRSIG
Signs child zone
Anchored by parent DS
DS record anchors trust
lepro.dev
Your zone — Cloudflare signs records
DNSKEYDSRRSIGA/AAAA
Anchored by parent DS

How Validation Works

When a DNSSEC-validating resolver (like 1.1.1.1 or 8.8.8.8) queries lepro.dev, it doesn’t just accept the A record. It requests the RRSIG (signature) alongside the record and walks the chain upward. The resolver already has the root KSK (Key Signing Key) hardcoded — that’s the trust anchor. It uses the root’s DNSKEY to verify the .dev DS record, then the .dev DNSKEY to verify the lepro.dev DS record, then the lepro.dev DNSKEY to verify the RRSIG on the actual A/AAAA record.

If any link breaks — an expired signature, a mismatched DS record, a missing DNSKEY — the resolver returns SERVFAIL. This is by design: a broken chain is treated as a potential attack, not a degraded service. That’s why DNSSEC misconfiguration is more dangerous than no DNSSEC at all. A non-DNSSEC zone simply has no signatures to verify; a broken DNSSEC zone actively fails validation.

Enabling DNSSEC with Pulumi

Cloudflare splits DNSSEC into two parts: zone signing (which Cloudflare handles at the edge) and DS record propagation (which connects the signed zone to the parent TLD). A single Pulumi resource enables zone signing:

const dnssec = new cloudflare.ZoneDnssec( “lepro-dnssec”, { zoneId: zoneId, });

export const dnssecDs = dnssec.ds; export const dnssecDigest = dnssec.digest;

export const dnssecKeyTag = dnssec.keyTag;

This creates the DNSKEY pair (algorithm 13, ECDSA P-256), starts signing all records with RRSIG, and publishes CDS/CDNSKEY records. The exported outputs contain the DS record that needs to reach the parent zone:

$ pulumi stack output dnssecDs

lepro.dev. 3600 IN DS 2371 13 2 4B6EFA5C9B894…55B1AE35F

For domains registered through Cloudflare Registrar (like lepro.dev), DS propagation to the parent TLD is automatic — Cloudflare scans the published CDS records and pushes the DS to the registry. This process takes 24–48 hours. For domains registered elsewhere, copy the DS record from the Pulumi outputs and add it manually at the registrar.

The Gap Between Signing and Validation

Zone signing is instant — Cloudflare starts signing records the moment ZoneDnssec is created. But the DS record must propagate to the parent TLD asynchronously, and this is the step that can stall. Check dig lepro.dev DS +short @ns-tld1.charlestonroadregistry.com. — an empty response means the chain is still incomplete and resolvers won’t validate.

Walking the Chain with dig

Once DNSSEC is fully propagated, you can walk the chain with dig to verify each level. Each step queries a specific record type at a specific level of the DNS hierarchy, tracing trust from the root down to lepro.dev.

Step 1 — Root DNSKEY (trust anchor). The root zone publishes its KSK (flag 257) and ZSK (flag 256). The KSK is hardcoded in every validating resolver — this is where all DNSSEC trust begins:

$ dig . DNSKEY +short | head -1 257 3 8 AwEAAaz/tAm8yTn4Mfeh5eyI96WSVexTBAvkMgJzkKTO…

Step 2 — Root signs .dev. The root publishes a DS record for the .dev TLD. This DS contains a SHA-256 hash (digest type 2) of .dev’s KSK — the cryptographic handoff from root to TLD:

$ dig dev. DS +short @a.root-servers.net.

60074 8 2 B942E2CE5AEBF62FCA59D05707E6DBB795211D54…33424785

Step 3 — .dev DNSKEY. The .dev TLD publishes its own key pair (algorithm 8, RSA/SHA-256). A resolver verifies that the KSK’s hash matches the DS from Step 2:

$ dig dev. DNSKEY +short 257 3 8 AwEAAYtM84o4wEWfgE0ywuvg89cB3uHoH705EtMkp4Xp… 256 3 8 AwEAAcbVHY7e2c1yEiSbarJwEUdUID0E1yKLix2VTTD+…

Step 4 — .dev signs lepro.dev. The .dev TLD publishes a DS record for lepro.dev, containing a hash of lepro.dev’s KSK. This is the record that Cloudflare Registrar propagates to Google Registry:

$ dig lepro.dev DS +short @ns-tld1.charlestonroadregistry.com.

2371 13 2 4B6EFA5C9B8940B56891AF2618DB5C5FB2EDFEF4…55B1AE35F

Step 5 — lepro.dev DNSKEY. Cloudflare generates and publishes a KSK and ZSK for the zone using ECDSA P-256 (algorithm 13) — shorter keys than RSA but equally strong:

$ dig lepro.dev DNSKEY +short 257 3 13 mdsswUyr3DPW132mOi8V9xESWE8jTo0dxCjjnopKl+Gq… 256 3 13 oJMRESz5E4gYzS/q6XDrvU1qMPYIjCWzJaOau8XNEZeq…

Step 6 — Signed A record. Cloudflare signs every DNS response with the ZSK. The RRSIG accompanies the A records:

$ dig lepro.dev A +dnssec +short @8.8.8.8

172.67.143.204 104.21.39.83

A 13 2 300 20260226113258 20260224093258 34505 lepro.dev.

vUzo0mtx…

When the full chain is in place, responses from public resolvers include the ad (Authenticated Data) flag — proof that every link from root to domain was cryptographically verified:

$ dig lepro.dev A +dnssec @8.8.8.8 | grep flags
;; flags: qr rd ra ad;    ← authenticated

Key Management

Every DNSSEC zone maintains two key pairs. The Key Signing Key (KSK) signs only the DNSKEY record set — it’s the key whose hash is published as a DS record in the parent zone. The Zone Signing Key (ZSK) signs everything else: A, AAAA, MX, TXT records. The split exists so you can rotate the ZSK frequently (every few weeks) without coordinating with the parent zone, while the KSK (which requires updating the parent’s DS record) rotates less often.

Cloudflare automates zone signing at the edge and handles key rotation transparently. The Pulumi cloudflare.ZoneDnssec resource exports the current DS record, digest, key tag, and algorithm — useful for auditing or for manually adding the DS at a non-Cloudflare registrar. For lepro.dev on Cloudflare Registrar, DS propagation to Google Registry (the .dev TLD operator) is automatic.

What DNSSEC Does Not Do

DNSSEC authenticates DNS data — it proves that the response came from the authoritative source and wasn’t tampered with. It does not encrypt DNS queries (that’s DoH/DoT), does not prevent DDoS attacks on DNS infrastructure, and does not replace TLS for securing the actual connection. Think of DNSSEC as ensuring you get the right IP address; TLS ensures you’re talking to the right server at that IP address.

The combination matters: DNSSEC without TLS means you reach the right IP but communicate in cleartext. TLS without DNSSEC means you might be talking to the wrong server entirely (if DNS was poisoned), though certificate validation catches most of this. Both together provide defense in depth — DNS integrity plus transport encryption.

Frequently Asked Questions

What does DNSSEC actually protect against?

DNSSEC prevents DNS spoofing and cache poisoning — attacks where a resolver is tricked into accepting forged DNS records. Without DNSSEC, an attacker between you and the resolver (or poisoning the resolver's cache) can redirect traffic to a malicious IP. DNSSEC adds cryptographic signatures to DNS records, so resolvers can verify that a response genuinely came from the authoritative nameserver and wasn't tampered with in transit.

Why is DNSSEC adoption still low despite existing since 2005?

Three operational costs slow adoption. First, zone signing adds complexity — you need to manage DNSKEY pairs, rotate keys on schedule, and keep DS records in sync with the parent zone. Second, DNSSEC responses are larger (signatures add bytes), which can trigger UDP fragmentation and fallback to TCP. Third, a misconfigured DNSSEC zone is worse than no DNSSEC: resolvers that validate will refuse to resolve the domain entirely, causing a total outage.

How does the chain of trust work from root to domain?

The root zone's public key (KSK) is hardcoded in validating resolvers — that's the trust anchor. The root signs the .dev TLD's DS record, which contains a hash of .dev's DNSKEY. The .dev TLD then signs the domain's DS record, which hashes the zone's DNSKEY. The zone signs its own records (A, AAAA, MX, etc.) with RRSIG. A resolver walks this chain top-down: root → TLD → domain, verifying each signature against the parent's vouched-for key.

How do you enable DNSSEC on Cloudflare with Pulumi?

A single Pulumi resource — cloudflare.ZoneDnssec — enables zone signing. Cloudflare generates the DNSKEY pair, signs all records, and publishes CDS/CDNSKEY records. For domains on Cloudflare Registrar, the DS record propagates to the parent TLD automatically within 24–48 hours. For other registrars, copy the DS record from Pulumi outputs and add it manually. Always verify with dig that the DS reached the parent.

Laurent Goudet

CTO at Freelancer.com

AI agents, networking, and infrastructure at scale

Other deep-dives

© 2026 Laurent Goudet · Bordeaux, France · lepro.dev

vd9714f4