commit 829f97037075ebb7022b01e8631d398a65919704 Author: Isis Lovecruft isis@torproject.org Date: Sat Jan 7 22:04:39 2017 +0000
Add support for blacklisting bad bridges.
* FIXES #21162: https://bugs.torproject.org/21162 --- bridgedb.conf | 10 +++++++ bridgedb/Main.py | 7 +++++ bridgedb/configure.py | 2 +- bridgedb/parse/blacklist.py | 67 +++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 85 insertions(+), 1 deletion(-)
diff --git a/bridgedb.conf b/bridgedb.conf index 2d73a2b..4c547f5 100644 --- a/bridgedb.conf +++ b/bridgedb.conf @@ -239,6 +239,16 @@ COLLECT_TIMESTAMPS = False # following countries: NO_DISTRIBUTION_COUNTRIES = ['IR', 'SY']
+# The path to a file containing the fingerprints of blacklisted bridges and +# their reason for being blacklisted. An entry should be in the form: +# +# FINGERPRINT [SP REASON] +# +# where REASON is optional and may contain whitespace. +# +# (See NO_DISTRIBUTION_FINGERPRINTS in the code for how this is used.) +NO_DISTRIBUTION_FILE = None + # A list of filenames that contain IP addresses (one per line) of proxies. # All IP-based distributors that see an incoming connection from a proxy # will treat them specially. diff --git a/bridgedb/Main.py b/bridgedb/Main.py index dc618cb..4990904 100644 --- a/bridgedb/Main.py +++ b/bridgedb/Main.py @@ -34,6 +34,7 @@ from bridgedb.configure import loadConfig from bridgedb.email.distributor import EmailDistributor from bridgedb.https.distributor import HTTPSDistributor from bridgedb.parse import descriptors +from bridgedb.parse.blacklist import parseBridgeBlacklistFile
import bridgedb.Storage
@@ -150,6 +151,8 @@ def load(state, hashring, clear=False): "but could not find bridge with that fingerprint.") % router.fingerprint)
+ blacklist = parseBridgeBlacklistFile(state.NO_DISTRIBUTION_FILE) + inserted = 0 logging.info("Inserting %d bridges into hashring..." % len(bridges)) for fingerprint, bridge in bridges.items(): @@ -159,6 +162,10 @@ def load(state, hashring, clear=False): if bridge.country in state.NO_DISTRIBUTION_COUNTRIES: logging.warn("Not distributing Bridge %s %s:%s in country %s!" % (bridge, bridge.address, bridge.orPort, bridge.country)) + # Skip insertion of blacklisted bridges. + elif bridge in blacklist.keys(): + logging.warn("Not distributing blacklisted Bridge %s %s:%s: %s" % + (bridge, bridge.address, bridge.orPort, blacklist[bridge])) else: # If the bridge is not running, then it is skipped during the # insertion process. diff --git a/bridgedb/configure.py b/bridgedb/configure.py index 6c13595..02eea65 100644 --- a/bridgedb/configure.py +++ b/bridgedb/configure.py @@ -113,7 +113,7 @@ def loadConfig(configFile=None, configCls=None): "LOG_FILE", "COUNTRY_BLOCK_FILE", "GIMP_CAPTCHA_DIR", "GIMP_CAPTCHA_HMAC_KEYFILE", "GIMP_CAPTCHA_RSA_KEYFILE", "EMAIL_GPG_HOMEDIR", - "EMAIL_GPG_PASSPHRASE_FILE"]: + "EMAIL_GPG_PASSPHRASE_FILE", "NO_DISTRIBUTION_FILE"]: setting = getattr(config, attr, None) if setting is None: setattr(config, attr, setting) diff --git a/bridgedb/parse/blacklist.py b/bridgedb/parse/blacklist.py new file mode 100644 index 0000000..092f3e1 --- /dev/null +++ b/bridgedb/parse/blacklist.py @@ -0,0 +1,67 @@ +# -*- coding: utf-8 ; test-case-name: bridgedb.test.test_parse_descriptors ; -*- +#_____________________________________________________________________________ +# +# This file is part of BridgeDB, a Tor bridge distribution system. +# +# :authors: Isis Lovecruft 0xA3ADB67A2CDB8B35 isis@torproject.org +# please also see AUTHORS file +# :copyright: (c) 2007-2017, The Tor Project, Inc. +# (c) 2014-2017, Isis Lovecruft +# :license: see LICENSE for licensing information +#_____________________________________________________________________________ + +"""Parsers for bridge blacklist files. + + +.. py:module:: bridgedb.parse.blacklist + :synopsis: Parsers for bridge blacklist files. + +bridgedb.parse.blacklist +=========================== +:: + + parseBridgeBlacklistFile - Parse a bridge blacklist file. +.. +""" + +from __future__ import print_function + +import logging + +from bridgedb.parse.fingerprint import isValidFingerprint + + +def parseBridgeBlacklistFile(filename): + """Parse a file of fingerprints of blacklisted bridges. + + This file should be specified in ``bridgedb.conf`` under the + ``NO_DISTRIBUTION_FILE`` setting, and each line in it should be + formatted in the following manner: + + FINGERPRINT [SP REASON] + + :type filename: str or None + :param filename: The path to or filename of the file containing + fingerprints of blacklisted bridges. + :returns: A dict whose keys are bridge fingerprints and values are + reasons for being blacklisted. + """ + fh = None + blacklist = {} + + if filename: + logging.info("Parsing bridge blacklist file: %s" % filename) + + try: + fh = open(filename) + except (OSError, IOError) as error: + logging.error("Error opening bridge blacklist file %s" % filename) + else: + for line in fh.readlines(): + fields = line.split(' ', 1) + fingerprint, reason = fields[0], fields[1] if len(fields)==2 else '' + + if isValidFingerprint(fingerprint): + blacklist[fingerprint] = reason + + return blacklist
tor-commits@lists.torproject.org