From 25a57a9f727f908e0027a598d56eaa6375ac5c25 Mon Sep 17 00:00:00 2001 From: Christian Poessinger Date: Fri, 13 Apr 2018 20:38:03 +0200 Subject: T560: dns-forwarding: replace dnsmasq with pdns-recursor --- interface-definitions/dns-forwarding.xml | 9 +--- src/conf-mode/vyos-config-dns-forwarding.py | 84 +++++++++++++++++++---------- 2 files changed, 58 insertions(+), 35 deletions(-) diff --git a/interface-definitions/dns-forwarding.xml b/interface-definitions/dns-forwarding.xml index f1edec414..d56911c60 100644 --- a/interface-definitions/dns-forwarding.xml +++ b/interface-definitions/dns-forwarding.xml @@ -32,7 +32,6 @@ DNS domain to forward to a local server - txt @@ -77,12 +76,8 @@ ipv6 Domain Name Server (DNS) IPv6 address - - - - - - Query all DNS servers, respond and cache fastest result + + ipv4,ipv6 diff --git a/src/conf-mode/vyos-config-dns-forwarding.py b/src/conf-mode/vyos-config-dns-forwarding.py index 742e111cb..7a8aed75d 100755 --- a/src/conf-mode/vyos-config-dns-forwarding.py +++ b/src/conf-mode/vyos-config-dns-forwarding.py @@ -19,11 +19,12 @@ import sys import os import time +import netifaces from vyos.config import Config from vyos.util import ConfigError -config_file = r'/etc/dnsmasq.d/vyos.conf' +config_file = r'/etc/powerdns/recursor.conf' # borrowed from: https://github.com/donjajo/py-world/blob/master/resolvconfReader.py, THX! def get_resolvers(file): @@ -65,7 +66,7 @@ def get_config(): if conf.exists('domain'): dns.setdefault('domain', []) for node in conf.list_nodes('domain'): - server = conf.return_value("domain {0} server".format(node)) + server = conf.return_values("domain {0} server".format(node)) domain = { "name": node, "server": server @@ -85,75 +86,102 @@ def get_config(): nameservers = conf.return_values('name-server') dns.setdefault('name-server', nameservers) - if conf.exists('query-all-servers'): - dns.setdefault('query-all-servers', True) - if conf.exists('system'): conf.set_level('system') nameservers = [] nameservers = conf.return_values('name-server') if len(nameservers) == 0: print("DNS forwarding warning: No name-servers set under 'system name-server'\n") - dns.setdefault('system-name-server', True) + else: + dns.setdefault('system-name-server', nameservers) return dns def verify(dns): if len(dns) > 0: if 'listen-on' not in dns.keys(): - raise ConfigError("Error: DNS forwarding requires a configured listen interface!") + raise ConfigError('Error: DNS forwarding requires a configured listen interface!') + + for interface in dns['listen-on']: + try: + netifaces.ifaddresses(interface)[netifaces.AF_INET] + except KeyError as e: + raise ConfigError('Error: Interface {0} has no IP address assigned'.format(interface)) + + if 'domain' in dns.keys(): + for domain in dns['domain']: + if len(domain['server']) == 0: + raise ConfigError('Error: No server configured for domain {0}'.format(domain['name'])) return None def generate(dns): config_header = '### Autogenerated by vyos-config-dns-forwarding.py on {tm} ###\n'.format(tm=time.strftime("%a, %d %b %Y %H:%M:%S", time.localtime())) + fwds = [] + fwds_src = [] + # write new configuration file f = open(config_file, 'w') f.write(config_header) - f.write("log-facility=/var/log/dnsmasq.log\n") - f.write("no-poll\n") - f.write("edns-packet-max=4096\n") - f.write("bind-interfaces\n") + f.write('daemon=yes\n') + f.write('threads=1\n') + f.write('allow-from=0.0.0.0/0\n') + f.write('log-common-errors=yes\n') if 'listen-on' in dns.keys(): + listen4 = [] + listen6 = [] for interface in dns['listen-on']: - f.write("interface={0}\n".format(interface)) + addrs = netifaces.ifaddresses(interface) + for ip4 in addrs[netifaces.AF_INET]: + listen4.append(ip4['addr']) + + for ip6 in addrs[netifaces.AF_INET6]: + listen6.append(ip6['addr']) + + # build local-address string, example: + # local-address=172.16.37.240, 127.0.0.1, 172.16.254.35, 172.16.77.1, 2001:DB8::1:25, ::1 + f.write('local-address=' + ', '.join(listen4) + ', ' + ', '.join(listen6) + '\n') + + if 'cache-size' in dns.keys(): + f.write("max-cache-entries={0}\n".format(dns['cache-size'])) if 'dhcp' in dns.keys(): for dhcp in dns['dhcp']: - for resolver in dhcp['resolvers']: - f.write("server={0}\t# dhcp {1}\n".format(resolver, dhcp['interface'])) + fwds_src.append('DHCP: {0} ({1})'.format(dhcp['interface'], ', '.join(str(ns) for ns in dhcp['resolvers']))) + fwds.append(', '.join(str(ns) for ns in dhcp['resolvers'])) if 'domain' in dns.keys(): + zones = [] for domain in dns['domain']: - f.write("server=/{0}/{1}\t# domain-override\n".format(domain['name'], domain['server'])) - - if 'cache-size' in dns.keys(): - f.write("cache-size={0}\n".format(dns['cache-size'])) + zones.append('{0}={1}'.format(domain['name'], ';'.join(str(ns) for ns in domain['server']))) + f.write('forward-zones=' + ', '.join(zones) + '\n') if 'ignore-hosts-file' in dns.keys(): - f.write("no-hosts\n") + f.write("export-etc-hosts=no\n") if 'name-server' in dns.keys(): - for nameserver in dns['name-server']: - f.write("server={0}\t# statically configured\n".format(nameserver)) - - if 'query-all-servers' in dns.keys(): - f.write("all-servers\n") + fwds_src.append('statically configured: {0}'.format(', '.join(str(ns) for ns in dns['name-server']))) + fwds.append(', '.join(str(ns) for ns in dns['name-server'])) if 'system-name-server' in dns.keys(): - # Read the IP addresses of the upstream nameservers from /etc/resolv.conf - f.write("resolv-file=/etc/resolv.conf\n") + fwds_src.append('system: {0}'.format(', '.join(str(ns) for ns in dns['system-name-server']))) + fwds.append(', '.join(str(ns) for ns in dns['system-name-server'])) + + if len(fwds) > 0: + f.write('\n') + f.write('# ' + '\n# '.join(fwds_src) + '\n') + f.write('forward-zones-recurse=.=' + '; '.join(fwds) + '\n') f.close() return None def apply(dns): if len(dns) == 0: - cmd = "sudo systemctl stop dnsmasq" + cmd = "sudo systemctl stop pdns-recursor" else: - cmd = "sudo systemctl restart dnsmasq" + cmd = "sudo systemctl restart pdns-recursor" os.system(cmd) return None -- cgit v1.2.3