I'm trying to implement a toy project DNSSEC supported DNS resolver to learn about both DNS and DNSSEC.
Most of my implementation are finished. But for some domains it's not working correctly, and I noticed some differences when comparing with results from https://dnssec-analyzer.verisignlabs.com/
So the simplified flow of my DNSSEC validation went like this:
getZoneKeys(fqdn) -> keys:
if fqdn == ".":
return rootKeys
// recursively find the parent zone keys
parentKeys = getZoneKeys(parentFqdn(fqdn))
// query the DS records
ds = dnsQuery(fqdn, TypeDS)
// query the DNSKEY records
dnskey = dnsQuery(fqdn, TypeDNSKEY)
// according to DNS zone delegation, DS records should be verified using parent zone keys
valid = verify(ds, parentKeys)
if valid == NSEC:
return Insecure
// after DS is verified, those keys referenced from the DS records can be added to the zone keys set
zoneKeys = findMatchingKeys(dnskey, ds)
// then use the verified zone keys so far to verify the whole DNSKEY RR set
valid = verify(dnskey, zoneKeys)
if valid == NSEC:
return Insecure
// all the reset keys in the DNSKEY RR set will be added to the zone key
zoneKeys = getAllDNSKEYs(dnskey)
dnsQueryAndValidate(fqdn, type) -> record, valid:
record = dnsQuery(fqdn, type)
zoneKeys = getZoneKeys(fqdn)
valid = verify(dsrecord, zoneKeys)
This is working for e.g. www.cloudflare.com
but not for e.g. dev.future.internetsociety.org
and exp.igw0.nyi.freebsd.org
. And I used https://dnssec-analyzer.verisignlabs.com/ to compare my flow with its results.
I found that for www.cloudflare.com
result, the zone key delegation happens all along the way down to www.cloudflare.com
, which means all .
, com.
, cloudflare.com.
and www.cloudflare.com.
have their own DNS zone, and each zone except the root zone receives key delegation from its parent through DS records. This is exactly how my program is checking for and is working.
However, for dev.future.internetsociety.org
result, the zone key delegation stops at internetsociety.org
, and it seems it doesn't even check the zone for future.internetsociety.org
, and directly jumps to checking dev.future.internetsociety.org
, and using internetsociety.org
's zone key to verify dev.future.internetsociety.org
's A RRset.
Furthermore, even more stangely, for exp.igw0.nyi.freebsd.org
result, the zone key delegation stops at freebsd.org
, and then the A RRSet for exp.igw0.nyi.freebsd.org
is being checked consecutively for four times.
I think I don't quit understand what DNS zone really means in practice. Does it mean if a subdomain doesn't have a DS record, with a NSEC proof, then its zone keys should inherit the keys from the cloest parent zone that has a zone keys? Or if there are other criteria to check if a domain has its own DNS zone? And finally, how to properly handle the zone delegation for DNSSEC?
example.com
can certainly havefoo.bar.example.com
in its zonefile without any delegations. DS are only needed at delegation points. If there are no delegations, there are no DS records either, and the "upper" ones are used. Note also that most zones use a split key model where the DS refer to the KSK which itself signs the ZSK which the one used to sign records.DS
enters into play only at zone cuts.