
le serveur xmpp.crans.org sert maintenant le protocole xmpp pour le domaine crans.org. Les utilisateurs sont authentifis sur la base ldap par leur login habituel et leur mot de passe. Encore en phase de test, mais a priori pas besoin de crer de compte :) (actuellement enregistr avec le jid segaud@crans.org) darcs-hash:20080913153209-e59bf-58e18017a650be23f08100e072d17290ca9921b7.gz
295 lines
12 KiB
Python
Executable file
295 lines
12 KiB
Python
Executable file
#! /usr/bin/env python
|
|
# -*- coding: iso-8859-15 -*-
|
|
|
|
""" Génération de la configuration pour bind9
|
|
|
|
Copyright (C) Frédéric Pauget
|
|
Licence : GPLv2
|
|
"""
|
|
import time, sys
|
|
sys.path.append('/usr/scripts/gestion')
|
|
from gen_confs import gen_config
|
|
from iptools import AddrInNet, AddrInNets
|
|
|
|
class dns(gen_config) :
|
|
"""
|
|
Génération des fichiers de configuration de bind9 :
|
|
* fichier DNS_CONF qui contient les définitions de zone conformément
|
|
à zone_template. Ce fichier doit être inclus à partir de la config statique
|
|
de bind
|
|
* les fichiers de zones, ce sont eux qui contiennent les données du
|
|
dns, ils ont appellés par le fichier DNS_CONF et sont générés dans DNS_DIR
|
|
Leur entète est générée à partir de zone_entete.
|
|
|
|
Les fichiers générés placent bind comme autoritaire sur les noms de
|
|
zones_direct et les adresses de zones_reverse. Les données proviennent de
|
|
la base LDAP
|
|
"""
|
|
######################################PARTIE DE CONFIGURATION
|
|
|
|
### Fichiers à écrire
|
|
# Répertoire d'écriture des fichiers de zone
|
|
DNS_DIR = '/etc/bind/generated/' # Avec un / à la fin
|
|
# Fichier de définition des zones pour le maître
|
|
DNS_CONF = DNS_DIR + 'zones_crans'
|
|
|
|
# Fichier de définition des zones pour les esclaves géré par BCfg2
|
|
DNS_CONF_BCFG2 = "/var/lib/bcfg2/Cfg/etc/bind/generated/zones_crans/zones_crans"
|
|
|
|
### Sur quelles zones on a autorité ?
|
|
## En cas de modification de ces zones penser à regéner le fichier de
|
|
## zone des esclaves (sur le serveur principal de cfengine : python /usr/scripts/gestion/gen_confs/bind.py puis lancer cfrun)
|
|
# Résolution directe
|
|
zones_direct = [ 'crans.org' , 'crans.ens-cachan.fr', 'wifi.crans.org' , 'ferme.crans.org' , 'clubs.ens-cachan.fr', 'adm.crans.org' ]
|
|
# Résolution inverse
|
|
zones_reverse = [ '138.231.136.0/21', '138.231.144.0/21', '10.231.136.0/24' ]
|
|
|
|
### Liste DNS
|
|
# Le premier doit être le maitre
|
|
DNSs = [ 'rouge.crans.org' , 'sila.crans.org' , 'freebox.crans.org' , 'ovh.crans.org' , 'sable.crans.org' ]
|
|
DNSs_private = ['vert.adm.crans.org']
|
|
ip_master_DNS = "10.231.136.3"
|
|
|
|
### Liste des délégations de zone
|
|
# Pour les demandes de ces zones, le DNS dira d'aller voir les serveurs listés ici
|
|
# Pour les noms des serveurs on met l'IP sans point ou le nom avec un point
|
|
DELEG = { 'tv.crans.org' : ['rouge.crans.org.' , 'sila.crans.org.' , 'freebox.crans.org.', 'sable.crans.org' , 'mouton.ferme.crans.org.'] }
|
|
|
|
### Serveurs de mail
|
|
# format : [ priorité serveur , .... ]
|
|
MXs = ['10 rouge.crans.org', '20 ovh.crans.org', '20 freebox.crans.org']
|
|
SRVs = ['_jabber._tcp.crans.org. 86400 IN SRV 5 0 5269 xmpp.crans.org.',
|
|
'_xmpp-server._tcp.crans.org. 86400 IN SRV 5 0 5269 xmpp.crans.org.',
|
|
'_xmpp-client._tcp.crans.org. 86400 IN SRV 5 0 5222 xmpp.crans.org.']
|
|
|
|
### Entète des fichiers de zone
|
|
zone_entete="""
|
|
$ORIGIN %(zone)s.
|
|
$TTL 86400
|
|
@\tIN\tSOA rouge.crans.org. root.crans.org. (
|
|
%(serial)i ; numero de serie
|
|
21600 ; refresh (s)
|
|
3600 ; retry (s)
|
|
1209600 ; expire (s)
|
|
86400 ; TTL (s)
|
|
)
|
|
"""
|
|
|
|
# Syntaxe utilisée dans le fichier DNS_CONF pour définir une zone sur le maître
|
|
zone_template="""
|
|
zone "%(NOM_zone)s" {
|
|
type master;
|
|
file "%(FICHIER_zone)s";
|
|
};
|
|
"""
|
|
# Syntaxe utilisée dans le fichier DNS_CONF_CFENFINE pour définir une zone sur un esclave
|
|
zone_template_slave="""
|
|
zone "%(NOM_zone)s" {
|
|
type slave;
|
|
file "%(FICHIER_zone)s";
|
|
masters { %(ip_master_DNS)s; };
|
|
};
|
|
"""
|
|
|
|
### Verbosité
|
|
# Si =2, ralera (chaine warnings) si machines hors zone trouvée
|
|
# Si =1, comme ci-dessus, mais ne ralera pas pour freebox
|
|
# Si =0, ralera seulement contre les machines ne pouvant être classées
|
|
verbose = 1
|
|
|
|
restart_cmd = '/etc/init.d/bind9 reload'
|
|
######################################FIN PARTIE DE CONFIGURATION
|
|
|
|
def __str__(self) :
|
|
return "DNS"
|
|
|
|
def gen_slave(self) :
|
|
""" Génération du fichier de config de zone pour les esclaves """
|
|
zones = self.zones_direct
|
|
|
|
# Ajout des zones reverse
|
|
for net in self.zones_reverse :
|
|
n = map(int,net.split('/')[0].split('.')[:3])
|
|
while 1 :
|
|
if not AddrInNet("%d.%d.%d.1" % tuple(n),net):
|
|
break
|
|
else :
|
|
n.reverse()
|
|
zones.append("%d.%d.%d.in-addr.arpa" % tuple(n))
|
|
n.reverse()
|
|
n[2] += 1
|
|
|
|
# Ecriture
|
|
fd = self._open_conf(self.DNS_CONF_BCFG2,'//')
|
|
for zone in zones :
|
|
fd.write(self.zone_template_slave % { 'NOM_zone' : zone,
|
|
'FICHIER_zone' : self.DNS_DIR + 'db.' + zone,
|
|
'ip_master_DNS': self.ip_master_DNS})
|
|
|
|
fd.close()
|
|
|
|
def _gen(self) :
|
|
### Génération du numéro de série
|
|
# Le + 1000.... s'explique pas l'idée précédente et peu pratique d'avoir
|
|
# le numéro de série du type AAAAMMJJNN (année, mois, jour, incrément par jour)
|
|
serial = time.time() + 1000000000
|
|
|
|
### DNS
|
|
DNS='; DNS de la zone par ordre de priorité\n'
|
|
for d in self.DNSs :
|
|
DNS += '@\tIN\tNS %s.\n' % d
|
|
DNS += '\n'
|
|
|
|
### Serveurs de mail
|
|
MX='; Serveurs de mails\n'
|
|
for m in self.MXs :
|
|
MX += '%(zone)s.\t' # Sera remplacé par le nom de zone plus tard
|
|
MX += 'IN\tMX\t%s.\n' % m
|
|
MX += '\n'
|
|
|
|
direct = {} # format : { zone : [ lignes correspondantes] }
|
|
reverse = {}
|
|
warnings = ''
|
|
|
|
direct['crans.org'] = ""
|
|
|
|
# P'tit lien vers irc.rezosup.org
|
|
#direct["crans.org"] = "\n; irc.crans.org -> irc.rezosup.org\n"
|
|
#direct["crans.org"] += "irc\tIN\tCNAME\tirc.rezosup.org.\n\n"
|
|
|
|
### Ajout des parametres SPF
|
|
direct['crans.org'] +='; Parametres SPF\n'
|
|
direct['crans.org'] +='crans.org.\tIN\tTXT\t"v=spf1 a mx ?all"\n'
|
|
for m in self.MXs:
|
|
direct['crans.org'] +='%s.\tIN\tTXT\t"v=spf1 a -all"\n' % m.split()[-1]
|
|
direct['crans.org'] += '\n'
|
|
|
|
direct['crans.ens-cachan.fr'] ='; Parametres SPF\n'
|
|
direct['crans.ens-cachan.fr'] +='crans.ens-cachan.fr.\tIN\tTXT\t"v=spf1 a:crans.org mx ?all"\n\n'
|
|
|
|
### Ajout d'eventuels champs SRV
|
|
direct['crans.org'] +='; Champs SRV\n'
|
|
for s in self.SRVs:
|
|
direct['crans.org'] += s + '\n'
|
|
direct['crans.org'] += '\n'
|
|
|
|
### Tri des machines
|
|
self.anim.iter=len(self.machines)
|
|
for machine in self.machines :
|
|
self.anim.cycle()
|
|
|
|
# Calculs préliminaires
|
|
try :
|
|
nom , zone = machine.nom().split('.',1)
|
|
zone = zone.encode('iso-8859-1')
|
|
except :
|
|
warnings += u'Machine ignorée (mid=%s) : format nom incorrect (%s)\n' % ( machine.id().encode('iso-8859-1'), machine.nom().encode('iso-8859-1') )
|
|
continue
|
|
|
|
# Le direct
|
|
if zone in self.zones_direct :
|
|
ligne = "%s\tIN\tA\t%s\n" % ( nom, machine.ip() )
|
|
try : direct[zone] += ligne
|
|
except : direct[zone] = ligne
|
|
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') )
|
|
|
|
# Le direct avec alias
|
|
for alias in machine.alias() :
|
|
# 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
|
|
continue
|
|
|
|
# Bon format ?
|
|
alias_l = alias.split('.')
|
|
ok = 0
|
|
for i in range(len(alias_l)) :
|
|
zone_essai = '.'.join(alias_l[i:])
|
|
if zone_essai in self.zones_direct :
|
|
# On est autoritaire sur cette zone
|
|
# On place donc l'alias dans le fichier de cette zone
|
|
zone = zone_essai
|
|
nom = '.'.join(alias_l[:i])
|
|
ok = 1
|
|
break
|
|
if not ok:
|
|
warnings += u'Alias ignoré (mid=%s) : %s\n' % ( machine.id().encode('iso-8859-1'), alias.encode('iso-8859-1') )
|
|
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
|
|
|
|
# Le reverse
|
|
if AddrInNets(machine.ip(), self.zones_reverse) :
|
|
base_ip = machine.ip().split('.')
|
|
base_ip.reverse()
|
|
zone = "%s.%s.%s.in-addr.arpa" % tuple(base_ip[1:])
|
|
zone = zone.encode('iso-8859-1')
|
|
ligne = '%s\tIN\tPTR\t%s.\n' % (base_ip[0],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'):
|
|
warnings += u'Résolution inverse ignorée (mid=%s) : ip sur zone non autoritaire (%s)\n' % ( machine.id().encode('iso-8859-1'), machine.ip().encode('iso-8859-1') )
|
|
|
|
### Ajouts pour les fichiers de résolution directs
|
|
for zone in direct.keys() :
|
|
# MXs
|
|
direct[zone] = MX % { 'zone' : zone } + direct[zone]
|
|
|
|
|
|
### Ajout des délégations de zones
|
|
for deleg in self.DELEG.keys():
|
|
nom, zone = deleg.split('.',1)
|
|
if not zone in direct.keys():
|
|
warnings += u'Délégation ignorée %s : on ne génère pas la zone parent\n' % deleg
|
|
continue
|
|
for serv in self.DELEG[deleg]:
|
|
direct[zone] = direct[zone] + "%s\tIN\tNS\t%s\n" % ( nom, serv )
|
|
|
|
### Ecriture des fichiers de zone et préparation du fichier de définition
|
|
f = ''
|
|
for zone, lignes in direct.items() + reverse.items() :
|
|
file = self.DNS_DIR + 'db.' + zone
|
|
fd = self._open_conf(file,';')
|
|
fd.write(self.zone_entete % \
|
|
{ 'zone' : zone, 'serveur_autoritaire' : self.DNSs[0] , 'serial' : serial } )
|
|
fd.write('\n')
|
|
fd.write(DNS)
|
|
fd.write(lignes)
|
|
fd.close()
|
|
f += self.zone_template % { 'NOM_zone' : zone, 'FICHIER_zone' : file }
|
|
|
|
### Ecriture fichier de définition
|
|
fd = self._open_conf(self.DNS_CONF,'//')
|
|
fd.write(f)
|
|
fd.close()
|
|
|
|
return warnings
|
|
|
|
|
|
if __name__ == '__main__' :
|
|
from socket import gethostname
|
|
from config import cfengine_main
|
|
def short_name(fullhostname):
|
|
return fullhostname.split(".")[0]
|
|
hostname = short_name(gethostname())
|
|
if hostname == short_name(cfengine_main):
|
|
print "Reconfiguration du fichier de cfengine pour configurer le bind d'un serveur en esclave (pensez à lancer cfrun)."
|
|
c = dns()
|
|
c.gen_slave()
|
|
if hostname == short_name(dns.DNSs[0]):
|
|
print "Ce serveur est également serveur maitre, mais la reconfiguration du DNS maitre se fait par generate."
|
|
elif hostname == short_name(dns.DNSs[0]):
|
|
print "Ce serveur est maître ! Utilisez generate."
|
|
elif hostname in map(lambda fullhostname : short_name(fullhostname),dns.DNSs[1:]+dns.DNSs_private):
|
|
print "Ce serveur est esclave! Lancez le sur %s, puis lancez cfrun" % cfengine_main
|
|
else:
|
|
print "Ce serveur ne correspond à rien pour la configuration DNS."
|
|
|
|
|