First ugly working version of dns reverse, to clean
This commit is contained in:
parent
7cba2399e3
commit
190cbfda16
1 changed files with 131 additions and 4 deletions
135
main.py
135
main.py
|
@ -2,6 +2,7 @@
|
|||
from configparser import ConfigParser
|
||||
import socket
|
||||
import datetime
|
||||
import netaddr
|
||||
|
||||
from re2oapi import Re2oAPIClient
|
||||
|
||||
|
@ -55,6 +56,8 @@ template_reverse = ("$TTL 2D\n"
|
|||
"\n"
|
||||
"{ns_records}\n"
|
||||
"\n"
|
||||
"{mx_records}\n"
|
||||
"\n"
|
||||
"{ptr_records}\n")
|
||||
|
||||
def write_dns_files(api_client):
|
||||
|
@ -149,11 +152,135 @@ def write_dns_files(api_client):
|
|||
with open(filename, 'w+') as f:
|
||||
f.write(zone_file_content)
|
||||
|
||||
def network_to_arpanets(nets):
|
||||
"""En ipv4, on ne pouvait définir
|
||||
que des plages reverse en /24, /16 ou /8. Cette fonction vise à retourner
|
||||
une liste des plages en tenant compte de ce critère (donc de taille
|
||||
32/24/16/8)
|
||||
|
||||
Ne touche à rien pour l'IPv6.
|
||||
"""
|
||||
subnets = []
|
||||
for net in nets:
|
||||
if not isinstance(net, netaddr.IPNetwork):
|
||||
net = netaddr.IPNetwork(net)
|
||||
# on fragmente les subnets
|
||||
# dans les tailles qui vont bien.
|
||||
if net.prefixlen > 24:
|
||||
subnets.extend(net.subnet(32))
|
||||
elif net.prefixlen > 16:
|
||||
subnets.extend(net.subnet(24))
|
||||
elif net.prefixlen > 8:
|
||||
subnets.extend(net.subnet(16))
|
||||
else:
|
||||
subnets.extend(net.subnet(8))
|
||||
return subnets
|
||||
|
||||
|
||||
def get_arpa(cidr):
|
||||
"""
|
||||
Renvoie la zone DNS inverse correspondant au réseau donné.
|
||||
"""
|
||||
net = netaddr.IPNetwork(cidr)
|
||||
byte_size = 8 if net.version == 4 else 4
|
||||
addr_bytes = 4 if net.version == 4 else 32
|
||||
net_class = max(((net.prefixlen - 1) // byte_size) + 1, 1)
|
||||
return ".".join(
|
||||
netaddr.IPAddress(net.first).reverse_dns.split('.')[addr_bytes - net_class:]
|
||||
)
|
||||
|
||||
def get_ip_reverse(ip, prefix_length):
|
||||
ip = netaddr.IPAddress(ip)
|
||||
return '.'.join(ip.reverse_dns.split('.')[:prefix_length])
|
||||
|
||||
|
||||
|
||||
def write_dns_reverse_file(api_client):
|
||||
pass
|
||||
|
||||
for zone in api_client.list("dns/reverse-zones"):
|
||||
|
||||
now = datetime.datetime.now(datetime.timezone.utc)
|
||||
serial = now.strftime("%Y%m%d") + str(int(100*(now.hour*3600 + now.minute*60 + now.second)/86400))
|
||||
|
||||
extension = zone['extension']
|
||||
soa_mail_fields = zone['soa']['mail'].split('@')
|
||||
soa_mail = "{}.{}.".format(soa_mail_fields[0].replace('.', '\\.'),
|
||||
soa_mail_fields[1])
|
||||
ns_records = "\n".join(
|
||||
template_ns.format(target=x['target'])
|
||||
for x in zone['ns_records']
|
||||
)
|
||||
|
||||
mx_records = "\n".join(
|
||||
template_mx.format(priority=x['priority'],
|
||||
target=x['target'])
|
||||
for x in zone['mx_records']
|
||||
)
|
||||
|
||||
### Start with ipv4 reverse
|
||||
net = network_to_arpanets(zone['cidrs'])[0]
|
||||
# Prend la première adresse ip de la plage, sauf si une est fournie
|
||||
_address = netaddr.IPAddress(net.first)
|
||||
# retourne le reverse splitté. (un reverse ressemble à 0.136.231.138.in-addr.arpa.)
|
||||
rev_dns_a = _address.reverse_dns.split('.')[:-1]
|
||||
|
||||
# En v4, le reverse étant de la forme 0.136.231.138.in-addr.arpa., soit
|
||||
# on a un /8, soit un /16, soit un /24.
|
||||
if net.prefixlen == 8:
|
||||
zone_name,prefix_length = ('.'.join(rev_dns_a[3:]), 3)
|
||||
elif net.prefixlen == 16:
|
||||
zone_name,prefix_length = ('.'.join(rev_dns_a[2:]), 2)
|
||||
elif net.prefixlen == 24:
|
||||
zone_name,prefix_length = ('.'.join(rev_dns_a[1:]), 1)
|
||||
|
||||
soa = template_soa.format(zone=zone_name,
|
||||
mail=soa_mail,
|
||||
serial=serial,
|
||||
refresh=zone['soa']['refresh'],
|
||||
retry=zone['soa']['retry'],
|
||||
expire=zone['soa']['expire'],
|
||||
ttl=zone['soa']['ttl'])
|
||||
ptr_records = "\n".join(
|
||||
template_ptr.format(hostname=host['hostname']+extension,
|
||||
target=get_ip_reverse(host['ipv4'],prefix_length))
|
||||
for host in zone['ptr_records'] if host['ipv4']
|
||||
)
|
||||
zone_file_content = template_reverse.format(soa=soa,
|
||||
ns_records=ns_records,
|
||||
mx_records=mx_records,
|
||||
ptr_records = ptr_records)
|
||||
|
||||
filename = 'dns.{zone}zone'.format(zone=zone_name)
|
||||
with open(filename, 'w+') as f:
|
||||
f.write(zone_file_content)
|
||||
|
||||
### Continue with the ipv6 reverse
|
||||
# hack because we do not have the /64 info
|
||||
zone6_name = get_arpa(zone['prefix_v6']+"/64")
|
||||
soa = template_soa.format(zone=zone6_name,
|
||||
mail=soa_mail,
|
||||
serial=serial,
|
||||
refresh=zone['soa']['refresh'],
|
||||
retry=zone['soa']['retry'],
|
||||
expire=zone['soa']['expire'],
|
||||
ttl=zone['soa']['ttl'])
|
||||
|
||||
net = netaddr.IPNetwork(zone['prefix_v6']+"/64")
|
||||
prefix_length = int((128 - net.prefixlen)/4)
|
||||
ptr_records = "\n".join(
|
||||
template_ptr.format(hostname=host['hostname']+extension,
|
||||
target=get_ip_reverse(ip['ipv6'],prefix_length))
|
||||
for host in zone['ptr_v6_records'] for ip in host['ipv6']
|
||||
)
|
||||
|
||||
zone_file_content = template_reverse.format(soa=soa,
|
||||
ns_records=ns_records,
|
||||
mx_records=mx_records,
|
||||
ptr_records = ptr_records)
|
||||
|
||||
|
||||
filename = 'dns.{zone}zone'.format(zone=zone6_name)
|
||||
with open(filename, 'w+') as f:
|
||||
f.write(zone_file_content)
|
||||
|
||||
api_client = Re2oAPIClient(api_hostname, api_username, api_password)
|
||||
|
||||
|
@ -163,6 +290,6 @@ for service in api_client.list("services/regen/"):
|
|||
# if service['hostname'] == client_hostname and \
|
||||
# service['service_name'] == 'dns' and \
|
||||
# service['need_regen']:
|
||||
write_dns_files(api_client)
|
||||
write_dns_reverse_file(api_client)
|
||||
#write_dns_files(api_client)
|
||||
write_dns_reverse_file(api_client)
|
||||
# api_client.patch(service['api_url'], data={'need_regen': False})
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue