def prepopulateRings(self): logging.info("Prepopulating %s distributor hashrings..." % self.name) # populate all rings (for dumping assignments and testing) for filterFn in [None, filterBridgesByIP4, filterBridgesByIP6]: n = self.nClusters for category in self.categories: g = filterAssignBridgesToRing(self.splitter.hmac, self.nClusters + len(self.categories), n) bridgeFilterRules = [g] if filterFn: bridgeFilterRules.append(filterFn) ruleset = frozenset(bridgeFilterRules) key1 = getHMAC(self.splitter.key, "Order-Bridges-In-Ring-%d" % n) n += 1 ring = bridgedb.Bridges.BridgeRing(key1, self.answerParameters) ring.setName('{0} Ring'.format(self.name)) self.splitter.addRing(ring, ruleset, filterBridgesByRules(bridgeFilterRules), populate_from=self.splitter.bridges) # populate all ip clusters for clusterNum in xrange(self.nClusters): g = filterAssignBridgesToRing(self.splitter.hmac, self.nClusters + len(self.categories), clusterNum) bridgeFilterRules = [g] if filterFn: bridgeFilterRules.append(filterFn) ruleset = frozenset(bridgeFilterRules) key1 = getHMAC(self.splitter.key, "Order-Bridges-In-Ring-%d" % clusterNum) ring = bridgedb.Bridges.BridgeRing(key1, self.answerParameters) self.splitter.addRing(ring, ruleset, filterBridgesByRules(bridgeFilterRules), populate_from=self.splitter.bridges)
def prepopulateRings(self): # populate all rings (for dumping assignments and testing) for filterFn in [None, filterBridgesByIP4, filterBridgesByIP6]: n = self.nClusters for category in self.categories: g = filterAssignBridgesToRing( self.splitter.hmac, self.nClusters + len(self.categories), n) bridgeFilterRules = [g] if filterFn: bridgeFilterRules.append(filterFn) ruleset = frozenset(bridgeFilterRules) key1 = bridgedb.Bridges.get_hmac( self.splitter.key, "Order-Bridges-In-Ring-%d" % n) n += 1 ring = bridgedb.Bridges.BridgeRing(key1, self.answerParameters) self.splitter.addRing(ring, ruleset, filterBridgesByRules(bridgeFilterRules), populate_from=self.splitter.bridges) # populate all ip clusters for clusterNum in xrange(self.nClusters): g = filterAssignBridgesToRing( self.splitter.hmac, self.nClusters + len(self.categories), clusterNum) bridgeFilterRules = [g] if filterFn: bridgeFilterRules.append(filterFn) ruleset = frozenset(bridgeFilterRules) key1 = bridgedb.Bridges.get_hmac( self.splitter.key, "Order-Bridges-In-Ring-%d" % clusterNum) ring = bridgedb.Bridges.BridgeRing(key1, self.answerParameters) self.splitter.addRing(ring, ruleset, filterBridgesByRules(bridgeFilterRules), populate_from=self.splitter.bridges)
def prepopulateRings(self): # populate all rings (for dumping assignments and testing) for filterFn in [None, filterBridgesByIP4, filterBridgesByIP6]: n = self.nClusters for category in self.categories: g = filterAssignBridgesToRing(self.splitter.hmac, self.nClusters + len(self.categories), n) bridgeFilterRules = [g] if filterFn: bridgeFilterRules.append(filterFn) ruleset = frozenset(bridgeFilterRules) key1 = bridgedb.Bridges.get_hmac(self.splitter.key, "Order-Bridges-In-Ring-%d"%n) n += 1 ring = bridgedb.Bridges.BridgeRing(key1, self.answerParameters) self.splitter.addRing(ring, ruleset, filterBridgesByRules(bridgeFilterRules), populate_from=self.splitter.bridges) # populate all ip clusters for clusterNum in xrange(self.nClusters): g = filterAssignBridgesToRing(self.splitter.hmac, self.nClusters + len(self.categories), clusterNum) bridgeFilterRules = [g] if filterFn: bridgeFilterRules.append(filterFn) ruleset = frozenset(bridgeFilterRules) key1 = bridgedb.Bridges.get_hmac(self.splitter.key, "Order-Bridges-In-Ring-%d"%clusterNum) ring = bridgedb.Bridges.BridgeRing(key1, self.answerParameters) self.splitter.addRing(ring, ruleset, filterBridgesByRules(bridgeFilterRules), populate_from=self.splitter.bridges)
def getBridgesForIP(self, ip, epoch, N=1, countryCode=None, bridgeFilterRules=None): """Return a list of bridges to give to a user. :param str ip: The user's IP address, as a dotted quad. :param str epoch: The time period when we got this request. This can be any string, so long as it changes with every period. :param int N: The number of bridges to try to give back. (default: 1) :param str countryCode: The two-letter geoip country code of the client's IP address. If given, it is assumed that any bridges distributed to that client should not be blocked in that country. (default: None) :param list bridgeFilterRules: A list of callables used filter the bridges returned in the response to the client. See :mod:`~bridgedb.Filters`. :rtype: list :return: A list of :class:`~bridgedb.Bridges.Bridge`s to include in the response. See :meth:`bridgedb.HTTPServer.WebResource.getBridgeRequestAnswer` for an example of how this is used. """ logging.info("Attempting to return %d bridges to client %s..." % (N, ip)) if not bridgeFilterRules: bridgeFilterRules=[] if not len(self.splitter): logging.warn("Bailing! Splitter has zero bridges!") return [] logging.debug("Bridges in splitter:\t%d" % len(self.splitter)) logging.debug("Client request epoch:\t%s" % epoch) logging.debug("Active bridge filters:\t%s" % ' '.join([x.func_name for x in bridgeFilterRules])) area = self.areaMapper(ip) logging.debug("IP mapped to area:\t%s" % area) key1 = '' pos = 0 n = self.nClusters # only one of ip categories or area clustering is active # try to match the request to an ip category for category in self.categories: # IP Categories if ip in category: # The tag is a tag applied to a proxy IP address when it is # added to the bridgedb.proxy.ProxySet. For Tor Exit relays, # the default is 'exit_relay'. For other proxies loaded from # the PROXY_LIST_FILES config option, the default tag is the # full filename that the IP address originally came from. tag = category.getTag(ip) logging.info("Client was from known proxy (tag: %s): %s" % (tag, ip)) g = filterAssignBridgesToRing(self.splitter.hmac, self.nClusters + len(self.categories), n) bridgeFilterRules.append(g) # Cluster Tor/proxy users into four groups. This means that # no matter how many different Tor Exits or proxies a client # uses, the most they can ever get is four different sets of # bridge lines (per period). group = (int(ipaddr.IPAddress(ip)) % 4) + 1 logging.debug(("Assigning client hashring position based on: " "known-proxy<%s>%s") % (epoch, group)) pos = self.areaOrderHmac("known-proxy<%s>%s" % (epoch, group)) key1 = getHMAC(self.splitter.key, "Order-Bridges-In-Ring-%d" % n) break n += 1 # if no category matches, use area clustering else: # IP clustering h = int( self.areaClusterHmac(area)[:8], 16) # length of numClusters clusterNum = h % self.nClusters g = filterAssignBridgesToRing(self.splitter.hmac, self.nClusters + len(self.categories), clusterNum) bridgeFilterRules.append(g) pos = self.areaOrderHmac("<%s>%s" % (epoch, area)) key1 = getHMAC(self.splitter.key, "Order-Bridges-In-Ring-%d" % clusterNum) # try to find a cached copy ruleset = frozenset(bridgeFilterRules) # See if we have a cached copy of the ring, # otherwise, add a new ring and populate it if ruleset in self.splitter.filterRings.keys(): logging.debug("Cache hit %s" % ruleset) _, ring = self.splitter.filterRings[ruleset] # else create the ring and populate it else: logging.debug("Cache miss %s" % ruleset) ring = bridgedb.Bridges.BridgeRing(key1, self.answerParameters) self.splitter.addRing(ring, ruleset, filterBridgesByRules(bridgeFilterRules), populate_from=self.splitter.bridges) # get an appropriate number of bridges numBridgesToReturn = getNumBridgesPerAnswer(ring, max_bridges_per_answer=N) answer = ring.getBridges(pos, numBridgesToReturn) return answer
def getBridgesForIP(self, ip, epoch, N=1, countryCode=None, bridgeFilterRules=None): """Return a list of bridges to give to a user. :param str ip: The user's IP address, as a dotted quad. :param str epoch: The time period when we got this request. This can be any string, so long as it changes with every period. :param int N: The number of bridges to try to give back. (default: 1) :param str countryCode: DOCDOC (default: None) :param list bridgeFilterRules: A list of callables used filter the bridges returned in the response to the client. See :mod:`~bridgedb.Filters`. :rtype: list :return: A list of :class:`~bridgedb.Bridges.Bridge`s to include in the response. See :meth:`bridgedb.HTTPServer.WebResource.getBridgeRequestAnswer` for an example of how this is used. """ logging.info("Attempting to return %d bridges to client %s..." % (N, ip)) if not bridgeFilterRules: bridgeFilterRules=[] if not len(self.splitter): logging.warn("Bailing! Splitter has zero bridges!") return [] logging.debug("Bridges in splitter:\t%d" % len(self.splitter)) logging.debug("Client request epoch:\t%s" % epoch) logging.debug("Active bridge filters:\t%s" % ' '.join([x.func_name for x in bridgeFilterRules])) area = self.areaMapper(ip) logging.debug("IP mapped to area:\t%s" % logSafely("{0}.0/24".format(area))) key1 = '' pos = 0 n = self.nClusters # only one of ip categories or area clustering is active # try to match the request to an ip category for category in self.categories: # IP Categories if category.contains(ip): g = filterAssignBridgesToRing(self.splitter.hmac, self.nClusters + len(self.categories), n) bridgeFilterRules.append(g) logging.info("category<%s>%s", epoch, logSafely(area)) pos = self.areaOrderHmac("category<%s>%s" % (epoch, area)) key1 = getHMAC(self.splitter.key, "Order-Bridges-In-Ring-%d" % n) break n += 1 # if no category matches, use area clustering else: # IP clustering h = int( self.areaClusterHmac(area)[:8], 16) # length of numClusters clusterNum = h % self.nClusters g = filterAssignBridgesToRing(self.splitter.hmac, self.nClusters + len(self.categories), clusterNum) bridgeFilterRules.append(g) pos = self.areaOrderHmac("<%s>%s" % (epoch, area)) key1 = getHMAC(self.splitter.key, "Order-Bridges-In-Ring-%d" % clusterNum) # try to find a cached copy ruleset = frozenset(bridgeFilterRules) # See if we have a cached copy of the ring, # otherwise, add a new ring and populate it if ruleset in self.splitter.filterRings.keys(): logging.debug("Cache hit %s" % ruleset) _,ring = self.splitter.filterRings[ruleset] # else create the ring and populate it else: logging.debug("Cache miss %s" % ruleset) ring = bridgedb.Bridges.BridgeRing(key1, self.answerParameters) self.splitter.addRing(ring, ruleset, filterBridgesByRules(bridgeFilterRules), populate_from=self.splitter.bridges) # get an appropriate number of bridges numBridgesToReturn = getNumBridgesPerAnswer(ring, max_bridges_per_answer=N) answer = ring.getBridges(pos, numBridgesToReturn) return answer
def getBridgesForIP(self, ip, epoch, N=1, countryCode=None, bridgeFilterRules=None): """Return a list of bridges to give to a user. ip -- the user's IP address, as a dotted quad. epoch -- the time period when we got this request. This can be any string, so long as it changes with every period. N -- the number of bridges to try to give back. """ if not bridgeFilterRules: bridgeFilterRules=[] logging.debug("getBridgesForIP(%s, %s, %s, %s", Util.logSafely(ip), epoch, N, bridgeFilterRules) if not len(self.splitter): logging.debug("bailing without splitter") return [] area = self.areaMapper(ip) logging.info("area is %s", Util.logSafely(area)) key1 = '' pos = 0 n = self.nClusters # only one of ip categories or area clustering is active # try to match the request to an ip category for category in self.categories: # IP Categories if category.contains(ip): g = filterAssignBridgesToRing(self.splitter.hmac, self.nClusters + len(self.categories), n) bridgeFilterRules.append(g) logging.info("category<%s>%s", epoch, Util.logSafely(area)) pos = self.areaOrderHmac("category<%s>%s" % (epoch, area)) key1 = bridgedb.Bridges.get_hmac(self.splitter.key, "Order-Bridges-In-Ring-%d"%n) break; n += 1 # if no category matches, use area clustering else: # IP clustering h = int( self.areaClusterHmac(area)[:8], 16) # length of numClusters clusterNum = h % self.nClusters g = filterAssignBridgesToRing(self.splitter.hmac, self.nClusters + len(self.categories), clusterNum) bridgeFilterRules.append(g) pos = self.areaOrderHmac("<%s>%s" % (epoch, area)) key1 = bridgedb.Bridges.get_hmac(self.splitter.key, "Order-Bridges-In-Ring-%d"%clusterNum) logging.debug("bridgeFilterRules: %s" % bridgeFilterRules) # try to find a cached copy ruleset = frozenset(bridgeFilterRules) # See if we have a cached copy of the ring, # otherwise, add a new ring and populate it if ruleset in self.splitter.filterRings.keys(): logging.debug("Cache hit %s" % ruleset) _,ring = self.splitter.filterRings[ruleset] # else create the ring and populate it else: logging.debug("Cache miss %s" % ruleset) ring = bridgedb.Bridges.BridgeRing(key1, self.answerParameters) self.splitter.addRing(ring, ruleset, filterBridgesByRules(bridgeFilterRules), populate_from=self.splitter.bridges) # get an appropriate number of bridges return ring.getBridges(pos, getNumBridgesPerAnswer(ring, max_bridges_per_answer=N))
def getBridgesForIP(self, ip, epoch, N=1, countryCode=None, bridgeFilterRules=None): """Return a list of bridges to give to a user. ip -- the user's IP address, as a dotted quad. epoch -- the time period when we got this request. This can be any string, so long as it changes with every period. N -- the number of bridges to try to give back. """ if not bridgeFilterRules: bridgeFilterRules = [] logging.debug("getBridgesForIP(%s, %s, %s, %s", Util.logSafely(ip), epoch, N, bridgeFilterRules) if not len(self.splitter): logging.debug("bailing without splitter") return [] area = self.areaMapper(ip) logging.info("area is %s", Util.logSafely(area)) key1 = '' pos = 0 n = self.nClusters # only one of ip categories or area clustering is active # try to match the request to an ip category for category in self.categories: # IP Categories if category.contains(ip): g = filterAssignBridgesToRing( self.splitter.hmac, self.nClusters + len(self.categories), n) bridgeFilterRules.append(g) logging.info("category<%s>%s", epoch, Util.logSafely(area)) pos = self.areaOrderHmac("category<%s>%s" % (epoch, area)) key1 = bridgedb.Bridges.get_hmac( self.splitter.key, "Order-Bridges-In-Ring-%d" % n) break n += 1 # if no category matches, use area clustering else: # IP clustering h = int(self.areaClusterHmac(area)[:8], 16) # length of numClusters clusterNum = h % self.nClusters g = filterAssignBridgesToRing( self.splitter.hmac, self.nClusters + len(self.categories), clusterNum) bridgeFilterRules.append(g) pos = self.areaOrderHmac("<%s>%s" % (epoch, area)) key1 = bridgedb.Bridges.get_hmac( self.splitter.key, "Order-Bridges-In-Ring-%d" % clusterNum) logging.debug("bridgeFilterRules: %s" % bridgeFilterRules) # try to find a cached copy ruleset = frozenset(bridgeFilterRules) # See if we have a cached copy of the ring, # otherwise, add a new ring and populate it if ruleset in self.splitter.filterRings.keys(): logging.debug("Cache hit %s" % ruleset) _, ring = self.splitter.filterRings[ruleset] # else create the ring and populate it else: logging.debug("Cache miss %s" % ruleset) ring = bridgedb.Bridges.BridgeRing(key1, self.answerParameters) self.splitter.addRing(ring, ruleset, filterBridgesByRules(bridgeFilterRules), populate_from=self.splitter.bridges) # get an appropriate number of bridges return ring.getBridges( pos, getNumBridgesPerAnswer(ring, max_bridges_per_answer=N))