opnsense / opnsense/plugins

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

Open Beginner friendly
#5,486 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
PHP
Stars
1.2k
Forks
863
Avg merge
2d 6h
Merged PRs (30d)
10

Description

Important notices
Before you add a new report, we ask you kindly to acknowledge the following:

Describe the bug
os-dnscrypt-proxy: The Listen Address field in the DNSCrypt-Proxy general settings UI
does not correctly handle IPv6 wildcard addresses in bracket notation (e.g. [::]:53).
Entering [::]:53 causes DNSCrypt-proxy to fail to start entirely. As a result,
DNSCrypt-proxy can only be configured to listen on [::1]:53 (loopback) via the UI,
which means it does not serve DNS queries arriving on the router's LAN IPv6 interface.

On dual-stack networks where OPNsense advertises the router's LAN IPv6 address as the
DNS server via DHCPv6/RA, this causes all IPv6 DNS queries from clients to fail
silently — bypassing DNSCrypt-proxy entirely.

To Reproduce

  1. Go to Services > DNSCrypt-Proxy > Configuration
  2. In the Listen Address field, add [::]:53 as a new token
  3. Save and apply
  4. Observe that DNSCrypt-proxy fails to start

Expected behavior
DNSCrypt-proxy should accept [::]:53 as a valid listen address and bind to all IPv6
interfaces, serving DNS queries from IPv6 clients on the LAN.

Screenshots
N/A

Relevant log files
Running DNSCrypt-proxy manually with the rendered TOML confirms the service starts and
binds correctly only when [::]:53 is added directly to the TOML — not via the UI:

sockstat -46 | grep dnscrypt
root dnscrypt-p 97335 7 udp46 *:53 :
root dnscrypt-p 97335 8 tcp46 *:53 :

Without the fix, only loopback IPv6 is bound:

root dnscrypt-p 97136 9 udp6 ::1:53 :

Additional context
Root cause: In General.xml, listen_addresses is typed as CSVListField with no Mask
validator and no IPv6 awareness. The tokenize UI widget (select_multiple with
allownew=true) corrupts bracket notation when serializing back to config.xml.

Proposed fix — add a Mask to General.xml that accepts both IPv4 and IPv6 address:port
format:

<listen_addresses type="CSVListField">
0.0.0.0:5353
Y
/^([?[0-9a-fA-F:.]+]?:[0-9]{1,5})(,[?[0-9a-fA-F:.]+]?:[0-9]{1,5})*$/
Please enter valid address:port combinations,
e.g. 0.0.0.0:53 or [::]:53
</listen_addresses>

Workaround until fixed — append '[::]:53' directly in the template at:
/usr/local/opnsense/service/templates/OPNsense/Dnscryptproxy/dnscrypt-proxy.toml

Change:
listen_addresses = [{{ "'" + ("','".join(OPNsense...listen_addresses.split(','))) + "'" }}]
To:
listen_addresses = [{{ "'" + ("','".join(OPNsense...listen_addresses.split(','))) + "'" }}, '[::]:53']

Then reload and restart:
configctl template reload OPNsense/Dnscryptproxy
service dnscrypt-proxy restart

Environment
OPNsense 25.x (amd64)
os-dnscrypt-proxy plugin
DNSCrypt-proxy 2.1.15
Sophos XG-115 hardware

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by reading General.xml and reproducing the [::]:53 entry through the DNSCrypt-Proxy configuration UI, then inspect the rendered output at /usr/local/opnsense/service/templates/OPNsense/Dnscryptproxy/dnscrypt-proxy.toml. Done means the UI preserves valid IPv4 and bracketed IPv6 address:port values and DNSCrypt-proxy starts with [::]:53; reload the template and restart the service to verify.

Written by the indexing model from the issue text.

Assessment

Tech stack
php
Domain
networking
Issue type
Bug
Difficulty
2/5
Estimated time
Half a day
Activity status
Quiet
Clarity
Clearly specified
Newbie friendliness
72/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.