Hurricane Electric requires asymmetric transfer config:
- AXFR pull from 216.218.133.2 (slave.dns.he.net / ns4.he.net)
- NOTIFY destination 216.218.130.2 (ns1.he.net)
CoreDNS's transfer plugin uses a single bidirectional `to` list for
both, which is fine in principle but breaks in a confirmed bug: any
`to` with more than one specific IPv4 silently kills server-block
listener startup (no error, zones load, but :53 never binds).
Reproduced on 1.11.3 + 1.12.2 even with a minimal fresh `docker run`.
Workaround:
- Corefile keeps `transfer { to * }` (open AXFR; firewall does the
real source-IP filtering on TCP/53)
- scripts/notify-he.py crafts and sends NOTIFY messages directly to
216.218.130.2 (only). Pure-stdlib Python — no dependencies.
- Makefile `prep` target runs notify-he.py after prepare-zones.sh
so every zone-bump fires NOTIFY automatically.
Verified end-to-end: HE acks NOTIFY (rcode=0) for the 10 zones it
hosts as secondaries; remaining 81 return REFUSED (rcode=5) because
HE doesn't have them configured yet. Note: HE's free slave service
acks NOTIFY but only actually re-pulls AXFR on its hourly poll cycle
(observed behavior — they're poll-based by design). NOTIFY still
useful long-term in case HE changes that behavior; harmless either way.
56 lines
1.7 KiB
Plaintext
56 lines
1.7 KiB
Plaintext
# 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
|
|
}
|