def test_HTTPSDistributor_getBridges_with_BridgeRingParameters(self): param = BridgeRingParameters(needPorts=[(443, 1)]) dist = distributor.HTTPSDistributor(3, self.key, answerParameters=param) bridges = self.bridges[:32] for b in self.bridges: b.orPort = 443 [dist.insert(bridge) for bridge in bridges] [dist.insert(bridge) for bridge in self.bridges[:250]] for _ in range(32): bridgeRequest = self.randomClientRequest() answer = dist.getBridges(bridgeRequest, 1) count = 0 fingerprints = {} for bridge in answer: fingerprints[bridge.identity] = 1 if bridge.orPort == 443: count += 1 self.assertEquals(len(fingerprints), len(answer)) self.assertGreater(len(fingerprints), 0) self.assertTrue(count >= 1)
def test_HTTPSDistributor_getBridges_with_some_blocked_bridges(self): dist = distributor.HTTPSDistributor(1, self.key) bridges = self.bridges[:] blockedCN = [] blockedIR = [] for bridge in bridges: if self.coinFlip(): bridge.setBlockedIn('cn') blockedCN.append(bridge.fingerprint) if self.coinFlip(): bridge.setBlockedIn('ir') blockedIR.append(bridge.fingerprint) [dist.insert(bridge) for bridge in bridges] for _ in range(5): clientRequest1 = self.randomClientRequestForNotBlockedIn('cn') bridges = dist.getBridges(clientRequest1, 1) for b in bridges: self.assertFalse(b.isBlockedIn('cn')) self.assertNotIn(b.fingerprint, blockedCN) # The client *should* have gotten some bridges still. self.assertGreater(len(bridges), 0) clientRequest2 = self.randomClientRequestForNotBlockedIn('ir') bridges = dist.getBridges(clientRequest2, 1) for b in bridges: self.assertFalse(b.isBlockedIn('ir')) self.assertNotIn(b.fingerprint, blockedIR) self.assertGreater(len(bridges), 0)
def test_HTTPSDistributor_getBridges_probing_vulnerable(self): dist = distributor.HTTPSDistributor(1, self.key) bridges = self.bridges[:] [dist.insert(bridge) for bridge in bridges] def requestTransports(bridges, transport, vulnerable): for _ in range(len(bridges)): request = HTTPSBridgeRequest(addClientCountryCode=False) request.client = randomValidIPv4String() request.isValid(True) if transport is not None: request.transports.append(transport) request.generateFilters() obtained_bridges = dist.getBridges(request, 1) for bridge in obtained_bridges: if vulnerable: self.assertFalse(bridge.hasProbingResistantPT()) for t in bridge.transports: self.assertTrue(t.methodname != 'obfs4' and t.methodname != 'scramblesuit') else: self.assertTrue(bridge.hasProbingResistantPT()) requestTransports(bridges, None, True) requestTransports(bridges, 'obfs2', True) requestTransports(bridges, 'obfs3', True) requestTransports(bridges, 'obfs4', False)
def test_HTTPSDistributor_getBridges_with_proxy_and_nonproxy_users(self): """An HTTPSDistributor should give separate bridges to proxy users.""" proxies = ProxySet( ['.'.join(['1.1.1', str(x)]) for x in range(1, 256)]) dist = distributor.HTTPSDistributor(3, self.key, proxies) [dist.insert(bridge) for bridge in self.bridges] for _ in range(10): bridgeRequest1 = self.randomClientRequest() bridgeRequest1.client = '.'.join( ['1.1.1', str(random.randrange(1, 255))]) bridgeRequest2 = self.randomClientRequest() bridgeRequest2.client = '.'.join( ['9.9.9', str(random.randrange(1, 255))]) n1 = dist.getBridges(bridgeRequest1, 1) n2 = dist.getBridges(bridgeRequest2, 1) self.assertGreater(len(n1), 0) self.assertGreater(len(n2), 0) for b in n1: self.assertNotIn(b, n2) for b in n2: self.assertNotIn(b, n1)
def test_HTTPSDistributor_prepopulateRings_with_proxies(self): """An HTTPSDistributor with proxies should prepopulate two extra subhashrings (one for each of HTTP-Proxy-IPv4 and HTTP-Proxy-IPv6). """ dist = distributor.HTTPSDistributor(3, self.key, ProxySet(['1.1.1.1', '2.2.2.2'])) [dist.insert(bridge) for bridge in self.bridges] dist.prepopulateRings() self.assertEqual(len(dist.hashring.filterRings), 8)
def test_HTTPSDistributor_mapSubnetToSubring_usingProxy(self): """HTTPSDistributor.mapSubnetToSubring() when the client was using a proxy should map the client to the proxy subhashring. """ dist = distributor.HTTPSDistributor(3, self.key, ProxySet(['1.1.1.1', '2.2.2.2'])) subnet = 'proxy-group-3' subring = dist.mapSubnetToSubring(subnet, usingProxy=True) self.assertEqual(subring, dist.proxySubring)
def test_HTTPSDistributor_init_with_proxies(self): """The HTTPSDistributor, when initialised with proxies, should add an extra hashring for proxy users. """ dist = distributor.HTTPSDistributor(3, self.key, ProxySet(['1.1.1.1', '2.2.2.2'])) self.assertIsNotNone(dist.proxies) self.assertGreater(dist.proxySubring, 0) self.assertEqual(dist.proxySubring, 4) self.assertEqual(dist.totalSubrings, 4)
def test_HTTPSDistributor_mapSubnetToSubring_with_proxies(self): """HTTPSDistributor.mapSubnetToSubring() when the client wasn't using a proxy, but the distributor does have some known proxies and a proxySubring, should not map the client to the proxy subhashring. """ dist = distributor.HTTPSDistributor(3, self.key, ProxySet(['1.1.1.1', '2.2.2.2'])) # Note that if they were actually from a proxy, their subnet would be # something like "proxy-group-3". subnet = '15.1.0.0/16' subring = dist.mapSubnetToSubring(subnet, usingProxy=False) self.assertNotEqual(subring, dist.proxySubring)
def test_HTTPSDistributor_getBridges_same_bridges_to_same_client(self): """The same client asking for bridges from the HTTPSDistributor multiple times in a row should get the same bridges in response each time. """ dist = distributor.HTTPSDistributor(3, self.key) [dist.insert(bridge) for bridge in self.bridges[:250]] bridgeRequest = self.randomClientRequest() responses = {} for i in range(5): responses[i] = dist.getBridges(bridgeRequest, 1) for i in range(4): self.assertItemsEqual(responses[i], responses[i+1])
def test_HTTPSDistributor_getBridges_with_blocked_bridges(self): dist = distributor.HTTPSDistributor(1, self.key) bridges = self.bridges[:] for bridge in bridges: bridge.setBlockedIn('cn') [dist.insert(bridge) for bridge in bridges] for _ in range(5): clientRequest1 = self.randomClientRequestForNotBlockedIn('cn') b = dist.getBridges(clientRequest1, 1) self.assertEqual(len(b), 0) clientRequest2 = self.randomClientRequestForNotBlockedIn('ir') b = dist.getBridges(clientRequest2, 1) self.assertEqual(len(b), 3)
def test_HTTPSDistributor_getBridges_ipv4(self): """A request for IPv4 bridges should return IPv4 bridges.""" dist = distributor.HTTPSDistributor(1, self.key) [dist.insert(bridge) for bridge in self.bridges[:250]] for i in xrange(500): bridgeRequest = self.randomClientRequest() bridgeRequest.generateFilters() bridges = dist.getBridges(bridgeRequest, "faketimestamp") self.assertTrue(type(bridges) is list) self.assertGreater(len(bridges), 0) bridge = random.choice(bridges) bridgeLine = bridge.getBridgeLine(bridgeRequest) addrport, fingerprint = bridgeLine.split() address, port = addrport.rsplit(':', 1) self.assertIsInstance(ipaddr.IPAddress(address), ipaddr.IPv4Address) self.assertIsNotNone(byIPv4(random.choice(bridges)))
def test_HTTPSDistributor_prepopulateRings_without_proxies(self): """An HTTPSDistributor without proxies should prepopulate totalSubrings * 2 subrings. """ dist = distributor.HTTPSDistributor(3, self.key) [dist.insert(bridge) for bridge in self.bridges] dist.prepopulateRings() self.assertEqual(len(dist.hashring.filterRings), 6) ipv4subrings = [] ipv6subrings = [] for subringName, (filters, subring) in dist.hashring.filterRings.items(): if 'IPv4' in subringName: ipv6subrings.append(subring) if 'IPv6' in subringName: ipv6subrings.append(subring) self.assertEqual(len(ipv4subrings), len(ipv6subrings))
def test_HTTPSDistributor_getBridges_ipv6_ipv4(self): """Asking for bridge addresses which are simultaneously IPv6 and IPv4 (in that order) should return IPv6 bridges. """ dist = distributor.HTTPSDistributor(1, self.key) [dist.insert(bridge) for bridge in self.bridges[:250]] bridgeRequest = self.randomClientRequest() bridgeRequest.withIPv6() bridgeRequest.generateFilters() bridgeRequest.filters.append(byIPv4) bridges = dist.getBridges(bridgeRequest, 1) self.assertEqual(len(bridges), 3) bridge = random.choice(bridges) bridgeLine = bridge.getBridgeLine(bridgeRequest) addrport, fingerprint = bridgeLine.split() address, port = addrport.rsplit(':', 1) address = address.strip('[]') self.assertIsInstance(ipaddr.IPAddress(address), ipaddr.IPv6Address) self.assertIsNotNone(byIPv6(random.choice(bridges)))
def test_HTTPSDistributor_getBridges_with_varied_blocked_bridges(self): dist = distributor.HTTPSDistributor(1, self.key) bridges = self.bridges[:] for bridge in bridges: # Pretend that China blocks all vanilla bridges: bridge.setBlockedIn('cn', methodname='vanilla') # Pretend that China blocks all obfs2: bridge.setBlockedIn('cn', methodname='obfs2') # Pretend that China blocks some obfs3: if self.coinFlip(): bridge.setBlockedIn('cn', methodname='obfs3') [dist.insert(bridge) for bridge in bridges] for i in xrange(5): bridgeRequest1 = self.randomClientRequestForNotBlockedIn('cn') bridgeRequest1.transports.append('obfs2') bridgeRequest1.generateFilters() # We shouldn't get any obfs2 bridges, since they're all blocked in # China: bridges = dist.getBridges(bridgeRequest1, "faketimestamp") self.assertEqual(len(bridges), 0) bridgeRequest2 = self.randomClientRequestForNotBlockedIn('cn') bridgeRequest2.transports.append('obfs3') bridgeRequest2.generateFilters() # We probably will get at least one bridge back! It's pretty # unlikely to lose a coin flip 500 times in a row. bridges = dist.getBridges(bridgeRequest2, "faketimestamp") self.assertGreater(len(bridges), 0) bridgeRequest3 = self.randomClientRequestForNotBlockedIn('nl') bridgeRequest3.transports.append('obfs3') bridgeRequest3.generateFilters() # We should get bridges, since obfs3 isn't blocked in netherlands: bridges = dist.getBridges(bridgeRequest3, "faketimestamp") self.assertGreater(len(bridges), 0)
def test_HTTPSDistributor_bridgesPerResponse_100_max_5(self): dist = distributor.HTTPSDistributor(3, self.key) dist._bridgesPerResponseMax = 5 [dist.insert(bridge) for bridge in self.bridges[:100]] self.assertEqual(dist.bridgesPerResponse(), 5)
def test_HTTPSDistributor_bridgesPerResponse_15(self): dist = distributor.HTTPSDistributor(3, self.key) [dist.insert(bridge) for bridge in self.bridges[:15]] self.assertEqual(dist.bridgesPerResponse(), 1)
def test_HTTPSDistributor_bridgesPerResponse_100(self): dist = distributor.HTTPSDistributor(3, self.key) [dist.hashring.insert(bridge) for bridge in self.bridges[:100]] self.assertEqual(dist.bridgesPerResponse(), 3)