
Ignore-this: 945ca164eeedf63ae960bc5a4321040 darcs-hash:20120901105646-3a55a-05e04aa63ffacc1fd37cbf064132d3414aaaf596.gz
1520 lines
61 KiB
Python
Executable file
1520 lines
61 KiB
Python
Executable file
#!/usr/bin/env python
|
|
# -*- coding: utf-8 -*-
|
|
# The authors of this code are
|
|
# Manuel Sabban <manu@feyd-rautha.org>
|
|
# Frédéric Pauget <pauget@crans.ens-cachan.fr>
|
|
# Mathieu Segaud <matt@minas-morgul.org>
|
|
# Nicolas Salles <salles@crans.org>
|
|
#
|
|
# Rewritten as inherited classes from firewall_crans
|
|
# by Mathieu Segaud <matt@minas-morgul.org>
|
|
#
|
|
# Copyright (c) 2004 Manuel Sabban, Frédéric Pauget
|
|
# Copyright (c) 2005 Mathieu Segaud
|
|
# Copyright (c) 2006 Nicolas Salles
|
|
#
|
|
# Permission to use, copy, and modify this software with or without fee
|
|
# is hereby granted, provided that this entire notice is included in
|
|
# all source code copies of any software which is or includes a copy or
|
|
# modification of this software.
|
|
#
|
|
# THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRSS OR
|
|
# IMPLIED WARRANTY. IN PARTICULAR, NONE OF THE AUTHORS MAKES ANY
|
|
# REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE
|
|
# MERCHANTABILITY OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR
|
|
# PURPOSE.
|
|
|
|
import sys
|
|
sys.path.append('/usr/scripts/gestion')
|
|
sys.path.append('/usr/scripts/lc_ldap')
|
|
|
|
import syslog
|
|
import pwd
|
|
import commands
|
|
from lock import *
|
|
from ldap_crans import crans_ldap, ann_scol, hostname
|
|
from ldap_crans import AssociationCrans, Machine, MachineWifi, BorneWifi
|
|
from affich_tools import *
|
|
from commands import getstatusoutput
|
|
from iptools import AddrInNet, NetSubnets, IpSubnet
|
|
from config import NETs, mac_komaz, mac_wifi, mac_titanic, mac_g, conf_fw, p2p, vlans, debit_max_radin, adm_users, accueil_route
|
|
from ipset import IpsetError, Ipset
|
|
from lc_ldap import lc_ldap
|
|
syslog.openlog('firewall')
|
|
|
|
debug = 1
|
|
db = crans_ldap()
|
|
QUERY=lc_ldap(uri='ldap://ldap.adm.crans.org/')
|
|
|
|
class IptablesError(Exception):
|
|
""" Gestion des erreurs d'iptables """
|
|
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)
|
|
|
|
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 iptables(cmd):
|
|
""" Interface d'iptables """
|
|
syslog.syslog(syslog.LOG_INFO,cmd)
|
|
status,output=getstatusoutput("/sbin/iptables "+cmd)
|
|
if status:
|
|
raise IptablesError(cmd,status,output)
|
|
return output
|
|
|
|
def tc(cmd):
|
|
""" Interface de tc """
|
|
syslog.syslog(syslog.LOG_INFO, cmd)
|
|
status, output = getstatusoutput("/sbin/tc " + cmd)
|
|
if status:
|
|
raise TcError(cmd, status, output)
|
|
return output
|
|
|
|
def redirect_chain(table, chain_in, chain_out, ip) :
|
|
try:
|
|
iptables("-t %s -N %s" % (table, chain_out))
|
|
except IptablesError:
|
|
iptables("-t %s -F %s" % (table, chain_out))
|
|
# On redirige les paquets de la chaîne in dans la chaîne out
|
|
iptables("-t %s -A %s -o ens -s %s -j %s" % (table, chain_in, ip, chain_out))
|
|
iptables("-t %s -A %s -o crans -d %s -j %s" % (table, chain_in, ip, chain_out))
|
|
|
|
|
|
class firewall_crans :
|
|
"""
|
|
Classe parente pour les firewalls du crans
|
|
Implémentée directement à partir du firewall de komaz, initialement
|
|
écrit par Manuel Sabban et Frédéric Pauget.
|
|
|
|
* les méthodes à surcharger pour l'implémentation eme des firewall
|
|
sont mangle_table, nat_table, filter_table, pour la préparation
|
|
du fw, start_fw_funcs pour la mise en place du filtrage.
|
|
|
|
* serveurs_maj, adh_maj_list_to_do et serveurs_maj_list_to_do,
|
|
pour la mise en place de la MAC-IP.
|
|
en particulier, adh_maj_list_to_do et serveurs_maj_list_to_do
|
|
sont factorisées pour la simple et bonne raison que les sources
|
|
de la liste to_do originale ne seront pas forcément identiques
|
|
(c'est un peu sale...)
|
|
|
|
* la classe parente contient à peu de choses prés tout ce qu'il
|
|
faut pour mettre en place un fw basique n'effectuant que la
|
|
verif MAC-IP.
|
|
"""
|
|
zone_serveur = NETs['serveurs'][0]
|
|
vlan_adm = NETs['adm'][0]
|
|
|
|
limit = " -m limit --limit 10/s --limit-burst 10 "
|
|
log_template = '-m limit --limit 1/s --limit-burst 1 -j LOG --log-level notice --log-prefix '
|
|
filtre_flood = '-m hashlimit --hashlimit 100/second --hashlimit-mode srcip,dstip,dstport --hashlimit-name flood'
|
|
|
|
machines = []
|
|
debug = 1
|
|
|
|
def exception_catcher(self,tache) :
|
|
""" Exécute la tache founie en gérant les diverses exceptions
|
|
pouvant survenir
|
|
Retourne 1 en cas d'erreur et 0 sinon """
|
|
try :
|
|
tache()
|
|
return 0
|
|
except IptablesError, c :
|
|
self.anim.reinit()
|
|
print ERREUR
|
|
if self.debug : print c
|
|
except :
|
|
self.anim.reinit()
|
|
print ERREUR
|
|
import traceback
|
|
if self.debug : traceback.print_exc()
|
|
return 1
|
|
|
|
def __machines(self) :
|
|
""" Liste des machines du crans """
|
|
return db.all_machines(graphic=True)
|
|
|
|
def __init__(self) :
|
|
""" Pose un lock """
|
|
make_lock('firewall')
|
|
self.mac_ip_set = Ipset("MAC-IP","macipmap","--from 138.231.136.0 --to 138.231.151.255")
|
|
self.mac_ip_adm_set = Ipset("MAC-IP-ADM","macipmap","--from 10.231.136.0 --to 10.231.136.255")
|
|
try:
|
|
self.mac_ip_set.list()
|
|
except IpsetError:
|
|
self.mac_ip_set.create()
|
|
try:
|
|
self.mac_ip_adm_set.list()
|
|
except IpsetError:
|
|
self.mac_ip_adm_set.create()
|
|
|
|
def __del__(self) :
|
|
""" Destruction du lock """
|
|
# Comprend pas pourquoi il faut réimporter ici -- Fred
|
|
from lock import remove_lock
|
|
remove_lock('firewall')
|
|
|
|
def reload_qos(self):
|
|
"""Recherche la QoS"""
|
|
return
|
|
|
|
def mangle_table(self) :
|
|
""" Remplit la table mangle """
|
|
return
|
|
|
|
def nat_table(self) :
|
|
""" Remplit la table nat """
|
|
return
|
|
|
|
def filter_table(self) :
|
|
""" Remplit la table filter """
|
|
self.anim = anim('\tStructure de la table filter')
|
|
print OK
|
|
|
|
def filter_table_tweaks(self) :
|
|
""" Complete la table filter """
|
|
return
|
|
|
|
def start_fw_funcs(self) :
|
|
""" Ordonnance la construction du firewall """
|
|
self.exception_catcher(self.test_mac_ip)
|
|
|
|
def post_start_hook(self) :
|
|
""" Hook de fin de demarrage """
|
|
return
|
|
|
|
def pre_stop_hook(self) :
|
|
""" Hook de debut d'arret """
|
|
return
|
|
|
|
def restart(self):
|
|
""" Rédémarrage du firewall """
|
|
cprint(u'Redémarrage firewall', 'gras')
|
|
self.start(False)
|
|
|
|
def start(self,aff_txt_intro=True) :
|
|
""" Construction du firewall
|
|
aff_txt_intro s'occupe uniquement de l'esthétisme
|
|
"""
|
|
if aff_txt_intro: cprint(u'Démarrage firewall', 'gras')
|
|
# Préliminaires
|
|
if not self.__machines() or self.exception_catcher(self.__stop) :
|
|
cprint(u"Abandon", 'rouge')
|
|
return
|
|
|
|
# Initialisation
|
|
self.exception_catcher(self.mangle_table)
|
|
self.exception_catcher(self.nat_table)
|
|
self.exception_catcher(self.filter_table)
|
|
self.exception_catcher(self.filter_table_tweaks)
|
|
|
|
# Remplissage
|
|
self.start_fw_funcs()
|
|
|
|
# On peux router
|
|
self.post_start_hook()
|
|
cprint(u"\t -> fin de la procédure de démarrage",'vert')
|
|
|
|
def stop(self):
|
|
""" Arrête le firewall """
|
|
cprint(u"Arrêt du firewall", 'gras')
|
|
self.pre_stop_hook()
|
|
self.exception_catcher(self.__stop)
|
|
cprint(u"\t -> fin de la procédure d'arrêt",'vert')
|
|
|
|
def __stop(self) :
|
|
self.anim = anim("\tSuppression des règles")
|
|
iptables("-t nat -P PREROUTING ACCEPT")
|
|
iptables("-F")
|
|
iptables("-t nat -F")
|
|
iptables("-t mangle -F")
|
|
iptables("-X")
|
|
iptables("-t nat -X")
|
|
iptables("-t mangle -X")
|
|
print OK
|
|
|
|
def test_mac_ip(self):
|
|
iptables('-t filter -F TEST_MAC-IP')
|
|
self.mac_ip_gen()
|
|
iptables('-t filter -A TEST_MAC-IP -m set --match-set %s src -j RETURN' % self.mac_ip_set.set)
|
|
iptables('-t filter -A TEST_MAC-IP -m set --match-set %s src -j RETURN' % self.mac_ip_adm_set.set)
|
|
|
|
# Proxy ARP de Komaz et Titanic pour OVH
|
|
ip_ovh = db.search('host=ovh.adm.crans.org')['machineCrans'][0].ip()
|
|
iptables('-t filter -A TEST_MAC-IP -m mac -s %s --mac-source %s -j RETURN' % (ip_ovh, mac_komaz))
|
|
iptables('-t filter -A TEST_MAC-IP -m mac -s %s --mac-source %s -j RETURN' % (ip_ovh, mac_titanic))
|
|
|
|
iptables('-t filter -A TEST_MAC-IP -j DROP')
|
|
|
|
def __test_mac_ip(self, machine, flushed = False):
|
|
ip = machine.ip()
|
|
if ip.startswith("138.231.1"):
|
|
if not flushed:
|
|
try:
|
|
self.mac_ip_set.delete(ip)
|
|
except IpsetError:
|
|
pass
|
|
if machine.__class__.__name__ == "MachineWifi" and hostname != 'gordon':
|
|
# Machine Wifi, c'est la mac de gordon
|
|
self.mac_ip_set.add("%s,%s" % (ip,mac_wifi))
|
|
else:
|
|
# Machine fixe
|
|
self.mac_ip_set.add("%s,%s" % (ip,machine.mac()))
|
|
elif ip.startswith("10.231.136."):
|
|
if not flushed:
|
|
try:
|
|
self.mac_ip_adm_set.delete(ip)
|
|
except IpsetError:
|
|
pass
|
|
self.mac_ip_adm_set.add("%s,%s" % (ip,machine.mac()))
|
|
|
|
def __test_mac_ip_delete(self, ip):
|
|
if ip.startswith("138.231.1"):
|
|
try:
|
|
self.mac_ip_set.delete(ip)
|
|
except IpsetError:
|
|
pass
|
|
elif ip.startswith("10.231.136."):
|
|
try:
|
|
self.mac_ip_adm_set.delete(ip)
|
|
except IpsetError:
|
|
pass
|
|
|
|
|
|
def mac_ip_maj(self, ip_list):
|
|
for ip in ip_list:
|
|
machines=db.search("ip=%s" % ip)['machine']
|
|
if not machines:
|
|
self.__test_mac_ip_delete(ip)
|
|
else:
|
|
try:
|
|
#~ self.mac_ip_set.add("%s,%s" % (ip, machines[0].mac()))
|
|
self.__test_mac_ip(machines[0])
|
|
except IpsetError:
|
|
pass
|
|
|
|
def mac_ip_gen(self):
|
|
self.anim = anim('\tChaîne TEST_MAC-IP', len(self.__machines()))
|
|
self.mac_ip_set.flush()
|
|
self.mac_ip_adm_set.flush()
|
|
|
|
self.anim.reinit()
|
|
for machine in self.__machines():
|
|
self.anim.cycle()
|
|
self.__test_mac_ip(machine, flushed = True)
|
|
self.anim.reinit()
|
|
print OK
|
|
|
|
|
|
def serveurs_maj(self):
|
|
pass
|
|
|
|
def serveurs_maj_list_to_do(self) :
|
|
pass
|
|
|
|
def adh_maj_list_to_do(self) :
|
|
pass
|
|
|
|
def port_maj(self,ip_list) :
|
|
""" Mise à jour des ports pour les ip fournies """
|
|
# Note : système bourrin (on efface les chaînes et on refait)
|
|
# mais rapide et efficace (si qqn veut se casser le cul à
|
|
# un système aussi délicat que pour la correspondance MAC-IP...)
|
|
# -- Fred
|
|
serveur_maj = False
|
|
adh_maj = False
|
|
for ip in ip_list :
|
|
if AddrInNet(ip,self.zone_serveur) :
|
|
serveur_maj = True
|
|
else :
|
|
adh_maj = True
|
|
if serveur_maj and adh_maj :
|
|
break
|
|
to_do=[]
|
|
if serveur_maj :
|
|
self.exception_catcher(self.serveurs_maj_list_to_do)
|
|
|
|
if adh_maj :
|
|
self.exception_catcher(self.adh_maj_list_to_do)
|
|
|
|
def build_chaine_adherent(self,chaine,methode) :
|
|
# On construit d'abord les autorisations particulières
|
|
if not self.build_chaine(chaine, methode) :
|
|
# Puis si pas de problèmes les autorisations par défaut
|
|
self.anim.reinit()
|
|
for proto in [ 'tcp' , 'udp' ] :
|
|
for port in self.ports_default["%s_%s" % ( proto, chaine) ] :
|
|
self.anim.cycle()
|
|
iptables("-I %s -p %s --dport %s -j ACCEPT" % (chaine, proto,port) )
|
|
self.anim.reinit()
|
|
print OK
|
|
|
|
def build_chaine(self,chaine, methode) :
|
|
self.anim = anim('\tChaîne %s' % chaine,len(self.__machines())+1)
|
|
iptables("-F %s" % chaine)
|
|
self.anim.cycle()
|
|
def procedure() :
|
|
for machine in self.__machines() :
|
|
methode(machine)
|
|
self.anim.cycle()
|
|
iptables("-A %s -j REJECT" % chaine)
|
|
return self.exception_catcher(procedure)
|
|
|
|
|
|
"""
|
|
Komaz
|
|
"""
|
|
|
|
class firewall_komaz(firewall_crans) :
|
|
"""
|
|
Structure du firewall :
|
|
table mangle :
|
|
PREROUTING (policy par défaut : ACCEPT)
|
|
1) proxy transparent
|
|
2) marquage des paquets bittorrent
|
|
|
|
POSTROUTING (policy par défaut : ACCEPT)
|
|
1) passage dans un sous-réseau de l'ip crans : SUBNET
|
|
|
|
SUBNET classe pour chaque ip de son réseau dans la classe htb correspondante
|
|
table nat :
|
|
PREROUTING (policy par défaut : ACCEPT)
|
|
1) passage par TEST_VIRUS_FLOOD pour tout ce qui n'est pas dans zone_serveur
|
|
2) passage dans RESEAUX_NON_ROUTABLES_DST
|
|
3) passage est paquets venant de l'extérieur dans RESEAUX_NON_ROUTABLES_SRC
|
|
4) on laisse passer vers filter les paquets suivants :
|
|
source ou destination les serveurs de serveurs_crans
|
|
ce qui vient de l'extérieur
|
|
5) passage par TEST_MAC-IP
|
|
|
|
TEST_VIRUS_FLOOD droppe les paquets contenant des virus ou les paquets de flood
|
|
RESEAUX_NON_ROUTABLES_DST droppe les paquets dont la destination est non routable
|
|
RESEAUX_NON_ROUTABLES_SRC droppe les paquets dont la source est non routable
|
|
TEST_MAC-IP envoi les bon paquets vers CRANS_VERS_EXT
|
|
|
|
table filter :
|
|
FORWARD (policy par défaut : ACCEPT)
|
|
1) passage par BLACKLIST
|
|
2) passage par FILTRE_P2P (ACCEPT sur le trafic de filtres_p2p, REJECT sur le trafic de
|
|
filtres_p2p_bloq, sanctions gérées par déconnexion.py)
|
|
3) ce qui a pour source les serveurs de serveurs_crans est dirigé vers SERVEURS_VERS_EXT
|
|
4) ce qui a pour destination les serveurs de serveurs_crans est dirigé EXT_VERS_SERVEURS
|
|
5) tout ce qui vient de l'interface externe est dirigé vers EXT_VERS_CRANS
|
|
6) ce qui a pour source les serveurs de serveurs_crans est dirigé vers EXT_VERS_CRANS
|
|
|
|
BLACKLIST fitre des ip blacklistées (REJECT)
|
|
FILTRE_P2P filtre le traffic de p2p : logging des paquets matchés par les protocoles de filtres_p2p
|
|
rejet des paquets matchés par les protocoles de filtres_p2p_bloq au dessus de la limite
|
|
EXT_VERS_CRANS et CRANS_VERS_EXT
|
|
ACCEPT pour les paquets vers les machines du crans (test port-ip)
|
|
REJECT pour le reste
|
|
EXT_VERS_SERVEURS et SERVEURS_VERS_EXT
|
|
ACCEPT pour bon mac-ip-port
|
|
REJECT pour le reste
|
|
INGRESS_FILTERING : ne laisse sortir que les paquets dont l'adresse IP source appartient au crans
|
|
"""
|
|
|
|
# interfaces physiques
|
|
eth_ext = "ens"
|
|
eth_int = "crans"
|
|
eth_adm = "crans.2"
|
|
|
|
# Ports ouverts
|
|
ports_default = { 'tcp_EXT_VERS_CRANS' : [ '22' ],
|
|
'tcp_CRANS_VERS_EXT': [ ':24', '26:79', '80:134', '136', '140:444', '446:'],
|
|
'udp_EXT_VERS_CRANS' : [ ],
|
|
'udp_CRANS_VERS_EXT': [ ':136','140:'] }
|
|
|
|
|
|
ports_virus = { 'tcp' : [ 135, 445 ] , 'udp' : [] }
|
|
|
|
# Filtrage du peer to peer
|
|
# Apple et WinMX desactives car possibilite de fausse detection par ipp2p
|
|
filtres_p2p = [ #('apple', 'AppleJuice'),
|
|
('soul', 'SoulSeek'),
|
|
#('winmx', 'WinMX'),
|
|
('edk', 'eDonkey'),
|
|
('dc', 'DirectConnect'),
|
|
('kazaa', 'KaZaa'),
|
|
('ares', 'Ares'),
|
|
('bit', 'Bittorrent'),
|
|
('gnu', 'GNUtella') ]
|
|
|
|
filtres_p2p_bloq = [
|
|
]
|
|
|
|
udp_torrent_tracker={
|
|
'tracker.openbittorrent.com':[['95.215.62.26',80],['95.215.62.5',80]],
|
|
'tracker.ccc.de':[['195.54.164.83',80]],
|
|
'tracker.istole.it':[['192.121.121.30',80]],
|
|
'tracker.publicbt.com':[['95.211.88.54',80],['95.211.88.49',80],['95.211.88.51',80]],
|
|
}
|
|
|
|
|
|
ports_p2p = [ '412', '1214', '4662:4665' , '6346:6347', '6699', '6881:6889' ]
|
|
|
|
liste_reseaux_non_routables = [ '10.0.0.0/8', '172.16.0.0/12',
|
|
'169.254.0.0/16', '192.168.0.0/16', '224.0.0.0/4', '100.64.0.0/10']
|
|
|
|
def reseaux_non_routables(self) :
|
|
""" Construction de RESEAUX_NON_ROUTABLES_{DST,SRC} """
|
|
self.anim = anim('\tFiltrage ip non routables',len(self.liste_reseaux_non_routables))
|
|
iptables("-t filter -A RESEAUX_NON_ROUTABLES_DST -d 10.231.136.0/24 -j RETURN")
|
|
iptables("-t filter -A RESEAUX_NON_ROUTABLES_SRC -d 10.231.136.0/24 -j RETURN")
|
|
for reseau in self.liste_reseaux_non_routables :
|
|
iptables("-t filter -A RESEAUX_NON_ROUTABLES_DST -d %s -j DROP" % reseau)
|
|
iptables("-t filter -A RESEAUX_NON_ROUTABLES_SRC -s %s -j DROP" % reseau)
|
|
self.anim.cycle()
|
|
self.anim.reinit()
|
|
print OK
|
|
|
|
|
|
def reload_qos(self):
|
|
self.mangle_table()
|
|
self.qos()
|
|
|
|
def mangle_table(self):
|
|
|
|
self.anim = anim('\tStructure de la table mangle')
|
|
|
|
# On vide complètement la table
|
|
iptables("-t mangle -F")
|
|
iptables("-t mangle -X")
|
|
|
|
#Log de paquets
|
|
iptables('-t mangle -A PREROUTING -i %s -m state --state NEW -j LOG --log-prefix "LOG_ALL "' % self.eth_int)
|
|
iptables('-t mangle -A PREROUTING -i %s -m state --state NEW -j LOG --log-prefix "LOG_ALL "' % self.eth_ext)
|
|
|
|
# Proxy transparent
|
|
iptables("-t mangle -A PREROUTING -s %s -j RETURN" % self.zone_serveur)
|
|
#~ iptables("-t mangle -A PREROUTING -p tcp --destination-port 80 "
|
|
#~ "-s %s -d ! %s -j MARK --set-mark %s" %
|
|
#~ (NETs['fil'][0], NETs['wifi'][0], conf_fw.mark['proxy']))
|
|
#~ iptables("-t mangle -A PREROUTING -m mark --mark %s -j ACCEPT" %
|
|
#~ conf_fw.mark['proxy'])
|
|
iptables("-t mangle -N BLACKLIST_SOFT")
|
|
iptables("-t mangle -A PREROUTING -p tcp --destination-port 80 "
|
|
"-s %s -d ! %s -j BLACKLIST_SOFT" %
|
|
(NETs['fil'][0], NETs['wifi'][0]))
|
|
iptables("-t mangle -A PREROUTING -m mark --mark %s -j ACCEPT" % conf_fw.mark['proxy'])
|
|
|
|
|
|
#connection de secours
|
|
iptables("-t mangle -A PREROUTING -p tcp -s 138.231.136.0/16 ! -d 138.231.136.0/16 --destination-port 80 -m condition --condition secours -j MARK --set-mark %s" % (conf_fw.mark['secours']))
|
|
iptables("-t mangle -A PREROUTING -m mark --mark %s -j ACCEPT" % conf_fw.mark['secours'])
|
|
|
|
# Parametres pour iptables/tc
|
|
mark = conf_fw.mark['bittorrent']
|
|
debit_max = conf_fw.debit_max
|
|
debit_max_semi=debit_max/2
|
|
eth_ext = self.eth_ext
|
|
eth_int = self.eth_int
|
|
|
|
# Classification du traffic : extérieur <-> ftp
|
|
iptables("-t mangle -A POSTROUTING -o %(eth_int)s -d 138.231.136.98 "
|
|
"-j CLASSIFY --set-class 1:9997" % locals())
|
|
iptables("-t mangle -A POSTROUTING -o %(eth_ext)s -s 138.231.136.98 "
|
|
"-j CLASSIFY --set-class 1:9997" % locals())
|
|
|
|
# On marque les paquets bittorrent uniquement
|
|
iptables("-t mangle -A PREROUTING -p tcp -j CONNMARK --restore-mark")
|
|
#iptables("-t mangle -A PREROUTING -p tcp -m mark ! --mark 0x0 -j ACCEPT")
|
|
iptables("-t mangle -A PREROUTING -p tcp -m ipp2p --bit "
|
|
"-j MARK --set-mark %s" % mark)
|
|
iptables("-t mangle -A PREROUTING -p tcp -m mark --mark %s "
|
|
"-j CONNMARK --save-mark" % mark)
|
|
|
|
warn = ''
|
|
|
|
# pas de QoS pour la zone ens
|
|
iptables("-t mangle -A POSTROUTING -d 138.231.0.0/16 -s 138.231.0.0/16 -j RETURN")
|
|
# Par défaut, on envoit les paquets dans la classe 9998
|
|
for net in NETs['all']:
|
|
iptables("-t mangle -A POSTROUTING -o %(eth_int)s -d %(net)s "
|
|
"-j CLASSIFY --set-class 1:9998" % locals())
|
|
iptables("-t mangle -A POSTROUTING -o %(eth_ext)s -s %(net)s "
|
|
"-j CLASSIFY --set-class 1:9998" % locals())
|
|
|
|
# On crée les chaînes de sous-réseaux
|
|
for net in NETs['all']:
|
|
for mask in conf_fw.mask:
|
|
for subnet in NetSubnets(net, mask):
|
|
index = conf_fw.mask.index(mask)
|
|
if index == 0:
|
|
prev_chain = "POSTROUTING"
|
|
else:
|
|
ip = subnet.split('/')[0]
|
|
prev_subnet = IpSubnet(ip, conf_fw.mask[index-1])
|
|
prev_chain = "SUBNET-%s" % prev_subnet
|
|
next_chain = "SUBNET-%s" % subnet
|
|
redirect_chain('mangle', prev_chain, next_chain, subnet)
|
|
print OK
|
|
|
|
|
|
self.anim = anim('\tLimitation du debit')
|
|
adherents = db.search('paiement=ok')['adherent']
|
|
self.adherents=adherents
|
|
debit_adh = int(debit_max / float(len(adherents)))
|
|
|
|
# Création des classes et qdisc
|
|
for interface in [eth_ext, eth_int]:
|
|
# On vide les classes et qdisc
|
|
try:
|
|
tc("qdisc del dev %s root" % interface)
|
|
except TcError, c:
|
|
warn += str(c) + '\n'
|
|
# On construit les classes et qdisc de base
|
|
# La partie principale qui définit le comportement par défaut
|
|
tc("qdisc add dev %(interface)s root handle 1: htb r2q 1" % locals())
|
|
tc("class add dev %(interface)s parent 1: classid 1:1 "
|
|
"htb rate %(debit_max)skbps ceil %(debit_max)skbps" % locals())
|
|
tc("class add dev %(interface)s parent 1:1 classid 1:9999 "
|
|
"htb rate %(debit_adh)skbps ceil %(debit_adh)skbps" % locals())
|
|
tc("qdisc add dev %(interface)s parent 1:9999 "
|
|
"handle 9999: sfq perturb 10" % locals())
|
|
debit_ftp = 1000 # kbps
|
|
tc("class add dev %(interface)s parent 1:1 classid 1:9997 "
|
|
"htb rate %(debit_ftp)skbps ceil %(debit_max_semi)skbps prio 1" % locals())
|
|
tc("qdisc add dev %(interface)s parent 1:9997 "
|
|
"handle 9997: sfq perturb 10" % locals())
|
|
|
|
tc("class add dev %(interface)s parent 1:1 classid 1:9998 "
|
|
"htb rate %(debit_max_semi)skbps ceil %(debit_max)skbps prio 1" % locals())
|
|
tc("qdisc add dev %(interface)s parent 1:9998 "
|
|
"handle 9998: sfq perturb 10" % locals())
|
|
print OK
|
|
|
|
def qos(self):
|
|
|
|
if len(self.adherents) == 0 :
|
|
self.mangle_table()
|
|
|
|
# Parametres pour iptables/tc
|
|
mark = conf_fw.mark['bittorrent']
|
|
debit_max = conf_fw.debit_max
|
|
debit_max_semi=debit_max/2
|
|
eth_ext = self.eth_ext
|
|
eth_int = self.eth_int
|
|
|
|
adherents = self.adherents
|
|
debit_adh = int(debit_max / float(len(adherents)))
|
|
|
|
|
|
self.anim = anim('\tGénération des classes de QoS', len(adherents))
|
|
# On construit ensuite les classes et qdisc pour chaque adhérent
|
|
for adherent in adherents:
|
|
self.anim.cycle()
|
|
# On ne peut pas reprendre le numéro 1
|
|
class_id = int(adherent.id()) + 1
|
|
# Il nous faut un n° inférieur à 9999 unique
|
|
qdisc_id = class_id
|
|
for interface in [self.eth_ext, self.eth_int]:
|
|
tc("class add dev %(interface)s parent 1:1 classid 1:%(class_id)d "
|
|
"htb rate %(debit_adh)skbps ceil %(debit_max)skbps prio 0" % locals())
|
|
tc("qdisc add dev %(interface)s parent 1:%(class_id)d "
|
|
"handle %(qdisc_id)d: sfq perturb 10" % locals())
|
|
|
|
# Classification des adhérents dans leur classe respective
|
|
for machine in adherent.machines():
|
|
ip = machine.ip()
|
|
if not AddrInNet(ip, NETs['all']):
|
|
# Cas particulier d'une machine ayant une IP non CRANS
|
|
continue
|
|
subnet = IpSubnet(machine.ip(), conf_fw.mask[-1])
|
|
iptables("-t mangle -A SUBNET-%(subnet)s -o crans -d %(ip)s "
|
|
"-j CLASSIFY --set-class 1:%(class_id)s" % locals())
|
|
iptables("-t mangle -A SUBNET-%(subnet)s -o ens -s %(ip)s "
|
|
"-j CLASSIFY --set-class 1:%(class_id)s" % locals())
|
|
|
|
# +-----------------+
|
|
# | QOS pour le ftp |
|
|
# +-----------------+
|
|
|
|
# On ne veut pas que les gens à l'éxtérieur bouffe toute la
|
|
# bande passante.
|
|
|
|
# Classification des paquets à destination du ftp
|
|
iptables("-t mangle -A POSTROUTING -o %(eth_int)s -p tcp -d 138.231.136.98 --dport 21 "
|
|
"-j CLASSIFY --set-class 1:9997" % locals())
|
|
|
|
self.anim.reinit()
|
|
print OK
|
|
|
|
def nat_table(self) :
|
|
self.anim = anim('\tStructure de la table nat')
|
|
|
|
iptables("-t nat -P PREROUTING ACCEPT")
|
|
iptables("-t nat -P OUTPUT ACCEPT")
|
|
iptables("-t nat -A PREROUTING -p tcp -d 138.231.136.2 --dport 22 -j DNAT --to-destination 138.231.136.1:22") # redirection du ssh vers zamok
|
|
iptables("-t nat -A PREROUTING -p tcp -d 138.231.136.2 --dport 443 -j DNAT --to-destination 138.231.136.1:22") # redirection du ssh vers zamok (pour passer dans un proxy, avec corkscrew)
|
|
iptables("-t nat -A PREROUTING -i %s -j ACCEPT" % self.eth_ext )
|
|
iptables("-t nat -A PREROUTING -s %s -j ACCEPT" % self.zone_serveur )
|
|
iptables("-t nat -A PREROUTING -d %s -j ACCEPT" % self.zone_serveur )
|
|
# iptables("-t nat -A PREROUTING -i %s -p tcp --dport 80 -s ! %s -j DNAT --to-destination 138.231.136.3:81" % (self.eth_int, self.zone_serveur) )
|
|
# iptables("-t nat -A POSTROUTING -o %s -p tcp --dport 81 -s 138.231.136.0/21 -d 138.231.136.3 -j SNAT --to-source 138.231.136.4" % self.eth_int )
|
|
|
|
# Proxy transparent
|
|
iptables("-t nat -A PREROUTING -p tcp -m mark --mark %s " % conf_fw.mark['proxy'] +
|
|
"-j DNAT --to-destination 10.231.136.9:3128")
|
|
|
|
#Connection de secours
|
|
iptables("-t nat -A PREROUTING -p tcp -m mark --mark %s " % conf_fw.mark['secours'] +
|
|
"-j DNAT --to-destination 10.231.136.9:3128")
|
|
print OK
|
|
|
|
def filter_table(self) :
|
|
self.anim = anim('\tStructure de la table filter')
|
|
for chaine in [ 'TEST_MAC-IP', 'RESEAUX_NON_ROUTABLES_SRC', 'RESEAUX_NON_ROUTABLES_DST' ] :
|
|
iptables('-t filter -N %s' % chaine)
|
|
|
|
|
|
iptables("-A FORWARD -i lo -j ACCEPT")
|
|
iptables("-A FORWARD -p icmp -j ACCEPT")
|
|
iptables("-A FORWARD -i tun-ovh -j ACCEPT")
|
|
iptables("-A FORWARD -d 224.0.0.0/4 -j DROP")
|
|
#iptables("-A FORWARD -m state --state ESTABLISHED,RELATED -j ACCEPT")
|
|
for net in NETs['fil'] + NETs['wifi']:
|
|
iptables("-A FORWARD -s %s -i %s -j TEST_MAC-IP" % (net, self.eth_int))
|
|
for net in NETs['adm']:
|
|
iptables("-A FORWARD -s %s -i %s -j TEST_MAC-IP" % (net, self.eth_adm))
|
|
|
|
iptables("-A FORWARD -j RESEAUX_NON_ROUTABLES_DST")
|
|
iptables("-A FORWARD -i %s -j RESEAUX_NON_ROUTABLES_SRC" % self.eth_ext )
|
|
|
|
# Proxy transparent, pour les deconnexion soft
|
|
iptables("-A FORWARD -m mark --mark %s -j ACCEPT" % conf_fw.mark['proxy'])
|
|
|
|
#Connection de secours
|
|
# on ne peut pas faire passer https dans un proxy transparent sans faire de man in the middle et sans recompiler squid
|
|
iptables("-A FORWARD -p tcp -s 138.231.136.0/16 ! -d 138.231.136.0/16 --destination-port 443 -m condition --condition secours -j REJECT")
|
|
iptables("-A FORWARD -m mark --mark %s -j ACCEPT" % conf_fw.mark['secours'])
|
|
|
|
iptables("-P FORWARD ACCEPT")
|
|
|
|
for net in NETs['fil'] + NETs['wifi']:
|
|
iptables("-A INPUT -s %s -i %s -j TEST_MAC-IP" % (net, self.eth_int))
|
|
for net in NETs['adm']:
|
|
iptables("-A INPUT -s %s -i %s -j TEST_MAC-IP" % (net, self.eth_adm))
|
|
iptables("-P INPUT ACCEPT")
|
|
|
|
print OK
|
|
|
|
def filter_table_tweaks(self) :
|
|
self.anim = anim('\tRègles spécifiques à komaz')
|
|
for chaine in [ 'ADMIN_VLAN', 'EXT_VERS_SERVEURS', 'SERVEURS_VERS_EXT',
|
|
'EXT_VERS_CRANS', 'CRANS_VERS_EXT', 'BLACKLIST_SRC',
|
|
'BLACKLIST_DST' , 'FILTRE_P2P', 'INGRESS_FILTERING',
|
|
'TEST_VIRUS_FLOOD', 'LOG_VIRUS', 'LOG_FLOOD','LOG_TRACKER','TRACKER_FILTER' ] :
|
|
iptables('-N %s' % chaine)
|
|
iptables("-A FORWARD -i %s -j BLACKLIST_DST" % self.eth_ext )
|
|
iptables("-A FORWARD -o %s -j BLACKLIST_SRC" % self.eth_ext )
|
|
iptables("-A FORWARD -s ! %s -d ! %s -j FILTRE_P2P" % (self.zone_serveur, self.zone_serveur) )
|
|
iptables("-A FORWARD -m state --state ESTABLISHED,RELATED -j ACCEPT")
|
|
iptables("-A FORWARD -j INGRESS_FILTERING")
|
|
# on ne route pas les paquets n'appartenant pas à notre plage ip -- xhub
|
|
for net in NETs['all']:
|
|
iptables("-A INGRESS_FILTERING -o ens -s %s -j RETURN" % net)
|
|
iptables("-A INGRESS_FILTERING -o ens -j LOG --log-prefix BAD_ROUTE ")
|
|
iptables("-A INGRESS_FILTERING -o ens -j DROP")
|
|
# protection contre un certain type de spoof
|
|
# cf http://travaux.ovh.net/?do=details&id=5183 -- xhub
|
|
for net_d in NETs['all']:
|
|
for net in NETs['all']:
|
|
iptables("-A INGRESS_FILTERING -i ens -s ! %s -d %s -j RETURN" % (net,net_d))
|
|
iptables("-A INGRESS_FILTERING -i ens -j LOG --log-prefix BAD_SRC ")
|
|
iptables("-A INGRESS_FILTERING -i ens -j DROP")
|
|
iptables("-A FORWARD -i %s -d %s -j ADMIN_VLAN" % (self.eth_int, self.vlan_adm) )
|
|
iptables("-A FORWARD -i %s -d %s -j REJECT" % (self.eth_ext, self.vlan_adm) )
|
|
iptables("-A FORWARD -s ! %s -j TEST_VIRUS_FLOOD" % self.zone_serveur)
|
|
iptables("-A FORWARD -i %s -d %s -j EXT_VERS_SERVEURS" % (self.eth_ext, self.zone_serveur) )
|
|
iptables("-A FORWARD -o %s -s %s -j SERVEURS_VERS_EXT" % (self.eth_ext, self.zone_serveur) )
|
|
iptables("-A FORWARD -i %s -j EXT_VERS_CRANS" % self.eth_ext )
|
|
iptables("-A FORWARD -o %s -j CRANS_VERS_EXT" % self.eth_ext )
|
|
|
|
|
|
print OK
|
|
|
|
def classes_p2p_maj(self, ip_list):
|
|
""" Mise à jour de la classification pour les ip fournies
|
|
On ne crée que les règles iptables pour classer les paquets, les
|
|
classes correspondantes ne sont à créer que toutes à la fois """
|
|
## Que faut-il faire ?
|
|
self.anim = anim('\tAnalyse du travail à effectuer')
|
|
if ip_list == ['']:
|
|
print OK + ' (rien à faire)'
|
|
return
|
|
|
|
print OK
|
|
|
|
## Traitement
|
|
# MAJ des règles de classification de l'IP
|
|
def procedure():
|
|
self.anim = anim('\tMise à jour des classes p2p')
|
|
|
|
# Liste des classes candidates a la suppression
|
|
scheduled_del = []
|
|
warn = ''
|
|
|
|
# Parametres pour iptables/tc
|
|
mark = conf_fw.mark['bittorrent']
|
|
debit_max = conf_fw.debit_max
|
|
debit_adh = int(conf_fw.debit_max / 1200.) # XXX: guesstimate
|
|
eth_ext = self.eth_ext
|
|
eth_int = self.eth_int
|
|
|
|
try:
|
|
for ip in ip_list:
|
|
recherche = db.search('ip=%s&paiement=ok' % ip)
|
|
# Si l'ip n'appartient pas à un adhérent,
|
|
# on ne cherche pas plus loin
|
|
if not recherche['adherent']:
|
|
continue
|
|
machines = recherche['machine']
|
|
if not machines:
|
|
# Il faut supprimer cette entrée
|
|
iptables_option = '-D'
|
|
subnet = IpSubnet(ip, conf_fw.mask[-1])
|
|
all_regles = iptables("-t mangle -L SUBNET-%(subnet)s -n" % locals()).split('\n')
|
|
regles = [line for line in all_regles if ip in line]
|
|
# On sélectionne la première qui doit contenir ce que l'on veut
|
|
regle = regles[0].split()
|
|
class_id = int(regle[7].split(':')[1])
|
|
# On marque la classe comme candidate a la suppression
|
|
scheduled_del.append(class_id)
|
|
elif len(machines) == 1:
|
|
# Il faut ajouter cette entrée
|
|
iptables_option = '-A'
|
|
machine = machines[0]
|
|
adherent = machine.proprietaire()
|
|
ip = machine.ip()
|
|
subnet = IpSubnet(ip, conf_fw.mask[-1])
|
|
# On ne peut pas reprendre le numéro 1
|
|
class_id = int(adherent.id()) + 1
|
|
# On cree la classe et la qdisc s'il elles n'existent pas deja
|
|
qdisc_id = class_id
|
|
try:
|
|
for interface in [eth_ext, eth_int]:
|
|
tc("class add dev %(interface)s "
|
|
"parent 1:1 classid 1:%(class_id)d htb "
|
|
"rate %(debit_adh)s ceil %(debit_max)s" % locals())
|
|
tc("qdisc add dev %(interface)s "
|
|
"parent 1:%(class_id)d handle %(qdisc_id)d: "
|
|
"sfq perturb 10" % locals())
|
|
except TcError, e:
|
|
if "File exists" in e.output:
|
|
# La classe existe deja
|
|
pass
|
|
else:
|
|
raise e
|
|
else:
|
|
warn += "Plusieurs machines avec l'IP %s\n" % ip
|
|
# Il nous faut un n° inférieur à 9999 unique
|
|
iptables("-t mangle %(iptables_option)s SUBNET-%(subnet)s "
|
|
"-o %(eth_int)s -d %(ip)s "
|
|
"-j CLASSIFY --set-class 1:%(class_id)s" % locals())
|
|
iptables("-t mangle %(iptables_option)s SUBNET-%(subnet)s "
|
|
"-o %(eth_ext)s -s %(ip)s "
|
|
"-j CLASSIFY --set-class 1:%(class_id)s" % locals())
|
|
except IptablesError, c:
|
|
warn += str(c) + '\n'
|
|
|
|
for class_id in scheduled_del:
|
|
# TODO: supprimer les classes qui sont vraiment vides
|
|
pass
|
|
|
|
if warn:
|
|
print WARNING
|
|
sys.stdout.write(warn)
|
|
else:
|
|
print OK
|
|
|
|
self.exception_catcher(procedure)
|
|
|
|
def post_start_hook(self) :
|
|
self.anim = anim("\tMise en place du routage")
|
|
warn = ''
|
|
for cmd in [ 'echo 1 > /proc/sys/net/ipv4/ip_forward' ,
|
|
'echo 65536 > /proc/sys/net/ipv4/netfilter/ip_conntrack_max' ,
|
|
'modprobe ip_conntrack_ftp' ,
|
|
'modprobe ip_conntrack_irc' ] :
|
|
status,output=getstatusoutput(cmd)
|
|
if status :
|
|
warn += output + '\n'
|
|
if warn :
|
|
print WARNING
|
|
if self.debug :
|
|
print warn
|
|
else :
|
|
print OK
|
|
|
|
def pre_stop_hook(self) :
|
|
self.anim = anim("\tArrêt du routage")
|
|
status,output=getstatusoutput('echo 0 > /proc/sys/net/ipv4/ip_forward')
|
|
if status :
|
|
print ERREUR
|
|
else :
|
|
print OK
|
|
|
|
def start_fw_funcs(self) :
|
|
self.exception_catcher(self.log_chaines)
|
|
self.exception_catcher(self.test_virus_flood)
|
|
self.exception_catcher(self.reseaux_non_routables)
|
|
self.exception_catcher(self.blacklist)
|
|
self.exception_catcher(self.admin_vlan)
|
|
self.exception_catcher(self.serveurs_vers_ext)
|
|
self.exception_catcher(self.ext_vers_serveurs)
|
|
self.exception_catcher(self.crans_vers_ext)
|
|
self.exception_catcher(self.ext_vers_crans)
|
|
self.exception_catcher(self.test_mac_ip)
|
|
self.exception_catcher(self.filtre_p2p)
|
|
self.exception_catcher(self.qos)
|
|
|
|
def serveurs_maj_list_to_do(self) :
|
|
self.exception_catcher(self.serveurs_vers_ext)
|
|
self.exception_catcher(self.ext_vers_serveurs)
|
|
|
|
def adh_maj_list_to_do(self) :
|
|
self.exception_catcher(self.crans_vers_ext)
|
|
self.exception_catcher(self.ext_vers_crans)
|
|
|
|
def log_chaines(self) :
|
|
""" Construction des chaînes de log (LOG_VIRUS et LOG_FLOOD) """
|
|
self.anim = anim('\tCréation des chaînes de log')
|
|
for filtre in [ 'VIRUS', 'FLOOD'] :
|
|
# Vidage de la chaîne
|
|
iptables('-F LOG_%s' % filtre)
|
|
iptables('-A LOG_%s %s %s:' % (filtre, self.log_template, filtre.capitalize()) )
|
|
iptables('-A LOG_%s -j DROP' % filtre )
|
|
self.anim.cycle()
|
|
self.anim.reinit()
|
|
print OK
|
|
|
|
def test_virus_flood(self) :
|
|
""" Construction de la chaîne TEST_VIRUS """
|
|
iptables('-F TEST_VIRUS_FLOOD')
|
|
self.anim = anim('\tFiltrage virus et floods')
|
|
|
|
ip_vers = ('65.19.154.90', '208.72.168.52', '66.109.25.121', '193.37.152.88', '89.149.202.101')
|
|
for ip in ip_vers:
|
|
iptables('-A TEST_VIRUS_FLOOD -s %s -j LOG_VIRUS' % ip)
|
|
iptables('-A TEST_VIRUS_FLOOD -d %s -j LOG_VIRUS' % ip)
|
|
|
|
for proto, ports in self.ports_virus.items() :
|
|
for port in ports :
|
|
iptables('-A TEST_VIRUS_FLOOD -p %s --dport %s -j LOG_VIRUS' % (proto, port) )
|
|
self.anim.cycle()
|
|
|
|
iptables('-A TEST_VIRUS_FLOOD %s -j RETURN' % self.filtre_flood) # Les limites en négatif ca ne marche pas.
|
|
self.anim.cycle()
|
|
iptables('-A TEST_VIRUS_FLOOD -j LOG_FLOOD')
|
|
self.anim.reinit()
|
|
print OK
|
|
|
|
def serveurs_vers_ext(self) :
|
|
""" Reconstruit la chaîne SERVEURS_VERS_EXT """
|
|
if not self.build_chaine('SERVEURS_VERS_EXT', self.__serveurs_vers_ext) :
|
|
self.anim.reinit()
|
|
print OK
|
|
|
|
def ext_vers_serveurs(self) :
|
|
""" Reconstruit la chaîne EXT_VERS_SERVEURS """
|
|
if not self.build_chaine('EXT_VERS_SERVEURS', self.__ext_vers_serveurs) :
|
|
self.anim.reinit()
|
|
print OK
|
|
# Attention les règles sont à l'envers. Hint '-I'
|
|
iptables("-I EXT_VERS_SERVEURS -p tcp --dport ssh -m state --state NEW\
|
|
-m recent --name SSH --update --seconds 60 --hitcount 4 --rttl -j DROP")
|
|
iptables("-I EXT_VERS_SERVEURS -p tcp --dport ssh -m state --state NEW\
|
|
-m recent --name SSH --set")
|
|
|
|
def crans_vers_ext(self) :
|
|
""" Reconstruit la chaîne CRANS_VERS_EXT """
|
|
self.build_chaine_adherent('CRANS_VERS_EXT',self.__crans_vers_ext)
|
|
# Protocole GRE pour les VPN
|
|
iptables("-I CRANS_VERS_EXT -p gre -j ACCEPT")
|
|
|
|
def ext_vers_crans(self) :
|
|
""" Reconstruit la chaîne EXT_VERS_CRANS """
|
|
self.build_chaine_adherent('EXT_VERS_CRANS',self.__ext_vers_crans)
|
|
# Attention les règles sont à l'envers. Hint '-I'
|
|
iptables("-I EXT_VERS_CRANS -p tcp --dport ssh -m state --state NEW -j ACCEPT")
|
|
iptables("-I EXT_VERS_CRANS -p tcp --dport ssh -m state --state NEW\
|
|
-m recent --name SSH --update --seconds 60 --hitcount 4 --rttl -j DROP")
|
|
iptables("-I EXT_VERS_CRANS -p tcp --dport ssh -m state --state NEW\
|
|
-m recent --name SSH --set")
|
|
|
|
def admin_vlan(self) :
|
|
""" Reconstruit la chaîne ADMIN_VLAN """
|
|
iptables("-F ADMIN_VLAN")
|
|
#nounou_machines = []
|
|
#for adherent in db.search('droits=Nounou')['adherent'] :
|
|
# for machine in adherent.machines() :
|
|
# nounou_machines.append(machine.ip())
|
|
iptables("-A ADMIN_VLAN -j REJECT")
|
|
#self.anim = anim('\tChaîne ADMIN_VLAN', len(nounou_machines))
|
|
#for machine in nounou_machines :
|
|
# self.anim.cycle()
|
|
# iptables("-I ADMIN_VLAN -p tcp -s %s --dport ssh -j ACCEPT" % machine)
|
|
# iptables("-I ADMIN_VLAN -p tcp -s %s --dport https -j ACCEPT" % machine)
|
|
#self.anim.reinit()
|
|
#print OK
|
|
|
|
def __serveurs_vers_ext(self,machine):
|
|
ip=machine.ip()
|
|
if not AddrInNet(ip,self.zone_serveur):
|
|
# C'est une machine adhérent, rien à faire ici
|
|
return
|
|
|
|
mac = machine.mac()
|
|
ports = { 'tcp' : machine.portTCPout(),
|
|
'udp' : machine.portUDPout() }
|
|
|
|
for proto in [ 'tcp', 'udp' ] :
|
|
for port in ports[proto]:
|
|
iptables("-I SERVEURS_VERS_EXT -s %s -p %s --dport %s -m mac --mac-source %s -j ACCEPT" \
|
|
%(ip,proto,port,mac))
|
|
|
|
def __ext_vers_serveurs(self,machine):
|
|
ip=machine.ip()
|
|
if not AddrInNet(ip,self.zone_serveur):
|
|
# C'est une machine adhérent, rien à faire ici
|
|
return
|
|
|
|
ports = { 'tcp' : machine.portTCPin(),
|
|
'udp' : machine.portUDPin() }
|
|
|
|
for proto in [ 'tcp', 'udp' ] :
|
|
for port in ports[proto]:
|
|
iptables("-I EXT_VERS_SERVEURS -d %s -p %s --dport %s -j ACCEPT"\
|
|
%(ip,proto,port))
|
|
|
|
def __crans_vers_ext(self,machine):
|
|
ip=machine.ip()
|
|
if AddrInNet(ip,self.zone_serveur):
|
|
# C'est un serveur, rien à faire ici
|
|
return
|
|
|
|
ports = { 'tcp' : machine.portTCPout(),
|
|
'udp' : machine.portUDPout() }
|
|
|
|
for proto in [ 'tcp', 'udp' ] :
|
|
for port in ports[proto]:
|
|
iptables("-I CRANS_VERS_EXT -s %s -p %s --dport %s -j ACCEPT" \
|
|
%(ip,proto,port))
|
|
|
|
def __ext_vers_crans(self,machine):
|
|
ip=machine.ip()
|
|
if AddrInNet(ip,self.zone_serveur):
|
|
# C'est un serveur, rien à faire ici
|
|
return
|
|
|
|
ports = { 'tcp' : machine.portTCPin(),
|
|
'udp' : machine.portUDPin() }
|
|
|
|
for proto in [ 'tcp', 'udp' ] :
|
|
for port in ports[proto]:
|
|
iptables("-I EXT_VERS_CRANS -d %s -p %s --dport %s -j ACCEPT" \
|
|
%(ip,proto,port))
|
|
|
|
def blacklist(self):
|
|
""" Construit les chaînes de blackliste (BLACKLIST_{DST,SRC}) """
|
|
iptables('-F BLACKLIST_DST')
|
|
iptables('-F BLACKLIST_SRC')
|
|
iptables('-t mangle -F BLACKLIST_SOFT')
|
|
|
|
# Peut-être à mettre dans config.py ?
|
|
blacklist_sanctions = ('upload', 'warez', 'p2p', 'autodisc_p2p', 'autodisc_upload', 'bloq')
|
|
blacklist_sanctions_soft = ('autodisc_virus','ipv6_ra','mail_invalide','virus',
|
|
'upload', 'warez', 'p2p', 'autodisc_p2p', 'autodisc_upload', 'bloq')
|
|
|
|
|
|
blacklist = []
|
|
blacklist_soft = []
|
|
|
|
# Recherche sur le champ ablacklist (clubs compris)
|
|
search = db.search('ablacklist=*&paiement=ok')
|
|
self.anim = anim("\tBlackliste adhérents+clubs", 2*len(search['adherent']+search['club']))
|
|
for entite in search['adherent'] + search['club']:
|
|
self.anim.cycle()
|
|
sanctions = entite.blacklist_actif()
|
|
for s in blacklist_sanctions:
|
|
if s in sanctions:
|
|
blacklist.extend(entite.machines())
|
|
break
|
|
for entite in search['adherent'] + search['club']:
|
|
self.anim.cycle()
|
|
sanctions = entite.blacklist_actif()
|
|
for s in blacklist_sanctions_soft:
|
|
if s in sanctions:
|
|
blacklist_soft.extend(entite.machines())
|
|
break
|
|
self.anim.reinit()
|
|
print OK
|
|
|
|
# Recherche sur le champ mblacklist
|
|
search = db.search('mblacklist=*&paiement=ok')
|
|
self.anim = anim("\tBlackliste machines", 2*len(search['machine']))
|
|
for entite in search['machine']:
|
|
self.anim.cycle()
|
|
sanctions = entite.blacklist_actif()
|
|
for s in blacklist_sanctions:
|
|
if s in sanctions:
|
|
blacklist.append(entite)
|
|
break
|
|
for entite in search['machine']:
|
|
self.anim.cycle()
|
|
sanctions = entite.blacklist_actif()
|
|
for s in blacklist_sanctions_soft:
|
|
if s in sanctions:
|
|
blacklist_soft.append(entite)
|
|
break
|
|
self.anim.reinit()
|
|
print OK
|
|
|
|
self.anim = anim("\tChaînes BLACKLIST", len(blacklist))
|
|
for machine in blacklist:
|
|
self.anim.cycle()
|
|
iptables("-A BLACKLIST_DST -d %s -j REJECT --reject-with icmp-host-prohibited" % machine.ip())
|
|
iptables("-A BLACKLIST_SRC -s %s -j REJECT --reject-with icmp-host-prohibited" % machine.ip())
|
|
self.anim.reinit()
|
|
print OK
|
|
self.anim = anim("\tMarquage des machines pour blacklist soft", len(blacklist_soft))
|
|
for machine in blacklist_soft:
|
|
self.anim.cycle()
|
|
iptables("-t mangle -I BLACKLIST_SOFT -s %s -j MARK --set-mark %s" % (machine.ip(), conf_fw.mark['proxy']))
|
|
self.anim.reinit()
|
|
print OK
|
|
|
|
def filtre_p2p(self):
|
|
""" Construit la chaînes de filtrage du p2p (FILTRE_P2P) """
|
|
self.anim = anim("\tFiltrage p2p")
|
|
iptables('-F FILTRE_P2P')
|
|
iptables('-F TRACKER_FILTER')
|
|
|
|
# On ne filtre que ce qui passe sur l'interface externe
|
|
iptables('-A FILTRE_P2P -i %s -o %s -j RETURN' % (self.eth_int, self.eth_int) )
|
|
|
|
|
|
for filtre in self.filtres_p2p :
|
|
iptables('-A FILTRE_P2P -m ipp2p --%s -j LOG --log-prefix "IPP2P=%s "' % (filtre[0],
|
|
filtre[1]))
|
|
iptables('-A FILTRE_P2P -m ipp2p --%s -j REJECT --reject-with icmp-admin-prohibited' % filtre[0])
|
|
#iptables('-A FILTRE_P2P -m ipp2p --%s -j RETURN' % filtre[0])
|
|
self.anim.cycle()
|
|
|
|
for filtre in self.filtres_p2p_bloq:
|
|
iptables('-A FILTRE_P2P -m ipp2p --%s -j LOG --log-prefix "IPP2P=%s "' % (filtre[0],
|
|
filtre[1]))
|
|
iptables('-A FILTRE_P2P -m ipp2p -m limit --%s --limit=%d/hour -j RETURN' % (filtre[0], p2p.limite[filtre[1]]/2))
|
|
iptables('-A FILTRE_P2P -m ipp2p --%s -j REJECT --reject-with icmp-admin-prohibited' % filtre[0])
|
|
self.anim.cycle()
|
|
#on rejetes les trackeur udp les plus connus
|
|
for tracker in self.udp_torrent_tracker.values():
|
|
for dest in tracker:
|
|
iptables('-A FILTRE_P2P -p udp -d %s --dport %s -j REJECT --reject-with icmp-admin-prohibited' % (dest[0],dest[1]))
|
|
|
|
#On log les requetes a des trackers torrents puis on les rejetes
|
|
iptables("-A TRACKER_FILTER -m string --algo kmp ! --string \"info_hash=\" -j ACCEPT")
|
|
iptables("-A TRACKER_FILTER -m string --algo kmp --string \"/scrape?\" -j LOG_TRACKER")
|
|
iptables("-A TRACKER_FILTER -m string --algo kmp ! --string \"peer_id=\" -j ACCEPT")
|
|
iptables("-A TRACKER_FILTER -m string --algo kmp ! --string \"port=\" -j ACCEPT")
|
|
iptables("-A TRACKER_FILTER -m string --algo kmp ! --string \"uploaded=\" -j ACCEPT")
|
|
iptables("-A TRACKER_FILTER -m string --algo kmp ! --string \"downloaded=\" -j ACCEPT")
|
|
iptables("-A TRACKER_FILTER -m string --algo kmp ! --string \"left=\" -j ACCEPT")
|
|
iptables("-A TRACKER_FILTER -j LOG_TRACKER")
|
|
|
|
#On analyse que les requetes http
|
|
iptables("-A FILTRE_P2P -i %s -p tcp -m string --algo kmp --string \"GET \" -j TRACKER_FILTER" % self.eth_int)
|
|
iptables("-A FILTRE_P2P -i %s -p tcp -m string --algo kmp --string \"get \" -j TRACKER_FILTER" % self.eth_int)
|
|
|
|
# fait bcp de faux positif, peux servir a detecter de nouveau trackers
|
|
iptables("-A FILTRE_P2P -i %s -p udp -m string --from 0 --to 65 --algo kmp --hex-string \"|4500002c00004000|\" -j LOG --log-level notice --log-prefix \"TRACKER_TORRENT: \"" % self.eth_int)
|
|
|
|
iptables('-A LOG_TRACKER -j LOG --log-level notice --log-prefix "TRACKER_TORRENT: "')
|
|
iptables('-A LOG_TRACKER -j REJECT --reject-with icmp-admin-prohibited')
|
|
self.anim.reinit()
|
|
print OK
|
|
|
|
def serveurs_maj(self) :
|
|
self.exception_catcher(self.serveurs_vers_ext)
|
|
|
|
"""
|
|
Zamok
|
|
"""
|
|
|
|
class firewall_zamok(firewall_crans) :
|
|
"""
|
|
Structure du firewall :
|
|
table nat :
|
|
SERV_OUT_ADM
|
|
TEST_MAC-IP
|
|
table filter :
|
|
FORWARD (policy par défaut : DROP)
|
|
rien ne passe pas la chaîne FORWARD
|
|
INPUT (policy par défaut : ACCEPT)
|
|
|
|
"""
|
|
|
|
# interfaces physiques
|
|
eth_pub = "crans"
|
|
eth_adm = "crans.2"
|
|
nfs_ports = ["111", "2049", "32765:32769"]
|
|
|
|
def serv_out_adm(self) :
|
|
self.anim = anim('\tOutput vers VLAN adm', len(adm_users))
|
|
# Supression des éventuelles règles
|
|
iptables("-t filter -F SERV_OUT_ADM")
|
|
|
|
for user in adm_users :
|
|
self.anim.cycle()
|
|
try:
|
|
iptables("-A SERV_OUT_ADM -m owner --uid-owner %d -j ACCEPT" % pwd.getpwnam(user)[2])
|
|
except KeyError:
|
|
continue
|
|
|
|
# LDAP et DNS toujours joignable
|
|
iptables("-A SERV_OUT_ADM -p tcp --dport ldap -j ACCEPT")
|
|
iptables("-A SERV_OUT_ADM -p tcp --dport domain -j ACCEPT")
|
|
iptables("-A SERV_OUT_ADM -p udp --dport domain -j ACCEPT")
|
|
|
|
# Pour le nfs (le paquet à laisser passer n'a pas d'owner)
|
|
iptables("-A SERV_OUT_ADM -d fx.adm.crans.org -j ACCEPT")
|
|
iptables("-A SERV_OUT_ADM -d daath.adm.crans.org -j ACCEPT")
|
|
|
|
# Rien d'autre ne passe
|
|
iptables("-A SERV_OUT_ADM -j REJECT --reject-with icmp-net-prohibited")
|
|
|
|
self.anim.reinit()
|
|
print OK
|
|
|
|
def nat_table(self) :
|
|
self.anim = anim('\tStructure de la table nat')
|
|
|
|
|
|
iptables("-t nat -P PREROUTING ACCEPT")
|
|
iptables("-t nat -A PREROUTING -i lo -j ACCEPT")
|
|
|
|
iptables("-t nat -P PREROUTING ACCEPT")
|
|
print OK
|
|
|
|
def filter_table(self):
|
|
self.anim = anim('\tStructure de la table filter')
|
|
iptables('-t filter -N SERV_OUT_ADM')
|
|
iptables('-t filter -N TEST_MAC-IP')
|
|
iptables("-t filter -A OUTPUT -d 224.0.0.0/4 -j DROP")
|
|
|
|
# <!> à placer dans filter
|
|
#for net in NETs['fil'] + NETs['adm'] + NETs['wifi'] :
|
|
# iptables("-t nat -A PREROUTING -s %s -j TEST_MAC-IP" % net)
|
|
iptables("-t filter -A OUTPUT -d 10.231.136.1 -j SERV_OUT_ADM") # moche mais visiblement ont avait acces a l'interface adm de zamok depuis zamok
|
|
iptables("-t filter -A OUTPUT -o lo -j ACCEPT")
|
|
|
|
# pour une connection entrante venant du VLAN adm, il faut que le ACK
|
|
# puisse passer (interaction avec pam, uid de l'utilisateur en OUTPUT)
|
|
# on accepte donc les paquets si la connection est
|
|
# en RELATED et ESTABLISHED
|
|
iptables("-t filter -A OUTPUT -m state --state RELATED,ESTABLISHED -j ACCEPT")
|
|
iptables("-t filter -A OUTPUT -o %s -j SERV_OUT_ADM" % self.eth_adm)
|
|
|
|
|
|
iptables("-t filter -P OUTPUT ACCEPT")
|
|
print OK
|
|
|
|
def start_fw_funcs(self) :
|
|
self.exception_catcher(self.test_mac_ip)
|
|
self.serv_out_adm()
|
|
|
|
def blacklist(self):
|
|
"""Fondamentalement, bloque l'accès internet sur zamok aux
|
|
adhérents sanctionnés"""
|
|
iptables("-F OUTPUT")
|
|
|
|
# Règles OUTPUT de nat_table() à remettre en place
|
|
iptables("-t filter -A OUTPUT -o lo -j ACCEPT")
|
|
iptables("-t filter -A OUTPUT -m state --state RELATED,ESTABLISHED -j ACCEPT")
|
|
iptables("-t filter -A OUTPUT -o %s -j SERV_OUT_ADM" % self.eth_adm)
|
|
|
|
self.filter_table()
|
|
|
|
blacklist_sanctions = ('upload', 'warez', 'p2p', 'autodisc_p2p', 'autodisc_upload', 'bloq')
|
|
|
|
# Recherche sur le champ ablacklist (clubs compris)
|
|
search = db.search('ablacklist=*&paiement=ok')
|
|
self.anim = anim("\tBlackliste des comptes Crans", len(search['adherent']))
|
|
for adh in search['adherent']:
|
|
self.anim.cycle()
|
|
sanctions = adh.blacklist_actif()
|
|
for s in blacklist_sanctions:
|
|
if s in sanctions:
|
|
try:
|
|
uid = adh.uidNumber()
|
|
iptables("-A OUTPUT -m owner --uid-owner %s -d 127.0.0.1/8 -j ACCEPT" % uid)
|
|
iptables("-A OUTPUT -m owner --uid-owner %s -d 138.231.136.1/21 -j ACCEPT" % uid)
|
|
iptables("-A OUTPUT -m owner --uid-owner %s -d 138.231.144.1/21 -j ACCEPT" % uid)
|
|
iptables("-A OUTPUT -m owner --uid-owner %s -j REJECT" % uid)
|
|
finally:
|
|
break
|
|
self.anim.reinit()
|
|
print OK
|
|
|
|
def filter_table_tweaks(self) :
|
|
self.anim = anim('\tRègles spécifiques à zamok')
|
|
iptables("-P INPUT ACCEPT")
|
|
iptables("-P FORWARD DROP")
|
|
print OK
|
|
|
|
"""
|
|
Rouge
|
|
"""
|
|
|
|
class firewall_redisdead(firewall_crans) :
|
|
"""
|
|
Structure du firewall :
|
|
table filter :
|
|
TEST_MAC-IP pour les paquets en INPUT
|
|
FORWARD (policy par défaut : DROP)
|
|
rien ne passe pas la chaîne FORWARD
|
|
INPUT (policy par défaut : ACCEPT)
|
|
|
|
"""
|
|
|
|
# interfaces physiques
|
|
eth_pub = "eth0"
|
|
eth_adm = "eth1"
|
|
|
|
def filter_table(self) :
|
|
self.anim = anim('\tStructure de la table filter')
|
|
iptables('-N TEST_MAC-IP')
|
|
for net in NETs['fil'] + NETs['wifi']:
|
|
iptables("-A INPUT -s %s -i %s -j TEST_MAC-IP" % (net, self.eth_pub))
|
|
for net in NETs['adm']:
|
|
iptables("-A INPUT -s %s -i %s -j TEST_MAC-IP" % (net, self.eth_adm))
|
|
iptables("-P INPUT ACCEPT")
|
|
iptables("-P OUTPUT ACCEPT")
|
|
print OK
|
|
|
|
def filter_table_tweaks(self) :
|
|
self.anim = anim('\tRègles spécifiques à redisdead')
|
|
iptables("-P INPUT ACCEPT")
|
|
iptables("-P FORWARD DROP")
|
|
print OK
|
|
|
|
|
|
"""
|
|
Vert
|
|
"""
|
|
|
|
class firewall_vert(firewall_crans) :
|
|
"""
|
|
Structure du firewall :
|
|
table nat :
|
|
MAC-IP
|
|
table filter :
|
|
FORWARD (policy par défaut : DROP)
|
|
rien ne passe pas la chaîne FORWARD
|
|
INPUT (policy par défaut : ACCEPT)
|
|
|
|
"""
|
|
|
|
# interfaces physiques
|
|
eth_crans = "crans"
|
|
|
|
def nat_table(self) :
|
|
self.anim = anim('\tStructure de la table nat')
|
|
iptables('-t nat -N TEST_MAC-IP')
|
|
|
|
iptables("-t nat -P PREROUTING ACCEPT")
|
|
iptables("-t nat -A PREROUTING -i lo -j ACCEPT")
|
|
iptables("-t nat -A PREROUTING -d 224.0.0.0/4 -j DROP")
|
|
|
|
for net in NETs['fil'] + NETs['adm'] + NETs['wifi'] :
|
|
iptables("-t nat -A PREROUTING -s %s -j TEST_MAC-IP" % net)
|
|
|
|
iptables("-t nat -P PREROUTING ACCEPT")
|
|
iptables("-t nat -P OUTPUT ACCEPT")
|
|
print OK
|
|
|
|
def filter_table_tweaks(self) :
|
|
self.anim = anim('\tRègles spécifiques à vert')
|
|
iptables("-P INPUT ACCEPT")
|
|
iptables("-P FORWARD DROP")
|
|
print OK
|
|
|
|
class firewall_sable(firewall_redisdead):
|
|
"""Comme pour rouge, avec le proxy transparent en plus"""
|
|
|
|
def filter_table_tweaks(self) :
|
|
iptables("-P INPUT ACCEPT")
|
|
iptables("-P FORWARD DROP")
|
|
for ip in accueil_route.keys():
|
|
for port in accueil_route[ip]:
|
|
iptables("-A FORWARD -p tcp -d %s --dport %s -j ACCEPT" % (ip,port))
|
|
iptables("-A FORWARD -p tcp -s %s --sport %s -j ACCEPT" % (ip,port))
|
|
|
|
def mangle_table(self):
|
|
iptables("-t mangle -F PREROUTING")
|
|
|
|
# Pour le transparent
|
|
iptables("-t mangle -i eth0.2 -A PREROUTING -p tcp --destination-port 3128 " +
|
|
"--destination 10.231.136.9 " +
|
|
"-m mac --mac-source %s " % mac_komaz +
|
|
"-j MARK --set-mark %s" % conf_fw.mark['proxy'])
|
|
iptables("-t mangle -A PREROUTING -m mark --mark %s -j ACCEPT" % conf_fw.mark['proxy'])
|
|
|
|
|
|
def nat_table(self):
|
|
firewall_redisdead.nat_table(self)
|
|
# Proxy transparent pour le filiaire
|
|
iptables("-t nat -I PREROUTING -i eth0.2 -m mark --mark %s -j ACCEPT" % conf_fw.mark['proxy'])
|
|
|
|
if_defaut = "eth0"
|
|
if_radin = "eth0.%d" % vlans["radin"]
|
|
if_accueil = "eth0.%d" % vlans["accueil"]
|
|
if_isolement = "eth0.%d" % vlans["isolement"]
|
|
|
|
#intranet et wiki pour le vlan accueil
|
|
for ip in accueil_route.keys():
|
|
for port in accueil_route[ip]:
|
|
iptables("-t nat -A PREROUTING -i eth0.7 -p tcp -d %s --dport %s -j ACCEPT" % (ip,port))
|
|
iptables("-t nat -A POSTROUTING -p tcp -s %s -d %s --dport %s -j MASQUERADE" % (NETs['accueil'][0],ip,port))
|
|
|
|
# Proxy transparent pour le wifi
|
|
iptables("-t nat -A PREROUTING -i %s -p tcp --dport 80" %if_defaut +
|
|
" -d ! 138.231.136.0/24 -j DNAT --to-destination" +
|
|
" 138.231.136.9:3128")
|
|
|
|
# Proxy transparent pour les vlans radin et accueil
|
|
for interface in [if_accueil, if_isolement]:
|
|
iptables("-t nat -i %s -A PREROUTING -p tcp --destination-port 80 -j DNAT --to-destination 10.51.0.1:3128" % interface)
|
|
iptables("-t nat -i %s -A PREROUTING -p tcp --destination-port 3128 -j ACCEPT" % interface)
|
|
iptables("-t nat -i %s -A PREROUTING -p tcp --destination-port 443 -j ACCEPT" % interface)
|
|
|
|
def post_start_hook(self) :
|
|
self.anim = anim("\tMise en place du routage")
|
|
warn = ''
|
|
for cmd in [ 'echo 1 > /proc/sys/net/ipv4/ip_forward' ,
|
|
'echo 65536 > /proc/sys/net/ipv4/netfilter/ip_conntrack_max' ] :
|
|
status,output=getstatusoutput(cmd)
|
|
if status :
|
|
warn += output + '\n'
|
|
if warn :
|
|
print WARNING
|
|
if self.debug :
|
|
print warn
|
|
else :
|
|
print OK
|
|
|
|
firewall_bleu = firewall_zamok
|
|
|
|
"""
|
|
Gordon
|
|
"""
|
|
|
|
class firewall_gordon(firewall_crans) :
|
|
"""
|
|
Structure du firewall :
|
|
table nat :
|
|
table filter :
|
|
MAC-IP
|
|
FORWARD (policy par défaut : ACCEPT)
|
|
INPUT (policy par défaut : ACCEPT)
|
|
table mangle :
|
|
POSTROUTING : le proxy transparent
|
|
|
|
"""
|
|
|
|
# interfaces physiques
|
|
eth_crans = "eth0"
|
|
eth_wifi = "eth0.3"
|
|
|
|
def filter_table(self) :
|
|
self.anim = anim('\tStructure de la table filter')
|
|
iptables('-t filter -N TEST_MAC-IP')
|
|
|
|
iptables("-t filter -P FORWARD ACCEPT")
|
|
iptables("-t filter -A FORWARD -i lo -j ACCEPT")
|
|
iptables("-t filter -A FORWARD -d 224.0.0.0/4 -j DROP")
|
|
|
|
for net in NETs['fil'] + NETs['adm'] + NETs['wifi'] :
|
|
iptables("-t filter -A FORWARD -s %s -j TEST_MAC-IP" % net)
|
|
|
|
iptables("-t filter -P FORWARD ACCEPT")
|
|
iptables("-t filter -P OUTPUT ACCEPT")
|
|
print OK
|
|
|
|
def filter_table_tweaks(self) :
|
|
self.anim = anim('\tRègles spécifiques à gordon')
|
|
iptables("-P INPUT ACCEPT")
|
|
iptables("-P FORWARD ACCEPT")
|
|
print OK
|
|
|
|
def mangle_table(self):
|
|
self.anim = anim('\tRègles spécifiques à gordon')
|
|
#~ iptables("-t mangle -A PREROUTING " +
|
|
#~ "-d ! 138.231.136.0/21 " +
|
|
#~ ("-i %s " % self.eth_wifi) +
|
|
#~ "-p tcp -m tcp --dport 80 " +
|
|
#~ "-j MARK --set-xmark %s/0xffffffff" % conf_fw.mark['proxy'])
|
|
print OK
|
|
|
|
def post_start_hook(self) :
|
|
self.anim = anim("\tMise en place du routage")
|
|
warn = ''
|
|
for cmd in [ 'echo 1 > /proc/sys/net/ipv4/ip_forward' ,
|
|
'echo 65536 > /proc/sys/net/ipv4/netfilter/ip_conntrack_max' ] :
|
|
status,output=getstatusoutput(cmd)
|
|
if status :
|
|
warn += output + '\n'
|
|
if warn :
|
|
print WARNING
|
|
if self.debug :
|
|
print warn
|
|
else :
|
|
print OK
|
|
|
|
|
|
if __name__ == '__main__' :
|
|
# Chaînes pouvant être recontruites
|
|
fw = eval('firewall_%s()' % hostname)
|
|
chaines = []
|
|
for nom in dir(fw) :
|
|
if nom in [ 'log_chaines' , 'test_virus_flood', 'reseaux_non_routables', 'test_mac_ip' , 'blacklist' , 'ext_vers_serveurs' , 'serveurs_vers_ext', 'ext_vers_crans', 'crans_vers_ext' , 'filtre_p2p', 'admin_vlan' , 'serv_out_adm', 'mangle_table', 'classes_p2p_maj','reload_qos' ] :
|
|
chaines.append(nom)
|
|
|
|
def __usage(txt=None) :
|
|
if txt!=None : cprint(txt,'gras')
|
|
|
|
print """Usage:
|
|
%(p)s start : Construction du firewall.
|
|
%(p)s restart : Reconstruction du firewall.
|
|
%(p)s stop : Arrêt du firewall.
|
|
%(p)s <noms de chaînes> : reconstruit les chaînes
|
|
Les chaînes pouvant être reconstruites sont :
|
|
%(chaines)s
|
|
Pour reconfiguration d'IPs particulières, utiliser generate. """ % \
|
|
{ 'p' : sys.argv[0].split('/')[-1] , 'chaines' : '\n '.join(chaines) }
|
|
sys.exit(-1)
|
|
|
|
# Bons arguments ?
|
|
if len(sys.argv) == 1 :
|
|
__usage()
|
|
for arg in sys.argv[1:] :
|
|
if arg in [ 'stop', 'restart', 'start' ] and len(sys.argv) != 2 :
|
|
__usage("L'argument %s ne peut être employé que seul." % arg)
|
|
|
|
if arg not in [ 'stop', 'restart', 'start' ] + chaines :
|
|
__usage("L'argument %s est inconnu." % arg)
|
|
|
|
for arg in sys.argv[1:] :
|
|
eval('fw.%s()' % arg )
|