--- /dev/null
+#!/usr/bin/env python
+#-*- coding: utf-8 -*-
+
+""" Script qui récupère la liste des IP des ayants-droits pour empêcher
+ un utilisateur système de communiquer avec en les ajoutant dans le firewall"""
+
+import urllib
+import re
+import zlib
+import netaddr
+import sys
+import subprocess
+import itertools
+import json
+
+### Configuration
+#: URL de la liste
+source_url = u"http://iblocklist.commiecast.com/f/tagqfxtteucbuldhezkz/bt_level1.gz"
+
+#: Nom d'utilisateur UNIX de l'user qui lance le client torrent
+torrent_username = "vincent"
+
+#: IPs qu'on ne veut surtout pas blacklister
+whitelist = [netaddr.IPAddress("138.231.136.1")]
+
+#: Faut-il parler sur la sortie standard ?
+DEBUG = True
+
+#: Nom de la chaîne créée
+chain_name = "TORRENT"
+
+#: Fichier où sauvegarder la liste des IPs
+memfile = "/root/torrent/blocked_ips.json"
+
+def _get_data():
+ """Récupère le raw de la page de la liste."""
+ if DEBUG:
+ print("Loading page")
+ page = urllib.urlopen(source_url)
+ zip = page.read()
+ if DEBUG:
+ print("Decompressing list")
+ data = zlib.decompress(zip, 15+32)
+ return data
+
+def retrieve_ips(limit=None):
+ """Récupère et parse la liste des IPs."""
+ data = _get_data()
+ lines = data.split("\n")
+ ip_regexp = re.compile(r".*?(?P<debut>(?:\d{1,3}\.){3}\d{1,3})-(?P<fin>(?:\d{1,3}\.){3}\d{1,3})$")
+ ips = []
+ if DEBUG:
+ print("Parsing list")
+ for l in lines:
+ match = ip_regexp.match(l)
+ if match:
+ ips.append([match.groupdict()["debut"], match.groupdict()["fin"]])
+ if limit:
+ return ips[:limit]
+ return ips
+
+def process_ranges(liste):
+ """Convertit la liste de [ip début, ip fin] en liste de cidr (/)."""
+ if DEBUG:
+ print("Converting to CIDRs (this may take some time)")
+ cidrs = []
+ for (i, [deb, fin]) in enumerate(liste):
+ #if not i%1000:
+ # print "%s/%s" % (i, len(liste))
+ cidrs.append(netaddr.iprange_to_cidrs(deb, fin))
+ cidrs = list(itertools.chain.from_iterable(cidrs))
+ return [str(s) for s in cidrs]
+
+def store_ips(slashes):
+ """Sauvegarde la liste des IPs toute utilisable."""
+ json.dump(slashes, open(memfile, "w"))
+
+def load_ips():
+ """Récupère la liste des IPs précédemment sauvegardée sur le disque."""
+ return json.load(open(memfile))
+
+def update_liste():
+ """Met à jour le fichier contenant la liste des IPs."""
+ ips = retrieve_ips()
+ slashes = process_ranges(ips)
+ store_ips(slashes)
+
+def compute_iptables_rules(slashes):
+ """Fabrique les règles iptables à partir de la liste des IPs."""
+ # On vérifie qu'on ne bloque pas une IP de la whitelist
+ if DEBUG:
+ print("Checking whitelist")
+ remove = []
+ for i in xrange(len(slashes)):
+ for white in whitelist:
+ if white in netaddr.IPNetwork(slashes[i]):
+ remove.append(i)
+ break
+ if remove:
+ print "Ranges contenant une IP whitelistée :"
+ print [str(slashes[i]) for i in remove]
+ remove.reverse()
+ for i in remove:
+ del slashes[i]
+ if DEBUG:
+ print("Generating rules")
+ rules = []
+ for s in slashes:
+ rules.append("-A %s -d %s -j REJECT" % (chain_name, s))
+ return rules
+
+def iptables(params):
+ """Appel à iptables"""
+ proc = subprocess.Popen(["iptables"] + params.split(), stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+ out, err = proc.communicate()
+ return err
+
+
+def flush():
+ """Nettoie le pare-feu des règles générées par ce script."""
+ if DEBUG:
+ print("Flushing rules")
+ err = iptables("-D OUTPUT -m owner --uid-owner %s -j %s" % (torrent_username, chain_name))
+ err += iptables("-F %s" % (chain_name,))
+ err += iptables("-X %s" % (chain_name,))
+ if DEBUG:
+ sys.stderr.write(err)
+
+def initialize():
+ """Créée les règles de base (indépendantes de la liste d'IPs)."""
+ if DEBUG:
+ print("Adding basic rules")
+# err = iptables("-N %s" % (chain_name,))
+ err = iptables("-A OUTPUT -m owner --uid-owner %s -j %s" % (torrent_username, chain_name))
+ if DEBUG:
+ sys.stderr.write(err)
+
+def add_rules(rules):
+ """Ajoute les règles computées"""
+ if DEBUG:
+ print("Adding rules")
+ generated = "*filter\n:%s - [0:0]" % chain_name
+ generated += "\n".join(rules)
+ generated += "\nCOMMIT\n"
+ proc = subprocess.Popen(["iptables-restore"], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+ out, err = proc.communicate(input=generated)
+ if DEBUG:
+ sys.stderr.write(err)
+
+if __name__ == "__main__":
+ if "--debug" in sys.argv:
+ DEBUG = True
+ if "--quiet" in sys.argv:
+ DEBUG = False
+ if len(sys.argv) == 1 or sys.argv[1] == "help" or "-h" in sys.argv:
+ print "Usage : fournir un paramètre update ou start ou stop"
+ elif sys.argv[1] == "update":
+ update_liste()
+ elif sys.argv[1] == "start":
+ slashes = load_ips()
+ rules = compute_iptables_rules(slashes)
+ add_rules(rules)
+ initialize()
+ elif sys.argv[1] == "stop":
+ flush()