]> gitweb.pimeys.fr Git - scripts-20-100.git/blob - firewall/block_torrent_ip.py
typo
[scripts-20-100.git] / firewall / block_torrent_ip.py
1 #!/usr/bin/env python
2 #-*- coding: utf-8 -*-
3
4 """ Script qui récupère la liste des IP des ayants-droits pour empêcher
5 un utilisateur système de communiquer avec en les ajoutant dans le firewall"""
6
7 import urllib
8 import re
9 import zlib
10 import netaddr
11 import sys
12 import subprocess
13 import itertools
14 import json
15
16 ### Configuration
17 #: URL de la liste
18 source_url = u"http://iblocklist.commiecast.com/f/tagqfxtteucbuldhezkz/bt_level1.gz"
19
20 #: Nom d'utilisateur UNIX de l'user qui lance le client torrent
21 torrent_username = "vincent"
22
23 #: IPs qu'on ne veut surtout pas blacklister
24 whitelist = [netaddr.IPAddress("138.231.136.1")]
25
26 #: Faut-il parler sur la sortie standard ?
27 DEBUG = True
28
29 #: Nom de la chaîne créée
30 chain_name = "TORRENT"
31
32 #: Fichier où sauvegarder la liste des IPs
33 memfile = "/root/torrent/blocked_ips.json"
34
35 def _get_data():
36 """Récupère le raw de la page de la liste."""
37 if DEBUG:
38 print("Loading page")
39 page = urllib.urlopen(source_url)
40 zip = page.read()
41 if DEBUG:
42 print("Decompressing list")
43 data = zlib.decompress(zip, 15+32)
44 return data
45
46 def retrieve_ips(limit=None):
47 """Récupère et parse la liste des IPs."""
48 data = _get_data()
49 lines = data.split("\n")
50 ip_regexp = re.compile(r".*?(?P<debut>(?:\d{1,3}\.){3}\d{1,3})-(?P<fin>(?:\d{1,3}\.){3}\d{1,3})$")
51 ips = []
52 if DEBUG:
53 print("Parsing list")
54 for l in lines:
55 match = ip_regexp.match(l)
56 if match:
57 ips.append([match.groupdict()["debut"], match.groupdict()["fin"]])
58 if limit:
59 return ips[:limit]
60 return ips
61
62 def process_ranges(liste):
63 """Convertit la liste de [ip début, ip fin] en liste de cidr (/)."""
64 if DEBUG:
65 print("Converting to CIDRs (this may take some time)")
66 cidrs = []
67 for (i, [deb, fin]) in enumerate(liste):
68 #if not i%1000:
69 # print "%s/%s" % (i, len(liste))
70 cidrs.append(netaddr.iprange_to_cidrs(deb, fin))
71 cidrs = list(itertools.chain.from_iterable(cidrs))
72 return [str(s) for s in cidrs]
73
74 def store_ips(slashes):
75 """Sauvegarde la liste des IPs toute utilisable."""
76 json.dump(slashes, open(memfile, "w"))
77
78 def load_ips():
79 """Récupère la liste des IPs précédemment sauvegardée sur le disque."""
80 return json.load(open(memfile))
81
82 def update_liste():
83 """Met à jour le fichier contenant la liste des IPs."""
84 ips = retrieve_ips()
85 slashes = process_ranges(ips)
86 store_ips(slashes)
87
88 def compute_iptables_rules(slashes):
89 """Fabrique les règles iptables à partir de la liste des IPs."""
90 # On vérifie qu'on ne bloque pas une IP de la whitelist
91 if DEBUG:
92 print("Checking whitelist")
93 remove = []
94 for i in xrange(len(slashes)):
95 for white in whitelist:
96 if white in netaddr.IPNetwork(slashes[i]):
97 remove.append(i)
98 break
99 if remove:
100 print "Ranges contenant une IP whitelistée :"
101 print [str(slashes[i]) for i in remove]
102 remove.reverse()
103 for i in remove:
104 del slashes[i]
105 if DEBUG:
106 print("Generating rules")
107 rules = []
108 for s in slashes:
109 rules.append("-A %s -d %s -j REJECT" % (chain_name, s))
110 return rules
111
112 def iptables(params):
113 """Appel à iptables"""
114 proc = subprocess.Popen(["iptables"] + params.split(), stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
115 out, err = proc.communicate()
116 return err
117
118
119 def flush():
120 """Nettoie le pare-feu des règles générées par ce script."""
121 if DEBUG:
122 print("Flushing rules")
123 err = iptables("-D OUTPUT -m owner --uid-owner %s -j %s" % (torrent_username, chain_name))
124 err += iptables("-F %s" % (chain_name,))
125 err += iptables("-X %s" % (chain_name,))
126 if DEBUG:
127 sys.stderr.write(err)
128
129 def initialize():
130 """Créée les règles de base (indépendantes de la liste d'IPs)."""
131 if DEBUG:
132 print("Adding basic rules")
133 # err = iptables("-N %s" % (chain_name,))
134 err = iptables("-A OUTPUT -m owner --uid-owner %s -j %s" % (torrent_username, chain_name))
135 if DEBUG:
136 sys.stderr.write(err)
137
138 def add_rules(rules):
139 """Ajoute les règles computées"""
140 if DEBUG:
141 print("Adding rules")
142 generated = "*filter\n:%s - [0:0]" % chain_name
143 generated += "\n".join(rules)
144 generated += "\nCOMMIT\n"
145 proc = subprocess.Popen(["iptables-restore"], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
146 out, err = proc.communicate(input=generated)
147 if DEBUG:
148 sys.stderr.write(err)
149
150 if __name__ == "__main__":
151 if "--debug" in sys.argv:
152 DEBUG = True
153 if "--quiet" in sys.argv:
154 DEBUG = False
155 if len(sys.argv) == 1 or sys.argv[1] == "help" or "-h" in sys.argv:
156 print "Usage : fournir un paramètre update ou start ou stop"
157 elif sys.argv[1] == "update":
158 update_liste()
159 elif sys.argv[1] == "start":
160 slashes = load_ips()
161 rules = compute_iptables_rules(slashes)
162 add_rules(rules)
163 initialize()
164 elif sys.argv[1] == "stop":
165 flush()