diff --git a/gestion/gen_confs/bind.py b/gestion/gen_confs/bind.py index 4359e0cb..70f1a8bf 100644 --- a/gestion/gen_confs/bind.py +++ b/gestion/gen_confs/bind.py @@ -9,7 +9,12 @@ Licence : GPLv2 import time, sys sys.path.append('/usr/scripts/gestion') from gen_confs import gen_config + +import config from iptools import AddrInNet, AddrInNets +import ip6tools + +import netaddr class dns(gen_config) : """ @@ -40,10 +45,23 @@ la base LDAP ## En cas de modification de ces zones penser à regéner le fichier de ## zone des esclaves (sur le serveur principal de bcfg2 : python /usr/scripts/gestion/gen_confs/bind.py puis lancer bcfg2 sur les miroirs) # Résolution directe - zones_direct = [ 'crans.org' , 'crans.ens-cachan.fr', 'wifi.crans.org' , 'ferme.crans.org' , 'clubs.ens-cachan.fr', 'adm.crans.org' ] + zones_direct = [ 'crans.org', 'crans.ens-cachan.fr', 'wifi.crans.org', 'ferme.crans.org' , 'clubs.ens-cachan.fr', 'adm.crans.org' ] + zones_v4_to_v6 = { + 'crans.org': 'v6.crans.org', + 'wifi.crans.org': 'wifi.v6.crans.org', + 'adm.crans.org': 'adm.v6.crans.org', + 'ferme.crans.org': 'ferme.v6.crans.org', + } # Résolution inverse - zones_reverse = [ '138.231.136.0/21', '138.231.144.0/21', '10.231.136.0/24', '10.2.9.0/24', '10.42.0.0/16' ] - + zones_reverse = config.NETs["all"] + config.NETs["adm"] + config.NETs["personnel-ens"] + zones_v6_to_net = { + 'crans.org': config.prefix["fil"][0], + 'wifi.crans.org': config.prefix["wifi"][0], + 'adm.crans.org': config.prefix["adm"][0], + 'ferme.crans.org': config.prefix["fil"][0], + # Hack pour générer un fichier de zone vide + '##HACK##': config.prefix["subnet"][0], + } ### Liste DNS # Le premier doit être le maitre DNSs = ['sable.crans.org', 'sila.crans.org', 'freebox.crans.org', 'ovh.crans.org', 'rouge.crans.org' ] @@ -103,12 +121,35 @@ zone "%(NOM_zone)s" { def __str__(self) : return "DNS" + def reverse(self, net, ip): + """Renvoie la zone DNS inverse correspondant au réseau et à + l'adresse donnés, ainsi que le nombre d'éléments de l'ip a + mettre dans le fichier de zone.""" + n = netaddr.IPNetwork(net) + a = netaddr.IPAddress(ip) + rev_dns_a = a.reverse_dns.split('.')[:-1] + assert a in n + if n.version == 4: + if n.prefixlen == 16: + return ('.'.join(rev_dns_a[2:]), 2) + else: + return ('.'.join(rev_dns_a[1:]), 1) + elif n.version == 6: + return ('.'.join(rev_dns_a[(128-n.prefixlen)/4:]), (128-n.prefixlen)/4) + + def gen_slave(self) : """ Génération du fichier de config de zone pour les esclaves """ zones = self.zones_direct + zones.extend(self.zones_v4_to_v6.values()) # Ajout des zones reverse - for net in self.zones_reverse : + for net in self.zones_reverse: + # IPv4 reverse + addr, prefixlen = net.split('/') + if prefixlen == '16': + zones.append("%s.in-addr.arpa" % '.'.join(reversed(addr.split('.')[0:2]))) + continue n = map(int,net.split('/')[0].split('.')[:3]) while 1 : try: @@ -124,6 +165,13 @@ zone "%(NOM_zone)s" { n.reverse() n[2] += 1 + for net in set(self.zones_v6_to_net.values()): + # IPv6 reverse + n = netaddr.IPNetwork(net) + network_reverse = netaddr.IPAddress(n.first).reverse_dns + zone = network_reverse.split('.')[(128-n.prefixlen)/4:-1] + zones.append('.'.join(zone)) + # Ecriture fd = self._open_conf(self.DNS_CONF_BCFG2,'//') for zone in zones : @@ -198,15 +246,41 @@ zone "%(NOM_zone)s" { elif self.verbose and machine.nom() != "ftp.federez.net": warnings += u'Résolution directe ignorée (mid=%s) : zone non autoritaire (%s)\n' % ( machine.id().encode('iso-8859-1'), zone.encode('iso-8859-1') ) + # IPv6 + if zone in self.zones_v4_to_v6: + # Direct + zone_v6 = self.zones_v4_to_v6[zone] + ipv6 = machine.ipv6() + net_v6 = machine.netv6() + ligne = "%s\tIN\tAAAA\t%s\n" % (nom, ipv6) + direct[zone_v6] = direct.get(zone_v6, "") + ligne + if machine.dnsIpv6(): + direct[zone] = direct.get(zone, "") + ligne + + # Reverse + zone_rev, length = self.reverse(net_v6, ipv6) + rev = '.'.join(ipv6.reverse_dns.split('.')[:length]) + ligne = "%s\tIN\tPTR\t%s.\n" % (rev, machine.nom6()) + reverse[zone_rev] = reverse.get(zone_rev, "") + ligne + + # Le direct avec alias for alias in machine.alias() : + alias = alias.encode('iso-8859-1') # Cas particulier : nom de l'alias = nom de la zone if alias in self.zones_direct : ligne = "@\tIN\tA\t%s\n" % machine.ip() ligne = ligne.encode('iso-8859-1') - alias = alias.encode('iso-8859-1') - try : direct[alias] += ligne - except : direct[alias] = ligne + direct[alias] = direct.get(alias, "") + ligne + if machine.dnsIpv6(): + ligne = "@\tIN\tAAAA\t%s\n" % machine.ipv6() + ligne = ligne.encode('iso-8859-1') + direct[alias]= direct.get(alias, "") + ligne + if alias in self.zones_v4_to_v6: + ligne = "@\tIN\tAAAA\t%s\n" % machine.ipv6() + ligne = ligne.encode('iso-8859-1') + zone6 = self.zones_v4_to_v6[alias] + direct[zone6] = direct.get(zone6, '') + ligne continue # Bon format ? @@ -226,16 +300,21 @@ zone "%(NOM_zone)s" { continue zone = zone.encode('iso-8859-1') ligne = "%s\tIN\tCNAME\t%s.\n" % ( nom, machine.nom() ) - try : direct[zone] += ligne - except : direct[zone] = ligne + direct[zone] = direct.get(zone, '') + ligne + if zone in self.zones_v4_to_v6: + zone6 = self.zones_v4_to_v6[zone] + ligne = "%s\tIN\tCNAME\t%s.\n" % ( nom, machine.nom6() ) + direct[zone6] = direct.get(zone6, '') + ligne # Le reverse - if AddrInNets(machine.ip(), self.zones_reverse) : - base_ip = machine.ip().split('.') + ip = machine.ip() + net = AddrInNets(ip, self.zones_reverse) + if net: + base_ip = ip.split('.') base_ip.reverse() - zone = "%s.%s.%s.in-addr.arpa" % tuple(base_ip[1:]) + zone, length = self.reverse(net, ip) zone = zone.encode('iso-8859-1') - ligne = '%s\tIN\tPTR\t%s.\n' % (base_ip[0],machine.nom()) + ligne = '%s\tIN\tPTR\t%s.\n' % ('.'.join(base_ip[:length]), machine.nom()) try : reverse[zone] += ligne except : reverse[zone] = ligne elif self.verbose >= 2 or machine.nom() not in ('freebox.crans.org', 'ovh.crans.org', 'kokarde.crans.org'): @@ -246,6 +325,10 @@ zone "%(NOM_zone)s" { # MXs direct[zone] = MX % { 'zone' : zone } + direct[zone] + ### XXX: création de la zone inverse pour le /48 IPv6 complet du Cr@ns + full_net_v6 = self.zones_v6_to_net["##HACK##"] + zone_rev, length = self.reverse(full_net_v6, netaddr.IPNetwork(full_net_v6).first) + reverse[zone_rev] = reverse.get(zone_rev, "") ### Ajout des délégations de zones for deleg in self.DELEG.keys():