diff options
-rw-r--r-- | tools/dhcpns/config/ddns.py | 10 | ||||
-rw-r--r-- | tools/dhcpns/config/dhcp4.py | 16 | ||||
-rw-r--r-- | tools/dhcpns/main.py | 63 |
3 files changed, 48 insertions, 41 deletions
diff --git a/tools/dhcpns/config/ddns.py b/tools/dhcpns/config/ddns.py index 531fc34..8490967 100644 --- a/tools/dhcpns/config/ddns.py +++ b/tools/dhcpns/config/ddns.py @@ -8,7 +8,13 @@ def base(ddns_domains = [], ddns_reverse_domains = []): "socket-type": "unix", "socket-name": "/tmp/kea-ddns-ctrl-socket" }, - "tsig-keys": [], + "tsig-keys": [ + { + "name": os.environ['KEA_DDNS_KEY_NAME'], + "algorithm": os.environ['KEA_DDNS_ALGORITHM'], + "secret": os.environ['KEA_DDNS_SECRET'] + } + ], "forward-ddns": { "ddns-domains": ddns_domains }, @@ -37,7 +43,7 @@ def ddns_domain(domain_name): "key-name": os.environ['KEA_DDNS_KEY_NAME'], "dns-servers": [ { - "ip-address": os.environ['NS1_V6'], + "ip-address": "::1", "port": 53 } ] diff --git a/tools/dhcpns/config/dhcp4.py b/tools/dhcpns/config/dhcp4.py index f9a9382..d1a779d 100644 --- a/tools/dhcpns/config/dhcp4.py +++ b/tools/dhcpns/config/dhcp4.py @@ -37,6 +37,17 @@ def base(subnet4): } } ], + "dhcp-ddns": { + "enable-updates": True, + "server-ip": "::1", + }, + "ddns-send-updates": True, + "ddns-override-no-update": False, + "ddns-override-client-update": False, + "ddns-replace-client-name": "always", + "ddns-generated-prefix": "dyn", + "ddns-update-on-renew": False, + "ddns-use-conflict-resolution": True, "interfaces-config": { "interfaces": [ os.environ.get('DHCP_INTERFACE', 'eth0') @@ -222,10 +233,14 @@ def base(subnet4): def subnet(vlan, prefix, domain_name, vlan_domain_name): network = ipaddress.ip_network(prefix.prefix) gw, start_ip, end_ip = network[1], network[2], network[-2] + return { "id": prefix.id, "subnet": prefix.prefix, "ddns-qualifying-suffix": vlan_domain_name, + # Check if the VLAN in netbox has dhcp-ddns. This will enable full ddns using client hostnames. + # Generate automatically using IP if not. + "ddns-replace-client-name": "always" if not any(t['slug'] == 'dhcp-ddns' for t in vlan.tags) else "when-not-present", "pools": [ { "pool": f"{start_ip} - {end_ip}" @@ -256,6 +271,7 @@ def fap(vlan, prefix): network = ipaddress.ip_network(prefix.prefix) gw, start_ip, end_ip = network[1], network[( math.ceil(network.num_addresses / 2))], network[-2] + return { "id": prefix.id, "client-class": "fap-class", diff --git a/tools/dhcpns/main.py b/tools/dhcpns/main.py index b81042f..e826a5f 100644 --- a/tools/dhcpns/main.py +++ b/tools/dhcpns/main.py @@ -46,7 +46,7 @@ kea_rddns_domains = [] # dhcp-client vlans = nb.ipam.vlans.filter(tag='dhcp-client') for vlan in vlans: - vlan_domain_name = f"{vlan.name}.{DOMAIN_NAME}" + vlan_domain_name = f"net-{vlan.name}.{DOMAIN_NAME}" prefixes4 = [] prefixes6 = [] kea_ddns_domains.append(ddns_domain(vlan_domain_name)) @@ -72,7 +72,7 @@ for vlan in vlans: network = ipaddress.ip_network(prefix) # Network ID - zone_rrsets.append({'name': f'net-{network[0]}.{vlan_domain_name}.', 'changetype': 'replace', 'type': 'A', 'records': [ + zone_rrsets.append({'name': f'id-{network[0]}.{vlan_domain_name}.', 'changetype': 'replace', 'type': 'A', 'records': [ {'content': str(network[0]), 'disabled': False, 'type':'A'}], 'ttl': 900}) # Gateway @@ -160,45 +160,30 @@ for device in devices: zone = "tg23.gathering.org" - print(device.name) - r = re.search('^([A-Za-z1-9]*)\.([A-Za-z1-9]*)$', device.name) - - if f"{device.name}.{zone}." in zones: - device_name = "" - zone = f"{device.name}.{zone}" - elif r is not None: - device_name = r.group(1) + "." - zone = "{}.{}".format(r.group(2), zone) - elif re.search('^([A-Za-z1-9]*) \(([A-Za-z1-9 -\/]*)\)', device.name) is not None: - zone = "{}".format(zone) - device_name = re.search( - '^([A-Za-z1-9]*) \(([A-Za-z1-9 -\/]*)\)', device.name).group(1) + "." - else: - zone = "{}".format(zone) - device_name = device.name + "." - - print(f"zone: {zone}") - print(f"name: {device_name}") - print(str(netaddr.IPNetwork(str(device.primary_ip4)).ip)) - print() - - # Network ID + # IPv4 zone_rrsets = [] - zone_rrsets.append({'name': f'{device_name}{zone}.', 'changetype': 'replace', 'type': 'A', 'records': [ - {'content': str(netaddr.IPNetwork(str(device.primary_ip4)).ip), 'disabled': False, 'type': 'A'}], 'ttl': 900}) - - # Apply zone_rrsets - print(pdns.set_records(f"{zone}", zone_rrsets)) - - rdns_zone = pdns.get_rdns_zone_from_ip( - str(netaddr.IPNetwork(str(device.primary_ip4)).ip)) - rdns_rrsets = [] - if rdns_zone is None: - print(f"Failed to find RDNS Zone for IP") - - # Broadcast + if device.primary_ip4 is not None: + zone_rrsets.append({'name': f'{device.name}.{zone}.', 'changetype': 'replace', 'type': 'A', 'records': [ + {'content': str(netaddr.IPNetwork(str(device.primary_ip4)).ip), 'disabled': False, 'type': 'A'}], 'ttl': 900}) + + # IPv6 + if device.primary_ip6 is not None: + zone_rrsets.append({'name': f'{device.name}.{zone}.', 'changetype': 'replace', 'type': 'AAAA', 'records': [ + {'content': str(netaddr.IPNetwork(str(device.primary_ip6)).ip), 'disabled': False, 'type': 'A'}], 'ttl': 900}) + + if len(zone_rrsets) > 1: + # Apply zone_rrsets + print(pdns.set_records(zone, zone_rrsets)) + + rdns_zone = pdns.get_rdns_zone_from_ip( + str(netaddr.IPNetwork(str(device.primary_ip4)).ip)) + rdns_rrsets = [] + if rdns_zone is None: + print(f"Failed to find RDNS Zone for IP") + + # IPv4 RDNS rdns_rrsets.append({"name": ipaddress.ip_address(str(netaddr.IPNetwork(str(device.primary_ip4)).ip)).reverse_pointer + '.', "changetype": "replace", "type": "PTR", "records": [ - {"content": f'{device_name}{zone}.', "disabled": False, "type": "PTR"}], "ttl": 900}) + {"content": f'{device.name}.{zone}.', "disabled": False, "type": "PTR"}], "ttl": 900}) # Apply rdns_rrsets print(pdns.set_records(rdns_zone, rdns_rrsets)) |