- Go 98.6%
- Makefile 0.8%
- Dockerfile 0.6%
| checker | ||
| plugin | ||
| .gitignore | ||
| Dockerfile | ||
| go.mod | ||
| go.sum | ||
| LICENSE | ||
| main.go | ||
| Makefile | ||
| NOTICE | ||
| README.md | ||
checker-dnssec
DNSSEC operational hygiene checker for happyDomain.
Cryptographic chain validation is delegated to checker-dnsviz. This
checker focuses on policy and operational hygiene:
- NSEC vs NSEC3 zone walking exposure
- RFC 9276 NSEC3 parameter compliance (iterations, salt)
- Algorithm policy and key sizes (allowed / forbidden / modern)
- RRSIG presence, validity windows and freshness
- TTL recommendations for DNSKEY / RRSIG
- Per-name-server consistency of the DNSKEY RRset and denial scheme
The HTML report is laid out so the most common operator-facing failure scenarios appear first, with a fix line citing the relevant RFC.
Usage
Standalone HTTP server
# Build and run
make
./checker-dnssec -listen :8080
The server exposes:
GET /health: health checkPOST /collect: collect DNSSEC observations (happyDomain external checker protocol)
Docker
make docker
docker run -p 8080:8080 happydomain/checker-dnssec
happyDomain plugin
make plugin
# produces checker-dnssec.so, loadable by happyDomain as a Go plugin
The plugin exposes a NewCheckerPlugin symbol returning the checker
definition and observation provider, which happyDomain registers in its
global registries at load time.
Versioning
The binary, plugin, and Docker image embed a version string overridable at build time:
make CHECKER_VERSION=1.2.3
make plugin CHECKER_VERSION=1.2.3
make docker CHECKER_VERSION=1.2.3
happyDomain remote endpoint
Set the endpoint admin option for the DNSSEC checker to the URL of the
running checker-dnssec server (e.g., http://checker-dnssec:8080).
happyDomain will delegate observation collection to this endpoint.
Build
make # standalone binary
make docker # FROM scratch image
make plugin # Go plugin (.so)
make test # tests
Options
Admin options
| Id | Type | Default | Description |
|---|---|---|---|
resolver |
string | /etc/resolv.conf |
Bootstrap recursive resolver (host:port) used to discover the apex name servers and look up the parent DS. |
User options
| Id | Type | Default | Description |
|---|---|---|---|
nsec3IterationsMax |
uint | 0 |
RFC 9276 §3.1 ceiling on NSEC3PARAM.Iterations. Increase only if your signer cannot publish 0 yet. |
nsec3IterationsSeverity |
choice | warn |
Severity when iterations exceed the ceiling. Use crit to enforce RFC 9276 strictly. |
signatureFreshness |
uint | 7 |
Warn when the closest RRSIG expires in fewer than this many days. |
signatureFreshnessCrit |
uint | 1 |
Critical when the closest RRSIG expires in fewer than this many days. |
minRSAKeySize |
uint | 2048 |
Minimum acceptable RSA modulus size, in bits. |
requireSEP |
bool | true |
Require at least one DNSKEY with the SEP bit (KSK). |
dnskeyTTLMin |
uint | 3600 |
Minimum DNSKEY TTL, in seconds; shorter TTLs hurt cacheability. |
Rules
Each rule emits a finding code. Severity may be affected by the options above.
| Code | Default severity | Condition |
|---|---|---|
dnssec_zone_signed |
critical | Parent DS is published but the apex serves no DNSKEY (broken chain of trust). |
dnssec_dnskey_consistent |
critical | Authoritative servers disagree on the apex DNSKEY RRset. |
dnssec_dnskey_query_ok |
warning | At least one authoritative server failed to answer the DNSKEY query. |
dnssec_algorithm_allowed |
critical (forbidden) / warning (not in allowlist) | A DNSKEY uses a forbidden algorithm or an algorithm not in allowedAlgorithms. |
dnssec_algorithm_modern |
warning | The zone still uses RSA-family DNSKEYs; ECDSAP256SHA256 (13) or Ed25519 (15) recommended. |
dnssec_rsa_keysize |
critical (<1024) / warning (<minRSAKeySize) |
An RSA DNSKEY has a modulus below the policy threshold. |
dnssec_ksk_present |
critical | No DNSKEY carries the SEP (KSK) flag while requireSEP is enabled. |
dnssec_dnskey_count |
warning | Eight or more DNSKEYs are published, bloating responses and amplification factor. |
dnssec_rrsig_present_dnskey |
critical | The apex DNSKEY RRset is unsigned. |
dnssec_rrsig_present_soa |
critical | The apex SOA RRset is unsigned. |
dnssec_rrsig_validity_window |
critical | An observed RRSIG is outside its [Inception, Expiration] window. |
dnssec_rrsig_freshness |
warning / critical | The closest RRSIG expires in fewer than signatureFreshness / signatureFreshnessCrit days. |
dnssec_denial_uses_nsec3 |
warning | The zone uses NSEC for denial of existence, exposing it to trivial walking (RFC 5155 / RFC 7129). |
dnssec_nsec3_iterations |
warning / critical (per nsec3IterationsSeverity) |
NSEC3PARAM.Iterations exceeds nsec3IterationsMax (RFC 9276 §3.1). |
dnssec_nsec3_salt_empty |
warning | NSEC3PARAM.SaltLength is non-zero (RFC 9276 §3.1: a salt buys no measurable protection). |
dnssec_nsec3_optout_only_when_signed_delegations |
info | The OPT-OUT flag is set in a leaf zone, where it serves no purpose. |
dnssec_denial_consistent |
critical | Authoritative servers disagree on the denial-of-existence scheme (NSEC vs NSEC3, or differing parameters). |
dnssec_dnskey_ttl_min |
warning | The DNSKEY TTL is below dnskeyTTLMin, hurting cache efficiency. |
License
Licensed under the MIT License (see LICENSE).