Warda asks the upstream servers with the AD bit (RFC 6840): a validating
resolver says whether it checked the signatures, without sending them. The
answers validated are counted. A minute after the start, then every 6 hours
(task dnssec.check), each upstream is asked isc.org (signed: AD
expected) and dnssec-failed.org (signed wrong: SERVFAIL expected): it
validates, or not. With Only ask the upstream servers that validate
DNSSEC (PUT /api/v1/dns-services/dnssec, meta dnssec_require), only
those are asked while at least one is known to validate; the others only
when none of them answers (names never stop resolving). POST /api/v1/dns-services/dnssec/check
checks at once.
Validation by Warda itself (beta)#
With Check the signatures in Warda itself (PUT /api/v1/dns-services/dnssec/native
{"enabled": true}, meta dnssec_validate, off by default), Warda asks
each name with the DO bit and validates the answer itself, from the trust
anchors of the root (KSK-2017 20326 and KSK-2024 38696): the keys (DNSKEY)
and delegations (DS) of each zone are asked to the same upstreams and kept
in memory (a minute to an hour, 4096 zones at most). Algorithms 8 and 10
(RSA/SHA-256 and SHA-512), 13 and 14 (ECDSA P-256 and P-384) and 15
(Ed25519); digests SHA-1, SHA-256 and SHA-384; the proofs of denial NSEC
and NSEC3 (150 iterations at most; closest encloser and wildcard proofs;
opt-out read as unsigned). The result of each answer:
- secure: every record verified up to the root: the AD flag is set;
- insecure: the zone is proven unsigned (or signed only with other algorithms): passed, without AD;
- bogus: a signed zone whose answer does not verify, an unsigned answer in a signed zone, a signature by a name that is no signed zone, or a name under a signed zone whose absence of DS is not proven: refused with SERVFAIL (not cached, not counted as an error of the upstream);
- indeterminate: Warda could not tell (an answer made from a wildcard, a denial signed but not proven, the types ANY and RRSIG): passed without AD, as insecure.
It fails open only when the keys of the root cannot be verified
(upstreams that remove the signatures, no network): everything is then
indeterminate for 5 minutes and the page says so
(dnssec.status.working false). Below the root, a key query that fails
costs the answer (SERVFAIL, asked again at the next query): only a proven
unsigned delegation makes a name insecure. It protects from answers forged
or changed on the way; a forged denial of existence that replays real
signed records passes without AD. Not to use with a filtering upstream
(Quad9, AdGuard, NextDNS, Cloudflare 1.1.1.2 or 1.1.1.3): its unsigned
blocks of signed names become SERVFAIL. A resolver that answers the DS
query of a zone from the zone itself (a local authoritative zone) makes it
bogus: such zones belong in WARDA_FORWARD, which is never validated. The
signatures are removed from the answer of a client that did not ask them
(no DO); a client that sets CD is not validated; the local zones
(WARDA_FORWARD) are never validated. The counts (secure, insecure,
bogus) are on the page; turning it on empties the cache, and
Restart the resolver forgets the keys.