diff --git a/gestion/gen_confs/firewall.py b/gestion/gen_confs/firewall.py index fddd6114..e7e0e8cd 100755 --- a/gestion/gen_confs/firewall.py +++ b/gestion/gen_confs/firewall.py @@ -85,8 +85,8 @@ def redirect_chain(table, chain_in, chain_out, ip) : # On redirige les paquets de la chaîne in dans la chaîne out iptables("-t %s -A %s -o ens -s %s -j %s" % (table, chain_in, ip, chain_out)) iptables("-t %s -A %s -o crans -d %s -j %s" % (table, chain_in, ip, chain_out)) - - + + class firewall_crans : """ Classe parente pour les firewalls du crans @@ -112,11 +112,11 @@ class firewall_crans : vlan_adm = NETs['vlan-adm'][0] adm_users = [ "root", "identd", "daemon", "postfix", "freerad", "amavis", "nut", "respbats", "list", "sqlgrey", "ntpd", "lp" ] - + limit = " -m limit --limit 10/s --limit-burst 10 " log_template = '-m limit --limit 1/s --limit-burst 1 -j LOG --log-level notice --log-prefix ' filtre_flood = '-m hashlimit --hashlimit 20 --hashlimit-mode srcip --hashlimit-name flood' - + machines = [] debug = 1 @@ -141,11 +141,11 @@ class firewall_crans : def __machines(self) : """ Liste des machines du crans """ return db.all_machines(graphic=True) - + def __init__(self) : """ Pose un lock """ make_lock('firewall') - + def __del__(self) : """ Destruction du lock """ # Comprend pas pourquoi il faut réimporter ici -- Fred @@ -195,16 +195,16 @@ class firewall_crans : if not self.__machines() or self.exception_catcher(self.__stop) : cprint(u"Abandon", 'rouge') return - + # Initialisation self.exception_catcher(self.mangle_table) self.exception_catcher(self.nat_table) self.exception_catcher(self.filter_table) self.exception_catcher(self.filter_table_tweaks) - + # Remplissage self.start_fw_funcs() - + # On peux router self.post_start_hook() cprint(u"\t -> fin de la procédure de démarrage",'vert') @@ -215,7 +215,7 @@ class firewall_crans : self.pre_stop_hook() self.exception_catcher(self.__stop) cprint(u"\t -> fin de la procédure d'arrêt",'vert') - + def __stop(self) : self.anim = anim("\tSuppression des règles") iptables("-t nat -P PREROUTING ACCEPT") @@ -227,14 +227,14 @@ class firewall_crans : iptables("-t mangle -X") print OK - + def test_mac_ip(self) : """ Reconstruit la correspondance MAC-IP des machines des adhérents """ self.anim = anim('\tChaîne TEST_MAC-IP',len(self.__machines())+1) iptables("-t nat -P PREROUTING ACCEPT") iptables("-t nat -F TEST_MAC-IP") self.anim.cycle() - + def procedure() : for machine in self.__machines() : self.__test_mac_ip(machine) @@ -243,10 +243,10 @@ class firewall_crans : iptables("-t nat -P PREROUTING ACCEPT") self.anim.reinit() print OK - + self.exception_catcher(procedure) - + def __test_mac_ip(self,machine): ip=machine.ip() mac=machine.mac() @@ -291,7 +291,7 @@ class firewall_crans : if adh_maj : self.exception_catcher(self.adh_maj_list_to_do) - + def mac_ip_maj(self,ip_list) : """ Mise à jour de la correspondance MAC-IP pour les ip fournies """ ## Que faut-il faire ? @@ -299,7 +299,7 @@ class firewall_crans : if ip_list == [''] : print OK + ' (rien à faire)' return - + mac_ip_maj = {} serveur_maj = False for ip in ip_list : @@ -325,14 +325,14 @@ class firewall_crans : print WARNING if debug : sys.stderr.write("Plusieurs machines avec l'IP %s\n" % ip) - + print OK - + ## Traitement # Serveurs if serveur_maj : self.serveurs_maj() - + # Correspondance MAC-IP if mac_ip_maj or serveur_maj : def procedure() : @@ -365,7 +365,7 @@ class firewall_crans : except IptablesError, c: warn += str(c) + '\n' - + # Ajout des machines qui n'étaient pas dans le firewall for machine in mac_ip_maj.values() : if machine : @@ -375,7 +375,7 @@ class firewall_crans : sys.stdout.write(warn) else : print OK - + self.exception_catcher(procedure) def build_chaine_adherent(self,chaine,methode) : @@ -401,7 +401,7 @@ class firewall_crans : iptables("-A %s -j REJECT" % chaine) return self.exception_catcher(procedure) - + """ Komaz """ @@ -413,10 +413,10 @@ class firewall_komaz(firewall_crans) : PREROUTING (policy par défaut : ACCEPT) 1) proxy transparent 2) marquage des paquets bittorrent - + POSTROUTING (policy par défaut : ACCEPT) 1) passage dans un sous-réseau de l'ip crans : SUBNET - + SUBNET classe pour chaque ip de son réseau dans la classe htb correspondante table nat : PREROUTING (policy par défaut : ACCEPT) @@ -427,12 +427,12 @@ class firewall_komaz(firewall_crans) : source ou destination les serveurs de serveurs_crans ce qui vient de l'extérieur 5) passage par TEST_MAC-IP - + TEST_VIRUS_FLOOD droppe les paquets contenant des virus ou les paquets de flood RESEAUX_NON_ROUTABLES_DST droppe les paquets dont la destination est non routable RESEAUX_NON_ROUTABLES_SRC droppe les paquets dont la source est non routable TEST_MAC-IP envoi les bon paquets vers CRANS_VERS_EXT - + table filter : FORWARD (policy par défaut : ACCEPT) 1) passage par BLACKLIST @@ -441,7 +441,7 @@ class firewall_komaz(firewall_crans) : 4) ce qui a pour destination les serveurs de serveurs_crans est dirigé EXT_VERS_SERVEURS 5) tout ce qui vient de l'interface externe est dirigé vers EXT_VERS_CRANS 6) ce qui a pour source les serveurs de serveurs_crans est dirigé vers EXT_VERS_CRANS - + BLACKLIST fitre des ip blacklistées (REJECT) FILTRE_P2P filtre le traffic de p2p EXT_VERS_CRANS et CRANS_VERS_EXT @@ -451,20 +451,20 @@ class firewall_komaz(firewall_crans) : ACCEPT pour bon mac-ip-port REJECT pour le reste """ - + # interfaces physiques eth_ext = "ens" eth_int = "crans" - + # Ports ouverts ports_default = { 'tcp_EXT_VERS_CRANS' : [ '22' ], 'tcp_CRANS_VERS_EXT': [ ':24', '26:79', '81:134', '136', '140:444', '446:'], 'udp_EXT_VERS_CRANS' : [ ], 'udp_CRANS_VERS_EXT': [ ':136','140:'] } - - + + ports_virus = { 'tcp' : [ 135, 445 ] , 'udp' : [] } - + # Filtrage du peer to peer filtres_p2p = [ ('bit', 'Bittorrent'), ('apple', 'AppleJuice'), @@ -494,11 +494,11 @@ class firewall_komaz(firewall_crans) : def mangle_table(self): self.anim = anim('\tStructure de la table mangle') - + # On vide complètement la table iptables("-t mangle -F") iptables("-t mangle -X") - + # Proxy transparent iptables("-t mangle -A PREROUTING -s %s -j RETURN" % self.zone_serveur) iptables("-t mangle -A PREROUTING -p tcp --destination-port 80 " @@ -513,10 +513,10 @@ class firewall_komaz(firewall_crans) : debit_max = p2p.debit_max eth_ext = self.eth_ext eth_int = self.eth_int - + # On ne va pas plus loin si il ne s'agit pas de bittorrent iptables("-t mangle -A POSTROUTING -m mark ! --mark %s -j ACCEPT" % mark) - + # On marque les paquets bittorrent uniquement iptables("-t mangle -A PREROUTING -p tcp -j CONNMARK --restore-mark") iptables("-t mangle -A PREROUTING -p tcp -m mark ! --mark 0x0 -j ACCEPT") @@ -524,16 +524,16 @@ class firewall_komaz(firewall_crans) : "-j MARK --set-mark %s" % mark) iptables("-t mangle -A PREROUTING -p tcp -m mark --mark %s " "-j CONNMARK --save-mark" % mark) - + warn = '' - + # Par défaut, on envoit les paquets dans la classe 9998 for net in NETs['all']: iptables("-t mangle -A POSTROUTING -o %(eth_int)s -d %(net)s " "-j CLASSIFY --set-class 1:9998" % locals()) iptables("-t mangle -A POSTROUTING -o %(eth_ext)s -s %(net)s " "-j CLASSIFY --set-class 1:9998" % locals()) - + # On crée les chaînes de sous-réseaux for net in NETs['all']: for mask in conf_fw.mask: @@ -568,7 +568,7 @@ class firewall_komaz(firewall_crans) : "htb rate %(debit_adh)s ceil %(debit_adh)s" % locals()) tc("qdisc add dev %(interface)s parent 1:9998 " "handle 9999: sfq perturb 10" % locals()) - + # On construit ensuite les classes et qdisc pour chaque adhérent for adherent in adherents: self.anim.cycle() @@ -581,7 +581,7 @@ class firewall_komaz(firewall_crans) : "htb rate %(debit_adh)s ceil %(debit_max)s" % locals()) tc("qdisc add dev %(interface)s parent 1:%(class_id)d " "handle %(qdisc_id)d: sfq perturb 10" % locals()) - + # Classification des adhérents dans leur classe respective for machine in adherent.machines(): ip = machine.ip() @@ -660,7 +660,7 @@ class firewall_komaz(firewall_crans) : # MAJ des règles de classification de l'IP def procedure(): self.anim = anim('\tMise à jour des classes p2p') - + # Liste des classes candidates a la suppression scheduled_del = [] warn = '' @@ -671,7 +671,7 @@ class firewall_komaz(firewall_crans) : debit_max = p2p.debit_max eth_ext = self.eth_ext eth_int = self.eth_int - + try: for ip in ip_list: recherche = db.search('ip=%s&paiement=ok' % ip) @@ -732,13 +732,13 @@ class firewall_komaz(firewall_crans) : for class_id in scheduled_del: # TODO: supprimer les classes qui sont vraiment vides pass - + if warn: print WARNING sys.stdout.write(warn) else: print OK - + self.exception_catcher(procedure) def post_start_hook(self) : @@ -798,22 +798,22 @@ class firewall_komaz(firewall_crans) : self.anim.cycle() self.anim.reinit() print OK - + def test_virus_flood(self) : """ Construction de la chaîne TEST_VIRUS """ iptables('-t nat -F TEST_VIRUS_FLOOD') self.anim = anim('\tFiltrage virus et floods') - + ip_vers = ('65.19.154.90', '208.72.168.52', '66.109.25.121', '193.37.152.88', '89.149.202.101') for ip in ip_vers: iptables('-t nat -A TEST_VIRUS_FLOOD -s %s -j LOG_VIRUS' % ip) iptables('-t nat -A TEST_VIRUS_FLOOD -d %s -j LOG_VIRUS' % ip) - + for proto, ports in self.ports_virus.items() : for port in ports : iptables('-t nat -A TEST_VIRUS_FLOOD -p %s --dport %s -j LOG_VIRUS' % (proto, port) ) self.anim.cycle() - + iptables('-t nat -A TEST_VIRUS_FLOOD %s -j RETURN' % self.filtre_flood) # Les limites en négatif ca ne marche pas. self.anim.cycle() iptables('-t nat -A TEST_VIRUS_FLOOD -j LOG_FLOOD') @@ -825,13 +825,13 @@ class firewall_komaz(firewall_crans) : if not self.build_chaine('SERVEURS_VERS_EXT', self.__serveurs_vers_ext) : self.anim.reinit() print OK - + def ext_vers_serveurs(self) : """ Reconstruit la chaîne EXT_VERS_SERVEURS """ if not self.build_chaine('EXT_VERS_SERVEURS', self.__ext_vers_serveurs) : self.anim.reinit() print OK - + def crans_vers_ext(self) : """ Reconstruit la chaîne CRANS_VERS_EXT """ self.build_chaine_adherent('CRANS_VERS_EXT',self.__crans_vers_ext) @@ -856,7 +856,7 @@ class firewall_komaz(firewall_crans) : #self.anim.reinit() #print OK - def __serveurs_vers_ext(self,machine): + prout __serveurs_vers_ext(self,machine): ip=machine.ip() if not AddrInNet(ip,self.zone_serveur): # C'est une machine adhérent, rien à faire ici @@ -876,43 +876,43 @@ class firewall_komaz(firewall_crans) : if not AddrInNet(ip,self.zone_serveur): # C'est une machine adhérent, rien à faire ici return - + ports = { 'tcp' : machine.portTCPin(), 'udp' : machine.portUDPin() } - + for proto in [ 'tcp', 'udp' ] : for port in ports[proto]: iptables("-I EXT_VERS_SERVEURS -d %s -p %s --dport %s -j ACCEPT"\ %(ip,proto,port)) - + def __crans_vers_ext(self,machine): ip=machine.ip() if AddrInNet(ip,self.zone_serveur): # C'est un serveur, rien à faire ici return - + ports = { 'tcp' : machine.portTCPout(), 'udp' : machine.portUDPout() } - + for proto in [ 'tcp', 'udp' ] : for port in ports[proto]: iptables("-I CRANS_VERS_EXT -s %s -p %s --dport %s -j ACCEPT" \ %(ip,proto,port)) - + def __ext_vers_crans(self,machine): ip=machine.ip() if AddrInNet(ip,self.zone_serveur): # C'est un serveur, rien à faire ici return - + ports = { 'tcp' : machine.portTCPin(), 'udp' : machine.portUDPin() } - + for proto in [ 'tcp', 'udp' ] : for port in ports[proto]: iptables("-I EXT_VERS_CRANS -d %s -p %s --dport %s -j ACCEPT" \ %(ip,proto,port)) - + def blacklist(self): """ Construit les chaînes de blackliste (BLACKLIST_{DST,SRC}) """ iptables('-F BLACKLIST_DST') @@ -920,9 +920,9 @@ class firewall_komaz(firewall_crans) : # Peut-être à mettre dans config.py ? blacklist_sanctions = ('upload', 'warez', 'p2p', 'autodisc_p2p', 'autodisc_upload', 'bloq') - + blacklist = [] - + # Recherche sur le champ ablacklist (clubs compris) search = db.search('ablacklist=*&paiement=%s' % ann_scol) self.anim = anim("\tBlackliste adhérents+clubs", len(search['adherent']+search['club'])) @@ -935,7 +935,7 @@ class firewall_komaz(firewall_crans) : break self.anim.reinit() print OK - + # Recherche sur le champ mblacklist search = db.search('mblacklist=*&paiement=%s' % ann_scol) self.anim = anim("\tBlackliste machines", len(search['machine'])) @@ -964,7 +964,7 @@ class firewall_komaz(firewall_crans) : # On ne filtre que ce qui passe sur l'interface externe iptables('-A FILTRE_P2P -i %s -o %s -j RETURN' % (self.eth_int, self.eth_int) ) - + for filtre in self.filtres_p2p : iptables('-A FILTRE_P2P -m ipp2p --%s -j LOG --log-prefix "IPP2P=%s "' % (filtre[0], @@ -972,10 +972,10 @@ class firewall_komaz(firewall_crans) : #iptables('-A FILTRE_P2P -m ipp2p --%s -j REJECT --reject-with icmp-admin-prohibited' % filtre[0]) iptables('-A FILTRE_P2P -m ipp2p --%s -j RETURN' % filtre[0]) self.anim.cycle() - + self.anim.reinit() print OK - + def serveurs_maj(self) : self.exception_catcher(self.serveurs_vers_ext) @@ -993,9 +993,9 @@ class firewall_zamok(firewall_crans) : FORWARD (policy par défaut : DROP) rien ne passe pas la chaîne FORWARD INPUT (policy par défaut : ACCEPT) - + """ - + # interfaces physiques eth_pub = "crans" eth_adm = "crans.2" @@ -1004,7 +1004,7 @@ class firewall_zamok(firewall_crans) : self.anim = anim('\tOutput vers VLAN adm', len(self.adm_users)) # Supression des éventuelles règles iptables("-t filter -F SERV_OUT_ADM") - + for user in self.adm_users : self.anim.cycle() try: @@ -1016,14 +1016,14 @@ class firewall_zamok(firewall_crans) : iptables("-A SERV_OUT_ADM -p tcp --dport ldap -j ACCEPT") iptables("-A SERV_OUT_ADM -p tcp --dport domain -j ACCEPT") iptables("-A SERV_OUT_ADM -p udp --dport domain -j ACCEPT") - + # Pour le nfs (le paquet à laisser passer n'a pas d'owner) iptables("-A SERV_OUT_ADM -d nfs.adm.crans.org -m owner ! --uid-owner 0 -j REJECT --reject-with icmp-net-prohibited") iptables("-A SERV_OUT_ADM -d nfs.adm.crans.org -j ACCEPT") - + # Rien d'autre ne passe iptables("-A SERV_OUT_ADM -j REJECT --reject-with icmp-net-prohibited") - + self.anim.reinit() print OK @@ -1031,11 +1031,11 @@ class firewall_zamok(firewall_crans) : self.anim = anim('\tStructure de la table nat') iptables('-t nat -N TEST_MAC-IP') iptables('-t filter -N SERV_OUT_ADM') - + iptables("-t nat -P PREROUTING ACCEPT") iptables("-t nat -A PREROUTING -i lo -j ACCEPT") iptables("-t nat -A PREROUTING -d 224.0.0.0/4 -j DROP") - + for net in NETs['fil'] + NETs['vlan-adm'] + NETs['wifi'] : iptables("-t nat -A PREROUTING -s %s -j TEST_MAC-IP" % net) iptables("-t filter -A OUTPUT -o lo -j ACCEPT") @@ -1075,7 +1075,7 @@ class firewall_rouge(firewall_crans) : FORWARD (policy par défaut : DROP) rien ne passe pas la chaîne FORWARD INPUT (policy par défaut : ACCEPT) - + """ # interfaces physiques @@ -1085,11 +1085,11 @@ class firewall_rouge(firewall_crans) : def nat_table(self) : self.anim = anim('\tStructure de la table nat') iptables('-t nat -N TEST_MAC-IP') - + iptables("-t nat -P PREROUTING ACCEPT") iptables("-t nat -A PREROUTING -i lo -j ACCEPT") iptables("-t nat -A PREROUTING -d 224.0.0.0/4 -j DROP") - + for net in NETs['fil'] + NETs['vlan-adm'] + NETs['wifi'] : iptables("-t nat -A PREROUTING -s %s -j TEST_MAC-IP" % net) @@ -1117,9 +1117,9 @@ class firewall_vert(firewall_crans) : FORWARD (policy par défaut : DROP) rien ne passe pas la chaîne FORWARD INPUT (policy par défaut : ACCEPT) - + """ - + # interfaces physiques eth_crans = "crans" @@ -1155,7 +1155,7 @@ class firewall_sila(firewall_rouge): "-m mac --mac-source %s " % mac_komaz + "-j MARK --set-mark %s" % conf_fw.mark['proxy']) iptables("-t mangle -A PREROUTING -m mark --mark %s -j ACCEPT" % conf_fw.mark['proxy']) - + def nat_table(self): firewall_rouge.nat_table(self) # Pour le proxy transparent @@ -1173,7 +1173,7 @@ if __name__ == '__main__' : def __usage(txt=None) : if txt!=None : cprint(txt,'gras') - + print """Usage: %(p)s start : Construction du firewall. %(p)s restart : Reconstruction du firewall. @@ -1184,14 +1184,14 @@ Les cha Pour reconfiguration d'IPs particulières, utiliser generate. """ % \ { 'p' : sys.argv[0].split('/')[-1] , 'chaines' : '\n '.join(chaines) } sys.exit(-1) - + # Bons arguments ? if len(sys.argv) == 1 : __usage() for arg in sys.argv[1:] : if arg in [ 'stop', 'restart', 'start' ] and len(sys.argv) != 2 : __usage("L'argument %s ne peut être employé que seul." % arg) - + if arg not in [ 'stop', 'restart', 'start' ] + chaines : __usage("L'argument %s est inconnu." % arg)