From f07999af6a11692e048934d1ba016800fd99e678 Mon Sep 17 00:00:00 2001 From: Valentin Samir Date: Sat, 6 Apr 2013 14:46:35 +0200 Subject: [PATCH] [firewall4] Ajout de la QoS sur komaz --- gestion/gen_confs/firewall4.py | 108 +++++++++++++++++++++++++++++++-- 1 file changed, 104 insertions(+), 4 deletions(-) diff --git a/gestion/gen_confs/firewall4.py b/gestion/gen_confs/firewall4.py index 22b0b558..a7a3fdb7 100755 --- a/gestion/gen_confs/firewall4.py +++ b/gestion/gen_confs/firewall4.py @@ -16,7 +16,8 @@ import socket from ipset import IpsetError, Ipset from iptools import AddrInNet, NetSubnets, IpSubnet, NetInNets import subprocess -from affich_tools import * +import syslog +from affich_tools import anim, OK, cprint squeeze = os.uname()[2] < '3' @@ -31,6 +32,29 @@ dev = hostname in config.firewall.dev.keys() and config.firewall.dev[hostname] o def pretty_print(table, chain): anim('\t%s dans %s' % (chain, table)) + +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 tc(cmd, block=True): + """ Interface de tc """ + params = ['/sbin/tc'] + params.extend(cmd.split()) + p = subprocess.Popen(params , stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE) + if block: + status = p.wait() + stdoutdata, stderrdata = p.communicate() + if status: + raise TcError(' '.join(params), status, stdoutdata + stderrdata) + return stdoutdata + stderrdata + class firewall_base(object) : def machines(self): @@ -145,6 +169,7 @@ class firewall_base(object) : } self.use_ipset = [self.blacklist_hard, self.test_mac_ip] + self.use_tc = [] self._machines = None self._adherents = None @@ -374,9 +399,11 @@ class firewall_komaz(firewall_base): 'blacklist_soft' : self.blacklist_soft, 'reseaux_non_routable' : self.reseaux_non_routable, 'filtrage_ports' : self.filtrage_ports, + 'limitation_debit' : self.limitation_debit, }) self.use_ipset.extend([self.blacklist_soft, self.reseaux_non_routable]) + self.use_tc.extend([self.limitation_debit]) self.ipset['reseaux_non_routable'] = { 'deny' : Ipset("RESEAUX-NON-ROUTABLE-DENY","nethash"), @@ -396,9 +423,9 @@ class firewall_komaz(firewall_base): self.add(table, chain, '-j %s' % self.connexion_secours(table)) self.add(table, chain, '-p tcp -j CONNMARK --restore-mark') - chain = 'POSTROUNTING' + chain = 'POSTROUTING' self.add(table, chain, '-j %s' % self.clamp_mss(table)) - #TODO QoS + self.add(table,chain, '-j %s' % self.limitation_debit(table, run_tc=True)) return def filter_table(self): @@ -695,6 +722,77 @@ class firewall_komaz(firewall_base): self.apply(table, chain) return chain + def limitation_debit(self, table=None, run_tc=False, apply=False): + chain = 'LIMITATION-DEBIT' + + debit_max = config.firewall.debit_max + uplink_speed = '1024mbit' + + if table == 'mangle': + pretty_print(table, chain) + self.add(table, chain, '-d 138.231.136.98 -j RETURN') + self.add(table, chain, '-s 138.231.136.98 -j RETURN') + + # Classification par defaut pour tous les paquets + for net in NETs['all']: + self.add(table, chain, '-o %s -s %s -j CLASSIFY --set-class 1:10' % (dev['out'], net)) + self.add(table, chain, '-o %s -d %s -j CLASSIFY --set-class 1:10' % (dev['fil'], net)) + self.add(table, chain, '-o %s -d %s -j CLASSIFY --set-class 1:10' % (dev['wifi'], net)) + + # Classification pour les appartements + for net in NETs['personnel-ens']: + self.add(table, chain, '-o %s -d %s -j CLASSIFY --set-class 1:3' % (dev['app'], net)) + self.add(table, chain, '-o %s -s %s -j CLASSIFY --set-class 1:2' % (dev['out'], net)) + print OK + + if run_tc: + anim('\tApplication des commandes tc') + for int_key in ['out', 'fil', 'wifi']: + try: + tc('qdisc del dev %s root' % dev[int_key]) + except TcError: + pass + tc('qdisc add dev %s root handle 1: htb r2q 1' % dev[int_key]) + tc("class add dev %s parent 1: classid 1:1 " + "htb rate %s ceil %s" % (dev[int_key], uplink_speed, uplink_speed)) + tc("class add dev %s parent 1:1 classid 1:2 " + "htb rate %skbps ceil %skbps" % (dev[int_key], debit_max, debit_max)) + + # Classe par defaut + tc('class add dev %s parent 1:2 classid 1:10 ' + 'htb rate %skbps ceil %skbps prio 1' % (dev[int_key], debit_max, debit_max)) + tc('qdisc add dev %s parent 1:10 ' + 'handle 10: sfq perturb 10' % dev[int_key]) + tc('filter add dev %s protocol all parent 10: handle 10 flow hash keys src perturb 30 divisor 1024 baseclass 1:10' % dev[int_key]) + + for int_key in ['app']: + try: + tc('qdisc del dev %s root' % dev[int_key]) + except TcError: + pass + tc('qdisc add dev %s root handle 1: htb r2q 1' % dev[int_key]) + + tc("class add dev %s parent 1: classid 1:1 " + "htb rate 128kbps ceil 128kbps" % dev[int_key]) + + # Classe pour l'upload des appartements + tc("class add dev %s parent 1:1 classid 1:2 " + "htb rate 128kbps ceil 128kbps" % dev[int_key]) + tc('qdisc add dev %s parent 1:2 ' + 'handle 2: sfq perturb 10' % dev[int_key]) + + # Classe pour le download des apparetments + tc("class add dev %s parent 1: classid 1:3 " + "htb rate %skbps ceil %skbps" % (dev[int_key], debit_max/10, debit_max/2)) + tc('qdisc add dev %s parent 1:3 ' + 'handle 3: sfq perturb 10' % dev[int_key]) + + print OK + + if apply: + self.apply(table, chain) + return chain + if __name__ == '__main__' : firewall = { @@ -751,7 +849,9 @@ Pour reconfiguration d'IPs particulières, utiliser generate. """ % \ fw.reloadable[arg](table) if fw.reloadable[arg] in fw.use_ipset: fw.reloadable[arg](fill_ipset=True) + if fw.reloadable[arg] in fw.use_tc: + fw.reloadable[arg](run_tc=True) anim('\tRestoration d\'iptables') fw.restore(noflush=True) - print OK \ No newline at end of file + print OK