[firewall4] Séparation en plusieurs fichiers
En gros, un par pare feu
This commit is contained in:
parent
964abdd565
commit
2d2cbf2d9f
8 changed files with 1335 additions and 1268 deletions
251
gestion/gen_confs/firewall4/utils.py
Normal file
251
gestion/gen_confs/firewall4/utils.py
Normal file
|
@ -0,0 +1,251 @@
|
|||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
import os
|
||||
import sys
|
||||
|
||||
if '/usr/scripts/' not in sys.path:
|
||||
sys.path.append('/usr/scripts/')
|
||||
|
||||
import syslog
|
||||
import subprocess
|
||||
|
||||
from gestion.affich_tools import anim, OK, cprint
|
||||
from gestion.iptools import AddrInNet, NetSubnets, IpSubnet, NetInNets
|
||||
|
||||
import lc_ldap.shortcuts
|
||||
import lc_ldap.objets
|
||||
import lc_ldap.attributs
|
||||
|
||||
squeeze = os.uname()[2] < '3'
|
||||
|
||||
#: Chaines par défaut d'iptables
|
||||
default_chains = ['INPUT', 'OUTPUT', 'FORWARD', 'PREROUTING', 'POSTROUTING']
|
||||
#: Tables d'iptables
|
||||
tables = ['raw', 'mangle', 'filter', 'nat']
|
||||
|
||||
|
||||
def pretty_print(table, chain):
|
||||
"""Affiche quelle chaine est en train d'être construite dans quelle table de NetFilter"""
|
||||
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_tools(object) :
|
||||
"""Classe de base du pare-feu implémentant l'association mac-ip (pour les machines filaires) et les blacklists hard"""
|
||||
|
||||
def machines(self):
|
||||
"""Renvois la liste de toutes les machines"""
|
||||
if self._machines:
|
||||
return self._machines
|
||||
self._machines, self._adherents = self.conn.allMachinesAdherents()
|
||||
return self._machines
|
||||
|
||||
def adherents(self):
|
||||
"""Renvois la liste de tous les adhérents"""
|
||||
if self._adherents:
|
||||
return self._adherents
|
||||
self._machines, self._adherents = self.conn.allMachinesAdherents()
|
||||
self._adherents = [ adh for adh in self._adherents if adh.paiement_ok ]
|
||||
return self._adherents
|
||||
|
||||
def blacklisted_machines(self):
|
||||
"""Renvois la liste de toutes les machines ayant une blackliste actives"""
|
||||
if self._blacklisted_machines:
|
||||
return self._blacklisted_machines
|
||||
self._blacklisted_machines = [ machine for machine in self.machines() if machine.blacklist_actif() ]
|
||||
return self._blacklisted_machines
|
||||
|
||||
def blacklisted_adherents(self, excepts=[]):
|
||||
"""Renvois la liste de tous les adhérents ayant une blackliste active"""
|
||||
if self._blacklisted_adherents and self._blacklisted_adherents_type == set(excepts):
|
||||
return self._blacklisted_adherents
|
||||
self._blacklisted_adherents = filter(lambda adh: adh.blacklist_actif(excepts), self.adherents())
|
||||
self._blacklisted_adherents_type = set(excepts)
|
||||
return self._blacklisted_adherents
|
||||
|
||||
def add(self, table, chain, rule):
|
||||
"""Ajoute la règle ``rule`` à la chaine ``chain`` dans la table ``table``"""
|
||||
if not chain in self.chain_list[table]:
|
||||
self.chain_list[table].append(chain)
|
||||
self.rules_list[table][chain]=[]
|
||||
self.rules_list[table][chain].append(rule)
|
||||
|
||||
def delete(self, table=None, chain=None):
|
||||
"""Supprime ``chain`` de ``table`` si fournis, sinon supprime ``table``, sinon toutes les tables"""
|
||||
if not table:
|
||||
for table in tables:
|
||||
self.delete(table, chain)
|
||||
if not chain:
|
||||
for chain in self.chain_list[table]:
|
||||
self.delete(table, chain)
|
||||
|
||||
if not chain in self.chain_list[table]:
|
||||
return
|
||||
if not chain in default_chains:
|
||||
self.chain_list[table].remove(chain)
|
||||
del(self.rules_list[table][chain])
|
||||
else:
|
||||
self.rules_list[table][chain]=[]
|
||||
|
||||
def flush(self, table=None, chain=None):
|
||||
"""Vide ``chain`` dans ``table`` si fournis, sinon vide toutes
|
||||
les chaines de ``table``, sinon vide toutes les chaines de toutes les tables"""
|
||||
if not table:
|
||||
for table in tables:
|
||||
self.flush(table, chain)
|
||||
if not chain:
|
||||
for chain in self.chain_list[table]:
|
||||
self.flush(table, chain)
|
||||
if not chain in self.chain_list[table]:
|
||||
self.chain_list[table].append(chain)
|
||||
self.rules_list[table][chain]=[]
|
||||
|
||||
def restore(self, table=None, chains=[], noflush=False):
|
||||
"""Restores les règles du pare-feu dans le noyau en appelant ``iptables-restore``.
|
||||
Si ``table`` est fournis, on ne restore que table.
|
||||
Si ``noflush`` n'est pas à ``True`` tout le contenu précédent est supprimé"""
|
||||
str=self.format(chains)
|
||||
f=open('/tmp/ipt_rules', 'w')
|
||||
f.write(str)
|
||||
f.close()
|
||||
params = ['/sbin/iptables-restore']
|
||||
if noflush:
|
||||
params.append('--noflush')
|
||||
if table and table in ['raw', 'mangle', 'filter', 'nat']:
|
||||
params.append('--table')
|
||||
params.append(table)
|
||||
p = subprocess.Popen(params , stdin=subprocess.PIPE)
|
||||
p.communicate(input=str)
|
||||
|
||||
def apply(self, table, chain):
|
||||
"""Applique les règles de ``chain`` dans ``table``"""
|
||||
if not chain in self.chain_list[table]:
|
||||
return
|
||||
self.restore(table, [chain], noflush=True)
|
||||
self.delete(table, chain)
|
||||
|
||||
def format(self, chains=[]):
|
||||
"""Transforme la structure interne des règles du pare-feu en celle comprise par ``iptables-restore``"""
|
||||
str = ''
|
||||
for table in self.chain_list.keys():
|
||||
str += '*%s\n' % table
|
||||
for chain in self.chain_list[table]:
|
||||
if not chains or chain in chains or chain in default_chains:
|
||||
str += ':%s %s [0:0]\n' % (chain, chain in default_chains and 'ACCEPT' or '-')
|
||||
for chain in self.chain_list[table]:
|
||||
if not chains or chain in chains :
|
||||
for rule in self.rules_list[table][chain]:
|
||||
str += '-A %s %s\n' % (chain, rule)
|
||||
str += 'COMMIT\n'
|
||||
return str
|
||||
|
||||
def reload(self, func_name):
|
||||
if squeeze and self.reloadable[func_name] in self.use_ipset:
|
||||
anim('\tVidage de %s' % self.reloadable[func_name]())
|
||||
for table in ['raw', 'mangle', 'filter', 'nat']:
|
||||
self.flush(table, self.reloadable[func_name]())
|
||||
self.restore(noflush=True)
|
||||
print OK
|
||||
|
||||
for table in ['raw', 'mangle', 'filter', 'nat']:
|
||||
self.reloadable[func_name](table)
|
||||
if self.reloadable[func_name] in self.use_ipset:
|
||||
self.reloadable[func_name](fill_ipset=True)
|
||||
if self.reloadable[func_name] in self.use_tc:
|
||||
self.reloadable[func_name](run_tc=True)
|
||||
|
||||
anim('\tRestoration d\'iptables')
|
||||
self.restore(noflush=True)
|
||||
print OK
|
||||
|
||||
def __init__(self):
|
||||
#initialisation des structures communes : récupération des ipset
|
||||
if os.getuid() != 0:
|
||||
from affich_tools import coul
|
||||
sys.stderr.write(coul("Il faut être root pour utiliser le firewall\n", 'gras'))
|
||||
sys.exit(1)
|
||||
|
||||
# Connection à la base ldap
|
||||
self.conn = lc_ldap.shortcuts.lc_ldap_admin(user=u'firewall')
|
||||
|
||||
self.reloadable = {}
|
||||
|
||||
self.use_ipset = []
|
||||
self.use_tc = []
|
||||
|
||||
self._machines = None
|
||||
self._adherents = None
|
||||
self._blacklisted_machines = None
|
||||
self._blacklisted_adherents = None
|
||||
|
||||
self.chain_list={
|
||||
'raw':['OUTPUT', 'PREROUTING'],
|
||||
'mangle':['INPUT', 'OUTPUT', 'FORWARD', 'PREROUTING', 'POSTROUTING'],
|
||||
'filter':['INPUT', 'OUTPUT', 'FORWARD'],
|
||||
'nat':['OUTPUT', 'PREROUTING', 'POSTROUTING']
|
||||
}
|
||||
self.rules_list = {
|
||||
'raw': { 'OUTPUT':[], 'PREROUTING':[] },
|
||||
'mangle':{'INPUT':[], 'OUTPUT':[], 'FORWARD':[], 'PREROUTING':[], 'POSTROUTING':[]},
|
||||
'filter':{'INPUT':[], 'OUTPUT':[], 'FORWARD':[]},
|
||||
'nat':{'OUTPUT':[], 'PREROUTING':[], 'POSTROUTING':[]}
|
||||
}
|
||||
|
||||
self.ipset={}
|
||||
|
||||
|
||||
|
||||
def start(self):
|
||||
"""Démarre le pare-feu : génère les règles, puis les restore"""
|
||||
anim('\tChargement des machines')
|
||||
self.machines()
|
||||
self.blacklisted_machines()
|
||||
print OK
|
||||
|
||||
if squeeze:
|
||||
anim('\tVidage du pare-feu')
|
||||
self.restore()
|
||||
print OK
|
||||
|
||||
self.raw_table()
|
||||
self.mangle_table()
|
||||
self.filter_table()
|
||||
self.nat_table()
|
||||
|
||||
anim('\tRestoration d\'iptables')
|
||||
self.restore()
|
||||
print OK
|
||||
return
|
||||
|
||||
def stop(self):
|
||||
"""Vide les règles du pare-feu"""
|
||||
self.delete()
|
||||
self.restore()
|
||||
return
|
||||
|
||||
def restart(self):
|
||||
"""Alias de :py:func:`start`"""
|
||||
self.start()
|
||||
return
|
||||
|
Loading…
Add table
Add a link
Reference in a new issue