Both directions
PTR for the address, AAAA for the generated name — always consistent, because both come from the same function of the 128-bit address.
PanoptiDNS is a small authoritative DNS server that computes PTR records and matching AAAA records per query — for every address in your prefixes, in both directions. A drop-in, hardened replacement for AllKnowingDNS that reads the same configuration file.
18 446 744 073 709 551 616
addresses in a single /64. No zone file can enumerate them — but the mapping between an address and a hostname is a pure function, so PanoptiDNS simply computes it for each query. SLAAC clients, privacy addresses and whole customer prefixes get consistent reverse and forward DNS without any provisioning.
One static binary, one configuration file, no database, no zone transfers.
PTR for the address, AAAA for the generated name — always consistent, because both come from the same function of the 128-bit address.
Reads the AllKnowingDNS v1.7 format as is; its acceptance vectors are part of
the test suite. %DIGITS% and %DIGITS-DASHED% templates.
--check-config reports every problem at once, rustc-style with a
caret. SIGHUP reloads; a broken file keeps the running config.
Query names are parsed into a u128 or rejected — never used as
text. Panics on the request path are denied by lint and caught as SERVFAIL.
On by default, with separate budgets for answers and negative responses,
per-prefix aggregation and BIND-style slip.
with upstream lookups are asynchronous, deadline-bound, behind a
circuit breaker, and relayed only through a strict record allowlist.
Apex SOA and NS, SOA in negative answers (RFC 2308), EDNS(0), TCP, and BADVERS for unknown EDNS versions.
~5 MB distroless image for amd64/arm64, uid 65532, read-only root, all
capabilities dropped. systemd unit with DynamicUser included.
Type any address. This runs in your browser with the same rule the server applies: the host part becomes the hex digits in the name.
The highlighted nibbles are the host part — 16 hex digits for a /64. Nothing is stored anywhere; the server does exactly this arithmetic per query.
Why a rewrite instead of a patch.
AllKnowingDNS v1.7 (Perl, unmaintained since 2013) could be
terminated by a single UDP packet. It built records by
interpolating the attacker-controlled query name into a DNS master-file
presentation string — and ; and " are not escaped
there. One raw ; in a label made the parser die, nothing caught
the exception, and the process exited.
PanoptiDNS makes that class of bug unrepresentable: names are never presentation text, a zone is an integer prefix and mask, and the request path cannot abort. Five further defects of the original — a 20 s blocking upstream lookup among them — each have a named regression test.
# attacker-controlled $qname → master-file text Net::DNS::RR->new("$qname $ttl $qclass $qtype $rdata") # one packet, no auth, endlessly repeatable $ dig PTR 'a;b.0.c.c.c.e.0.0.1.8.b.d.0.1.0.0.2.ip6.arpa' → AllKnowingDNS: process exits → PanoptiDNS: NXDOMAIN, keeps serving
Write a config, start the container, delegate the zones. Multi-arch images on
GHCR and Docker Hub; pin an exact version like 0.2.0 in production.
primary ns1.example.net.
hostmaster hostmaster.example.net.
ns ns1.example.net.
network 2001:db8:100e:ccc0::/64
resolves to ipv6-%DIGITS%.nutzer.example.net
Save as panoptidns.conf next to the compose file, then validate and start:
docker compose run --rm panoptidns --check-config
docker compose up -d
; reverse
0.c.c.c.e.0.0.1.8.b.d.0.1.0.0.2.ip6.arpa. IN NS ipv6-rdns.example.net.
; forward
nutzer.example.net. IN NS ipv6-rdns.example.net.
Images:
ghcr.io/cygnusnetworks/panoptidns:stable
cygnusnetworks/panoptidns:stable
Same config file, same answers — without the remote kill switch.