[firewall4, generate] Documentation
This commit is contained in:
parent
fcda8784c9
commit
703bf964a9
3 changed files with 72 additions and 28 deletions
|
@ -4,7 +4,7 @@
|
|||
""" Variables de configuration pour le firewall """
|
||||
|
||||
import datetime
|
||||
|
||||
#: Interfaces réseaux des machines ayant un pare-feu particulié
|
||||
dev = {
|
||||
'komaz': {
|
||||
'out' : 'ens',
|
||||
|
@ -51,12 +51,13 @@ else:
|
|||
#: Est-ce qu'on est en connexion de jour ou de nuit/week-end ?
|
||||
debit_jour = False
|
||||
|
||||
|
||||
#: Liste des réseaux non routables
|
||||
reseaux_non_routables = [ '10.0.0.0/8', '172.16.0.0/12','198.18.0.0/15',
|
||||
'169.254.0.0/16', '192.168.0.0/16', '224.0.0.0/4', '100.64.0.0/10',
|
||||
'0.0.0.0/8','127.0.0.0/8','192.0.2.0/24','198.51.100.0/24','203.0.113.0/24',
|
||||
]
|
||||
|
||||
#: Ports ouverts à défaut pour les adhérents dans le pare-feu
|
||||
ports_default = {
|
||||
'tcp' : {
|
||||
'input' : [ '22' ],
|
||||
|
|
|
@ -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':
|
||||
|
|
|
@ -4,14 +4,14 @@
|
|||
# Copyright (C) Frédéric Pauget
|
||||
# Licence : GPLv2
|
||||
|
||||
"""Ce script permet de lancer la reconfiguration des divers services
|
||||
|
||||
Usage: %(prog)s options
|
||||
Les options possibles sont :
|
||||
\t%(options)s
|
||||
Les options avec = doivent être suivies d'un argument. Plusieurs
|
||||
arguments peuvent être founis pour une même option, les séparer par &
|
||||
"""
|
||||
#"""Ce script permet de lancer la reconfiguration des divers services
|
||||
#
|
||||
#Usage: %(prog)s options
|
||||
#Les options possibles sont :
|
||||
#\t%(options)s
|
||||
#Les options avec = doivent être suivies d'un argument. Plusieurs
|
||||
#arguments peuvent être founis pour une même option, les séparer par &
|
||||
#"""
|
||||
|
||||
import sys, signal, os, getopt
|
||||
|
||||
|
@ -27,11 +27,6 @@ from syslog import *
|
|||
import platform
|
||||
openlog("generate")
|
||||
|
||||
# On vérifie que l'on est root
|
||||
if os.getuid() != 0:
|
||||
sys.stderr.write("Il faut être root\n")
|
||||
sys.exit(1)
|
||||
|
||||
signal.signal(signal.SIGINT, signal.SIG_IGN) # Pas de Ctrl-C
|
||||
|
||||
db = crans_ldap()
|
||||
|
@ -73,6 +68,11 @@ class base_reconfigure:
|
|||
|
||||
def __init__(self, to_do=None):
|
||||
|
||||
# On vérifie que l'on est root
|
||||
if os.getuid() != 0:
|
||||
sys.stderr.write("Il faut être root\n")
|
||||
sys.exit(1)
|
||||
|
||||
if not to_do:
|
||||
if debug:
|
||||
print 'Lecture des services à redémarrer dans la base LDAP...'
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue