diff options
author | Indrajit Raychaudhuri <irc@indrajit.com> | 2023-03-25 18:51:34 -0500 |
---|---|---|
committer | Indrajit Raychaudhuri <irc@indrajit.com> | 2023-03-27 01:42:38 -0500 |
commit | c6494f12f92746cc4603fceca6b1a22fed010b93 (patch) | |
tree | 030b60d9e082e0c6875f0166a11095fad0a8456a | |
parent | 8f1e8d720d63dffa2b5a3413c8827c9ad176f2ac (diff) | |
download | vyos-1x-c6494f12f92746cc4603fceca6b1a22fed010b93.tar.gz vyos-1x-c6494f12f92746cc4603fceca6b1a22fed010b93.zip |
dns: T5113: Support custom port for name-server forwarders
Support custom port for name-server forwarders that would allow using
custom ports in name server forwarders to enable forwarding to
alternative name servers (unbound, stubby, dnscrypt-proxy etc.)
operating on non-default port.
This would also allow using DNS Over TLS in PowerDNS Recursor 4.6 onwards
(pdns doesn't support certificate check for validity yet) by enabling
'dot-to-port-853'. This is set by default if compiled in with DoT support.
See: https://doc.powerdns.com/recursor/settings.html#dot-to-port-853
This also partially implements T921, T2195 (DoT without certificate check).
Implementation details:
- In 'dns/forwarding' configuration, 'name-server' now allows optional
'port' (defaults to 53).
- Instead of modifying 'name-server-ipv4-ipv6.xml.i' to add optional
'port', a new file 'name-server-ipv4-ipv6-port.xml.i' has been used
to avoid impacting other places where it is reused because not all of
them honor ports (mostly VPN related).
- The `host:port` entries to be used by PowerDNS recursor config are
normalized eagerly at the point of loading VyOS `Config` instead of
doing them lazily while rendering the Jinja2 template to keep the
implementation less intrusive. The alternative would entail making
quite a bit of change in how 'vyos-hostsd' processes 'static'
'name_servers' entries or persists their runtime states.
-rw-r--r-- | interface-definitions/dns-forwarding.xml.in | 2 | ||||
-rw-r--r-- | interface-definitions/include/name-server-ipv4-ipv6-port.xml.i | 25 | ||||
-rwxr-xr-x | src/conf_mode/dns_forwarding.py | 17 |
3 files changed, 41 insertions, 3 deletions
diff --git a/interface-definitions/dns-forwarding.xml.in b/interface-definitions/dns-forwarding.xml.in index 371f198c6..b23eaa351 100644 --- a/interface-definitions/dns-forwarding.xml.in +++ b/interface-definitions/dns-forwarding.xml.in @@ -635,7 +635,7 @@ </properties> <defaultValue>1500</defaultValue> </leafNode> - #include <include/name-server-ipv4-ipv6.xml.i> + #include <include/name-server-ipv4-ipv6-port.xml.i> <leafNode name="source-address"> <properties> <help>Local addresses from which to send DNS queries</help> diff --git a/interface-definitions/include/name-server-ipv4-ipv6-port.xml.i b/interface-definitions/include/name-server-ipv4-ipv6-port.xml.i new file mode 100644 index 000000000..cf86e66a2 --- /dev/null +++ b/interface-definitions/include/name-server-ipv4-ipv6-port.xml.i @@ -0,0 +1,25 @@ +<!-- include start from name-server-ipv4-ipv6-port.xml.i --> +<tagNode name="name-server"> + <properties> + <help>Domain Name Servers (DNS) addresses</help> + <valueHelp> + <format>ipv4</format> + <description>Domain Name Server (DNS) IPv4 address</description> + </valueHelp> + <valueHelp> + <format>ipv6</format> + <description>Domain Name Server (DNS) IPv6 address</description> + </valueHelp> + <constraint> + <validator name="ipv4-address"/> + <validator name="ipv6-address"/> + </constraint> + </properties> + <children> + #include <include/port-number.xml.i> + <leafNode name="port"> + <defaultValue>53</defaultValue> + </leafNode> + </children> +</tagNode> +<!-- include end --> diff --git a/src/conf_mode/dns_forwarding.py b/src/conf_mode/dns_forwarding.py index d0d87d73e..4d6b85d92 100755 --- a/src/conf_mode/dns_forwarding.py +++ b/src/conf_mode/dns_forwarding.py @@ -24,7 +24,7 @@ from vyos.config import Config from vyos.configdict import dict_merge from vyos.hostsd_client import Client as hostsd_client from vyos.template import render -from vyos.template import is_ipv6 +from vyos.template import bracketize_ipv6 from vyos.util import call from vyos.util import chown from vyos.util import dict_search @@ -58,8 +58,16 @@ def get_config(config=None): default_values = defaults(base) # T2665 due to how defaults under tag nodes work, we must clear these out before we merge del default_values['authoritative_domain'] + del default_values['name_server'] dns = dict_merge(default_values, dns) + # T2665: we cleared default values for tag node 'name_server' above. + # We now need to add them back back in a granular way. + if 'name_server' in dns: + default_values = defaults(base + ['name-server']) + for server in dns['name_server']: + dns['name_server'][server] = dict_merge(default_values, dns['name_server'][server]) + # some additions to the default dictionary if 'system' in dns: base_nameservers = ['system', 'name-server'] @@ -329,7 +337,12 @@ def apply(dns): # sources hc.delete_name_servers([hostsd_tag]) if 'name_server' in dns: - hc.add_name_servers({hostsd_tag: dns['name_server']}) + # 'name_server' is a dict of the form + # {'192.0.2.1': {'port': 53}, '2001:db8::1': {'port': 853}, ...} + # canonicalize them as ['192.0.2.1:53', '[2001:db8::1]:853', ...] with IPv6 hosts bracketized + nslist = [(lambda h, p: f"{bracketize_ipv6(h)}:{p['port']}")(h, p) + for (h, p) in dns['name_server'].items()] + hc.add_name_servers({hostsd_tag: nslist}) # delete all nameserver tags hc.delete_name_server_tags_recursor(hc.get_name_server_tags_recursor()) |