DNSSEC15
Status: Final
Purpose
- Verify presence and consistency of CDS and CDNSKEY RRsets and detect mismatches between the two at child nameservers.
Preconditions And Inputs
- Preconditions:
- A
zone.Zoneobject is available.
- A
- Required inputs:
- Child nameserver sets from
GlueNameserversandApexNameservers. - CDS and CDNSKEY query responses with DNSSEC enabled.
- Child nameserver sets from
- Profile/config knobs that affect behavior:
net.ipv4andnet.ipv6: disabled transports are skipped with transport debug tags.resolver.defaults.parallel: parallel nameserver query fanout.
Algorithm And Decision Flow
- Emit
TEST_CASE_START. - Build child nameserver set from the union of
GlueNameserversandApexNameservers(deduplicated byns.String()), then deduplicate by IP. - For each unique nameserver IP (parallelized):
- If transport is disabled, emit
IPV4_DISABLEDorIPV6_DISABLEDfor rrtypesCDSandCDNSKEYand skip. - Query
CDSwith DNSSEC enabled; when response is authoritativeNOERROR, store CDS answer RRset (which may contain zero records). - Query
CDNSKEYwith DNSSEC enabled; when response is authoritativeNOERROR, store CDNSKEY answer RRset (which may contain zero records).
- If transport is disabled, emit
- If no non-empty CDS/CDNSKEY RRset exists anywhere, emit
DS15_NO_CDS_CDNSKEY. - Otherwise, per nameserver present in both RRset maps:
- Classify nameserver into:
Has CDS No CDNSKEY(non-empty CDS, empty CDNSKEY),Has CDNSKEY No CDS(non-empty CDNSKEY, empty CDS),Has CDS And CDNSKEY(both non-empty).
- Build a digest-filtered CDS view that retains only records whose digest type is designated MUST in the IANA “Implement for DNSSEC Delegation” column (currently SHA-256 and SHA-384), plus any RFC 8078 delete-signal record (algorithm 0, digest type 0, key tag 0). The classification step above operates on the unfiltered RRset; all later cross-server and cross-RRset consistency checks operate on the filtered view per RFC 9975.
- If both the filtered CDS and the CDNSKEY RRsets are non-empty for a nameserver, compare each CDS against the CDNSKEY set and each CDNSKEY against the CDS set; a pair is considered to reference the same key when both the key tag and the DNSSEC algorithm match, or when both records use algorithm
0(delete signal). Mark nameserver mismatch when no match is found.
- Classify nameserver into:
- Emit classification tags with
addresses. - Emit
DS15_INCONSISTENT_CDSwhen the digest-filtered CDS RRsets differ across nameservers. - Emit
DS15_INCONSISTENT_CDNSKEYwhen CDNSKEY RRsets differ across nameservers. - Emit
DS15_MISMATCH_CDS_CDNSKEYfor nameservers with CDS/CDNSKEY mismatch. - Emit
DS15_CDS_NON_MUST_DIGESTfor nameservers that returned at least one CDS record with a non-MUST digest type (records that the consistency check already excluded). - Emit
TEST_CASE_END.
Per-NS CDS/CDNSKEY Presence and Match (steps 2-10)
Emitted Tags (Possible Set)
| Tag | Emitted when |
|---|---|
DS15_CDS_NON_MUST_DIGEST | Nameserver returned at least one CDS record whose digest type is not designated MUST by IANA. |
DS15_HAS_CDNSKEY_NO_CDS | Nameserver has non-empty CDNSKEY RRset and empty CDS RRset. |
DS15_HAS_CDS_AND_CDNSKEY | Nameserver has both non-empty CDS and non-empty CDNSKEY RRsets. |
DS15_HAS_CDS_NO_CDNSKEY | Nameserver has non-empty CDS RRset and empty CDNSKEY RRset. |
DS15_INCONSISTENT_CDNSKEY | CDNSKEY RRsets are not identical across participating nameservers. |
DS15_INCONSISTENT_CDS | Digest-filtered CDS RRsets are not identical across participating nameservers. |
DS15_MISMATCH_CDS_CDNSKEY | Nameserver has both RRsets but CDS/CDNSKEY matching checks failed. |
DS15_NO_CDS_CDNSKEY | No non-empty CDS or CDNSKEY RRset found on participating nameservers. |
IPV4_DISABLED | IPv4 transport is disabled for a queried nameserver (CDS, CDNSKEY). |
IPV6_DISABLED | IPv6 transport is disabled for a queried nameserver (CDS, CDNSKEY). |
TEST_CASE_END | Testcase completion marker is emitted. |
TEST_CASE_START | Testcase start marker is emitted. |
Tag Arguments
| Tag | Argument key | Type | Meaning |
|---|---|---|---|
DS15_CDS_NON_MUST_DIGEST | addresses | array<string> | Structured child nameserver IP list that returned at least one non-MUST CDS digest. |
DS15_HAS_CDNSKEY_NO_CDS | addresses | array<string> | Structured child nameserver IP list. |
DS15_HAS_CDS_AND_CDNSKEY | addresses | array<string> | Structured child nameserver IP list. |
DS15_HAS_CDS_NO_CDNSKEY | addresses | array<string> | Structured child nameserver IP list. |
DS15_INCONSISTENT_CDNSKEY | - | - | No arguments. |
DS15_INCONSISTENT_CDS | - | - | No arguments. |
DS15_MISMATCH_CDS_CDNSKEY | addresses | array<string> | Structured child nameserver IP list with mismatch. |
DS15_NO_CDS_CDNSKEY | - | - | No arguments. |
IPV4_DISABLED | ns | string | Nameserver identity (ns name only; use address for IP) skipped on IPv4. |
IPV4_DISABLED | address | string | Nameserver IP address for the same endpoint. |
IPV4_DISABLED | rrtype | string | rrtype skipped (CDS or CDNSKEY). |
IPV6_DISABLED | ns | string | Nameserver identity (ns name only; use address for IP) skipped on IPv6. |
IPV6_DISABLED | address | string | Nameserver IP address for the same endpoint. |
IPV6_DISABLED | rrtype | string | rrtype skipped (CDS or CDNSKEY). |
TEST_CASE_END | testcase | string | Testcase display name (DNSSEC15). |
TEST_CASE_START | testcase | string | Testcase display name (DNSSEC15). |
Severity Levels Per Tag
| Tag | Level | Notes |
|---|---|---|
DS15_CDS_NON_MUST_DIGEST | NOTICE | Default from share/profile.json (test_levels.DNSSEC). |
DS15_HAS_CDNSKEY_NO_CDS | NOTICE | Default from share/profile.json (test_levels.DNSSEC). |
DS15_HAS_CDS_AND_CDNSKEY | INFO | Default from share/profile.json (test_levels.DNSSEC). |
DS15_HAS_CDS_NO_CDNSKEY | NOTICE | Default from share/profile.json (test_levels.DNSSEC). |
DS15_INCONSISTENT_CDNSKEY | ERROR | Default from share/profile.json (test_levels.DNSSEC). |
DS15_INCONSISTENT_CDS | ERROR | Default from share/profile.json (test_levels.DNSSEC). |
DS15_MISMATCH_CDS_CDNSKEY | ERROR | Default from share/profile.json (test_levels.DNSSEC). |
DS15_NO_CDS_CDNSKEY | INFO | Default from share/profile.json (test_levels.DNSSEC). |
IPV4_DISABLED | DEBUG | Default from share/profile.json (test_levels.DNSSEC). |
IPV6_DISABLED | DEBUG | Default from share/profile.json (test_levels.DNSSEC). |
TEST_CASE_END | DEBUG | Default from share/profile.json (test_levels.DNSSEC). |
TEST_CASE_START | DEBUG | Default from share/profile.json (test_levels.DNSSEC). |
Differences From Upstream
- Differences (Upstream vs Gonemaster):
- Upstream: CDS/CDNSKEY matching is described as “derived from the same DNSKEY” (or both delete). Gonemaster: mismatch check pairs records when both the key tag and the DNSSEC algorithm match (or both records use algorithm
0), without deeper digest/material derivation checks. Key tag alone is insufficient because two keys with different algorithms can share a key tag. - Upstream: does not explicitly specify testcase boundary and transport-disabled debug emissions in this testcase summary. Gonemaster: emits
TEST_CASE_START,TEST_CASE_END,IPV4_DISABLED, andIPV6_DISABLED.
- Upstream: CDS/CDNSKEY matching is described as “derived from the same DNSKEY” (or both delete). Gonemaster: mismatch check pairs records when both the key tag and the DNSSEC algorithm match (or both records use algorithm
- Potential upstream report:
no
RFC References
- RFC 7344: defines CDS and CDNSKEY semantics for child-to-parent DS maintenance.
- RFC 8078: defines the delete signal (algorithm
0, digest type0, key tag0) that asks the parent to remove the DS RRset. - RFC 9975: clarifies CDS/CDNSKEY consistency rules for parental agents. Gonemaster applies the digest-type filter from RFC 9975 to its consistency checks: only CDS records whose digest type is designated MUST in the IANA “Implement for DNSSEC Delegation” column participate in
DS15_INCONSISTENT_CDSandDS15_MISMATCH_CDS_CDNSKEY. The delete signal is preserved across the filter so that mixed delete/update responses still surface as inconsistent.
Edge Cases And Limitations
- Only nameservers that produced authoritative
NOERRORresponses are included in CDS/CDNSKEY set maps; others are silently ignored except for transport-disabled debug tags. - RRset consistency comparison uses RR string signatures over the digest-filtered CDS view; ordering differences are normalized by sorting.
- CDS records whose digest type is not designated MUST by IANA are excluded from consistency checks per RFC 9975. They still appear in the underlying DNS responses; only the consistency comparison ignores them.
- Nameserver evaluation is deduplicated by IP.