[firewall4] Ajout de la QoS sur komaz

This commit is contained in:
Valentin Samir 2013-04-06 14:46:35 +02:00
parent 88ba72332a
commit f07999af6a

View file

@ -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
print OK