dns-tools

DNS Tools (SuperTool)

An MXToolbox-style DNS lookup + diagnostics console built into the control plane. One input box runs every common DNS/email/network diagnostic; type a domain, IP, or URL and the tool auto-detects what to run, or pick a command explicitly.

100% ours — pure Node standard library (node:dns, node:net, node:tls), no third-party packages. Everything runs server-side behind admin auth and the dns.use permission.

Where it lives

LayerPath
Pagecontrol-plane/web/app/(god)/dns-tools/page.tsx
UIcontrol-plane/web/components/dns-tools/{super-tool,result-view,command-help}.tsx
Server action (auth gate)control-plane/web/lib/dns/actions.ts
Dispatcher / parsercontrol-plane/web/lib/dns/supertool.ts
Toolkit modulescontrol-plane/web/lib/dns/*.ts
Permissiondns.use in lib/rbac.ts
Navlib/nav.ts → Infrastructure → “DNS Tools” (chord g n)

Commands

CommandWhat it does
dnsA, AAAA, MX, NS, TXT, SOA, CAA in one shot
a aaaa cname mx ns txt soa srv caaIndividual record types
ptr (alias reverse)Reverse DNS for an IP
spfFind + validate SPF (recursive ≤10-lookup rule, all qualifier)
dmarcParse the _dmarc policy
dkimselector:domain, or probe ~30 common selectors
smtpConnect to the top MX: banner, EHLO caps, STARTTLS (read-only; no relay test)
blacklist (alias rbl)Check an IP against ~28 DNSBLs
whoisDomain (IANA→registry→registrar) or IP (ARIN→RIR) with referral following
https (alias http)Status, redirect chain, server + security headers
cert (alias ssl/tls)Certificate chain, expiry, SANs, hostname match
portTCP connect test to host:port
pingTCP-connect latency (not ICMP — labelled as such)
propagation (alias dnscheck)Same record across 6 public resolvers
dnshealthDelegation, NS reachability, SOA-serial agreement, apex CNAME

Input accepts a leading keyword (mx example.com, blacklist 1.2.3.4) or a bare argument that gets classified: URL → https, IP → blacklist, host:portport, otherwise → dns.

Design notes

  • One result shape. Every tool returns ToolResult (lib/dns/types.ts): findings (checks with pass/warn/fail/info severity), zero or more generic tables, optional raw text, timing. The UI (result-view.tsx) renders any command generically. Results must stay plain-serializable (they cross the 'use server' boundary).
  • Resolver choice is deliberate. Single lookups pin to Cloudflare (1.1.1.1) and report which resolver answered. DNSBL queries use the system resolver on purpose — Spamhaus & friends refuse queries arriving via large public resolvers; 127.255.255.0/24 answers are surfaced as control codes, not listings.
  • Read-only & honest. SMTP does not run an open-relay test. "ping" is a TCP probe, not ICMP. Limits (lookup counts, redirect hops, response bytes) are bounded; the action has a 30 s overall backstop on top of per-tool timeouts.

Extending

Add a tool by writing a lib/dns/<name>.ts that returns a ToolResult, wiring it into runCommand + the Command union and COMMANDS catalog in types.ts. The picker, auto-detect, and renderer pick it up automatically.


Telemetry monitors (Layer 2)

Saved watches that run on a schedule, keep history, and raise alerts on degradation or drift. Each monitor maps to a SuperTool command (or Cloudflare drift); the runner reduces the ToolResult to a status + a stable signature.

PiecePath
Types + cataloglib/dns/monitors/types.ts
Store (PG + in-memory)lib/dns/monitors/store.ts
Runner (status/signature/alerts)lib/dns/monitors/runner.ts
Server actionslib/dns/monitors/actions.ts (perm dns.monitors)
Schemacontrol-plane/db/schema-dns-monitors.sql
Scheduler entrypointapp/api/v1/monitors/run/route.ts
UIcomponents/dns-tools/monitors-panel.tsx

Monitor types: record (drift), tls_expiry, blacklist (MTA reputation), propagation, dns_health, whois_expiry, http, cloudflare_drift.

Status & alerting. A run yields pass | warn | fail | error. An event is raised when the status gets worse (warn→warn, fail→critical), when the answer drifts (signature changed), or on recovery. Signatures deliberately exclude volatile data — TTL columns are dropped, rows are sorted (so record rotation isn't drift), blacklist uses only the listed set (transient unreachable zones don't flap), and http uses status + security-header presence (not volatile header values). blacklist/whois_expiry get type-specific status (listed-count / days-to-expiry) instead of the generic check rollup.

In-app events are the alert of record. External channels (email / Slack / PagerDuty / webhook) hook into deliver() in the runner once configured; they're gated per plan by the monitor's alertChannels.

Scheduling

The scheduler is infra-agnostic — any cron hits the endpoint on an interval:

curl -fsS -X POST https://<control-plane>/v1/monitors/run \
  -H "Authorization: Bearer $MONITORS_CRON_SECRET"

It runs every due monitor once (bounded concurrency) and returns { ran, changed, alerted }. Fail-closed: with MONITORS_CRON_SECRET unset the endpoint refuses to run. Wire it from a Coolify scheduled task, GitHub Actions schedule, or any external pinger (every 1–5 min is plenty; per-monitor intervals do the real pacing).

Cloudflare drift (Layer 3)

lib/dns/cloudflare-drift.ts reads the zone's records via the Cloudflare API (lib/fleet/dns.tslistZoneRecords, scoped CLOUDFLARE_DNS_TOKEN) and compares each DNS-only record's intended content against what a public resolver observes. Drift = the live answer no longer matches the zone (stale cache, competing source, or hijack). Proxied (orange-cloud) records resolve to Cloudflare's edge by design and are reported as proxied, not drift.

Plan gating

lib/billing/entitlements.ts is the single source of truth for what each LicenseTier unlocks (monitor quota, min interval, monitor types, Cloudflare, alert channels, white-label reports). The matrix renders in the UI (components/dns-tools/tier-matrix.tsx); actions.ts enforces it. The god console operator is treated as top tier; the customer dashboard will pass the tenant's own tier.

Environment

VarPurpose
DATABASE_URLPersist monitors/results/events (else in-memory)
MONITORS_CRON_SECRETBearer secret for /v1/monitors/run (required to run)
CLOUDFLARE_DNS_TOKENCloudflare drift + zone telemetry (scoped Zone:DNS)