コード例 #1
0
    def setUp(self):

        self.bridges = copy.deepcopy(util.generateFakeBridges())

        self.fd, self.fname = tempfile.mkstemp(suffix=".sqlite",
                                               dir=os.getcwd())
        bridgedb.Storage.initializeDBLock()
        self.db = bridgedb.Storage.openDatabase(self.fname)
        bridgedb.Storage.setDBFilename(self.fname)

        key = 'fake-hmac-key'
        self.splitter = Bridges.BridgeSplitter(key)
        ringParams = Bridges.BridgeRingParameters(needPorts=[(443, 1)],
                                                  needFlags=[("Stable", 1)])
        self.https_distributor = HTTPSDistributor(4,
                                                  crypto.getHMAC(
                                                      key,
                                                      "HTTPS-IP-Dist-Key"),
                                                  None,
                                                  answerParameters=ringParams)
        self.moat_distributor = MoatDistributor(4,
                                                crypto.getHMAC(
                                                    key, "Moat-Dist-Key"),
                                                None,
                                                answerParameters=ringParams)
        self.unallocated_distributor = Bridges.UnallocatedHolder()

        self.splitter.addRing(self.https_distributor.hashring, "https", p=10)
        self.splitter.addRing(self.moat_distributor.hashring, "moat", p=10)
        self.splitter.addRing(self.unallocated_distributor,
                              "unallocated",
                              p=10)
        self.https_ring = self.splitter.ringsByName.get("https")
        self.moat_ring = self.splitter.ringsByName.get("moat")
        self.unallocated_ring = self.splitter.ringsByName.get("unallocated")
コード例 #2
0
def createBridgeRings(cfg, proxyList, key):
    """Create the bridge distributors defined by the config file

    :type cfg:  :class:`Conf`
    :param cfg: The current configuration, including any in-memory settings
        (i.e. settings whose values were not obtained from the config file,
        but were set via a function somewhere)
    :type proxyList: :class:`~bridgedb.proxy.ProxySet`
    :param proxyList: The container for the IP addresses of any currently
        known open proxies.
    :param bytes key: Hashring master key
    :rtype: tuple
    :returns: A BridgeSplitter hashring, an
        :class:`~bridgedb.https.distributor.HTTPSDistributor` or None, and an
        :class:`~bridgedb.email.distributor.EmailDistributor` or None.
    """
    # Create a BridgeSplitter to assign the bridges to the different
    # distributors.
    hashring = Bridges.BridgeSplitter(crypto.getHMAC(key, "Hashring-Key"))
    logging.debug("Created hashring: %r" % hashring)

    # Create ring parameters.
    ringParams = Bridges.BridgeRingParameters(needPorts=cfg.FORCE_PORTS,
                                              needFlags=cfg.FORCE_FLAGS)

    emailDistributor = ipDistributor = None
    # As appropriate, create an IP-based distributor.
    if cfg.HTTPS_DIST and cfg.HTTPS_SHARE:
        logging.debug("Setting up HTTPS Distributor...")
        ipDistributor = HTTPSDistributor(cfg.N_IP_CLUSTERS,
                                         crypto.getHMAC(
                                             key, "HTTPS-IP-Dist-Key"),
                                         proxyList,
                                         answerParameters=ringParams)
        hashring.addRing(ipDistributor.hashring, "https", cfg.HTTPS_SHARE)

    # As appropriate, create an email-based distributor.
    if cfg.EMAIL_DIST and cfg.EMAIL_SHARE:
        logging.debug("Setting up Email Distributor...")
        emailDistributor = EmailDistributor(
            crypto.getHMAC(key, "Email-Dist-Key"),
            cfg.EMAIL_DOMAIN_MAP.copy(),
            cfg.EMAIL_DOMAIN_RULES.copy(),
            answerParameters=ringParams,
            whitelist=cfg.EMAIL_WHITELIST.copy())
        hashring.addRing(emailDistributor.hashring, "email", cfg.EMAIL_SHARE)

    # As appropriate, tell the hashring to leave some bridges unallocated.
    if cfg.RESERVED_SHARE:
        hashring.addRing(Bridges.UnallocatedHolder(), "unallocated",
                         cfg.RESERVED_SHARE)

    # Add pseudo distributors to hashring
    for pseudoRing in cfg.FILE_BUCKETS.keys():
        hashring.addPseudoRing(pseudoRing)

    return hashring, emailDistributor, ipDistributor
コード例 #3
0
def startup(cfg):
    """Parse bridges,
    """
    # Expand any ~ characters in paths in the configuration.
    cfg.BRIDGE_FILES = [os.path.expanduser(fn) for fn in cfg.BRIDGE_FILES]
    for key in ("RUN_IN_DIR", "DB_FILE", "DB_LOG_FILE", "MASTER_KEY_FILE",
                "ASSIGNMENTS_FILE", "HTTPS_CERT_FILE", "HTTPS_KEY_FILE",
                "PIDFILE", "LOGFILE", "STATUS_FILE"):

        v = getattr(cfg, key, None)
        if v:
            setattr(cfg, key, os.path.expanduser(v))
    if hasattr(cfg, "PROXY_LIST_FILES"):
        cfg.PROXY_LIST_FILES = [
            os.path.expanduser(v) for v in cfg.PROXY_LIST_FILES
        ]
    else:
        cfg.PROXY_LIST_FILES = []

    # Write the pidfile.
    if cfg.PIDFILE:
        f = open(cfg.PIDFILE, 'w')
        f.write("%s\n" % os.getpid())
        f.close()

    # Set up logging.
    configureLogging(cfg)

    #XXX import Server after logging is set up
    # Otherwise, python will create a default handler that logs to
    # the console and ignore further basicConfig calls
    import bridgedb.Server as Server

    # Load the master key, or create a new one.
    key = getKey(cfg.MASTER_KEY_FILE)

    # Initialize our DB file.
    db = bridgedb.Storage.Database(cfg.DB_FILE + ".sqlite", cfg.DB_FILE)
    bridgedb.Storage.setGlobalDB(db)

    # Get a proxy list.
    proxyList = ProxyCategory()
    proxyList.replaceProxyList(loadProxyList(cfg))

    # Create a BridgeSplitter to assign the bridges to the different
    # distributors.
    splitter = Bridges.BridgeSplitter(Bridges.get_hmac(key, "Splitter-Key"))

    # Create ring parameters.
    forcePorts = getattr(cfg, "FORCE_PORTS")
    forceFlags = getattr(cfg, "FORCE_FLAGS")
    if not forcePorts: forcePorts = []
    if not forceFlags: forceFlags = []
    ringParams = Bridges.BridgeRingParameters(needPorts=forcePorts,
                                              needFlags=forceFlags)

    emailDistributor = ipDistributor = None
    # As appropriate, create an IP-based distributor.
    if cfg.HTTPS_DIST and cfg.HTTPS_SHARE:
        categories = []
        if proxyList.ipset:
            categories.append(proxyList)
        ipDistributor = Dist.IPBasedDistributor(Dist.uniformMap,
                                                cfg.N_IP_CLUSTERS,
                                                Bridges.get_hmac(
                                                    key, "HTTPS-IP-Dist-Key"),
                                                categories,
                                                answerParameters=ringParams)
        splitter.addRing(ipDistributor, "https", cfg.HTTPS_SHARE)
        #webSchedule = Time.IntervalSchedule("day", 2)
        webSchedule = Time.NoSchedule()

    # As appropriate, create an email-based distributor.
    if cfg.EMAIL_DIST and cfg.EMAIL_SHARE:
        for d in cfg.EMAIL_DOMAINS:
            cfg.EMAIL_DOMAIN_MAP[d] = d
        emailDistributor = Dist.EmailBasedDistributor(
            Bridges.get_hmac(key, "Email-Dist-Key"),
            cfg.EMAIL_DOMAIN_MAP.copy(),
            cfg.EMAIL_DOMAIN_RULES.copy(),
            answerParameters=ringParams)
        splitter.addRing(emailDistributor, "email", cfg.EMAIL_SHARE)
        #emailSchedule = Time.IntervalSchedule("day", 1)
        emailSchedule = Time.NoSchedule()

    # As appropriate, tell the splitter to leave some bridges unallocated.
    if cfg.RESERVED_SHARE:
        splitter.addRing(Bridges.UnallocatedHolder(), "unallocated",
                         cfg.RESERVED_SHARE)

    # Add pseudo distributors to splitter
    for p in cfg.FILE_BUCKETS.keys():
        splitter.addPseudoRing(p)

    # Make the parse-bridges function get re-called on SIGHUP.
    def reload():
        logging.info("Caught SIGHUP")
        load(cfg, splitter, clear=True)
        proxyList.replaceProxyList(loadProxyList(cfg))
        logging.info("%d bridges loaded", len(splitter))
        if emailDistributor:
            logging.info("%d for email", len(emailDistributor.ring))
        if ipDistributor:
            logging.info("%d for web:", len(ipDistributor.splitter))
            logging.info("  by location set: %s",
                         " ".join(str(len(r)) for r in ipDistributor.rings))
            logging.info(
                "  by category set: %s",
                " ".join(str(len(r)) for r in ipDistributor.categoryRings))
            logging.info("Here are all known bridges in the category section:")
            for r in ipDistributor.categoryRings:
                for name, b in r.bridges.items():
                    logging.info("%s" % b.getConfigLine(True))

        # Dump bridge pool assignments to disk.
        try:
            f = open(cfg.ASSIGNMENTS_FILE, 'a')
            f.write("bridge-pool-assignment %s\n" %
                    time.strftime("%Y-%m-%d %H:%M:%S"))
            splitter.dumpAssignments(f)
            f.close()
        except IOError:
            logging.info("I/O error while writing assignments")

    global _reloadFn
    _reloadFn = reload
    signal.signal(signal.SIGHUP, _handleSIGHUP)

    # And actually load it to start.
    reload()

    # Configure HTTP and/or HTTPS servers.
    if cfg.HTTPS_DIST and cfg.HTTPS_SHARE:
        Server.addWebServer(cfg, ipDistributor, webSchedule)

    # Configure Email servers.
    if cfg.EMAIL_DIST and cfg.EMAIL_SHARE:
        Server.addSMTPServer(cfg, emailDistributor, emailSchedule)

    # Actually run the servers.
    try:
        logging.info("Starting reactors.")
        Server.runServers()
    finally:
        db.close()
        if cfg.PIDFILE:
            os.unlink(cfg.PIDFILE)