DNSSEC Chain & Rollover Monitor
Pricing
$2.00 / 1,000 successful dnssec domain checks
DNSSEC Chain & Rollover Monitor
Monitor public domains for DS/DNSKEY chain mismatches, DNSSEC signature expiry, and key-rollover drift with persistent cross-run history.
Pricing
$2.00 / 1,000 successful dnssec domain checks
Rating
0.0
(0)
Developer
Maarten Vreeburg
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
6 days ago
Last modified
Categories
Share
Monitor public DNSSEC-signed domains for parent DS / child DNSKEY mismatch, invalid DNSKEY or apex SOA signatures, expiring RRSIG records, recursive-resolver validation failure, and key-rollover drift. Results are structured for Apify schedules, datasets, webhooks, and downstream incident workflows.
This Actor is an independent DNS protocol monitor. It is not affiliated with or endorsed by Cloudflare, ICANN, IANA, any DNS operator, registry, registrar, or DNS provider. The default cloudflare.com target is a public interoperability/QA example only.
Why use it?
A DNSSEC chain can fail even while the zone and nameservers are reachable. A stale parent DS, an incomplete key rollover, or expired signatures can make validating resolvers return SERVFAIL. This Actor gives you a persistent, reviewable observation instead of a one-time checker page.
It does not guarantee availability, global propagation, or complete DNSSEC correctness. One run observes one configured recursive-resolver path. Treat changed, ds_dnskey_mismatch, invalid_signature, bogus_or_servfail, and expiry warnings as review signals and confirm material decisions with your authoritative DNS provider, registrar, and additional independent resolvers.
Input
{"monitorId": "production-domains","domains": [{"domain": "example.com","label": "Customer portal","expectedKeyTags": [12345]}],"warningHours": 24,"timeoutSeconds": 15,"maxConcurrency": 3}
| Field | Required | Limits | Purpose |
|---|---|---|---|
monitorId | yes | 1–200 characters | Stable namespace for cross-run history. Reuse it on scheduled runs. |
domains | yes | 1–50 unique public FQDNs | A string or object containing domain, optional label, and up to 20 expected DNSKEY key tags. |
warningHours | no | 1–720; default 24 | Warn when the earliest observed DNSKEY/SOA RRSIG expires in less than this window. |
timeoutSeconds | no | 3–30; default 15 | Bound for each DNS query/probe. |
maxConcurrency | no | 1–5; default 3 | Maximum domains processed concurrently. |
The Actor accepts domain names only—not URLs, IP ranges, resolver addresses, arbitrary record types, or credentials.
Output
One dataset row is emitted per domain. Important fields include:
status:initial_snapshot,unchanged,changed, or non-billablequery_errorposture:secure_observed,unsigned,island_of_security,missing_dnskey,ds_dnskey_mismatch,invalid_signature,incomplete_signature_evidence, orindeterminate_digest_policy- normalized
parent_dsrecords - normalized
child_dnskeyswith key tags, flags, algorithms, and SHA-256 fingerprints of public DNSKEY wire data (not raw key material) matching_key_tagsdnskey_signature_validandsoa_signature_validearliest_rrsig_expiration,hours_until_earliest_rrsig_expiration, andrrsig_healthrecursive_validation.status, includingsecure_ad,insecure_no_ad,bogus_or_servfail, or a bounded probe errorauthoritative_nameserverand the pinned publicauthoritative_ipused for child-zone evidencesnapshot_hash,previous_snapshot_hash, andchanged_fields- expected-key-tag matching when configured
state_store_mode,charged_event, and a bounded error field
Example:
{"domain": "cloudflare.com","status": "unchanged","posture": "secure_observed","matching_key_tags": [2371],"dnskey_signature_valid": true,"soa_signature_valid": true,"recursive_validation": {"status": "secure_ad", "ad": true},"rrsig_health": "ok","authoritative_nameserver": "ns3.cloudflare.com","authoritative_ip": "162.159.0.33","state_store_mode": "named","charged_event": "dnssec_domain_check"}
Key tags and RRSIG expiry times can legitimately change during a healthy rollover or signing cycle. changed means “review the structural chain evidence,” not “outage” or “attack.” Routine movement of only the RRSIG expiration timestamp does not flip the persistent structural status; use rrsig_health and hours_until_earliest_rrsig_expiration for expiry alerting.
Persistence
Successful observations are stored in the explicit named key-value store:
dnssec-chain-rollover-monitor-state-v1
Each state key is a SHA-256 digest of monitorId + domain. Reuse the same monitorId to get initial_snapshot → unchanged → changed behavior across Apify runs. Failed observations do not overwrite the last successful baseline.
Changing monitorId intentionally creates a new baseline. The default run-scoped store is not used for monitor history.
DNSSEC observation model and limitations
For each domain, the Actor:
- requests parent
DS, resolves authoritative nameservers, blocks non-global destinations, and pins direct public authoritative queries for childDNSKEYand apexSOAevidence with DNSSEC records enabled so a broken chain can still be inspected; - compares supported DS digests to observed DNSKEYs;
- cryptographically validates the DNSKEY RRset's self-signature and the apex SOA signature with the observed DNSKEY set;
- performs a separate normal recursive-resolver probe and records the
ADresult or a possible bogus/SERVFAILoutcome; - compares the normalized observation with the previous successful snapshot.
Important boundaries:
- The Actor does not run a globally distributed resolver network.
- Parent
DSdiscovery and the recursiveADprobe use the runtime resolver; child DNSKEY/SOA signatures come from one pinned public authoritative nameserver. - Private, loopback, link-local, reserved, and otherwise non-global authoritative destinations are blocked before any direct query.
- A recursive
bogus_or_servfailresponse can also reflect an upstream resolver or network failure; confirm independently. secure_observedis deliberately narrower than a guarantee: it proves matching/validating evidence in this observation, not universal propagation or future correctness.- The Actor does not modify DNS, registrar settings, trust anchors, or keys.
- It does not enumerate subdomains or scan IP ranges.
- Public DNS responses can change between queries during normal cache and rollover windows.
Pricing
The Actor uses pay per event:
- event:
dnssec_domain_check - one event per successfully queried, classified, compared, and stored domain observation
- invalid input and
query_errorrows are not charged by this custom event
A run-level maximum charge limit is honored before domains are processed and charged.
Recommended schedule
- Routine managed DNS: every 1–6 hours
- Active KSK/ZSK rollover: every 15–60 minutes while respecting your DNS provider's guidance
- Keep
monitorIdstable - Alert on
status = changed, non-secure_observedposture for domains expected to be signed,recursive_validation.status = bogus_or_servfail, orrrsig_health != ok
Local development
python -m venv .venv.venv/bin/pip install -r requirements.txtAPIFY_LOCAL_STORAGE_DIR="$PWD/storage" .venv/bin/python -m src.venv/bin/python smoke_test.pynpx --yes apify-cli validate-schema
Run the Actor twice with the same input and storage directory to verify named-store reuse.