diff options
-rw-r--r-- | data/templates/dns-forwarding/recursor.conf.tmpl | 44 | ||||
-rwxr-xr-x | src/conf_mode/dns_forwarding.py | 133 |
2 files changed, 88 insertions, 89 deletions
diff --git a/data/templates/dns-forwarding/recursor.conf.tmpl b/data/templates/dns-forwarding/recursor.conf.tmpl new file mode 100644 index 000000000..9d1e019fa --- /dev/null +++ b/data/templates/dns-forwarding/recursor.conf.tmpl @@ -0,0 +1,44 @@ +### Autogenerated by dns_forwarding.py ### + +# XXX: pdns recursor doesn't like whitespace near entry separators, +# especially in the semicolon-separated lists of name servers. +# Please be careful if you edit the template. + +# Non-configurable defaults +daemon=yes +threads=1 +allow-from={{ allow_from | join(',') }} +log-common-errors=yes +non-local-bind=yes +query-local-address=0.0.0.0 +query-local-address6=:: + +# cache-size +max-cache-entries={{ cache_size }} + +# negative TTL for NXDOMAIN +max-negative-ttl={{ negative_ttl }} + +# ignore-hosts-file +export-etc-hosts={{ export_hosts_file }} + +# listen-on +local-address={{ listen_on | join(',') }} + +# dnssec +dnssec={{ dnssec }} + +# forward-zones / recursion +# +# statement is only inserted if either one forwarding domain or nameserver is configured +# if nothing is given at all, powerdns will act as a real recursor and resolve all requests by its own +# +{% if name_servers or domains %}forward-zones-recurse= +{%- for d in domains %} +{{ d.name }}={{ d.servers | join(";") }} +{{- ", " if not loop.last -}} +{%- endfor -%} +{%- if name_servers -%} +{%- if domains -%}, {% endif -%}.={{ name_servers | join(';') }} +{% endif %} +{% endif %} diff --git a/src/conf_mode/dns_forwarding.py b/src/conf_mode/dns_forwarding.py index 38f3cb4de..bbb69cdf7 100755 --- a/src/conf_mode/dns_forwarding.py +++ b/src/conf_mode/dns_forwarding.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # -# Copyright (C) 2018 VyOS maintainers and contributors +# Copyright (C) 2018-2020 VyOS maintainers and contributors # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License version 2 or later as @@ -13,76 +13,26 @@ # # You should have received a copy of the GNU General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. -# -# -import sys import os - import argparse -import jinja2 -import netifaces -import vyos.util -import vyos.hostsd_client +from sys import exit +from copy import deepcopy +from jinja2 import FileSystemLoader, Environment from vyos.config import Config +from vyos.defaults import directories as vyos_data_dir +from vyos.hostsd_client import Client as hostsd_client +from vyos.util import wait_for_commit_lock from vyos import ConfigError - parser = argparse.ArgumentParser() parser.add_argument("--dhclient", action="store_true", help="Started from dhclient-script") config_file = r'/etc/powerdns/recursor.conf' -# XXX: pdns recursor doesn't like whitespace near entry separators, -# especially in the semicolon-separated lists of name servers. -# Please be careful if you edit the template. -config_tmpl = """ -### Autogenerated by dns_forwarding.py ### - -# Non-configurable defaults -daemon=yes -threads=1 -allow-from={{ allow_from | join(',') }} -log-common-errors=yes -non-local-bind=yes -query-local-address=0.0.0.0 -query-local-address6=:: - -# cache-size -max-cache-entries={{ cache_size }} - -# negative TTL for NXDOMAIN -max-negative-ttl={{ negative_ttl }} - -# ignore-hosts-file -export-etc-hosts={{ export_hosts_file }} - -# listen-on -local-address={{ listen_on | join(',') }} - -# dnssec -dnssec={{ dnssec }} - -# forward-zones / recursion -# -# statement is only inserted if either one forwarding domain or nameserver is configured -# if nothing is given at all, powerdns will act as a real recursor and resolve all requests by its own -# -{% if name_servers or domains %}forward-zones-recurse= -{%- for d in domains %} -{{ d.name }}={{ d.servers | join(";") }} -{{- ", " if not loop.last -}} -{%- endfor -%} -{%- if name_servers -%} -{%- if domains -%}, {% endif -%}.={{ name_servers | join(';') }} -{% endif %} -{% endif %} - -""" - default_config_data = { 'allow_from': [], 'cache_size': 10000, @@ -96,74 +46,74 @@ default_config_data = { def get_config(arguments): - dns = default_config_data + dns = deepcopy(default_config_data) conf = Config() + base = ['service', 'dns', 'forwarding'] if arguments.dhclient: conf.exists = conf.exists_effective conf.return_value = conf.return_effective_value conf.return_values = conf.return_effective_values - if not conf.exists('service dns forwarding'): + if not conf.exists(base): return None - conf.set_level('service dns forwarding') + conf.set_level(base) - if conf.exists('allow-from'): - dns['allow_from'] = conf.return_values('allow-from') + if conf.exists(['allow-from']): + dns['allow_from'] = conf.return_values(['allow-from']) - if conf.exists('cache-size'): - cache_size = conf.return_value('cache-size') + if conf.exists(['cache-size']): + cache_size = conf.return_value(['cache-size']) dns['cache_size'] = cache_size if conf.exists('negative-ttl'): - negative_ttl = conf.return_value('negative-ttl') + negative_ttl = conf.return_value(['negative-ttl']) dns['negative_ttl'] = negative_ttl - if conf.exists('domain'): - for node in conf.list_nodes('domain'): - servers = conf.return_values("domain {0} server".format(node)) + if conf.exists(['domain']): + for node in conf.list_nodes(['domain']): + servers = conf.return_values(['domain', node, 'server']) domain = { "name": node, "servers": bracketize_ipv6_addrs(servers) } dns['domains'].append(domain) - if conf.exists('ignore-hosts-file'): + if conf.exists(['ignore-hosts-file']): dns['export_hosts_file'] = "no" - if conf.exists('name-server'): - name_servers = conf.return_values('name-server') + if conf.exists(['name-server']): + name_servers = conf.return_values(['name-server']) dns['name_servers'] = dns['name_servers'] + name_servers - if conf.exists('system'): - conf.set_level('system') + if conf.exists(['system']): + conf.set_level(['system']) system_name_servers = [] - system_name_servers = conf.return_values('name-server') + system_name_servers = conf.return_values(['name-server']) if not system_name_servers: - print( - "DNS forwarding warning: No name-servers set under 'system name-server'\n") + print("DNS forwarding warning: No name-servers set under 'system name-server'\n") else: dns['name_servers'] = dns['name_servers'] + system_name_servers - conf.set_level('service dns forwarding') + conf.set_level(base) dns['name_servers'] = bracketize_ipv6_addrs(dns['name_servers']) - if conf.exists('listen-address'): - dns['listen_on'] = conf.return_values('listen-address') + if conf.exists(['listen-address']): + dns['listen_on'] = conf.return_values(['listen-address']) - if conf.exists('dnssec'): - dns['dnssec'] = conf.return_value('dnssec') + if conf.exists(['dnssec']): + dns['dnssec'] = conf.return_value(['dnssec']) # Add name servers received from DHCP - if conf.exists('dhcp'): + if conf.exists(['dhcp']): interfaces = [] - interfaces = conf.return_values('dhcp') - hc = vyos.hostsd_client.Client() + interfaces = conf.return_values(['dhcp']) + hc = hostsd_client() for interface in interfaces: - dhcp_resolvers = hc.get_name_servers("dhcp-{0}".format(interface)) - dhcpv6_resolvers = hc.get_name_servers("dhcpv6-{0}".format(interface)) + dhcp_resolvers = hc.get_name_servers(f'dhcp-{interface}') + dhcpv6_resolvers = hc.get_name_servers(f'dhcpv6-{interface}') if dhcp_resolvers: dns['name_servers'] = dns['name_servers'] + dhcp_resolvers @@ -202,7 +152,12 @@ def generate(dns): if dns is None: return None - tmpl = jinja2.Template(config_tmpl, trim_blocks=True) + # Prepare Jinja2 template loader from files + tmpl_path = os.path.join(vyos_data_dir['data'], 'templates', 'dns-forwarding') + fs_loader = FileSystemLoader(tmpl_path) + env = Environment(loader=fs_loader, trim_blocks=True) + + tmpl = env.get_template('recursor.conf.tmpl') config_text = tmpl.render(dns) with open(config_file, 'w') as f: f.write(config_text) @@ -223,7 +178,7 @@ if __name__ == '__main__': if args.dhclient: # There's a big chance it was triggered by a commit still in progress # so we need to wait until the new values are in the running config - vyos.util.wait_for_commit_lock() + wait_for_commit_lock() try: c = get_config(args) @@ -232,4 +187,4 @@ if __name__ == '__main__': apply(c) except ConfigError as e: print(e) - sys.exit(1) + exit(1) |