# Shared zone-loading + recursive-forwarding config. (common) { auto { directory /zones (.*)\.zone {1} reload 30s } # AXFR is open to everyone here. The FortiWiFi firewall does the # real source-IP filtering (only 216.218.133.2 / slave.dns.he.net # can reach our public :53/tcp). # # Why not narrow the `to` list to HE's IPs? CoreDNS's transfer # plugin has a confirmed bug: any `to` with more than one specific # IPv4 address silently breaks listener startup (no error logged, # zones load, but .:53 / tls://.:853 / https://.:443 never bind). # Reproduced in 1.11.3 and 1.12.2, even in a minimal fresh # `docker run` — not a compose state issue. Single-IP works, but # we need asymmetric config (AXFR from .133.2, NOTIFY to .130.2) # which the single-line `to` directive can't express. # # NOTIFY is sent externally by scripts/notify-he.py (invoked from # `make prep`) so we can target ns1.he.net specifically. transfer { to * } forward . 1.1.1.1 1.0.0.1 9.9.9.9 { max_concurrent 1000 } cache 30 errors log loop reload 10s } # Plain DNS — UDP/TCP :53. Health + metrics live here only (one binding). . { import common health :8080 prometheus :9153 } # DNS-over-TLS — RFC 7858. Port 853 is the IANA-assigned DoT port. tls://.:853 { tls /etc/coredns/certs/cert.pem /etc/coredns/certs/key.pem import common } # DNS-over-HTTPS — RFC 8484. Default path is /dns-query. # Clients: curl -H 'accept: application/dns-message' https://host:8443/dns-query?dns=... https://.:443 { tls /etc/coredns/certs/cert.pem /etc/coredns/certs/key.pem import common }