Internet exposure checks and response rate limiting

Jarl works out which views are reachable from the internet (match-clients
ending in a catch-all, not private-looking addresses: an internal view of a
global IPv6 prefix is still yours; a server without views: open allow-query
and a non-private listen address), with a per-view override (schema 9), and
checks public ones: rate limiting, open resolver, minimal-any, cache
snooping, open NOTIFY and transfers, version and host name, management
interfaces. Fixes are staged like any change, including rate limiting from
ISC's example in log-only mode with the secondaries exempt, then enforcing.
named logs what rate limiting limits (or would, in log-only mode, where its
counters don't move) as query-errors; Jarl routes those lines to its log
and counts them (rrl breakdown, ratelimited top lists, Prometheus
jarl_ratelimit_logged_total), shown on the new Exposure page.

A change that newly opens a public view up must be confirmed (accept_risk,
--accept-risk, a checkbox on the Changes page; 409 confirm_risk
otherwise). Findings can be acknowledged with a reason and stay visible as
info. GET /exposure, POST /exposure/fix|ack|unack, jarl exposure,
docs/exposure.md.

Also fixes query statistics skipping TSIG-signed queries ("IP#port/key
NAME" in named's log).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
adamandClaude Opus 5.5 committed 2026-10-12 10:38:56 +01:00
1 parent cf550bd512
commit bdd7acfd3b
50 files changed
+2019 -52

No files matched your search

+9
View File
@@ -71,6 +71,14 @@ error: www.adbraun.lol has a CNAME, so it can't have any other records (found A)
queries, record types, cache hit rate. Shown in the web UI and the CLI,
and exportable as JSON. Stored as aggregates in a separate database with
retention you set.
* **Internet exposure checks**: Jarl works out which views are reachable
from the internet (a GUA-addressed internal network still counts as
yours) and checks them: response rate limiting (set up in log-only mode
first, with what it would limit shown before you enforce it), open
resolvers, ANY amplification, cache snooping, version and host name
leaks, open management interfaces. Fixes are staged for review, changes
that open a public view up must be confirmed, and deliberate exceptions
can be acknowledged with a reason.
* **Prometheus metrics** (optional): health to alert on (named down,
configuration problems, drift, failing blocklists, stale backups, DNSSEC
steps waiting at the parent, expiring tokens) and query counters per
@@ -125,6 +133,7 @@ in `/etc/jarl/jarl.yaml` to reach it from your management network.
| [docs/dnssec.md](docs/dnssec.md) | DNSSEC signing, going public with your own name servers, Porkbun |
| [docs/acme.md](docs/acme.md) | Let's Encrypt DNS-01 with certbot, acme.sh, lego and Traefik |
| [docs/stats.md](docs/stats.md) | Query statistics: enabling, what is collected, retention |
| [docs/exposure.md](docs/exposure.md) | Internet exposure: which views are public, hardening checks, response rate limiting |
| [docs/metrics.md](docs/metrics.md) | Prometheus metrics: access, what is exported, example alerts |
| [docs/blocking.md](docs/blocking.md) | Blocking ads, trackers and malware: blocklists, your own rules, views, memory |
| [docs/validation.md](docs/validation.md) | Every check Jarl makes |