From 58d1bd6309d0bf9f4dbbff9f5218f2d8adaf9f30 Mon Sep 17 00:00:00 2001 From: Vincent Le Gallic Date: Mon, 21 Oct 2013 00:17:54 +0200 Subject: [PATCH] =?utf8?q?Pour=20faire=20du=20torrent=20sans=20se=20faire?= =?utf8?q?=20d=C3=A9tecter?= MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit --- firewall/block_torrent_ip.py | 165 +++++++++++++++++++++++++++++++++++ 1 file changed, 165 insertions(+) create mode 100755 firewall/block_torrent_ip.py diff --git a/firewall/block_torrent_ip.py b/firewall/block_torrent_ip.py new file mode 100755 index 0000000..450701a --- /dev/null +++ b/firewall/block_torrent_ip.py @@ -0,0 +1,165 @@ +#!/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(?:\d{1,3}\.){3}\d{1,3})-(?P(?:\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() -- 2.39.2