[firewall4, generate] Documentation
This commit is contained in:
parent
fcda8784c9
commit
703bf964a9
3 changed files with 72 additions and 28 deletions
|
@ -7,11 +7,6 @@ import sys
|
|||
sys.path.append('/usr/scripts/gestion')
|
||||
sys.path.append('/usr/scripts/lc_ldap')
|
||||
|
||||
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)
|
||||
|
||||
from config import NETs, blacklist_sanctions, blacklist_sanctions_soft, mac_komaz, mac_titanic, adm_users, accueil_route
|
||||
|
||||
import pwd
|
||||
|
@ -26,15 +21,21 @@ from affich_tools import anim, OK, cprint
|
|||
|
||||
squeeze = os.uname()[2] < '3'
|
||||
|
||||
#: Connection à labase ldap
|
||||
conn = lc_ldap.lc_ldap_admin()
|
||||
#: Nom de la machine exécutant le script
|
||||
hostname = socket.gethostname()
|
||||
|
||||
#: Chaines par défaut d'iptables
|
||||
default_chains = ['INPUT', 'OUTPUT', 'FORWARD', 'PREROUTING', 'POSTROUTING']
|
||||
#: Tables d'iptables
|
||||
tables = ['raw', 'mangle', 'filter', 'nat']
|
||||
|
||||
#: Association des interfaces de ``hostname``
|
||||
dev = hostname in config.firewall.dev.keys() and config.firewall.dev[hostname] or {}
|
||||
|
||||
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))
|
||||
|
||||
|
||||
|
@ -61,14 +62,17 @@ def tc(cmd, block=True):
|
|||
return stdoutdata + stderrdata
|
||||
|
||||
class firewall_base(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 = 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 = conn.allMachinesAdherents()
|
||||
|
@ -76,6 +80,7 @@ class firewall_base(object) :
|
|||
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
|
||||
if self._machines:
|
||||
|
@ -93,18 +98,21 @@ class firewall_base(object) :
|
|||
return self._blacklisted_machines
|
||||
|
||||
def blacklisted_adherents(self):
|
||||
"""Renvois la liste de tous les adhérents ayant une blackliste active"""
|
||||
if self._blacklisted_adherents:
|
||||
return self._blacklisted_adherents
|
||||
self._blacklisted_adherents = filter(lambda adh: adh.blacklist_actif(), self.adherents())
|
||||
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)
|
||||
|
@ -121,6 +129,8 @@ class firewall_base(object) :
|
|||
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)
|
||||
|
@ -132,6 +142,9 @@ class firewall_base(object) :
|
|||
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)
|
||||
|
@ -146,12 +159,14 @@ class firewall_base(object) :
|
|||
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
|
||||
|
@ -167,6 +182,11 @@ class firewall_base(object) :
|
|||
|
||||
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)
|
||||
|
||||
|
||||
self.reloadable = {
|
||||
'blacklist_hard' : self.blacklist_hard,
|
||||
|
@ -210,7 +230,7 @@ class firewall_base(object) :
|
|||
|
||||
|
||||
def start(self):
|
||||
# On precache avant tout la liste des machines et des adhérents, on en aura besoin
|
||||
"""Démarre le pare-feu : génère les règles, puis les restore"""
|
||||
anim('\tChargement des machines')
|
||||
self.machines()
|
||||
print OK
|
||||
|
@ -231,27 +251,32 @@ class firewall_base(object) :
|
|||
return
|
||||
|
||||
def stop(self):
|
||||
|
||||
"""Vide les règles du pare-feu"""
|
||||
fw.delete()
|
||||
fw.restore()
|
||||
return
|
||||
|
||||
def restart(self):
|
||||
"""Alias de :py:func:`start`"""
|
||||
self.start()
|
||||
return
|
||||
|
||||
def blacklist_maj(self, ips):
|
||||
"""Met à jours les blacklists pour les ip présentent dans la liste ``ips``"""
|
||||
self.blacklist_hard_maj(ips)
|
||||
|
||||
def raw_table(self):
|
||||
"""Génère les règles pour la table ``raw`` et remplis les chaines de la table"""
|
||||
table = 'raw'
|
||||
return
|
||||
|
||||
def mangle_table(self):
|
||||
"""Génère les règles pour la table ``mangle`` et remplis les chaines de la table"""
|
||||
table = 'mangle'
|
||||
return
|
||||
|
||||
def filter_table(self):
|
||||
"""Génère les règles pour la table ``filter`` et remplis les chaines de la table"""
|
||||
table = 'filter'
|
||||
|
||||
mac_ip_chain = self.test_mac_ip(table, fill_ipset=True)
|
||||
|
@ -271,6 +296,7 @@ class firewall_base(object) :
|
|||
return
|
||||
|
||||
def nat_table(self):
|
||||
"""Génère les règles pour la table ``nat`` et remplis les chaines de la table"""
|
||||
table = 'nat'
|
||||
return
|
||||
|
||||
|
@ -278,6 +304,7 @@ class firewall_base(object) :
|
|||
|
||||
|
||||
def blacklist_hard_maj(self, ip_list):
|
||||
"""Met à jour les blacklists hard, est appelée par :py:func:`blacklist_maj`"""
|
||||
for ip in ip_list:
|
||||
machine = conn.search("ipHostNumber=%s" % ip)
|
||||
# Est-ce qu'il y a des blacklists hard parmis les blacklists de la machine
|
||||
|
@ -289,6 +316,9 @@ class firewall_base(object) :
|
|||
except IpsetError: pass
|
||||
|
||||
def blacklist_hard(self, table=None, fill_ipset=False, apply=False):
|
||||
"""Génère la chaine ``BLACKLIST_HARD``.
|
||||
Si ``fill_ipset`` est à ``True``, remplis l'ipset ``BLACKLIST-HARD``.
|
||||
Si ``apply`` est à True, applique directement les règles"""
|
||||
chain = 'BLACKLIST_HARD'
|
||||
|
||||
if fill_ipset:
|
||||
|
@ -317,7 +347,7 @@ class firewall_base(object) :
|
|||
return chain
|
||||
|
||||
def test_mac_ip_dispatch(self, func, machine):
|
||||
"""Détermine à quel set de mac-ip appliquer la fonction func (add, delete, append, ...)"""
|
||||
"""Détermine à quel set de mac-ip appliquer la fonction ``func`` (add, delete, append, ...)"""
|
||||
ips = machine['ipHostNumber']
|
||||
for ip in ips:
|
||||
# Si la machines est sur le réseau des adhérents
|
||||
|
@ -331,6 +361,9 @@ class firewall_base(object) :
|
|||
func('adm', "%s,%s" % (ip, machine['macAddress'][0]))
|
||||
|
||||
def test_mac_ip(self, table=None, fill_ipset=False, apply=False):
|
||||
"""Génère la chaine ``TEST_MAC-IP``.
|
||||
Si ``fill_ipset`` est à ``True``, remplis les ipsets ``MAC-IP-ADH``, ``MAC-IP-ADM``, ``MAC-IP-ADM``.
|
||||
Si ``apply`` est à True, applique directement les règles"""
|
||||
chain = 'TEST_MAC-IP'
|
||||
|
||||
if fill_ipset:
|
||||
|
@ -369,6 +402,7 @@ class firewall_base(object) :
|
|||
return chain
|
||||
|
||||
def mac_ip_maj(self, ip_list):
|
||||
"""Met à jour la correspondance mac-ip"""
|
||||
for ip in ip_list:
|
||||
machine = conn.search("ipHostNumber=%s" % ip)
|
||||
if machine:
|
||||
|
@ -523,6 +557,7 @@ class firewall_komaz(firewall_base):
|
|||
return
|
||||
|
||||
def clamp_mss(self, table=None, apply=False):
|
||||
"""Force la MSS (Max Segment Size) TCP à rentrer dans la MTU (Max Transfert Unit)"""
|
||||
chain = 'CLAMP-MSS'
|
||||
if table == 'mangle':
|
||||
pretty_print(table, chain)
|
||||
|
@ -535,10 +570,8 @@ class firewall_komaz(firewall_base):
|
|||
return chain
|
||||
|
||||
def ingress_filtering(self, table=None, apply=False):
|
||||
"""
|
||||
Pour ne pas router les paquêtes n'appartenant pas à notre plage ip voulant sortir de notre réseau
|
||||
et empêcher certain type de spoof (cf http://travaux.ovh.net/?do=details&id=5183)
|
||||
"""
|
||||
"""Pour ne pas router les paquêtes n'appartenant pas à notre plage ip voulant sortir de notre réseau
|
||||
et empêcher certain type de spoof (cf http://travaux.ovh.net/?do=details&id=5183)"""
|
||||
chain = 'INGRESS_FILTERING'
|
||||
if table == 'filter':
|
||||
pretty_print(table, chain)
|
||||
|
@ -559,6 +592,7 @@ class firewall_komaz(firewall_base):
|
|||
return chain
|
||||
|
||||
def ssh_on_https(self, table=None, apply=False):
|
||||
"""Pour faire fonctionner ssh2.crans.org"""
|
||||
chain = 'SSH2'
|
||||
|
||||
if table == 'nat':
|
||||
|
@ -572,6 +606,7 @@ class firewall_komaz(firewall_base):
|
|||
return chain
|
||||
|
||||
def connexion_secours(self, table=None, apply=False):
|
||||
"""Redirige les paquets vers un proxy lorsqu'on est en connexion de secours"""
|
||||
chain = 'CONNEXION-SECOURS'
|
||||
|
||||
if table == 'mangle':
|
||||
|
@ -596,6 +631,7 @@ class firewall_komaz(firewall_base):
|
|||
return chain
|
||||
|
||||
def connexion_appartement(self, table=None, apply=False):
|
||||
"""PNAT les appartements derrière appartement.crans.org"""
|
||||
chain = 'CONNEXION-APPARTEMENT'
|
||||
|
||||
if table == 'nat':
|
||||
|
@ -628,6 +664,7 @@ class firewall_komaz(firewall_base):
|
|||
except IpsetError: pass
|
||||
|
||||
def blacklist_soft(self, table=None, fill_ipset=False, apply=False):
|
||||
"""Redirige les gens blacklisté vers le portail captif"""
|
||||
chain = 'BLACKLIST_SOFT'
|
||||
|
||||
if fill_ipset:
|
||||
|
@ -670,6 +707,7 @@ class firewall_komaz(firewall_base):
|
|||
return chain
|
||||
|
||||
def reseaux_non_routable(self, table=None, fill_ipset=False, apply=False):
|
||||
"""Bloque les réseaux non routables autres que ceux utilisés par le crans"""
|
||||
chain = 'RESEAUX_NON_ROUTABLES'
|
||||
|
||||
if fill_ipset:
|
||||
|
@ -695,6 +733,7 @@ class firewall_komaz(firewall_base):
|
|||
self.filtrage_ports('filter', apply=True)
|
||||
|
||||
def filtrage_ports(self, table=None, apply=False):
|
||||
"""Ouvre les ports vers et depuis les machines du réseau crans"""
|
||||
chain = 'FILTRAGE-PORTS'
|
||||
|
||||
def format_port(port):
|
||||
|
@ -745,6 +784,7 @@ class firewall_komaz(firewall_base):
|
|||
return chain
|
||||
|
||||
def limitation_debit(self, table=None, run_tc=False, apply=False):
|
||||
"""Limite le débit de la connexion selon l'agréement avec l'ENS"""
|
||||
chain = 'LIMITATION-DEBIT'
|
||||
|
||||
debit_max = config.firewall.debit_max
|
||||
|
@ -896,7 +936,8 @@ class firewall_zamok(firewall_base):
|
|||
print OK
|
||||
|
||||
def blacklist_output(self, table=None, apply=False):
|
||||
chain='BLACKLIST'
|
||||
"""Empêche les gens blacklisté d'utiliser zamok comme relaie"""
|
||||
chain='BLACKLIST-OUTPUT'
|
||||
|
||||
if table == 'filter':
|
||||
self.add(table, chain, '-d 127.0.0.1/8 -j ACCEPT')
|
||||
|
@ -954,6 +995,7 @@ class firewall_routeur(firewall_base):
|
|||
return
|
||||
|
||||
def portail_captif_route(self, table=None, apply=False):
|
||||
"""PNAT les (ip,port) à laisser passer à travers le portail captif"""
|
||||
chain = 'CAPTIF-ROUTE'
|
||||
|
||||
if table == 'filter':
|
||||
|
@ -979,6 +1021,7 @@ class firewall_routeur(firewall_base):
|
|||
return chain
|
||||
|
||||
def portail_captif(self, table=None, apply=False):
|
||||
"""Redirige vers le portail captif"""
|
||||
chain = 'PORTAIL-CAPTIF'
|
||||
|
||||
if table == 'nat':
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue