From e828d63a855ce8a309f869d45fb81bbcdfacf39d Mon Sep 17 00:00:00 2001 From: Joshua Tauberer Date: Tue, 13 Dec 2022 08:03:14 -0500 Subject: [PATCH] Allow secondary DNS xfr: items to be hostnames that are resolved to IP addresses when generating the nsd configuration --- CHANGELOG.md | 1 + management/dns_update.py | 51 ++++++++++++++-------------- management/templates/custom-dns.html | 2 +- 3 files changed, 28 insertions(+), 26 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0d4ae98b..837a9fd9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,7 @@ Control panel: * Control panel pages can be opened in a new tab/window and bookmarked and browser history navigation now works. * Add a Copy button to put the rsync backup public key on clipboard. +* Allow secondary DNS xfr: items added in the control panel to be hostnames too. * Fixed issue where sshkeygen fails when IPv6 is disabled. * Fixed issue opening munin reports. * Fixed report formatting in status emails sent to the administrator. diff --git a/management/dns_update.py b/management/dns_update.py index 29372ddf..9a768ea8 100755 --- a/management/dns_update.py +++ b/management/dns_update.py @@ -1005,32 +1005,33 @@ def get_secondary_dns(custom_dns, mode=None): values.append(hostname) continue - # This is a hostname. Before including in zone xfr lines, - # resolve to an IP address. Otherwise just return the hostname. - # It may not resolve to IPv6, so don't throw an exception if it - # doesn't. - if not hostname.startswith("xfr:"): - if mode == "xfr": - try: - response = resolver.resolve(hostname+'.', "A", raise_on_no_answer=False) - values.extend(map(str, response)) - except dns.exception.DNSException: - pass - - try: - response = resolver.resolve(hostname+'.', "AAAA", raise_on_no_answer=False) - values.extend(map(str, response)) - except dns.exception.DNSException: - pass - continue - values.append(hostname) + # If the entry starts with "xfr:" only include it in the zone transfer settings. + if hostname.startswith("xfr:"): + if mode != "xfr": continue + hostname = hostname[4:] - # This is a zone-xfer-only IP address. Do not return if - # we're querying for NS record hostnames. Only return if - # we're querying for zone xfer IP addresses - return the - # IP address. - elif mode == "xfr": - values.append(hostname[4:]) + # If is a hostname, before including in zone xfr lines, + # resolve to an IP address. + # It may not resolve to IPv6, so don't throw an exception if it + # doesn't. Skip the entry if there is a DNS error. + if mode == "xfr": + try: + ipaddress.ip_interface(hostname) # test if it's an IP address or CIDR notation + values.append(hostname) + except ValueError: + try: + response = dns.resolver.resolve(hostname+'.', "A", raise_on_no_answer=False) + values.extend(map(str, response)) + except dns.exception.DNSException: + pass + try: + response = dns.resolver.resolve(hostname+'.', "AAAA", raise_on_no_answer=False) + values.extend(map(str, response)) + except dns.exception.DNSException: + pass + + else: + values.append(hostname) return values diff --git a/management/templates/custom-dns.html b/management/templates/custom-dns.html index e19bdddf..7d3b6b37 100644 --- a/management/templates/custom-dns.html +++ b/management/templates/custom-dns.html @@ -96,7 +96,7 @@

Multiple secondary servers can be separated with commas or spaces (i.e., ns2.hostingcompany.com ns3.hostingcompany.com). - To enable zone transfers to additional servers without listing them as secondary nameservers, add an IP address or subnet using xfr:10.20.30.40 or xfr:10.0.0.0/8. + To enable zone transfers to additional servers without listing them as secondary nameservers, prefix a hostname, IP address, or subnet with xfr:, e.g. xfr:10.20.30.40 or xfr:10.0.0.0/8.