ITADN

dns/dnscrypt-proxy: listen_addresses CSVListField does not support IPv6 bracket notation, preventing [::]:53 from being saved correctly

#5485Closedskyweir 创建于 2026-06-07
incomplete
S
skyweircommented
## Summary The listen_addresses field in the DNSCrypt-proxy plugin uses CSVListField with no validation mask. The tokenize UI widget corrupts IPv6 bracket notation (e.g. [::]:53) when saving, causing DNSCrypt-proxy to either fail to start or fall back to [::1]:53 (loopback only) instead of binding to all IPv6 interfaces. ## Environment - OPNsense 25.x - os-dnscrypt-proxy plugin - DNSCrypt-proxy 2.1.15 ## Problem On dual-stack networks, OPNsense advertises the router's LAN IPv6 address as the DNS server via DHCPv6/RA. Clients send DNS queries to that IPv6 address. DNSCrypt-proxy must listen on [::]:53 to handle these queries. Attempting to enter [::]:53 via the UI results in DNSCrypt-proxy failing to start. The value is either mangled by the tokenize widget or rejected before reaching the template, leaving only [::1]:53 (loopback) in the rendered TOML. ## Root Cause In General.xml, listen_addresses is defined as: <listen_addresses type="CSVListField"> <Default>0.0.0.0:5353</Default> <Required>Y</Required> </listen_addresses> CSVListField has no Mask validator and no awareness of IPv6 address format. The tokenize widget in general.xml renders the field as select_multiple with allownew=true, which does not handle bracket notation in IPv6 addresses correctly when serializing back to config.xml. Additionally, the Jinja2 template renders listen_addresses with a naive comma-split: listen_addresses = [{{ "'" + ("','".join( OPNsense.dnscryptproxy.general.listen_addresses.split(','))) + "'" }}] This works for IPv4 but produces malformed TOML for IPv6 addresses containing colons and brackets. ## Proposed Fix Two changes are needed: **1. General.xml — add a Mask that accepts both IPv4 and IPv6 address:port format:** <listen_addresses type="CSVListField"> <Default>0.0.0.0:5353</Default> <Required>Y</Required> <Mask>/^(\[?[0-9a-fA-F:\.]+\]?:[0-9]{1,5})(,\[?[0-9a-fA-F:\.]+\]?:[0-9]{1,5})*$/</Mask> <ValidationMessage>Please enter valid address:port combinations, e.g. 0.0.0.0:53 or [::]:53</ValidationMessage> </listen_addresses> **2. dnscrypt-proxy.toml template — handle IPv6 entries correctly when rendering:** The current naive split on ',' is ambiguous for IPv6. Since IPv6 addresses in bracket notation do not contain commas, the split is technically safe, but the template should be updated to make this explicit and ensure bracket notation is preserved verbatim: listen_addresses = [{{ "'" + ("','".join( OPNsense.dnscryptproxy.general.listen_addresses.split(','))) + "'" }}] No change needed here if the model correctly stores and retrieves the bracket notation — the split-on-comma approach works as long as the value is not corrupted upstream. The primary fix is in the model/UI layer. ## Workaround Until fixed, manually append '[::]:53' in the template at: /usr/local/opnsense/service/templates/OPNsense/Dnscryptproxy/dnscrypt-proxy.toml Change: listen_addresses = [{{ "'" + ("','".join( OPNsense.dnscryptproxy.general.listen_addresses.split(','))) + "'" }}] To: listen_addresses = [{{ "'" + ("','".join( OPNsense.dnscryptproxy.general.listen_addresses.split(','))) + "'" }}, '[::]:53'] Then reload and restart: configctl template reload OPNsense/Dnscryptproxy service dnscrypt-proxy restart
关闭于 2026-06-07 2 条评论