From 9c7cbce83edb52bf3c8b3ec4e75120d76b6db6bc Mon Sep 17 00:00:00 2001 From: Valentin Samir Date: Wed, 3 Apr 2013 10:20:47 +0200 Subject: [PATCH] =?UTF-8?q?[firewall4]=20D=C3=A9but=20de=20remise=20au=20p?= =?UTF-8?q?ropre=20du=20pare-feu=20ipv4=20Celui=20de=20komaz=20et=20le=20p?= =?UTF-8?q?are-feu=20g=C3=A9n=C3=A9rique=20(mac-ip=20et=20blacklist)=20son?= =?UTF-8?q?t=20fonctionnel,=20il=20ne=20manque=20que=20la=20limitation=20d?= =?UTF-8?q?e=20d=C3=A9bit=20et=20la=20QoS=20pour=20komaz?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- gestion/gen_confs/firewall4.py | 757 +++++++++++++++++++++++++++++++++ 1 file changed, 757 insertions(+) create mode 100755 gestion/gen_confs/firewall4.py diff --git a/gestion/gen_confs/firewall4.py b/gestion/gen_confs/firewall4.py new file mode 100755 index 00000000..22b0b558 --- /dev/null +++ b/gestion/gen_confs/firewall4.py @@ -0,0 +1,757 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + + + +import sys +import os +sys.path.append('/usr/scripts/gestion') +sys.path.append('/usr/scripts/lc_ldap') + +from config import NETs, blacklist_sanctions, blacklist_sanctions_soft, mac_komaz, mac_titanic + +import config.firewall +import lc_ldap +import socket +from ipset import IpsetError, Ipset +from iptools import AddrInNet, NetSubnets, IpSubnet, NetInNets +import subprocess +from affich_tools import * + +squeeze = os.uname()[2] < '3' + +conn = lc_ldap.lc_ldap_admin() +hostname = socket.gethostname() + +default_chains = ['INPUT', 'OUTPUT', 'FORWARD', 'PREROUTING', 'POSTROUTING'] +tables = ['raw', 'mangle', 'filter', 'nat'] + +dev = hostname in config.firewall.dev.keys() and config.firewall.dev[hostname] or {} + +def pretty_print(table, chain): + anim('\t%s dans %s' % (chain, table)) + +class firewall_base(object) : + + def machines(self): + if self._machines: + return self._machines + self._machines, self._adherents = conn.allMachinesAdherents() + return self._machines + + def adherents(self): + if self._adherents: + return self._adherents + self._machines, self._adherents = conn.allMachinesAdherents() + self._adherents = [ adh for adh in self._adherents if adh.paiement_ok ] + return self._adherents + + def blacklisted_machines(self): + if self._blacklisted_machines: + return self._blacklisted_machines + if self._machines: + self._blacklisted_machines = [ machine for machine in self._machines if machine.blacklist_actif() ] + return self._blacklisted_machines + blacklisted = [ machine for machine in conn.search("blacklist=*",sizelimit=4096) if machine.blacklist_actif() ] + self._blacklisted_machines = set() + for item in blacklisted: + if isinstance(item, lc_ldap.proprio): + self._blacklisted_machines = self._blacklisted_machines.union(item.machines()) + elif isinstance(item, lc_ldap.machine): + self._blacklisted_machines.add(item) + else: + print >> sys.stderr, 'Objet %s inconnu blacklisté' % a.__class__.__name__ + return self._blacklisted_machines + + def add(self, table, chain, rule): + 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): + if not table: + for table in tables: + self.delete(table, chain) + if not chain: + for chain in self.chain_list[table]: + self.delete(table, chain) + self.clear(table, chain) + + def flush(self, table=None, chain=None): + if not table: + for table in tables: + self.flush(table, chain) + if not chain: + for chain in self.chain_list[table]: + self.flush(table, chain) + self.clear(table, chain) + self.chain_list[table].append(chain) + self.rules_list[table][chain]=[] + + def clear(self, table, chain): + if not chain in self.chain_list[table]: + return + if not chain in default_chains: + self.chain_list[table].remove(chain) + del(self.rules_list[table][chain]) + else: + self.rules_list[table][chain]=[] + + def restore(self, noflush=False, table=None, chains=[]): + str=self.format(chains) + f=open('/tmp/ipt_rules', 'w') + f.write(str) + f.close() + params = ['/sbin/iptables-restore'] + if noflush: + params.append('--noflush') + if table and table in ['raw', 'mangle', 'filter', 'nat']: + params.append('--table') + params.append(table) + p = subprocess.Popen(params , stdin=subprocess.PIPE) + p.communicate(input=str) + + def apply(self, table, chain): + if not chain in self.chain_list[table]: + return + + str = self.format([chain]) + # TODO + + self.clear(table, chain) + + def format(self, chains=[]): + str = '' + for table in self.chain_list.keys(): + str += '*%s\n' % table + for chain in self.chain_list[table]: + if not chains or chain in chains or chain in default_chains: + str += ':%s %s [0:0]\n' % (chain, chain in default_chains and 'ACCEPT' or '-') + for chain in self.chain_list[table]: + if not chains or chain in chains : + for rule in self.rules_list[table][chain]: + str += '-A %s %s\n' % (chain, rule) + self.clear(table, chain) + str += 'COMMIT\n' + return str + + def __init__(self): + #initialisation des structures communes : récupération des ipset + + self.reloadable = { + 'blacklist_hard' : self.blacklist_hard, + 'test_mac_ip' : self.test_mac_ip, + } + + self.use_ipset = [self.blacklist_hard, self.test_mac_ip] + + self._machines = None + self._adherents = None + self._blacklisted_machines = None + + self.chain_list={ + 'raw':['OUTPUT', 'PREROUTING'], + 'mangle':['INPUT', 'OUTPUT', 'FORWARD', 'PREROUTING', 'POSTROUTING'], + 'filter':['INPUT', 'OUTPUT', 'FORWARD'], + 'nat':['OUTPUT', 'PREROUTING', 'POSTROUTING'] + } + self.rules_list = { + 'raw': { 'OUTPUT':[], 'PREROUTING':[] }, + 'mangle':{'INPUT':[], 'OUTPUT':[], 'FORWARD':[], 'PREROUTING':[], 'POSTROUTING':[]}, + 'filter':{'INPUT':[], 'OUTPUT':[], 'FORWARD':[]}, + 'nat':{'OUTPUT':[], 'PREROUTING':[], 'POSTROUTING':[]} + } + + self.ipset={} + + self.ipset['mac_ip']={ + 'adh' : Ipset("MAC-IP-ADH","macipmap","--from 138.231.136.0 --to 138.231.151.255"), + 'adm' : Ipset("MAC-IP-ADM","macipmap","--from 10.231.136.0 --to 10.231.136.255"), + 'app' : Ipset("MAC-IP-APP","macipmap","--from 10.2.9.0 --to 10.2.9.255"), + } + + self.ipset['blacklist']={ + 'soft' : Ipset("BLACKLIST-SOFT","ipmap","--from 138.231.136.0 --to 138.231.151.255"), + 'hard' : Ipset("BLACKLIST-HARD","ipmap","--from 138.231.136.0 --to 138.231.151.255"), + } + + + + def start(self): + # On precache avant tout la liste des machines et des adhérents, on en aura besoin + anim('\tChargement des machines') + self.machines() + print OK + + if squeeze: + anim('\tVidage du pare-feu') + fw.restore() + print OK + + self.raw_table() + self.mangle_table() + self.filter_table() + self.nat_table() + + anim('\tRestoration d\'iptables') + fw.restore() + print OK + return + + def stop(self): + + fw.delete() + fw.restore() + return + + def restart(self): + self.start() + return + + + def raw_table(self): + table = 'raw' + return + + def mangle_table(self): + table = 'mangle' + return + + def filter_table(self): + table = 'filter' + + mac_ip_chain = self.test_mac_ip(table, fill_ipset=True) + blacklist_hard_chain = self.blacklist_hard(table, fill_ipset=True) + + chain = 'INPUT' + self.add(table, chain, '-i lo -j ACCEPT') + self.add(table, chain, '-p icmp -j ACCEPT') + self.add(table, chain, '-m state --state RELATED,ESTABLISHED -j ACCEPT') + for net in NETs['all'] + NETs['adm'] + NETs['personnel-ens']: + self.add(table, chain, '-s %s -j %s' % (net, mac_ip_chain)) + self.add(table, chain, '-j %s' % blacklist_hard_chain) + + chain = 'FORWARD' + self.add(table, chain, '-j REJECT') + + return + + def nat_table(self): + table = 'nat' + return + + + + + def blacklist_hard_maj(self, ip_list): + for ip in ip_list: + machine = db.search("ipHostNumber=%s" % ip) + # Est-ce qu'il y a des blacklists hard parmis les blacklists de la machine + if set([bl.value['type'] for bl in machine.blacklist_actif() ]).intersection(blacklist_sanctions): + try: self.ipset['blacklist']['hard'].add(ip) + except IpsetError: pass + else: + try: self.ipset['blacklist']['hard'].delete(ip) + except IpsetError: pass + + def blacklist_hard(self, table=None, fill_ipset=False, apply=False): + chain = 'BLACKLIST_HARD' + + if fill_ipset: + anim('\tRestoration de l\'ipset %s' % self.ipset['blacklist']['hard']) + # On récupère la liste de toutes les ips blacklistés hard + bl_hard_ips = set( + str(ip) for ips in + [ + machine['ipHostNumber'] for machine in self.blacklisted_machines() + if set([bl.value['type'] for bl in machine.blacklist_actif() ]).intersection(blacklist_sanctions) + ] + for ip in ips + ) + + self.ipset['blacklist']['hard'].restore(bl_hard_ips) + print OK + + if table == 'filter': + pretty_print(table, chain) + self.add(table, chain, '-m set --match-set %s src -j REJECT' % self.ipset['blacklist']['hard'] ) + self.add(table, chain, '-m set --match-set %s dst -j REJECT' % self.ipset['blacklist']['hard'] ) + print OK + + if apply: + self.apply(table, chain) + return chain + + def test_mac_ip_dispatch(self, func, machine): + """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 + if AddrInNet(str(ip), NETs['wifi']): + # Komaz voit directement les machines wifi + if hostname == 'komaz': + func('adh', "%s,%s" % (ip, machine['macAddress'][0])) + # Les autres serveurs les voient à travers komaz + else: + func('adh', "%s,%s" % (ip, mac_komaz)) + elif AddrInNet(str(ip), NETs['fil']): + func('adh', "%s,%s" % (ip, machine['macAddress'][0])) + # Si la machine est sur le réseau admin + elif AddrInNet(str(ip), NETs['adm']): + func('adm', "%s,%s" % (ip, machine['macAddress'][0])) + # Si la machine est sur le réseaux des appartements de l'ENS + elif AddrInNet(str(ip), NETs['personnel-ens']): + # Les machines sont natter derrire komaz + if hostname == 'komaz': + func('app', "%s,%s" % (ip, machine['macAddress'][0])) + + def test_mac_ip(self, table=None, fill_ipset=False, apply=False): + chain = 'TEST_MAC-IP' + + if fill_ipset: + anim('\tRestoration des ipsets %s' % ', '.join(self.ipset['mac_ip'].keys())) + rules={ + 'adh':[], + 'adm':[], + 'app':[], + } + for machine in self.machines(): + self.test_mac_ip_dispatch(lambda set, data: rules[set].append(data), machine) + + for set,rules in rules.items(): + self.ipset['mac_ip'][set].restore(rules) + print OK + + if table == 'filter': + pretty_print(table, chain) + if hostname == 'komaz': + for key in ['out', 'tun-ovh' ]: + self.add(table, chain, '-i %s -j RETURN' % dev[key]) + + for key in ['accueil', 'isolement', ]: + for net in NETs[key]: + self.add(table, chain, '-s %s -j RETURN' % net) + for key in self.ipset['mac_ip'].keys(): + self.add(table, chain, '-m set --match-set %s src,src -j RETURN' % self.ipset['mac_ip'][key]) + + # Proxy ARP de Komaz et Titanic pour OVH + ip_ovh = conn.search("host=ovh.adm.crans.org")[0]['ipHostNumber'][0] + self.add(table, chain, '-m mac -s %s --mac-source %s -j RETURN' % (ip_ovh, mac_komaz)) + self.add(table, chain, '-m mac -s %s --mac-source %s -j RETURN' % (ip_ovh, mac_titanic)) + + self.add(table, chain, '-j REJECT') + print OK + + if apply: + self.apply(table, chain) + return chain + + def mac_ip_maj(self, ip_list): + for ip in ip_list: + machine = db.search("ipHostNumber=%s" % ip) + if machine: + try: test_mac_ip_dispatch(lambda set, data: self.ipset['mac_ip'][set].add(data), machine) + except IpsetError: pass + else: + try: test_mac_ip_dispatch(lambda set, data: self.ipset['mac_ip'][set].delete(data), machine) + except IpsetError: pass + + +class firewall_komaz(firewall_base): + + def __init__(self): + super(self.__class__, self).__init__() + + self.reloadable.update({ + 'log_all' : self.log_all, + 'admin_vlan' : self.admin_vlan, + 'clamp_mss' : self.clamp_mss, + 'ingress_filtering' : self.ingress_filtering, + 'ssh_on_https' : self.ssh_on_https, + 'connexion_secours' : self.connexion_secours, + 'connexion_appartement' : self.connexion_appartement, + 'blacklist_soft' : self.blacklist_soft, + 'reseaux_non_routable' : self.reseaux_non_routable, + 'filtrage_ports' : self.filtrage_ports, + }) + + self.use_ipset.extend([self.blacklist_soft, self.reseaux_non_routable]) + + self.ipset['reseaux_non_routable'] = { + 'deny' : Ipset("RESEAUX-NON-ROUTABLE-DENY","nethash"), + 'allow' : Ipset("RESEAUX-NON-ROUTABLE-ALLOW","nethash"), + } + + def raw_table(self): + return + + def mangle_table(self): + table = 'mangle' + super(self.__class__, self).mangle_table() + + chain = 'PREROUTING' + self.add(table, chain, '-j %s' % self.log_all(table)) + self.add(table, chain, '-j %s' % self.blacklist_soft(table, fill_ipset=True)) + self.add(table, chain, '-j %s' % self.connexion_secours(table)) + self.add(table, chain, '-p tcp -j CONNMARK --restore-mark') + + chain = 'POSTROUNTING' + self.add(table, chain, '-j %s' % self.clamp_mss(table)) + #TODO QoS + return + + def filter_table(self): + table = 'filter' + super(self.__class__, self).filter_table() + + mac_ip_chain = self.test_mac_ip() + blacklist_hard_chain = self.blacklist_hard() + + chain = 'FORWARD' + self.clear(table, chain) + self.add(table, chain, '-i lo -j ACCEPT') + self.add(table, chain, '-p icmp -j ACCEPT') + self.add(table, chain, '-j %s' % self.admin_vlan(table)) + self.add(table, chain, '-m state --state RELATED,ESTABLISHED -j ACCEPT') + self.add(table, chain, '-j %s' % self.reseaux_non_routable(table, fill_ipset=True)) + self.add(table, chain, '-j %s' % self.blacklist_soft(table)) + for net in NETs['all'] + NETs['adm'] + NETs['personnel-ens']: + self.add(table, chain, '-s %s -j %s' % (net, mac_ip_chain)) + self.add(table, chain, '-i %s -j %s' % (dev['out'], blacklist_hard_chain)) + self.add(table, chain, '-o %s -j %s' % (dev['out'], blacklist_hard_chain)) + self.add(table, chain, '-j %s' % self.connexion_secours(table)) + self.add(table, chain, '-j %s' % self.connexion_appartement(table)) + self.add(table, chain, '-j %s' % self.ingress_filtering(table)) + self.add(table, chain, '-j %s' % self.filtrage_ports(table)) + return + + def nat_table(self): + table = 'nat' + super(self.__class__, self).nat_table() + + chain = 'PREROUTING' + self.add(table, chain, '-j %s' % self.ssh_on_https(table)) + self.add(table, chain, '-j %s' % self.connexion_secours(table)) + self.add(table, chain, '-j %s' % self.blacklist_soft(table)) + + chain = 'POSTROUTING' + self.add(table, chain, '-j %s' % self.connexion_appartement(table)) + return + + + def log_all(self, table=None, apply=False): + chain = 'LOG_ALL' + + if table == 'mangle': + pretty_print(table, chain) + for device in dev.values(): + self.add(table, chain, '-i %s -m state --state NEW -j LOG --log-prefix "LOG_ALL "' % device) + print OK + + if apply: + self.apply(table, chain) + return chain + + def admin_vlan(self, table=None, apply=False): + chain = 'VLAN-ADM' + + if table == 'filter': + pretty_print(table, chain) + for net in NETs['adm']: + self.add(table, chain, '-d %s -j REJECT' % net) + print OK + + if apply: + self.apply(table, chain) + return chain + + def qos(self, table=None, apply=False): + return + + def clamp_mss(self, table=None, apply=False): + chain = 'CLAMP-MSS' + if table == 'mangle': + pretty_print(table, chain) + + self.add(table, chain, '-p tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu') + print OK + + if apply: + self.apply(table, chain) + 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) + """ + chain = 'INGRESS_FILTERING' + if table == 'filter': + pretty_print(table, chain) + + for net in NETs['all']: + self.add(table, chain, '-o %s -s %s -j RETURN' % (dev['out'], net)) + self.add(table, chain, '-o %s -j LOG --log-prefix BAD_ROUTE' % dev['out']) + self.add(table, chain, '-o %s -j DROP' % dev['out']) + for net_d in NETs['all']: + for net_s in NETs['all']: + self.add(table, chain,'-i %s ! -s %s -d %s -j RETURN' % (dev['out'], net_s, net_d)) + self.add(table, chain,'-i %s -j LOG --log-prefix BAD_SRC' % dev['out']) + self.add(table, chain,'-i %s -j DROP' % dev['out']) + print OK + + if apply: + self.apply(table, chain) + return chain + + def ssh_on_https(self, table=None, apply=False): + chain = 'SSH2' + + if table == 'nat': + pretty_print(table, chain) + self.add(table, chain, '-p tcp -d 138.231.136.2 --dport 22 -j DNAT --to-destination 138.231.136.1:22') # redirection du ssh vers zamok + self.add(table, chain, '-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) + print OK + + if apply: + self.apply(table, chain) + return chain + + def connexion_secours(self, table=None, apply=False): + chain = 'CONNEXION-SECOURS' + + if table == 'mangle': + pretty_print(table, chain) + self.add(table, chain, '-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' % (config.firewall.mark['secours'])) + self.add(table, chain, '-m mark --mark %s -j ACCEPT' % config.firewall.mark['secours']) + print OK + + if table == 'nat': + pretty_print(table, chain) + self.add(table, chain, '-p tcp -m mark --mark %s -j DNAT --to-destination 10.231.136.4:3129' % config.firewall.mark['secours'] ) + print OK + + if table == 'filter': + pretty_print(table, chain) + self.add(table, chain, '-p tcp -s 138.231.136.0/16 ! -d 138.231.136.0/16 --destination-port 443 -m condition --condition secours -j REJECT') + self.add(table, chain, '-m mark --mark %s -j ACCEPT' % config.firewall.mark['secours']) + print OK + + if apply: + self.apply(table, chain) + return chain + + def connexion_appartement(self, table=None, apply=False): + chain = 'CONNEXION-APPARTEMENT' + + if table == 'nat': + pretty_print(table, chain) + for dev_key in ['out', 'fil', 'wifi']: + for net in NETs['personnel-ens']: + self.add(table, chain, '-o %s -s %s -j SNAT --to 138.231.136.44' % (dev[dev_key], net)) + print OK + + if table == 'filter': + pretty_print(table, chain) + for net in NETs['personnel-ens']: + self.add(table, chain, '-s %s -j ACCEPT' % net) + self.add(table, chain, '-d %s -j ACCEPT' % net) + print OK + + if apply: + self.apply(table, chain) + return chain + + def blacklist_soft_maj(self, ip_list): + for ip in ip_list: + machine = db.search("ipHostNumber=%s" % ip) + if not machine: + try: self.ipset['blacklist']['soft'].delete(ip) + except IpsetError: pass + else: + # Est-ce qu'il y a des blacklists soft parmis les blacklists de la machine + if set([bl.value['type'] for bl in machine.blacklist_actif() ]).intersection(blacklist_sanctions_soft): + try: self.ipset['blacklist']['soft'].add(ip) + except IpsetError: pass + else: + try: self.ipset['blacklist']['soft'].delete(ip) + except IpsetError: pass + + def blacklist_soft(self, table=None, fill_ipset=False, apply=False): + chain = 'BLACKLIST_SOFT' + + if fill_ipset: + anim('\tRestoration de l\'ipset %s' % self.ipset['blacklist']['soft']) + # On récupère la liste de toutes les ips blacklistés soft + bl_soft_ips = set( + str(ip) for ips in + [ + machine['ipHostNumber'] for machine in self.blacklisted_machines() + if set([bl.value['type'] for bl in machine.blacklist_actif() ]).intersection(blacklist_sanctions_soft) + ] + for ip in ips + ) + + self.ipset['blacklist']['soft'].restore(bl_soft_ips) + print OK + + if table == 'mangle': + pretty_print(table, chain) + self.add(table, chain, '-p tcp ! --dport 80 -j RETURN') + self.add(table, chain, '! -p tcp -j RETURN') + for net in NETs['all']: + self.add(table, chain, '-d %s -j RETURN' % net) + self.add(table, chain, '-m set --match-set %s src -j MARK --set-mark %s' + % (self.ipset['blacklist']['soft'], config.firewall.mark['proxy'])) + print OK + + if table == 'filter': + pretty_print(table, chain) + self.add(table, chain, '-m mark --mark %s -j ACCEPT' % config.firewall.mark['proxy']) + print OK + + if table == 'nat': + pretty_print(table, chain) + self.add(table, chain, '-p tcp -m mark --mark %s -j DNAT --to-destination 10.231.136.4:3128' % config.firewall.mark['proxy'] ) + print OK + + if apply: + self.apply(table, chain) + return chain + + def reseaux_non_routable(self, table=None, fill_ipset=False, apply=False): + chain = 'RESEAUX_NON_ROUTABLES' + + if fill_ipset: + anim('\tRestoration de l\'ipset reseaux_non_routable') + allowed = [ net for nets in NETs.values() for net in nets if NetInNets(net, config.firewall.reseaux_non_routables) ] + self.ipset['reseaux_non_routable']['allow'].restore(allowed) + self.ipset['reseaux_non_routable']['deny'].restore(config.firewall.reseaux_non_routables) + print OK + + if table == 'filter': + pretty_print(table, chain) + self.add(table, chain, '-m set --match-set %s src -j RETURN' % self.ipset['reseaux_non_routable']['allow']) + self.add(table, chain, '-m set --match-set %s dst -j RETURN' % self.ipset['reseaux_non_routable']['allow']) + self.add(table, chain, '-m set --match-set %s src -j DROP' % self.ipset['reseaux_non_routable']['deny']) + self.add(table, chain, '-m set --match-set %s dst -j DROP' % self.ipset['reseaux_non_routable']['deny']) + print OK + + if apply: + self.apply(table, chain) + return chain + + def filtrage_ports_maj(self, ip_lists): + self.filtrage_ports('filter', apply=True) + + def filtrage_ports(self, table=None, apply=False): + chain = 'FILTRAGE-PORTS' + + def format_port(port): + port = str(port) + if port.endswith(':'): + port = '%s65535' % port + if port.startswith(':'): + port = '0%s' % port + return port + + def add_ports(ip, proto, sens): + self.add( + table, + chain, + '-p %s -%s %s -m multiport --dports %s -j RETURN' % ( + proto, + (sens=='out' and 's') or (sens == 'in' and 'd'), + ip, + ','.join( format_port(port) for port in machine['portTCP%s' % sens]) + ) + ) + + if table == 'filter': + pretty_print(table, chain) + for machine in self.machines(): + for ip in machine['ipHostNumber']: + if 'portTCPout' in machine.attrs.keys(): + add_ports(ip,'tcp','out') + if 'portUDPout' in machine.attrs.keys(): + add_ports(ip,'udp','out') + if 'portTCPin' in machine.attrs.keys(): + add_ports(ip,'tcp','in') + if 'portUDPin' in machine.attrs.keys(): + add_ports(ip,'udp','in') + + for net in NETs['adherents'] + NETs['wifi-adh'] + NETs['personnel-ens']: + for proto in config.firewall.ports_default.keys(): + if config.firewall.ports_default[proto]['output']: + self.add(table, chain, '-p %s -s %s -m multiport --dports %s -j RETURN' % (proto, net, ','.join( format_port(port) for port in config.firewall.ports_default[proto]['output']))) + if config.firewall.ports_default[proto]['input']: + self.add(table, chain, '-p %s -d %s -m multiport --dports %s -j RETURN' % (proto, net, ','.join( format_port(port) for port in config.firewall.ports_default[proto]['input']))) + + self.add(table, chain, '-j REJECT') + print OK + + if apply: + self.apply(table, chain) + return chain + + +if __name__ == '__main__' : + firewall = { + 'komaz' : firewall_komaz, + } + # Chaînes pouvant être recontruites + if hostname in firewall.keys(): + fw = firewall[hostname]() + else: + fw = firewall_base() + chaines = fw.reloadable.keys() + + 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 : 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:] : + if arg == 'stop': + fw.stop() + elif arg == 'start': + fw.start() + elif arg == 'restart': + fw.restart() + else: + + if squeeze: + anim('\tVidage de %s' % fw.reloadable[arg]()) + for table in ['raw', 'mangle', 'filter', 'nat']: + fw.flush(table, fw.reloadable[arg]()) + fw.restore(noflush=True) + print OK + + for table in ['raw', 'mangle', 'filter', 'nat']: + fw.reloadable[arg](table) + if fw.reloadable[arg] in fw.use_ipset: + fw.reloadable[arg](fill_ipset=True) + + anim('\tRestoration d\'iptables') + fw.restore(noflush=True) + print OK \ No newline at end of file