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?

  • (copying my comment from the SO question) It seems the core of the problem is that you think a dot in a name is necessarily a delegation point. It is not. Said otherwise, the owner of example.com can certainly have foo.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. Aug 22, 2022 at 13:20
  • You can look at rfc-editor.org/rfc/rfc7816#appendix-A to see an algorithm on how to find zone cuts, aka delegations. DS enters into play only at zone cuts. Aug 22, 2022 at 13:20
  • So if I change the DS verification to this: ``` valid = verify(ds, parentKeys) if valid == NSEC: return parentKeys ``` It should work properly isn't it?
    – Rix
    Aug 22, 2022 at 19:08


You must log in to answer this question.

Browse other questions tagged .