[tor-commits] [bridgedb/develop] Add support for blacklisting bad bridges.

isis at torproject.org isis at torproject.org
Mon Jan 9 20:01:54 UTC 2017


commit 829f97037075ebb7022b01e8631d398a65919704
Author: Isis Lovecruft <isis at 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 at 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





More information about the tor-commits mailing list