From a0871abf9ad7c19d49933c566ace39f390da96fa Mon Sep 17 00:00:00 2001 From: "Yvan E. Watchman" Date: Sat, 29 Oct 2022 15:49:24 +0200 Subject: [PATCH 1/2] initial dns delegation stuff --- netbox_ddns/background_tasks.py | 38 +++++++++++++++++++++++++++++++-- netbox_ddns/utils.py | 32 +++++++++++++++++++++++++++ 2 files changed, 68 insertions(+), 2 deletions(-) diff --git a/netbox_ddns/background_tasks.py b/netbox_ddns/background_tasks.py index 14d04fe..4e56cee 100644 --- a/netbox_ddns/background_tasks.py +++ b/netbox_ddns/background_tasks.py @@ -7,10 +7,10 @@ from django.db import IntegrityError from django_rq import job from dns import rcode -from netaddr import ip +from netaddr import ip, IPNetwork from netbox_ddns.models import ACTION_CREATE, ACTION_DELETE, DNSStatus, RCODE_NO_ZONE, ReverseZone, Zone -from netbox_ddns.utils import get_soa +from netbox_ddns.utils import get_soa, check_servers_authoritative, get_ip logger = logging.getLogger('netbox_ddns') @@ -198,3 +198,37 @@ def dns_delete(dns_name: str, address: ip.IPAddress, forward=True, reverse=True, status.save(force_update=True) return ', '.join(output) + + +# TODO: dns_create,dns_remove check if it is not delegated to another server +def create_reverse_delegation(nameservers: List[str], prefix: IPNetwork, status: Optional[DNSStatus], output: List[str]): + if prefix.size > 24: + output.append(f'Classless delegation is not implemented, prefix size too big: {prefix.cidr}') + + if status: + status.reverse_action = ACTION_CREATE + + nameservers = {x: get_ip(x) for x in nameservers} + + subnets = prefix.subnet(24) + has_next = True + while has_next: + subnet = next(subnets, None) + if subnet is None: + break + + zone = ReverseZone.objects.find_for_address(subnet.network) + if zone: + for nameserver, addresses in nameservers.items(): + # TODO: check authority + nameserver = {} + if check_servers_authoritative(zone.name, addresses): + pass + update = zone.server.create_update(zone.name) + for nameserver in nameservers: + update.add( + zone.name, + zone.ttl, + dns.rdatatype.NS, + nameserver + ) diff --git a/netbox_ddns/utils.py b/netbox_ddns/utils.py index 4714e82..e1367e2 100644 --- a/netbox_ddns/utils.py +++ b/netbox_ddns/utils.py @@ -1,3 +1,5 @@ +from typing import List, Dict + import dns.rdatatype import dns.resolver @@ -26,3 +28,33 @@ def get_soa(dns_name: str) -> str: for rrset in response.authority: if rrset.rdtype == dns.rdatatype.SOA: return rrset.name.to_text() + + +def check_servers_authoritative(zone: str, nameservers: Dict[str, List[str]]) -> Dict[str, bool]: + resolver = dns.resolver.Resolver() + res = {} + + for ns, addr in nameservers.items(): + try: + resolver.nameservers = [addr] + answer = resolver.resolve(zone, dns.rdatatype.NS) + if ns in answer.rrset.to_text(): + res[ns] = True + else: + res[ns] = False + except dns.resolver.NoNameservers: + res[ns] = False + + return res + + +def get_ip(address: str, family=0) -> List[str]: + resolver = dns.resolver.Resolver() + + if family == 0: + answer_a = [res.to_text() for res in resolver.resolve(address, dns.rdatatype.A)] + answer_aaaa = [res.to_text() for res in resolver.resolve(address, dns.rdatatype.AAAA)] + return answer_a + answer_aaaa + else: + answer = resolver.resolve(address, dns.rdatatype.AAAA if family == 6 else dns.rdatatype.A) + return [res.to_text() for res in answer] \ No newline at end of file From 960c62f5984d0ad3d4216183f356b6c10698af4b Mon Sep 17 00:00:00 2001 From: "Yvan E. Watchman" Date: Sat, 29 Oct 2022 15:54:26 +0200 Subject: [PATCH 2/2] loop, keys, env --- .idea/misc.xml | 2 +- .idea/netbox_ddns.iml | 3 ++- netbox_ddns/background_tasks.py | 7 +++---- netbox_ddns/utils.py | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/.idea/misc.xml b/.idea/misc.xml index a04b7b5..e0c1040 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -3,5 +3,5 @@ - + \ No newline at end of file diff --git a/.idea/netbox_ddns.iml b/.idea/netbox_ddns.iml index 6a289e5..b3f21cc 100644 --- a/.idea/netbox_ddns.iml +++ b/.idea/netbox_ddns.iml @@ -16,8 +16,9 @@ + - + diff --git a/netbox_ddns/background_tasks.py b/netbox_ddns/background_tasks.py index 4e56cee..e5ac9d4 100644 --- a/netbox_ddns/background_tasks.py +++ b/netbox_ddns/background_tasks.py @@ -211,8 +211,7 @@ def create_reverse_delegation(nameservers: List[str], prefix: IPNetwork, status: nameservers = {x: get_ip(x) for x in nameservers} subnets = prefix.subnet(24) - has_next = True - while has_next: + while 1: subnet = next(subnets, None) if subnet is None: break @@ -221,11 +220,11 @@ def create_reverse_delegation(nameservers: List[str], prefix: IPNetwork, status: if zone: for nameserver, addresses in nameservers.items(): # TODO: check authority - nameserver = {} + nameserver = {nameserver: address} if check_servers_authoritative(zone.name, addresses): pass update = zone.server.create_update(zone.name) - for nameserver in nameservers: + for nameserver in nameservers.keys(): update.add( zone.name, zone.ttl, diff --git a/netbox_ddns/utils.py b/netbox_ddns/utils.py index e1367e2..daa4da0 100644 --- a/netbox_ddns/utils.py +++ b/netbox_ddns/utils.py @@ -57,4 +57,4 @@ def get_ip(address: str, family=0) -> List[str]: return answer_a + answer_aaaa else: answer = resolver.resolve(address, dns.rdatatype.AAAA if family == 6 else dns.rdatatype.A) - return [res.to_text() for res in answer] \ No newline at end of file + return [res.to_text() for res in answer]