From 76bf5f8ab8d6cb55a1cbf952f25a6395564fbdd5 Mon Sep 17 00:00:00 2001 From: sabban Date: Wed, 27 Oct 2004 21:20:14 +0200 Subject: [PATCH] -> firewall dans le cvs darcs-hash:20041027192014-1d643-ab1724aa01fbf9cdb0f3278644685aa10bb2d2ef.gz --- gestion/classe_firewall.py | 374 +++++++++++++++++++++++++++++++++++++ gestion/config_firewall.py | 66 +++++++ gestion/firewall.py | 99 ++++++++++ 3 files changed, 539 insertions(+) create mode 100755 gestion/classe_firewall.py create mode 100644 gestion/config_firewall.py create mode 100755 gestion/firewall.py diff --git a/gestion/classe_firewall.py b/gestion/classe_firewall.py new file mode 100755 index 00000000..05c32e1b --- /dev/null +++ b/gestion/classe_firewall.py @@ -0,0 +1,374 @@ +#!/usr/bin/env python +# -*- coding: iso-8859-1 -*- +# The author of this code is Manuel Sabban +# +# Copyright (c) 2004 Manuel Sabban. +# +# Permission to use, copy, and modify this software with or without fee +# is hereby granted, provided that this entire notice is included in +# all source code copies of any software which is or includes a copy or +# modification of this software. +# +# THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR +# IMPLIED WARRANTY. IN PARTICULAR, NONE OF THE AUTHORS MAKES ANY +# REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE +# MERCHANTABILITY OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR +# PURPOSE. +""" classe Firewall de Komaz """ +import sys,os +import iptools,config,fileinput +from ldap_crans import * +from config_firewall import * +from affich_tools import * +def test(fredgroscon): + print fredgroscon + os.system(fredgroscon) + +class ErrorArgument(Exception): + """ + User defined exception + Erreur sur les arguments d'appel du firewall + """ + pass +class ErrorIp(Exception): + """ + User defined exception + Erreur dans les fonctions Ips + """ + def __init__(self, ip): + self.ip=ip +class ErrorMoreThanOneIp(ErrorIp): + """ + User defined exception + Au moins deux utilisateurs ont la même ip + """ + pass +class ErrorIptables(Exception): + pass + """ + User defined exception + Les erreurs d'iptables + """ + +class ErrorNoSuchIp(ErrorIp): + """ + User defined exception + Personne n'a cette ip + """ + pass + +class firewall: + def start(self): + """ + Construit le firewall + Pas d'arguments + """ + self.komaz + self.serveurs() + self.filtrage_mac() + self.create_forward() + self.blacklist() + self.create_adherents() + + def stop(self): + """ + Arrête le firewall + Pas d'arguments + """ + print "Arrêt du firewall" + os.system("iptables -F") + os.system("iptables -t nat -F") + os.system("iptables -X") + + def create_defaults(self): + """ + Crée la chaîne par laquelle tous les adhérents passent par défault + Pas d'argument + """ + for proto in ["tcp","udp"]: + for i in range(len(config.port_default["%s_input" % proto])): + test("iptables -A DEFAULT_INPUT -p %s --dport "%proto+\ + config.port_default["%s_input" % proto][i]+\ + " -j ACCEPT") + for i in range(len(config.port_default["%s_output" % proto])): + test("iptables -A DEFAULT_OUTPUT -p %s --sport "%proto+\ + config.port_default["%s_output" % proto][i]+\ + " -j ACCEPT") + + + def del_entree(self,ip): + """ + Détruit une entrée dans le firewall + Note: Il faut *tester lourdement* cette fonction. + """ + try: + os.system("iptables -L -n > /tmp/firewall") + except: + print "Impossible de créer le fichier d'états /tmp/firewall" + exit() + chaines=[] + count=0 + for line in fileinput.input('/tmp/firewall'): + count=count+1 + if "Chain" in line: + tmp=line.split(' ') + chaine=tmp[1] + count=0 + if ip in line: + test("iptables -D %i %s"%(count,chaine)) + os.system("rm -f /tmp/firewall") + + def paire_macip(self,ip,mac): + """ + Crée le filtrage pour une paire mac-ip + """ + os.system("iptables -t nat -A PREROUTING -s %s -m mac --mac-source %s -j ACCEPT"\ + %(ip,mac)) + + def filtrage_mac(self): + """ + Crée tout le routage sur la chaîne PREROUTING + """ + db=crans_ldap() + search=db.search('host!=*.wifi.crans.org')['machine'] + barre=anim("Filtrage mac-ip des machines fixes.",len(search)) + for i in range(0,len(search)): + self.paire_macip(search[i].ip(),search[i].mac()) + barre.cycle() + search=db.search('host=*.wifi.crans.org')['machine'] + + barre=anim("Filtrage mac-ip des machines wifi.",len(search)) + for i in range(0,len(search)): + self.paire_macip(search[i].ip(),'00:0c:f1:fa:f1:4b') + barre.cycle() + + os.system("iptables -t nat -A PREROUTING -i %s -s \\!"%int_crans+\ + " 138.231.136.0/21 -j ACCEPT") + os.system("iptables -t nat -A PREROUTING -i %s -s \\!"%int_crans+\ + " 138.231.148.0/22 -j ACCEPT") + for i in reseaux_non_routables: + os.system("iptables -t nat -A PREROUTING -i %s -s %s"%(int_crans,i)+\ + " -m limit --limit %s --limit-burst %s"%(loglimit,logburst)+\ + " -j LOG --log-level %s --log-prefix %s"%\ + (loglevel,logprefix_macip)) + os.system("iptables -t nat -A PREROUTING -i %s -s %s -j DROP"%\ + (int_crans,i)) + os.system("iptables -t nat -A PREROUTING -i %s -d %s"%(int_crans,i)+\ + " -m limit --limit %s --limit-burst %s"%(loglimit,logburst)+\ + " -j LOG --log-level %s --log-prefix %s"%\ + (loglevel,logprefix_macip)) + os.system("iptables -t nat -A PREROUTING -i %s -d %s -j DROP"%\ + (int_crans,i)) + test("iptables -t nat -A PREROUTING -i %s -p tcp "%int_crans+\ + " -m limit --limit %s --limit-burst %s"%(loglimit,logburst)+\ + " -j LOG --log-level %s --log-prefix %s"%\ + (loglevel,logprefix_macip)) + test("iptables -t nat -A PREROUTING -i %s -p tcp"%int_crans+\ + " -j REJECT --reject-with tcp-reset") + test("iptables -t nat -A PREROUTING -i %s -p udp"%int_crans+\ + " -m limit --limit %s --limit-burst %s"%(loglimit,logburst)+\ + " -j LOG --log-level %s --log-prefix %s"%\ + (loglevel,logprefix_macip)) + test("iptables -t nat -A PREROUTING -i %s -p udp"%int_crans+\ + " -j REJECT --reject-with icmp-port-unreachable") + + def komaz(self): + """ + Crée les règles spécifiques à la machine komaz + """ + ports=komaz_ports['portTCPin'] + for i in ports.split(' '): + os.system("iptables -A INPUT -d 138.231.136.4 -p tcp --dport %s"%i+\ + " -j ACCEPT") + ports=komaz_ports['portTCPout'] + for i in ports.split(' '): + os.system("iptables -A OUTPUT -s 138.231.136.4 -p tcp --dport %s"%i+\ + " -j ACCEPT") + ports=komaz_ports['portUDPin'] + for i in ports.split(' '): + os.system("iptables -A INPUT -d 138.231.136.4 -p udp --dport %s"%i+\ + " -j ACCEPT") + ports=komaz_ports['portUDPout'] + for i in ports.split(' '): + os.system("iptables -A OUTPUT -s 138.231.136.4 -p udp --dport %s"%i+\ + " -j ACCEPT") + + def serveurs(self): + def fonction_utile(valeur): + return valeur + """ + Définit les chaînes relatives au serveur + Note: Ça marche pas si port{TCP,UDP}{in,out} est '' + Fred corrigera + """ + for serveur in serveurs_list: + ports=serveurs_ports[serveur]['portTCPin'] + for i in ports.split(' '): + os.system("iptables -A FORWARD -d %s"%\ + eval(fonction_utile(serveur))['ip']+\ + " -p tcp --dport %s -j ACCEPT"%i) + ports=serveurs_ports[serveur]['portTCPout'] + for i in ports.split(' '): + os.system("iptables -A FORWARD -s %s"%\ + eval(fonction_utile(serveur))['ip']+\ + " -p tcp --dport %s -j ACCEPT"%i) + ports=serveurs_ports[serveur]['portUDPin'] + for i in ports.split(' '): + os.system("iptables -A FORWARD -d %s"%\ + eval(fonction_utile(serveur))['ip']+\ + " -p udp --dport %s -j ACCEPT"%i) + ports=serveurs_ports[serveur]['portUDPout'] + for i in ports.split(' '): + os.system("iptables -A FORWARD -s %s"%\ + eval(fonction_utile(serveur))['ip']+\ + " -p udp --dport %s -j ACCEPT"%i) + for serveur in serveurs_list: + self.paire_macip(eval(fonction_utile(serveur))['ip'],\ + eval(fonction_utile(serveur))['mac']) + + def blacklist(self): + """ + Bloque les adhérents blacklistés + """ + os.system("iptables -N DEFAULT_INPUT") + os.system("iptables -N DEFAULT_OUTPUT") + + db=crans_ldap() + blacklist=[] + search=db.search('blacklist=*&paiement=%s'%ann_scol) + for entite in search['adherent']+\ + search['club']+search['machine']: + if 'upload' in entite.blacklist_actif(): + if search.__class__==machine: + blacklist+=[entite] + else: + blacklist+=entite.machines() + for instance_machine in blacklist: + test("iptables -A BLACKLIST_INPUT -d %s"%\ + instance_machine.ip().encode("iso-8859-15")+\ + "-m limit --limit %s --limit-burst %s"%(loglimit,logburst)+\ + "-j LOG --log-level %s --log-prefix_macip %s"%\ + (loglevel,logprefix_blacklist)) + test("iptables -A BLACKLIST_INPUT -d %s -j REJECT"%\ + instance_machine.ip()) + test("iptables -A BLACKLIST_OUTPUT -s %s"%\ + instance_machine.ip().encode("iso-8859-15")+\ + "-m limit --limit %s --limit-burst %s"%(loglimit,logburst)+\ + "-j LOG --log-level %s --log-prefix_macip %s"%\ + (loglevel,logprefix_blacklist)) + test("iptables -A BLACKLIST_OUTPUT -s %s -j REJECT"%\ + instance_machine.ip()) + os.system("iptables -A BLACKLIST_INPUT -j DEFAULT_INPUT") + os.system("iptables -A BLACKLIST_OUTPUT -j DEFAULT_OUTPUT") + + def create_forward(self): + """ + Différencie ce qui arrive et ce qui part dans la chaîne FORWARD + """ + os.system("iptables -N BLACKLIST_INPUT") + os.system("iptables -N BLACKLIST_OUTPUT") + os.system("iptables -A FORWARD -s 138.231.136.0/21 -j BLACKLIST_OUTPUT") + os.system("iptables -A FORWARD -s 138.231.136.0/22 -j BLACKLIST_OUTPUT") + os.system("iptables -A FORWARD -d 138.231.148.0/21 -j BLACKLIST_INPUT") + os.system("iptables -A FORWARD -d 138.231.148.0/22 -j BLACKLIST_INPUT") + + def create_adherents(self): + """ + Crée toutes les règles relatives aux adhérents ayant des règles + spéciales + """ + os.system("iptables -N ADHERENTS_OUTPUT") + os.system("iptables -N ADHERENTS_INPUT") + + os.system("iptables -A ADHERENTS_INPUT -m state --state "+\ + "RELATED -j ACCEPT") + os.system("iptables -A ADHERENTS_OUTPUT -m state --state "+\ + "RELATED -j ACCEPT") + os.system("iptables -A ADHERENTS_INPUT -m state --state "+\ + "ESTABLISHED -m limit --limit-burst "+\ + "%s -j ACCEPT"%limite_connexion) + os.system("iptables -A ADHERENTS_OUTPUT -m state --state "+\ + "ESTABLISHED -m limit --limit-burst "+\ + "%s-j ACCEPT"%limite_connexion) + test("iptables -A DEFAULT_INPUT -j ADHERENTS_INPUT") + test("iptables -A DEFAULT_OUTPUT -j ADHERENTS_OUTPUT") + + db=crans_ldap() + search=db.search('host=*.crans.org & portTCPin=*')['machine'] + for champ in search: + ports=champ.portTCPin() + for j in ports.split(' '): + os.system("iptables -A ADHERENTS_INPUT -d %s"%champ.ip()+\ + " -p tcp --dport %s -j ACCEPT"%j) + search=db.search('host=*.crans.org & portTCPout=*')['machine'] + for champ in search: + ports=champ.portTCPout() + for j in ports.split(' '): + os.system("iptables -A ADHERENTS_OUTPUT -d %s"%champ.ip()+\ + " -p tcp --dport %s -j ACCEPT"%j) + search=db.search('host=*.crans.org & portUDPin=*')['machine'] + for champ in search: + ports=champ.portUDPin() + for j in ports.split(' '): + os.system("iptables -A ADHERENTS_INPUT -d %s"%champ.ip()+\ + " -p udp --dport %s -j ACCEPT"%j) + search=db.search('host=*.crans.org & portUDPin=*')['machine'] + for champ in search: + ports=champ.portUDPout() + for j in ports.split(' '): + os.system("iptables -A ADHERENTS_OUTPUT -d %s"%champ.ip()+\ + " -p udp --dport %s -j ACCEPT"%j) + os.system("iptables -A ADHERENTS_INPUT"+\ + " -m limit --limit %s --limit-burst %s"%(loglimit,logburst)+\ + " -j LOG --log-level %s --log-prefix %s"%\ + (loglevel,logprefix_adherents)) + os.system("iptables -A ADHERENTS_INPUT -j REJECT") + os.system("iptables -A ADHERENTS_OUTPUT"+\ + " -m limit --limit %s --limit-burst %s"%(loglimit,logburst)+\ + " -j LOG --log-level %s --log-prefix %s"%\ + (loglevel,logprefix_adherents)) + os.system("iptables -A ADHERENTS_OUTPUT -j REJECT") + + def adherent(self,ip): + """ + Gère complètement l'ajout d'un adhérent dans le firewall + Tester la blacklist + """ + db=crans_ldap() + search=db.search('ip='+ip)['machine'] + if len(search)==0: + raise ErrorNoSuchIp(ip) + elif len(search)!=1: + raise ErrorMoreThanOneIp(ip) + i=0 + wifi=False + while (i +# +# Copyright (c) 2004 Manuel Sabban. +# +# Permission to use, copy, and modify this software with or without fee +# is hereby granted, provided that this entire notice is included in +# all source code copies of any software which is or includes a copy or +# modification of this software. +# +# THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR +# IMPLIED WARRANTY. IN PARTICULAR, NONE OF THE AUTHORS MAKES ANY +# REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE +# MERCHANTABILITY OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR +# PURPOSE. +""" Firewall de Komaz """ +import sys,os +import iptools,config +from classe_firewall import * + +def usage(): + """ + Vérifie le contenu et le contenant des arguments + de la ligne de commande. + En cas d'appel correct, apelle les fonctions de classe_firewall.py + """ + fw=firewall() + if len(sys.argv) < 2: + raise ErrorArgument,"Il faut au moins deux arguments." + try: + i=1 + if len(sys.argv) >= 2: + if ((sys.argv[1]=="start")or(sys.argv[1]=="restart"))\ + and(len(sys.argv)==2): + fw.stop() + try: + fw.start() + except KeyboardInterrupt: + fw.stop() + print "Firewall arrêté." + elif ((sys.argv[1]=="stop")and(len(sys.argv)==2)): + fw.stop() + else: + while (i