From 5e7dc580b71cc87fc8cd2779ab63537edf078a4c Mon Sep 17 00:00:00 2001 From: Ben Vincent Date: Sun, 12 Jul 2026 22:17:16 +1000 Subject: [PATCH] Exempt internal split-horizon zones from resolver DNSSEC validation (#251) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Why Resolving any `unkin.net` record through the resolver (`.7`) returns **SERVFAIL**, while the authoritative (`.6`) answers fine. Confirmed from the resolver's querylog: ``` view openforwarder: validating unkin.net/SOA: got insecure response; parent indicates it should be secure broken trust chain resolving 'ausyd1nxvm2120.main.unkin.net/A/IN': 198.18.200.6#53 query failed (broken trust chain) ``` The resolver runs `dnssec-validation auto`. The public `unkin.net` is DNSSEC-signed (the `.net` parent publishes a DS), but the in-cluster split-horizon authoritative serves `unkin.net` **unsigned**. The validator sees "parent says secure" + an insecure answer → treats it as spoofing → SERVFAIL. The authoritative works directly because it does no validation. ## Fix Add `validate-except` (via `spec.extraOptions`) for the forwarded internal domains, so the resolver treats them as insecure and skips validation: ``` validate-except { unkin.net; 18.198.in-addr.arpa; consul } ``` - `unkin.net` covers all `*.unkin.net` (incl. `main.unkin.net`, `k8s.syd1.au.unkin.net`) - `18.198.in-addr.arpa` covers every `NN.18.198.in-addr.arpa` reverse zone (subtree) - `consul` covers the consul TLD This also makes internal resolution independent of Internet egress (no DNSSEC chain-walk needed). External-name validation is unchanged. No operator change required. ## Validation `bind-internal` renders and passes `kubeconform` (56/56); pre-commit clean. ## Activation After merge + operator reconcile, the resolver ConfigMap re-renders; the running pods hold a startup snapshot, so they need a reload: `kubectl -n bind-internal rollout restart statefulset/bind-resolvers`. Reviewed-on: https://git.unkin.net/unkin/argocd-apps/pulls/251 Co-authored-by: Ben Vincent Co-committed-by: Ben Vincent --- apps/base/bind-internal/resolvers/cluster.yaml | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/apps/base/bind-internal/resolvers/cluster.yaml b/apps/base/bind-internal/resolvers/cluster.yaml index cfefc58..2fc2888 100644 --- a/apps/base/bind-internal/resolvers/cluster.yaml +++ b/apps/base/bind-internal/resolvers/cluster.yaml @@ -21,6 +21,15 @@ spec: forwarders: - 8.8.8.8 - 1.1.1.1 + # The internal split-horizon zones are served UNSIGNED by the in-cluster + # authoritative, but their public parents publish DS records (e.g. unkin.net + # is DNSSEC-signed on the Internet). With dnssec-validation on, the validator + # sees "parent indicates secure" but gets an insecure answer and returns + # SERVFAIL (broken trust chain). Treat the forwarded internal domains as + # insecure so they are not validated. unkin.net covers all *.unkin.net + # (incl. k8s.syd1.au.unkin.net); 18.198.in-addr.arpa covers every reverse zone. + extraOptions: + - "validate-except { unkin.net; 18.198.in-addr.arpa; consul }" resources: requests: cpu: 20m