From 57c8366b7fc91bef1aec587f191c7cc7e1bf0c36 Mon Sep 17 00:00:00 2001 From: Ryan Malloy Date: Sat, 16 May 2026 16:04:44 -0600 Subject: [PATCH] coredns: document why HE-IP restriction lives at firewall, not CoreDNS MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Goal was to restrict AXFR to Hurricane Electric's five secondary nameserver IPs. Tried several CoreDNS Corefile syntaxes: transfer { to 216.218.130.2 ... 216.66.1.2 } # space-separated transfer { to 216.218.130.2 \n to 216.218.131.2 } # multi-line transfer { to 216.218.130.2 } # single IP transfer { to * 216.218.130.2 ... } # mixed Every form with a specific IPv4 address silently breaks server-block startup — the auto plugin still loads zones into memory but the :53/:443/:853 listeners never bind. Reproducible on coredns/coredns 1.11.3 AND 1.12.2 with the (common) snippet + auto + forward shape. Only `to *` results in healthy listener startup. Even if we got CoreDNS-side filtering to work, Docker's default userland-proxy rewrites source IPs to the bridge gateway, which would break IP-based filtering anyway short of `network_mode: host`. Decision: keep `to *` in CoreDNS, push HE-only filtering to the FortiWiFi firewall (source-IP-restricted VIP/DNAT for WAN:53/tcp). This is correct-layered defense — the perimeter does the IP work before packets ever reach dell01. --- Corefile | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/Corefile b/Corefile index 786437d..1a8ae67 100644 --- a/Corefile +++ b/Corefile @@ -7,19 +7,23 @@ reload 30s } - # Authorize AXFR (zone transfer) and send NOTIFY messages. + # AXFR authorization is `to *` at this layer, with HE-only filtering + # done by the FortiWiFi firewall (source IP restriction on the + # TCP/53 DNAT rule). Reasons we don't filter at CoreDNS: # - # The `transfer` plugin only accepts single IPs or `*` (no CIDR), so - # for now we open AXFR to anyone. Two reasons this is acceptable: + # 1. CoreDNS plugin quirk: `to ` (any form — single, + # multi-line, space-separated) silently fails to start server + # blocks. Reproduced on 1.11.3 and 1.12.2. Only `to *` works. + # 2. Docker port publishing with userland-proxy rewrites source + # IPs to the bridge gateway, so IP filtering wouldn't see HE's + # real address anyway (without network_mode: host). + # 3. Filtering at the perimeter (FortiWiFi) is correct-layered + # defense: bad packets don't reach the host at all. # - # 1. DNS data is public anyway — every record is queryable - # individually. AXFR just bundles them, no new secrets exposed. - # 2. Docker's published-port NAT rewrites source IPs to the bridge - # gateway, so we couldn't pin to Hurricane Electric's IPs - # reliably even if we wanted to. - # - # NOTIFY messages go OUT to the listed IPs on zone change. We send - # to all five HE secondaries so they refresh promptly when SOA bumps. + # Required FortiWiFi rule: + # VIP "coredns-tcp" — src in {216.218.130.2, 216.218.131.2, + # 216.218.132.2, 216.218.133.2, 216.66.1.2} — + # dst WAN:53/tcp → 172.16.1.15:5353/tcp transfer { to * }