95ff0b33968f07fb376dd061770e790578b2e71a
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
zonemaster-tools
The JSON API behind the DNS tools on zonemaster.es, the pages next to the
Zonemaster test. The GUI lives in CloudHost/zonemaster-gui-es, and Zonemaster
itself is in the stock backend.
Endpoint (/tools-api/…) |
What it does |
|---|---|
propagation?domain=&type= |
Sends the same question to 18 public resolvers worldwide, plus Google with an EDNS Client Subnet from 11 regions. Compares the answers against the zone's authoritative answer, found by walking down from the root. |
resolvers?domain=&type=&resolver= |
Asks 11 resolvers over UDP, TCP and DoH (HTTP/2). Reports latency, rcode and DNSSEC validation (AD bit). resolver adds a public IP of your choice. |
security?domain= |
14 checks: DNSSEC (asked of four validators), NS diversity, SOA serial consistency, open AXFR, SPF (with RFC 7208 lookup count), DMARC, DKIM (35 common selectors), MX, CAA, MTA-STS, TLS-RPT, BIMI, dangling CNAMEs / takeover-prone targets, and wildcard. Returns a 0–100 score and grade, and stores one history row per change. |
security/history?domain= |
The tracker: past scores and per-check statuses. |
infra?domain= |
CDN/WAF/hosting from CNAMEs and HTTP headers, ASN per IP (Team Cymru), PTR, TLS certificate, and DNS and mail provider. |
graph?domain= |
Nodes and edges: the delegation path from the root, then NS/MX/web names, CNAME chains, IPs and ASNs. |
blocklists?domain= |
Checks 7 Pi-hole/AdGuard lists (AdGuard DNS, StevenBlack, HaGeZi PRO and TIF, OISD small, URLhaus, Phishing Army) the way each blocker matches them, plus 8 filtering resolvers asked live. |
blacklists?domain= |
Checks 6 domain DNSBLs (Spamhaus DBL, SURBL, URIBL…) and 10 IP DNSBLs for each web and mail IP. Queries go straight to each list's own nameservers. |
All output is language-neutral: ids, statuses and data, never prose. The GUI writes the sentences in each locale.
Guard rails
- Only public addresses. A user-supplied resolver, every probed IP and every HTTP connection must be
is_global. The jail sits on10.20.0.0/24next to every other jail on gringo.tests/test_parsers.pypins this. - Rate limit: 30 cost units per client per minute (a blacklist check costs 3), and 12 heavy requests in flight overall. The client comes from
X-Real-IP, set by the host nginx. - Cache: 20 s for propagation and resolvers, 120 s for everything else.
- The web probe sends one GET and reads headers only. It never follows a redirect or reads a body.
Run
pkg install python312 py312-sqlite3 py312-dnspython py312-httpx py312-h2
cp -R zmtools /usr/local/zmtools/
cp rc.d/zmtools /usr/local/etc/rc.d/zmtools
pw useradd zmtools -d /var/db/zmtools -s /usr/sbin/nologin
sysrc zmtools_enable=YES zmtools_host=10.20.0.22
service zmtools start
State lives in /var/db/zmtools/:
blocklists.sqlite: about 80 MB, rebuilt every 12 h beside the live copy and then swapped in.history.sqlite: the tracker's history.
The log is /var/log/zmtools.log.
Test
python3 -m pytest -q tests # offline: parsing, validation, matching rules
Description
DNS tools API for zonemaster.es: propagation, resolvers, security tracker, infrastructure, graph, blocklists and DNSBLs
76 KiB
Languages
Python
98.6%
Shell
1.4%