-
-
Notifications
You must be signed in to change notification settings - Fork 253
Description
When CNAME record in the custom zone file points to external domains, blocky panics and returns no respone
Custom DNS config (it is provisioned by a script, so formatting is not "human")
customDNS:
customTTL: 30m
rewrite:
[REDACTED]: internal
zone: '$ORIGIN internal.
a 3600 A 1.1.1.1
c 3600 CNAME example.com.
'Testing
$ dig a.internal @10.10.10.10
; <<>> DiG 9.18.39 <<>> a.internal @10.10.10.10
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 7011
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0
;; QUESTION SECTION:
;a.internal. IN A
;; ANSWER SECTION:
a.internal. 3600 IN A 1.1.1.1
;; Query time: 1 msec
;; SERVER: 10.10.10.10#53(10.10.10.10) (UDP)
;; WHEN: Tue Sep 16 01:55:54 +04 2025
;; MSG SIZE rcvd: 44
$ dig c.internal @10.10.10.10
; <<>> DiG 9.18.39 <<>> c.internal @10.10.10.10
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: SERVFAIL, id: 573
;; flags: qr rd; QUERY: 1, ANSWER: 0, AUTHORITY: 0, ADDITIONAL: 0
;; WARNING: recursion requested but not available
;; QUESTION SECTION:
;c.internal. IN A
;; Query time: 1 msec
;; SERVER: 10.10.10.10#53(10.10.10.10) (UDP)
;; WHEN: Tue Sep 16 01:55:57 +04 2025
;; MSG SIZE rcvd: 28Logs:
Sep 15 21:55:54 dns-1 blocky[3760]: [2025-09-15 21:55:54] TRACE new incoming request client_id= client_ip=10.10.0.1 client_request_id=7011 protocol=UDP question=A (a.internal.) req_id=09894299-7520-4f9c-9fd2-f01c87012c99
Sep 15 21:55:54 dns-1 blocky[3760]: [2025-09-15 21:55:54] TRACE query_logging.rewrite: go to inner resolver client_ip=10.10.0.1 client_names=10.10.0.1 question=A (a.internal.) req_id=09894299-7520-4f9c-9fd2-f01c87012c99 resolver=custom_dns
Sep 15 21:55:54 dns-1 blocky[3760]: [2025-09-15 21:55:54] DEBUG query_logging.rewrite.custom_dns: returning custom dns entry answer=A (1.1.1.1) client_ip=10.10.0.1 client_names=10.10.0.1 domain=a.internal question=A (a.internal.) req_id=09894299-7520-4f9c-9fd2-f01c87012c99
Sep 15 21:55:54 dns-1 blocky[3760]: [2025-09-15 21:55:54] INFO queryLog: query resolved answer=A (1.1.1.1) client_ip=10.10.0.1 client_names=10.10.0.1 instance=dns-1 question_name=a.internal. question_type=A response_code=NOERROR response_reason=CUSTOM DNS response_type=CUSTOMDNS
Sep 15 21:55:57 dns-1 blocky[3760]: [2025-09-15 21:55:57] TRACE new incoming request client_id= client_ip=10.10.0.1 client_request_id=573 protocol=UDP question=A (c.internal.) req_id=c49e209b-626a-4c70-ba22-53fb93ac2979
Sep 15 21:55:57 dns-1 blocky[3760]: [2025-09-15 21:55:57] TRACE query_logging.rewrite: go to inner resolver client_ip=10.10.0.1 client_names=10.10.0.1 question=A (c.internal.) req_id=c49e209b-626a-4c70-ba22-53fb93ac2979 resolver=custom_dns
Sep 15 21:55:57 dns-1 blocky[3760]: [2025-09-15 21:55:57] TRACE query_logging.rewrite.custom_dns: go to next resolver client_ip=10.10.0.1 client_names=10.10.0.1 next_resolver=noop question=A (c.internal.) req_id=c49e209b-626a-4c70-ba22-53fb93ac2979
Sep 15 21:55:57 dns-1 blocky[3760]: [2025-09-15 21:55:57] ERROR error on processing request:panic occurred: runtime error: invalid memory address or nil pointer dereference client_ip=10.10.0.1 question=A (c.internal.) req_id=c49e209b-626a-4c70-ba22-53fb93ac2979
I have looked through the code, it seems the culprit is
blocky/resolver/custom_dns_resolver.go
Lines 278 to 284 in a2cfb0b
| // resolve the target recursively | |
| targetResp, err := r.processRequest(ctx, logger, targetRequest, cnames) | |
| if err != nil { | |
| return nil, err | |
| } | |
| result = append(result, targetResp.Res.Answer...) |
which calls to this (because external domain is not specified in the zone file)
blocky/resolver/custom_dns_resolver.go
Line 162 in a2cfb0b
| logger.WithField("next_resolver", Name(r.next)).Trace("go to next resolver") |
but next is noop, as initialized in here
Line 325 in a2cfb0b
| resolver.NewRewriterResolver(cfg.CustomDNS.RewriterConfig, resolver.NewCustomDNSResolver(cfg.CustomDNS)), |
blocky/resolver/rewriter_resolver.go
Lines 28 to 46 in a2cfb0b
| func NewRewriterResolver(cfg config.RewriterConfig, inner ChainedResolver) ChainedResolver { | |
| if len(cfg.Rewrite) == 0 { | |
| return inner | |
| } | |
| // ensures that the rewrites map contains all rewrites in lower case | |
| for k, v := range cfg.Rewrite { | |
| cfg.Rewrite[strings.ToLower(k)] = strings.ToLower(v) | |
| } | |
| inner.Next(NewNoOpResolver()) | |
| return &RewriterResolver{ | |
| configurable: withConfig(&cfg), | |
| typed: withType("rewrite"), | |
| inner: inner, | |
| } | |
| } |
which returns nil in the response somewhere I think, so when CNAME handler tries to access it and append it to result slice, it panics.
I'm not sure what behavior was intended here, so I'm couldn't make a PR to fix it myself. I stumbled upon this bug when trying to implement CNAMES to my router DNS, populated from DHCP. I was hoping the CNAME resolution would go through my conditional config, which points unqualified DNS requests to the router and so I would have DHCP+DNS service discovery, which would allow me to setup something like
conditional:
mapping:
.: 10.0.0.1 # router with DNS enabledapplication 3600 CNAME reverse-proxy. ;; this is the hostname of the proxy VM, registered by DHCP and resolvable by router's DNS
I'm more than willing to take upon fixing this, but I would like to hear maintainer's opinion on this case
Thank you for blocky btw, aside from this edge case it has been rock solid local DNS solution