/!\ Cette solution n'a pas encore reu l'aval du CA et n'est donc pas
officiellement utilisable. /!\ Cration des classes ncessaires au filtrage du p2p avec bande passante limite par adhrent. On cre une classe pour le p2p avec un debit max On cre une classe htb avec un dbit garanti de max/nb_adherent par adherent + 1 pour les paquets non associs un adhrent (club, ...) chaque classe on associ un qdisc avec sfq pour garantir de l'galit des flux malgr la diminution de dbit. On cre ensuite des rgles iptables qui classent les paquets marqus 1 dans la classe de l'adhrent correspondant. Les paquets appartenant un flux de bittorrent sont marqus 1 (pas encore dans le script de firewall) darcs-hash:20060424121458-72cb0-7288a90bfde1cd51abd4fa8b5d0d2481c259f326.gz
This commit is contained in:
parent
486b27ad13
commit
8b33c17bd8
1 changed files with 155 additions and 10 deletions
|
@ -49,6 +49,16 @@ class IptablesError(Exception):
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return "%s\n status : %s\n %s" % (self.cmd,self.err_code,self.output)
|
return "%s\n status : %s\n %s" % (self.cmd,self.err_code,self.output)
|
||||||
|
|
||||||
|
class TcError(Exception):
|
||||||
|
""" Gestion des erreurs de tc """
|
||||||
|
def __init__(self,cmd,err_code,output):
|
||||||
|
self.cmd=cmd
|
||||||
|
self.err_code=err_code
|
||||||
|
self.output=output
|
||||||
|
syslog.syslog(syslog.LOG_ERR,"%s : status %s,%s" % (cmd,err_code,output))
|
||||||
|
def __str__(self):
|
||||||
|
return "%s\n status : %s\n %s" % (self.cmd,self.err_code,self.output)
|
||||||
|
|
||||||
def iptables(cmd):
|
def iptables(cmd):
|
||||||
""" Interface d'iptables """
|
""" Interface d'iptables """
|
||||||
syslog.syslog(syslog.LOG_INFO,cmd)
|
syslog.syslog(syslog.LOG_INFO,cmd)
|
||||||
|
@ -57,6 +67,15 @@ def iptables(cmd):
|
||||||
raise IptablesError(cmd,status,output)
|
raise IptablesError(cmd,status,output)
|
||||||
return output
|
return output
|
||||||
|
|
||||||
|
def tc(cmd):
|
||||||
|
""" Interface de tc """
|
||||||
|
syslog.syslog(syslog.LOG_INFO,cmd)
|
||||||
|
status,output=getstatusoutput("/sbin/tc "+cmd)
|
||||||
|
#print cmd
|
||||||
|
if status:
|
||||||
|
raise TcError(cmd,status,output)
|
||||||
|
return output
|
||||||
|
|
||||||
|
|
||||||
class firewall_crans :
|
class firewall_crans :
|
||||||
"""
|
"""
|
||||||
|
@ -125,6 +144,10 @@ class firewall_crans :
|
||||||
from lock import remove_lock
|
from lock import remove_lock
|
||||||
remove_lock('firewall')
|
remove_lock('firewall')
|
||||||
|
|
||||||
|
def mangle_table(self) :
|
||||||
|
""" Remplit la table mangle """
|
||||||
|
return
|
||||||
|
|
||||||
def nat_table(self) :
|
def nat_table(self) :
|
||||||
""" Remplit la table nat """
|
""" Remplit la table nat """
|
||||||
return
|
return
|
||||||
|
@ -166,6 +189,7 @@ class firewall_crans :
|
||||||
return
|
return
|
||||||
|
|
||||||
# Initialisation
|
# Initialisation
|
||||||
|
#self.exception_catcher(self.mangle_table)
|
||||||
self.exception_catcher(self.nat_table)
|
self.exception_catcher(self.nat_table)
|
||||||
self.exception_catcher(self.filter_table)
|
self.exception_catcher(self.filter_table)
|
||||||
self.exception_catcher(self.filter_table_tweaks)
|
self.exception_catcher(self.filter_table_tweaks)
|
||||||
|
@ -189,14 +213,16 @@ class firewall_crans :
|
||||||
iptables("-t nat -P PREROUTING ACCEPT")
|
iptables("-t nat -P PREROUTING ACCEPT")
|
||||||
iptables("-F")
|
iptables("-F")
|
||||||
iptables("-t nat -F")
|
iptables("-t nat -F")
|
||||||
|
iptables("-t mangle -F")
|
||||||
iptables("-X")
|
iptables("-X")
|
||||||
iptables("-t nat -X")
|
iptables("-t nat -X")
|
||||||
|
iptables("-t mangle -X")
|
||||||
print OK
|
print OK
|
||||||
|
|
||||||
|
|
||||||
def test_mac_ip(self) :
|
def test_mac_ip(self) :
|
||||||
""" Reconstruit la correspondance MAC-IP des machines des adhérents """
|
""" Reconstruit la correspondance MAC-IP des machines des adhérents """
|
||||||
self.anim = anim('\tChaine TEST_MAC-IP',len(self.__machines())+1)
|
self.anim = anim('\tChaîne TEST_MAC-IP',len(self.__machines())+1)
|
||||||
iptables("-t nat -P PREROUTING ACCEPT")
|
iptables("-t nat -P PREROUTING ACCEPT")
|
||||||
iptables("-t nat -F TEST_MAC-IP")
|
iptables("-t nat -F TEST_MAC-IP")
|
||||||
self.anim.cycle()
|
self.anim.cycle()
|
||||||
|
@ -261,7 +287,7 @@ class firewall_crans :
|
||||||
def mac_ip_maj(self,ip_list) :
|
def mac_ip_maj(self,ip_list) :
|
||||||
""" Mise à jour de la correspondance MAC-IP pour les ip fournies """
|
""" Mise à jour de la correspondance MAC-IP pour les ip fournies """
|
||||||
## Que faut-il faire ?
|
## Que faut-il faire ?
|
||||||
self.anim = anim('\tAnalyse travail à effectuer')
|
self.anim = anim('\tAnalyse du travail à effectuer')
|
||||||
if ip_list == [''] :
|
if ip_list == [''] :
|
||||||
print OK + ' (rien à faire)'
|
print OK + ' (rien à faire)'
|
||||||
return
|
return
|
||||||
|
@ -436,6 +462,12 @@ class firewall_komaz(firewall_crans) :
|
||||||
liste_reseaux_non_routables = [ '10.0.0.0/8', '172.16.0.0/12',
|
liste_reseaux_non_routables = [ '10.0.0.0/8', '172.16.0.0/12',
|
||||||
'169.254.0.0/16', '192.168.0.0/16', '224.0.0.0/4']
|
'169.254.0.0/16', '192.168.0.0/16', '224.0.0.0/4']
|
||||||
|
|
||||||
|
# Valeur des débits autorisés pour le p2p
|
||||||
|
machines = db.search('*')['machine']
|
||||||
|
debit_p2p_max = 1000000 #"1mbit"
|
||||||
|
debit_p2p_adh = debit_p2p_max/(len(machines)+1)
|
||||||
|
|
||||||
|
|
||||||
def reseaux_non_routables(self) :
|
def reseaux_non_routables(self) :
|
||||||
""" Construction de RESEAUX_NON_ROUTABLES_{DST,SRC} """
|
""" Construction de RESEAUX_NON_ROUTABLES_{DST,SRC} """
|
||||||
self.anim = anim('\tFiltrage ip non routables',len(self.liste_reseaux_non_routables))
|
self.anim = anim('\tFiltrage ip non routables',len(self.liste_reseaux_non_routables))
|
||||||
|
@ -446,6 +478,59 @@ class firewall_komaz(firewall_crans) :
|
||||||
self.anim.reinit()
|
self.anim.reinit()
|
||||||
print OK
|
print OK
|
||||||
|
|
||||||
|
def mangle_table(self) :
|
||||||
|
from affich_tools import anim, cprint, OK
|
||||||
|
self.anim = anim('\tStructure de la table mangle')
|
||||||
|
iptables("-t mangle -F POSTROUTING")
|
||||||
|
# On crée les chaines de sous-réseaux
|
||||||
|
for subnet in range(136,145)+range(148,152) :
|
||||||
|
try :
|
||||||
|
iptables("-t mangle -N SUBNET-%s_24" % subnet)
|
||||||
|
except IptablesError :
|
||||||
|
iptables("-t mangle -F SUBNET-%s_24" % subnet)
|
||||||
|
# On redirige les paquets dans la chaine appropriée
|
||||||
|
iptables("-t mangle -A POSTROUTING -o ens -s 138.231.%s.0/24 -j SUBNET-%s_24" % (subnet, subnet))
|
||||||
|
iptables("-t mangle -A POSTROUTING -o crans -d 138.231.%s.0/24 -j SUBNET-%s_24" % (subnet, subnet))
|
||||||
|
print OK
|
||||||
|
|
||||||
|
adherents = db.search('paiement=ok')['adherent']
|
||||||
|
|
||||||
|
a = anim('\tGénération des classes de filtrage p2p', len(adherents))
|
||||||
|
warn = ''
|
||||||
|
# Création des classes et qdisc
|
||||||
|
for interface in [self.eth_ext, self.eth_int] :
|
||||||
|
# On vide les classes et qdisc
|
||||||
|
try :
|
||||||
|
tc("qdisc del dev %s root" % interface)
|
||||||
|
except TcError, c:
|
||||||
|
warn += str(c) + '\n'
|
||||||
|
# On construit les classes et qdisc de base
|
||||||
|
# La partie principale qui définit le comportement par défaut
|
||||||
|
tc("qdisc add dev %s root handle 1: htb" % interface)
|
||||||
|
tc("class add dev %s parent 1: classid 1:1 htb rate %s ceil %s" % (interface, self.debit_p2p_max, self.debit_p2p_max))
|
||||||
|
tc("class add dev %s parent 1:1 classid 1:9998 htb rate %s ceil %s" % (interface, self.debit_p2p_adh, self.debit_p2p_max))
|
||||||
|
tc("qdisc add dev %s parent 1:9998 handle 9999: sfq perturb 10" % interface)
|
||||||
|
# On construit ensuite les classes et qdisc pour chaque adhérent
|
||||||
|
for adherent in adherents :
|
||||||
|
a.cycle()
|
||||||
|
class_id = int(adherent.id())+1 # On ne peut pas reprendre le numéro 1
|
||||||
|
qdisc_id = class_id+5000 # Il nous faut un n° inférieur à 9998 unique
|
||||||
|
for interface in [self.eth_ext, self.eth_int] :
|
||||||
|
tc("class add dev %s parent 1:1 classid 1:%d htb rate %s ceil %s" % (interface, class_id, self.debit_p2p_adh, self.debit_p2p_max))
|
||||||
|
tc("qdisc add dev %s parent 1:%d handle %d: sfq perturb 10" % (interface, class_id, qdisc_id))
|
||||||
|
|
||||||
|
# Classification des adhérents dans leur classe respective
|
||||||
|
for machine in adherent.machines() :
|
||||||
|
ip = machine.ip()
|
||||||
|
subnet = machine.ip().split('.')[2]
|
||||||
|
iptables("-t mangle -A SUBNET-%s_24 -o crans -d %s -m mark --mark 1 -j CLASSIFY --set-class 1:%s" % (subnet, ip, class_id))
|
||||||
|
iptables("-t mangle -A SUBNET-%s_24 -o ens -s %s -m mark --mark 1 -j CLASSIFY --set-class 1:%s" % (subnet, ip, class_id))
|
||||||
|
# Par défaut on envoit les paquets dans la classe 9998
|
||||||
|
iptables("-t mangle -A POSTROUTING -o crans -m mark --mark 1 -j CLASSIFY --set-class 1:9998")
|
||||||
|
iptables("-t mangle -A POSTROUTING -o ens -m mark --mark 1 -j CLASSIFY --set-class 1:9998")
|
||||||
|
|
||||||
|
print OK
|
||||||
|
|
||||||
def nat_table(self) :
|
def nat_table(self) :
|
||||||
self.anim = anim('\tStructure de la table nat')
|
self.anim = anim('\tStructure de la table nat')
|
||||||
for chaine in [ 'TEST_MAC-IP', 'RESEAUX_NON_ROUTABLES_SRC', 'RESEAUX_NON_ROUTABLES_DST', 'TEST_VIRUS_FLOOD', 'LOG_VIRUS', 'LOG_FLOOD' ] :
|
for chaine in [ 'TEST_MAC-IP', 'RESEAUX_NON_ROUTABLES_SRC', 'RESEAUX_NON_ROUTABLES_DST', 'TEST_VIRUS_FLOOD', 'LOG_VIRUS', 'LOG_FLOOD' ] :
|
||||||
|
@ -477,7 +562,7 @@ class firewall_komaz(firewall_crans) :
|
||||||
print OK
|
print OK
|
||||||
|
|
||||||
def filter_table_tweaks(self) :
|
def filter_table_tweaks(self) :
|
||||||
self.anim = anim('\trègles spécifiques à komaz')
|
self.anim = anim('\tRègles spécifiques à komaz')
|
||||||
for chaine in [ 'ADMIN_VLAN', 'EXT_VERS_SERVEURS', 'SERVEURS_VERS_EXT' , 'EXT_VERS_CRANS', 'CRANS_VERS_EXT', 'BLACKLIST_SRC', 'BLACKLIST_DST' , 'FILTRE_P2P' ] :
|
for chaine in [ 'ADMIN_VLAN', 'EXT_VERS_SERVEURS', 'SERVEURS_VERS_EXT' , 'EXT_VERS_CRANS', 'CRANS_VERS_EXT', 'BLACKLIST_SRC', 'BLACKLIST_DST' , 'FILTRE_P2P' ] :
|
||||||
iptables('-N %s' % chaine)
|
iptables('-N %s' % chaine)
|
||||||
iptables("-A FORWARD -i lo -j ACCEPT")
|
iptables("-A FORWARD -i lo -j ACCEPT")
|
||||||
|
@ -497,8 +582,67 @@ class firewall_komaz(firewall_crans) :
|
||||||
iptables("-I FORWARD -m mark --mark 2 -j ACCEPT")
|
iptables("-I FORWARD -m mark --mark 2 -j ACCEPT")
|
||||||
print OK
|
print OK
|
||||||
|
|
||||||
|
def classe_p2p_maj(self,ip_list=['138.231.137.170']) :
|
||||||
|
""" Mise à jour de la classification pour les ip fournies
|
||||||
|
On ne crée que les règles iptables pour classer les paquets, les
|
||||||
|
classes correspondantes ne sont à créer que toutes à la fois """
|
||||||
|
## Que faut-il faire ?
|
||||||
|
self.anim = anim('\tAnalyse du travail à effectuer')
|
||||||
|
if ip_list == [''] :
|
||||||
|
print OK + ' (rien à faire)'
|
||||||
|
return
|
||||||
|
|
||||||
|
maj = {}
|
||||||
|
for ip in ip_list :
|
||||||
|
machine = db.search('ip=%s'% ip)['machine']
|
||||||
|
if not machine :
|
||||||
|
# Suppression de la règle associée à la machine
|
||||||
|
maj[machine[0]] = '-'
|
||||||
|
|
||||||
|
elif len(machine) == 1 :
|
||||||
|
# Ajout de la machine
|
||||||
|
maj[machine[0]] = '+'
|
||||||
|
else :
|
||||||
|
print WARNING
|
||||||
|
if debug :
|
||||||
|
sys.stderr.write("Plusieurs machines avec l'IP %s\n" % ip)
|
||||||
|
|
||||||
|
print OK
|
||||||
|
|
||||||
|
## Traitement
|
||||||
|
# MAJ des règles de classification de l'IP
|
||||||
|
def procedure() :
|
||||||
|
self.anim = anim('\tMise à jour des classes p2p')
|
||||||
|
warn = ''
|
||||||
|
try :
|
||||||
|
for machine in maj.keys() :
|
||||||
|
adherent = machine.proprietaire()
|
||||||
|
ip = machine.ip()
|
||||||
|
subnet = ip.split('.')[2]
|
||||||
|
class_id = int(adherent.id())+1 # On ne peut pas reprendre le numéro 1
|
||||||
|
if maj[machine] == '+' :
|
||||||
|
# Il faut ajouter cette entrée
|
||||||
|
option = '-A'
|
||||||
|
else :
|
||||||
|
# Il faut supprimer cette entrée
|
||||||
|
option = '-D'
|
||||||
|
iptables("-t mangle %s SUBNET-%s_24 -o ens -s %s -m mark --mark 1 -j CLASSIFY --set-class 1:%s" % (option, subnet, ip, class_id))
|
||||||
|
iptables("-t mangle %s SUBNET-%s_24 -o crans -d %s -m mark --mark 1 -j CLASSIFY --set-class 1:%s" % (option, subnet, ip, class_id))
|
||||||
|
except IptablesError, c:
|
||||||
|
warn += str(c) + '\n'
|
||||||
|
except KeyError :
|
||||||
|
print OK
|
||||||
|
|
||||||
|
if warn :
|
||||||
|
print WARNING
|
||||||
|
sys.stdout.write(warn)
|
||||||
|
else :
|
||||||
|
print OK
|
||||||
|
|
||||||
|
self.exception_catcher(procedure)
|
||||||
|
|
||||||
def post_start_hook(self) :
|
def post_start_hook(self) :
|
||||||
self.anim = anim("\tMise en place routage")
|
self.anim = anim("\tMise en place du routage")
|
||||||
warn = ''
|
warn = ''
|
||||||
for cmd in [ 'echo 1 > /proc/sys/net/ipv4/ip_forward' ,
|
for cmd in [ 'echo 1 > /proc/sys/net/ipv4/ip_forward' ,
|
||||||
'echo 65536 > /proc/sys/net/ipv4/ip_conntrack_max' ,
|
'echo 65536 > /proc/sys/net/ipv4/ip_conntrack_max' ,
|
||||||
|
@ -515,7 +659,7 @@ class firewall_komaz(firewall_crans) :
|
||||||
print OK
|
print OK
|
||||||
|
|
||||||
def pre_stop_hook(self) :
|
def pre_stop_hook(self) :
|
||||||
self.anim = anim("\tArret routage")
|
self.anim = anim("\tArrêt du routage")
|
||||||
status,output=getstatusoutput('echo 0 > /proc/sys/net/ipv4/ip_forward')
|
status,output=getstatusoutput('echo 0 > /proc/sys/net/ipv4/ip_forward')
|
||||||
if status :
|
if status :
|
||||||
print ERREUR
|
print ERREUR
|
||||||
|
@ -523,6 +667,7 @@ class firewall_komaz(firewall_crans) :
|
||||||
print OK
|
print OK
|
||||||
|
|
||||||
def start_fw_funcs(self) :
|
def start_fw_funcs(self) :
|
||||||
|
self.exception_catcher(self.classe_p2p_maj)
|
||||||
self.exception_catcher(self.log_chaines)
|
self.exception_catcher(self.log_chaines)
|
||||||
self.exception_catcher(self.test_virus_flood)
|
self.exception_catcher(self.test_virus_flood)
|
||||||
self.exception_catcher(self.reseaux_non_routables)
|
self.exception_catcher(self.reseaux_non_routables)
|
||||||
|
@ -803,7 +948,7 @@ class firewall_zamok(firewall_crans) :
|
||||||
self.serv_out_adm()
|
self.serv_out_adm()
|
||||||
|
|
||||||
def filter_table_tweaks(self) :
|
def filter_table_tweaks(self) :
|
||||||
self.anim = anim('\tRegles specifiques a zamok')
|
self.anim = anim('\tRègles spécifiques à zamok')
|
||||||
iptables("-P INPUT ACCEPT")
|
iptables("-P INPUT ACCEPT")
|
||||||
iptables("-P FORWARD DROP")
|
iptables("-P FORWARD DROP")
|
||||||
print OK
|
print OK
|
||||||
|
@ -846,7 +991,7 @@ class firewall_rouge(firewall_crans) :
|
||||||
print OK
|
print OK
|
||||||
|
|
||||||
def filter_table_tweaks(self) :
|
def filter_table_tweaks(self) :
|
||||||
self.anim = anim('\tRegles specifiques a rouge')
|
self.anim = anim('\tRègles spécifiques à rouge')
|
||||||
iptables("-P INPUT ACCEPT")
|
iptables("-P INPUT ACCEPT")
|
||||||
iptables("-P FORWARD DROP")
|
iptables("-P FORWARD DROP")
|
||||||
print OK
|
print OK
|
||||||
|
@ -888,7 +1033,7 @@ class firewall_vert(firewall_crans) :
|
||||||
print OK
|
print OK
|
||||||
|
|
||||||
def filter_table_tweaks(self) :
|
def filter_table_tweaks(self) :
|
||||||
self.anim = anim('\tRegles specifiques a vert')
|
self.anim = anim('\tRègles spécifiques à vert')
|
||||||
iptables("-P INPUT ACCEPT")
|
iptables("-P INPUT ACCEPT")
|
||||||
iptables("-P FORWARD DROP")
|
iptables("-P FORWARD DROP")
|
||||||
print OK
|
print OK
|
||||||
|
@ -908,11 +1053,11 @@ class firewall_sila(firewall_rouge):
|
||||||
firewall_bleu = firewall_zamok
|
firewall_bleu = firewall_zamok
|
||||||
|
|
||||||
if __name__ == '__main__' :
|
if __name__ == '__main__' :
|
||||||
# Chaines pouvant être recontruites
|
# Chaînes pouvant être recontruites
|
||||||
fw = eval('firewall_%s()' % hostname)
|
fw = eval('firewall_%s()' % hostname)
|
||||||
chaines = []
|
chaines = []
|
||||||
for nom in dir(fw) :
|
for nom in dir(fw) :
|
||||||
if nom in [ 'log_chaines' , 'test_virus_flood', 'reseaux_non_routables', 'test_mac_ip' , 'blacklist' , 'ext_vers_serveurs' , 'serveurs_vers_ext', 'ext_vers_crans', 'crans_vers_ext' , 'filtre_p2p', 'admin_vlan' , 'serv_out_adm'] :
|
if nom in [ 'log_chaines' , 'test_virus_flood', 'reseaux_non_routables', 'test_mac_ip' , 'blacklist' , 'ext_vers_serveurs' , 'serveurs_vers_ext', 'ext_vers_crans', 'crans_vers_ext' , 'filtre_p2p', 'admin_vlan' , 'serv_out_adm', 'mangle_table', 'classe_p2p_maj'] :
|
||||||
chaines.append(nom)
|
chaines.append(nom)
|
||||||
|
|
||||||
def __usage(txt=None) :
|
def __usage(txt=None) :
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue