mirror of
https://github.com/hickory-dns/hickory-dns.git
synced 2026-04-25 11:15:54 +03:00
[GH-ISSUE #3011] Store one Proof per RRset, instead of per record #1112
Labels
No labels
blocked
breaking-change
bug
bug:critical
bug:tests
cleanup
compliance
compliance
compliance
crate:all
crate:client
crate:native-tls
crate:proto
crate:recursor
crate:resolver
crate:resolver
crate:rustls
crate:server
crate:util
dependencies
docs
duplicate
easy
easy
enhance
enhance
enhance
feature:dns-over-https
feature:dns-over-quic
feature:dns-over-tls
feature:dnsssec
feature:global_lb
feature:mdns
feature:tsig
features:edns
has workaround
ops
perf
platform:WASM
platform:android
platform:fuchsia
platform:linux
platform:macos
platform:windows
pull-request
question
test
tools
tools
trust
unclear
wontfix
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
starred/hickory-dns#1112
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Originally created by @divergentdave on GitHub (May 23, 2025).
Original GitHub issue: https://github.com/hickory-dns/hickory-dns/issues/3011
Proofenums are currently attached to records or an error variant. This is not a good way to represent DNSSEC validation results, because validation is done one RRset at a time. We could remove theprooffield from theRecordstruct andProtoErrorKind::Nsecand instead store aHashMap<RrKey, Proof>alongside a response. The proof inProtoErrorKind::Nsecrepresents the verification state of the queried RRset in name error or no data responses. Being able to track the verification state of other RRsets, different from the queried RRset, and without any matching records, would be useful for properly validating wildcard expansion, see #2882.@divergentdave commented on GitHub (Jul 10, 2025):
After reading through RFC 4035 again and thinking through this some more, I think the solution will need to be a bit different than described above.
There are two different kinds of validation results we can produce. We can determine that a particular RRset is secure, bogus, or insecure, and we can separately determine whether an entire response to a query is valid/authenticated/secure, bogus, or insecure/not authenticated. The per-record
Proofs in positive responses reflect the former, while theProofinsideProtoErrorKind::Nsecfor negative responses reflects the latter. TheDnssecSummaryproduced from the per-recordProofs is supposed to reflect overall response validity as well. We need to validate the RRSIG over an RRset before we can determine if the overall response that contains the RRset in its Answer section is valid, but validating the overall response may require validating an authenticated denial of existence as well.As a result, I don't think it would make sense to mix
Proofenums representing both validated RRsets and validated nonexistence of RRsets in oneHashMap. If anything, it might be useful to memoize validation of RRsets. For example, we may need to refer to the same validated NSEC or NSEC3 RR multiple times if it covers multiple names we're interested in. Even so, that doesn't need to live in theMessagestruct, as it doesn't need to live past validation.RFC 4035 section 5.3.4 says that, whenever an RRset is the result of expanding wildcard records, "Once the validator has verified the signature, as described in section 5.3, it must take additional steps to verify the non-existence of an exact match or closer wildcard match for the query." This means that the wildcard-related validation rules apply both to validation of a single RRset, such as in positive responses, and to overall response validation, such as when authenticating a wildcard no data response. This also means that validation of individual RRsets cannot be done independently from each other, or even one section at a time, as
DnssecDnsHandle::verify_response()does. We may need to validate an NSEC/NSEC3 record in order to finish validating some other RRset.We may need to pass something like a
DnssecSummaryout of the validation code to theCatalogin the future, especially if we stop representing NXDOMAIN/no data as aResult::Err. To do so, we'll have to add it to theDnsResponsestruct, change theDnsHandletrait to add some extensibility, or replace the use ofDnsHandleto interface withDnssecDnsHandle.@djc commented on GitHub (Jul 10, 2025):
FYI, I started hacking on this a little bit today.
@djc commented on GitHub (Jul 15, 2025):
This feels like the right solution to me at least in terms of the library API. I think the question I'm struggling with a little is how we want to present DNSSEC verification capabilities to the user.
validate: trueto enable verification and this results inRecord::proofpotentially being set, but this is otherwise being ignored (although it is available in low-level APIs to callers).Validatingmode (enabled viaDnssecPolicy::ValidateWithStaticKey), we will useproof.is_indeterminate()to determine whether we can yield cache results. It doesn't seem likeproofvalues actually influence the data that we return?From what I can tell it doesn't seem like
DnssecDnsHandle::verify_rrsets()actually changes theRecorddata that it gets, it only seems to augment it withProofdata.For the resolver library API, perhaps it makes more sense to expose a separate
DnssecResolverAPI which will expose an API that, for each record, wraps it in its proof status?For the recursor, I'm not completely sure what the intended behavior for a validating recursor is (nor does this seem to be clearly documented in the
RecursorMode::ValidatingorDnssecPolicy::ValidateWithStaticKey). Should it only return secure records?@djc commented on GitHub (Jul 15, 2025):
A quick web search turns up this documentation from PowerDNS. Describing its default
processmode:RFC 2535, section 6.1:
@djc commented on GitHub (Jul 15, 2025):
I suppose 2535 has been declared obsolete in favor of 4035.
Section 3.1.6:
And section 3.2.3:
@divergentdave commented on GitHub (Jul 15, 2025):
FWIW this check is needed because the recursor can insert cache entries both before and after validation. This check prevents using a pre-validation response without going through the validation process again.
The big place where the rubber meets the road (when running the recursor or forwarder in a server) is in
build_forwarded_response(), which usesDnssecSummary::from_records()to consume proofs. I discussed this a bit in https://github.com/hickory-dns/hickory-dns/issues/3041#issuecomment-3032905729.