scripts/gestion/ipt.py
Olivier Huber e63dfbccd1 [gestion/ipt.py] Elements de base pour la generation des firewalls
Ce module ajoute des fonctions plutôt de bas niveau pour générer des
firewalls. Pour l'instant seul le firewall ipv6 utilise ce module.
Cela fait quelque temps que le firewall6 tourne et tout semble bien marcher.
Un effort a été fait pour tester tous les bouts de code, mais certaines parties
peuvent avoir échappé à ma vigilance.

L'organisation du code se présente ainsi :
- un module ipt qui contient :
  o les classes Ip6tables, Table et Chain qui sont là pour "collecter" toutes
 les règles iptables. Ces dernières sont alors écrite dans un fichier dans /tmp
 et ensuite appliquée à l'aide d'un ip6tables-restore. L'instance qui contient
 toutes les règles est stockée en pickle et utilisée lors des mises à jours des
 règles :

  o il y ensuite les diverses fonctions qui permettent d'effectuer les actions
 nécessaires à la génération des règles. Elles ont été écrite dans le but
 d'être le plus générique possible et de pouvoir prendre en compte le protocole
 ip utilisé (toutes le ne sont pas forcément)

  o il y a une classe Update qui a des methodes associées au diverses
 mise à jour possible via generate ;

  o il y a aussi toutes les exceptions.

- un script firewall6 qui sera présenté dans le prochain commit.

- _toute_ la partie configuration devrait être écrite dans config.py.

Le développement du module devrait se poursuivre un peu pour avoir toutes les
fonctionnalités requises pour générer le firewall ipv4

Toute remarque, suggestion, critique (tant qu'elle est constructive) sera la
bienvenue, sur nounou@ ou en privé.

darcs-hash:20100226030644-8fbb1-926f7d4b7e8a6b834e1119bb28af89f239a598b8.gz
2010-02-26 04:06:44 +01:00

722 lines
25 KiB
Python
Executable file

#!/usr/bin/python
# -*- coding: utf-8 -*-
#
# IPT.PY -- Gestion du firewall
#
# Copyright (C) 2010 Olivier Huber
# Authors: Olivier Huber <huber@crans.org>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
import os, re, syslog, cPickle
from ldap_crans import crans_ldap, hostname
from commands import getstatusoutput
from config import NETs, role, prefix, mid, output_file, filter_policy
from config import blacklist_sanctions, file_pickle
from iptools import AddrInNet
from midtools import Mid
import subprocess
import netaddr
Mangle_policy = """
*mangle
:PREROUTING ACCEPT [0:0]
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
:POSTROUTING ACCEPT [0:0]
"""
Raw_policy = """
*raw
:PREROUTING ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
"""
Filter_policy_template = """
*filter
:INPUT %(policy_input)s [0:0]
:FORWARD %(policy_forward)s [0:0]
:OUTPUT %(policy_output)s [0:0]
"""
dprefix = { 'fil' : 'fil', 'fil-v6' : 'fil', 'adm' : 'adm', 'wifi' : 'wifi',
'wifi-v6' : 'wifi' }
default_chains = [ 'PREROUTING', 'INPUT', 'FORWARD', 'OUTPUT', 'POSTROUTING' ]
# On ouvre une connexion avec la base
db = crans_ldap()
##############################################################################
#
# Déclaration des classes pour les règles du firewall
#
##############################################################################
class Chain(object):
''' Classe regroupant toutes les règles du firewall '''
def __init__(self):
self.items = []
def __call__(self, cmd):
self.items.append(cmd)
class Table(object):
''' Classe contenant toutes les chaînes du firewall '''
# TODO voir si on peut pas créer dynamiquement les méthodes
def __init__(self):
self.prerouting = Chain()
self.input = Chain()
self.forward = Chain()
self.output = Chain()
self.postrouting = Chain()
self.mac = Chain()
self.macfil = Chain()
self.macfilv6 = Chain()
self.macadm = Chain()
self.extfil = Chain()
self.extfilv6 = Chain()
self.extwifi = Chain()
self.extwifiv6 = Chain()
self.cransfil = Chain()
self.cransfilv6 = Chain()
self.cranswifi = Chain()
self.cranswifiv6 = Chain()
self.ieui64 = Chain()
self.feui64 = Chain()
self.blacklist_src = Chain()
self.blacklist_dst = Chain()
self.srv_out_adm = Chain()
class Ip6tables(object):
''' Classe pour '''
def __init__(self):
self.filter = Table()
self.mangle = Table()
self.raw = Table()
def macip(self, mac, type_m):
'''Fait la correspondance MAC-IP'''
type_mm = re.sub('-', '', type_m)
eval('self.filter.mac' + type_mm)(" ".join(['-m mac --mac-source', mac,
'-j RETURN']))
# self.filter.mac(" ".join(['-m mac --mac-source', mac,
# '-j RETURN']))
def extcrans(self, type_machine, ports, mac, dev):
'''Ouverture des ports de l'extérieur vers la zone crans'''
tab = { 'fil' : 'self.filter.extfil', 'fil-v6' : 'self.filter.extfilv6',
'wifi' : 'self.filter.extwifi',
'wifi-v6' : 'self.filter.extwifiv6' }
ip = ipv6_addr(mac, type_machine)
for proto in ['tcp', 'udp']:
for port in ports[proto]:
if port != ':':
eval(tab[type_machine])('-i %s -p %s -d %s --dport %s -j \
ACCEPT' % (dev, proto, ip, port))
else:
eval(tab[type_machine])('-i %s -p %s -s %s -j ACCEPT' %
(dev, proto, ip))
def cransext(self, type_machine, ports, mac, dev):
'''Ouverture des ports de la zone crans vers l'extérieur'''
tab = { 'fil' : 'self.filter.cransfil', 'fil-v6' :
'self.filter.cransfilv6', 'wifi' : 'self.filter.cranswifi',
'wifi-v6' : 'self.filter.cranswifiv6' }
ip = ipv6_addr(mac, type_machine)
for proto in ['tcp', 'udp']:
for port in ports[proto]:
if port != ':':
eval(tab[type_machine])('-i %s -p %s -s %s --sport %s -j \
ACCEPT' % (dev, proto, ip, port))
else:
eval(tab[type_machine])('-i %s -p %s -s %s -j ACCEPT' %
(dev, proto, ip))
def blacklist(self, machine):
''' Met des règles empêchant toute communication
vers et à partir de la machine considérée '''
ident = int(machine.id())
ip = ""
for type_m in mid.keys():
if ident in range(mid[type_m][0], mid[type_m][1]):
ip = ipv6_addr(machine.mac(), type_m)
break
if ip:
self.filter.blacklist_src('-s %s -j REJECT --reject-with \
icmp6-adm-prohibited' % ip)
self.filter.blacklist_dst('-d %s -j REJECT --reject-with \
icmp6-adm-prohibited' % ip)
def version(self):
''' methode retournant la version du protocole ip
pour l'instance de la classe '''
return 6
class Update(object):
''' Cette classe comprend toutes les méthodes nécessaires
à une mise-à-jour ou un régénération partielle du firewall'''
def ports(self, mids, ip_proto = 4):
''' Met à jour les autorisations par machine sur l'ouverture des ports.
Prend en argument une liste de mid (entier(s)) de machines à changer'''
check_ip_proto(ip_proto)
ipt_p = open_pickle(ip_proto)
dev_crans = iface6('fil')
if ip_proto == 4:
dev_ext = iface('ens')
elif ip_proto == 6:
dev_ext = iface6('sixxs2')
net = ""
for m in mids:
for type_m in mid.keys():
if int(m) in range(mid[type_m][0], mid[type_m][1]):
net = type_m
if net == "":
raise MidError("Il n'y a pas de réseau associé au mid %i" % m)
if '-v6' in net and ip_proto == 4:
raise MismatchMidIpProto(m, ip_proto, net)
machine = db.search('mid=%i' % m)['machine']
if len(machine) != 1:
msg = "Il y a %i machines associée(s) au mid %i" % (
len(machine), m)
raise MidError(msg)
else:
if ip_proto == 4:
ip = Mid(int(m)).to_ipv4()
elif ip_proto == 6:
ip = ipv6_addr(machine[0].mac(), net)
# On vérifie si la machine a déjà des entrées dans les chaînes
# On est un peu sous optimal ici
for sens in ['crans', 'ext']:
items = eval('ipt_p.filter.%s.items' % (sens + re.sub('-', '',
net)))
i = 0
while i < len(items):
if ip in items[i] or 'REJECT' in items[i]:
del items[i]
else:
i = i + 1
ports_io(ipt_p, machine[0], net, dev_ext, dev_crans)
eval('ipt_p.filter.ext' + re.sub('-', '', net))('-j \
REJECT --reject-with icmp6-port-unreachable')
eval('ipt_p.filter.crans' + re.sub('-', '', net))('-j \
REJECT --reject-with icmp6-port-unreachable')
# On écrit et applique les règles
write_rules(ipt_p)
apply_rules(ip_proto)
os.remove(file_pickle[ip_proto])
# On sauve les chaînes
save_pickle(ipt_p)
return 0
def blacklist(self, ip_proto = 4):
''' Permet de regénérer les diverses blacklistes '''
#TODO vérifier que la fonctionn est _vraiement_ ipv4 aware
check_ip_proto(ip_proto)
ipt_p = open_pickle(ip_proto)
blacklist(ipt_p)
# On écrit et applique les règles
write_rules(ipt_p)
apply_rules(ip_proto)
os.remove(file_pickle[ip_proto])
# On sauve les chaînes
save_pickle(ipt_p)
return 0
def macs(self, macs, ip_proto = 4):
''' Méthode temporaire le temps de trouver une solution plus élégante
l'interface devrait être la même que pour la fonction finale'''
check_ip_proto(ip_proto)
ipt_p = open_pickle(ip_proto)
for type_m in ['fil', 'fil-v6', 'adm']:
type_mm = re.sub('-', '', type_m)
eval('ipt_p.filter.mac%s.items' % type_mm)[:] = []
machines = db.all_machines(graphic = True)
macips(ipt_p, machines, ['fil', 'fil-v6', 'adm'])
write_rules(ipt_p)
apply_rules(ip_proto)
os.remove(file_pickle[ip_proto])
save_pickle(ipt_p)
return 0
# Il faut voir comment passer les mac en argument
# def macs(self, macs, ip_proto = 4):
# ''' Fonction pour mettre à jour les adresses mac acceptées sur le réseau.
# Prend comme argument un dictionnaire ayant pour clé 'remove' et 'add',
# contenant respectivement les adresses mac a ôter et celles à ajouter'''
# #TODO vérifier que la fonctionn est _vraiement_ ipv4 aware
# ipt_p = open_pickle(ip_proto)
# # On modifie la chaîne mac
# nb = len(ipt_p.filter.mac.items)
# for mac in macs['remove']:
# for i in range(1, nb):
# if mac in ipt_p.filter.mac.items[i]:
# ipt_p.filter.mac.items.remove[i]
# break
# print "Erreur, la mac " + mac + " n'est pas dans la chaîne."
#
# for mac in macs['add']:
# ipt_p.macip(mac)
#
# # On écrit et applique les règles
# write_rules(ipt_p)
# apply_rules(6)
#
# os.remove(file_pickle[ip_proto])
#
# # On sauve les chaînes
# save_pickle(ipt_p)
# return 0
#
##############################################################################
#
# Déclaration des exceptions
#
##############################################################################
class NoIface(Exception):
''' Exception invoquée lorsqu'il n'y a pas
d'interface associé à un réseau'''
def __init__(self, msg):
self.msg = msg
syslog.syslog(syslog.LOG_ERR,"Pas d'interface associé à %s"
% self.msg)
def __str__(self):
return "Pas d'interface associé à %s" % self.msg
class Iproute2Error(Exception):
''' Exception invoquée lorsqu'un appel à iproute2 renvoie une erreur'''
def __init__(self, cmd, code, msg):
self.cmd = cmd
self.code = code
self.msg = msg
syslog.syslog(syslog.LOG_ERR,"%s : %s %s" % (self.cmd, self.code,
self.msg))
def __str__(self):
return "%s: %s %s" % ( self.cmd, self.code, self.msg)
class NoRtTable(Exception):
''' Exception invoquée lorsqu'une table de routage n'existe pas'''
def __init__(self, msg):
self.msg = msg
syslog.syslog(syslog.LOG_ERR,"La table donnée n'existe pas : %s" %
self.msg)
def __str__(self):
return "La table donnée n'existe pas : %s" % self.msg
class ApplyRulesError(Exception):
''' Exception invoquée lorsque l'application des règles par
ip(6|)tables-restore échoue '''
def __init__(self, cmd, code, msg):
self.cmd = cmd
self.code = code
self.msg = msg
syslog.syslog(syslog.LOG_ERR,"%s : %s \n %s" %
(self.cmd, self.code, self.msg))
def __str__(self):
return "%s : %s \n %s" % (self.cmd, self.code, self.msg)
class SysctlError(Exception):
''' Exception invoquée lorsque la modification d'un état dans /proc/sys
échoue '''
def __init__(self, cmd, code, msg):
self.cmd = cmd
self.code = code
self.msg = msg
syslog.syslog(syslog.LOG_ERR,"%s : %s %s" % (self.cmd, self.code,
self.msg))
def __str__(self):
return "%s: %s %s" % ( self.cmd, self.code, self.msg)
class Ip6tablesError(Exception):
def __init__(self, cmd, code, msg):
self.cmd = cmd
self.code = code
self.msg = msg
syslog.syslog(syslog.LOG_ERR,"%s : %s %s" % (self.cmd, self.code,
self.msg))
def __str__(self):
return "%s: %s %s" % ( self.cmd, self.code, self.msg)
class MidError(Exception):
''' Exception invoquée lorsqu'il y a un soucis avec un mid fourni '''
def __init__(self, msg):
self.msg = msg
syslog.syslog(syslog.LOG_ERR,"%s" % self.msg)
def __str__(self):
return "%s" % self.msg
class MismatchMidIpProto(Exception):
''' Exception invoquée lorsqu'il y a un défaut d'appariement entre le mid
et le protocole ip concerné'''
def __init__(self, mmid, ip_proto, net):
self.mmid = mmid
self.ip_proto = ip_proto
self.net = net
self.msg = "Défaut d'appariement entre le mid %i (%s) \
et le protocole ip %i" % (self.mmid, self.net, self.ip_proto)
syslog.syslog(syslog.LOG_ERR, self.msg)
def __str__(self):
return self.msg
class IpProtoError(Exception):
''' Exception quand le protocole ip fourni est inconnu '''
def __init__(self, proto):
self.msg = "Le protocole ip %i est inconnu" % proto
syslog.syslog(syslog.LOG_ERR,"%s" % self.msg)
def __str__(self):
return "%s" % self.msg
class UnknowUserError(Exception):
''' Exception quand l'utilisateur demandé n'existe pas sur la machine '''
def __init__(self, user):
self.msg = "L'utilisateur %s est inconnu" % user
syslog.syslog(syslog.LOG_ERR,"%s" % self.msg)
def __str__(self):
return "%s" % self.msg
##############################################################################
#
# Déclaration des fonctions
#
##############################################################################
def check_ip_proto(ip_proto):
''' Vérifie que le protocole ip fourni est valide '''
if ip_proto != 4 and ip_proto != 6:
raise IpProtoError(ip_proto)
def ipv6_addr(mac, net):
''' Renvoie l'adresse ipv6 d'auto-configuration de la mac sur le réseau '''
mac_s = mac.split(':')
eui = '2'+':'.join(mac_s[1:3])+'ff:fe'+':'.join(mac_s[3:5])+mac_s[5]
return re.sub(':/64', eui , prefix[dprefix[net]][0])
# TODO Fusionner les deux fonctions.
def iface(net):
'''Retourne l'interface réseau associée à un certain type de réseau
Pour l'instant on se base sur l'ipv4 pour identifier l'interface'''
if net == 'fil-v6':
net = 'fil'
if net == 'wifi-v6':
net = 'wifi'
cmd = "ip a show| egrep 'inet[^6]'"
code, msg = getstatusoutput(cmd)
if code:
raise Iproute2Error(cmd, code, msg)
output = msg.splitlines()
for line in output:
if AddrInNet(line.split()[1].split('/')[0], NETs[net]):
return line.split()[-1]
raise NoIface(net)
def iface6(net):
'''Retourne l'interface réseau associée à
un certain type de réseau ipv6'''
cmd = "ip -6 a show"
code, msg = getstatusoutput(cmd)
if code:
raise Iproute2Error(cmd, code, msg)
output = msg.splitlines()
subnet = netaddr.IPNetwork(prefix[net][0])
i = 0
while i < len(output):
if re.match('^[0-9]:', output[i]):
dev = re.sub('(@.*|:)', '', output[i].split()[1])
i = i + 1
while (i < len(output)) and ('inet6' in output[i]):
if netaddr.IPNetwork(output[i].split()[1]) == subnet:
return dev
else:
i = i + 2
else:
i = i + 1
raise NoIface(net)
def check_table(table):
''' Vérifie que la table existe bien '''
ctables = open('/etc/iproute2/rt_tables', 'r')
rt_tables = ctables.readlines()
tables = [item for item in rt_tables if not re.match('#', item)]
if any(re.search(table, elt) for elt in tables):
return 0
else:
raise NoRtTable(table)
def custom_default_route(table, default, net, ip_proto = 4):
''' Permet de créer une route par default personnalisée'''
check_ip_proto(ip_proto)
check_table(table)
dev = iface(net)
cmd = "ip -%i route add table %s default via %s dev %s" % (ip_proto, table,
default, dev)
code, msg = getstatusoutput(cmd)
if code:
raise Iproute2Error(cmd, code, msg)
def custom_subnet_route(table, subnet, net, ip_proto = 4):
''' Permet de créer une route personnalisée'''
check_ip_proto(ip_proto)
check_table(table)
dev = iface(net)
cmd = "ip -%i route add table %s from %s dev %s" % (ip_proto, table, subnet,
dev)
code, msg = getstatusoutput(cmd)
if code:
raise Iproute2Error(cmd, code, msg)
def custom_subnet_via_route(table, subnet, net, via, ip_proto = 4):
''' Permet de créer une route personnalisée'''
check_ip_proto(ip_proto)
check_table(table)
dev = iface(net)
cmd = "ip -%i route add table %s from %s via %s dev %s" % (ip_proto, table,
subnet, via, dev)
code, msg = getstatusoutput(cmd)
if code:
raise Iproute2Error(cmd, code, msg)
def custom_ip_rule(table, subnet, ip_proto = 4):
''' Ajout d'un règle de routage personnalisée basée
sur un sous-reseaux de provenance'''
check_ip_proto(ip_proto)
check_table(table)
cmd = "ip -%i rule add from %s table %s" % (ip_proto, subnet, table)
code, msg = getstatusoutput(cmd)
if code:
raise Iproute2Error(cmd, code, msg)
def custom_mark_rule(table, fw_mark, ip_proto = 4):
''' Ajout d'une règle de routage personnalisée basée sur une marque'''
check_ip_proto(ip_proto)
check_table(table)
cmd = "ip -%i rule add fwmark %s table %s" % (ip_proto, fw_mark, table)
code, msg = getstatusoutput(cmd)
if code:
raise Iproute2Error(cmd, code, msg)
def srv(attribute):
''' Renvoie le (ou les) serveur(s) qui possède l'attribut '''
return [ server for server, attr in role.iteritems() if (attribute in attr)]
def ip_attribut(attribute, cl, ip_proto = 4):
''' Renvoie l'ip du serveur qui possède l'attribut '''
check_ip_proto(ip_proto)
host = srv(attribute)[0]
#Gestion erreur ?
# Autre net que fil ?
if ip_proto == 4:
return cl.search('host=%s.crans.org' % host)['machine'][0].ip()
elif ip_proto == 6:
mac = cl.search('host=%s.crans.org' % host)['machine'][0].mac()
if mac:
return ipv6_addr(mac, 'fil')
else:
print "Error" + " host=%s.crans.org" % name
def apply_rules(ip_proto = 4):
''' Applique les règles fournies dans le fichier passé en arguement '''
check_ip_proto(ip_proto)
f = open(output_file[ip_proto], 'r')
if ip_proto == 4:
cmd = '/sbin/iptables-restore'
elif ip_proto == 6:
cmd = '/sbin/ip6tables-restore'
try:
p1 = subprocess.Popen(cmd, stdin=f, stdout=subprocess.PIPE)
except OSError:
syslog.syslog(syslog.LOG_ERR,"Le fichier %s n'existe pas" % f.name)
print "Le fichier %s n'existe pas" % f.name
stdout, stderr = p1.communicate()
if p1.returncode < 0:
raise ApplyRulesError(cmd, -p1.returncode, 'STDOUT\n' + stdout +
'STDERR\n' + stderr )
def enable_forwarding(ip_proto = 4):
''' Autorise le forwarding sur la machine considérée '''
check_ip_proto(ip_proto)
cmd = 'echo 1 > /proc/sys/net/ipv%i/conf/all/forwarding' % ip_proto
code, msg = getstatusoutput(cmd)
if code:
raise SysctlError(cmd, code, msg)
def disable_forwarding(ip_proto = 4):
''' Désactive le forwarding sur la machine considérée '''
check_ip_proto(ip_proto)
cmd = 'echo 0 > /proc/sys/net/ipv%i/conf/all/forwarding' % ip_proto
code, msg = getstatusoutput(cmd)
if code:
raise SysctlError(cmd, code, msg)
def not_private(arg):
''' Retourne un boolén suivant que la fonction passé en argument
est privée ou non'''
if re.match('^_.*', str(arg)):
return False
else:
return True
def open_pickle(ip_proto = 4):
''' Cette fonction ouvre un fichier contenant un dump d'une classe
Ip(|6)tables'''
check_ip_proto(ip_proto)
try:
f = open(file_pickle[ip_proto], 'r')
except OSError:
syslog.syslog(syslog.LOG_ERR,"Le fichier %s n'existe pas" %
file_pickle[ip_proto])
print "Le fichier %s n'existe pas" % file_pickle[ip_proto]
#XXX gestion des erreurs
return cPickle.load(f)
def save_pickle(ipt):
''' Cette fonction sauvegarde une instance de Ip(|6)tables'''
fout = open(file_pickle[ipt.version()], 'w')
cPickle.dump(ipt, fout)
fout.close()
def write_rules(ipt):
''' Cette fonction écrit les règles dans un fichier '''
# TODO vérifier que la fonctionn est _vraiement_ ipv4 aware
ip_proto = ipt.version()
fout = open(output_file[ip_proto], 'w')
# On recherche si la machine a des politiques particulières
if hostname in filter_policy.keys():
key = hostname
else:
key = 'default'
# On applique les politiques par défaut sur les chaînes canoniques
output = { 'filter' : Filter_policy_template % filter_policy[key],
'mangle' : Mangle_policy,
'raw' : Raw_policy
}
# On parcours une première fois l'instance pour initialiser correctement
# nos chaînes
for itables in ['filter', 'mangle', 'raw']:
for ichain in filter(not_private,
dir(ipt.__getattribute__(itables))):
if ichain.upper() not in default_chains:
if ipt.__getattribute__(itables).__getattribute__(ichain).items:
output[itables] += ":%s - [0:0]\n" % ichain.upper()
# On ajoute maintenant les règles
for itables in ['filter', 'mangle', 'raw']:
for ichain in filter(not_private,
dir(ipt.__getattribute__(itables))):
for rule in ipt.__getattribute__(itables).__getattribute__(ichain).items:
output[itables] += '-A ' + ichain.upper() + ' ' + rule + '\n'
# Ecriture dans le fichier
fout.writelines(output['filter'])
fout.write('COMMIT\n')
fout.write('')
fout.writelines(output['mangle'])
fout.write('COMMIT\n')
fout.write('')
fout.writelines(output['raw'])
fout.write('COMMIT\n')
fout.close()
def blacklist(ipt):
''' Permet de peupler les chaînes concernant les diverses blacklistes '''
blcklst = []
s = db.search('ablacklist=*&paiement=ok')
for target in s['adherent'] + s['club']:
sanctions = target.blacklist_actif()
if [x for x in sanctions if x in blacklist_sanctions]:
blcklst.extend(target.machines())
s = db.search('mblacklist=*&paiement=ok')
for target in s['machine']:
sanctions = target.blacklist_actif()
if [x for x in sanctions if x in blacklist_sanctions]:
blcklst.append(target)
if ipt.filter.blacklist_src.items:
ipt.filter.blacklist_src.items[:] = []
if ipt.filter.blacklist_dst.items:
ipt.filter.blacklist_dst.items[:] = []
for machine in blcklst:
ipt.blacklist(machine)
return 0
def ports_io(ipt, machine, type_machine, dev_ext, dev_crans):
''' Fonction ouvrant les ports d'une machine selon le contenu de la base
LDAP'''
ports_in = { 'tcp' : machine.portTCPin(),
'udp' : machine.portUDPin() }
ports_out = { 'tcp' : machine.portTCPout(),
'udp' : machine.portUDPout() }
if ports_in.values() != [[], []]:
ipt.extcrans(type_machine, ports_in, machine.mac(),
dev_ext)
if ports_out.values() != [[], []]:
ipt.cransext(type_machine, ports_out, machine.mac(),
dev_crans)
def mac_ip(ipt, machines, types_machines):
'''Réalise une correspondance MAC-IP pour un réseau considéré
On vérifie d'abord que la MAC est connue et ensuite on n'accepte que les
adresses en eui64'''
macips(ipt, machines, types_machines)
# TODO Il faut raffiner avant de rajouter le wifi
for type_m in types_machines:
if not '-v6' in type_m:
dev = iface6(type_m)
ipt.filter.input('-i %s -s %s -j %s' % (dev, prefix[type_m][0],
'MAC' + type_m.upper()))
ipt.filter.input('-i %s -j IEUI64' % dev)
ipt.filter.ieui64('-i %s -s %s -m eui64 -j RETURN' % (dev,
prefix[type_m][0]))
ipt.filter.ieui64('-s fe80::/64 -m eui64 -j RETURN')
ipt.filter.ieui64('-j DROP')
def macips(ipt, machines, types_machines):
''' Construit la chaîne MAC '''
for machine in machines:
for type_m in types_machines:
if int(machine.id()) in range(mid[type_m][0], mid[type_m][1]):
ipt.macip(machine.mac(), type_m)
break
for type_m in types_machines:
type_mm = re.sub('-', '', type_m)
eval('ipt.filter.mac' + type_mm)('-j DROP')
return 0