Пример #1
0
def generateFakeBridges(n=500):
    """Generate a set of **n** :class:`~bridgedb.bridges.Bridges` with random
    data.
    """
    from bridgedb.bridges import Bridge
    from bridgedb.bridges import PluggableTransport

    global _FAKE_BRIDGES

    if _FAKE_BRIDGES:
        return _FAKE_BRIDGES

    bridges = []

    for i in range(n):
        addr = randomValidIPv4String()
        nick = 'bridge-%d' % i
        port = randomHighPort()
        # Real tor currently only supports one extra ORAddress, and it can
        # only be IPv6.
        addrs = [(randomValidIPv6(), randomHighPort(), 6)]
        fpr = "".join(random.choice('abcdef0123456789') for _ in range(40))

        supported = ["obfs2", "obfs3", "fte"]
        transports = []
        for j, method in zip(range(1, len(supported) + 1), supported):
            pt = PluggableTransport(fpr, method, addr, port - j, {})
            transports.append(pt)

        # Every tenth bridge supports obfs4.
        if i % 10 == 0:
            obfs4Args = {
                'iat-mode':
                '1',
                'node-id':
                '2a79f14120945873482b7823caabe2fcde848722',
                'public-key':
                '0a5b046d07f6f971b7776de682f57c5b9cdc8fa060db7ef59de82e721c8098f4'
            }
            pt = PluggableTransport(fpr, "obfs4", addr, port - j, obfs4Args)
            transports.append(pt)

        # Every fifteenth bridge supports scramblesuit.
        if i % 15 == 0:
            scramblesuitArgs = {'password': '******'}
            pt = PluggableTransport(fpr, "scramblesuit", addr, port - j,
                                    scramblesuitArgs)
            transports.append(pt)

        bridge = Bridge(nick, addr, port, fpr)
        bridge.flags.update("Running Stable")
        bridge.transports = transports
        bridge.orAddresses = addrs
        bridges.append(bridge)

    _FAKE_BRIDGES = bridges
    return bridges
Пример #2
0
    def setUp(self):
        """Create a Bridge whose address is 1.1.1.1, orPort is 1111, and
        fingerprint is 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'.  Also,
        create an HMAC function whose key is 'plasma'.
        """
        self.bridge = Bridge()
        self.bridge.address = '1.1.1.1'
        self.bridge.orPort = 1111
        self.bridge.fingerprint = 'a' * 40

        self.hmac = getHMACFunc('plasma')
Пример #3
0
    def setUp(self):
        """Create a Bridge whose address is 1.1.1.1, orPort is 1111, and
        fingerprint is 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'.  Also,
        create an HMAC function whose key is 'plasma'.
        """
        self.bridge = Bridge()
        self.bridge.address = '1.1.1.1'
        self.bridge.orPort = 1111
        self.bridge.fingerprint = 'a' * 40

        self.hmac = getHMACFunc('plasma')

        PluggableTransport.probing_resistant_transports = [
            'scramblesuit', 'obfs4'
        ]
Пример #4
0
    def setUp(self):
        """Create a Bridge whose address is 1.1.1.1, orPort is 1111, and
        fingerprint is 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'.  Also,
        create an HMAC function whose key is 'plasma'.
        """
        self.bridge = Bridge()
        self.bridge.address = '1.1.1.1'
        self.bridge.orPort = 1111
        self.bridge.fingerprint = 'a' * 40

        self.hmac = getHMACFunc('plasma')
Пример #5
0
def generateFakeBridges(n=500):
    """Generate a set of **n** :class:`~bridgedb.bridges.Bridges` with random
    data.
    """
    from bridgedb.bridges import Bridge
    from bridgedb.bridges import PluggableTransport

    global _FAKE_BRIDGES

    if _FAKE_BRIDGES:
        return _FAKE_BRIDGES

    bridges = []

    for i in range(n):
        addr = randomValidIPv4String()
        nick = 'bridge-%d' % i
        port = randomHighPort()
        # Real tor currently only supports one extra ORAddress, and it can
        # only be IPv6.
        addrs = [(randomValidIPv6(), randomHighPort(), 6)]
        fpr = "".join(random.choice('abcdef0123456789') for _ in xrange(40))

        # We only support the ones without PT args, because they're easier to fake.
        supported = ["obfs2", "obfs3", "fte"]
        transports = []
        for j, method in zip(range(1, len(supported) + 1), supported):
            pt = PluggableTransport(fpr, method, addr, port - j, {})
            transports.append(pt)

        bridge = Bridge(nick, addr, port, fpr)
        bridge.flags.update("Running Stable")
        bridge.transports = transports
        bridge.orAddresses = addrs
        bridges.append(bridge)

    _FAKE_BRIDGES = bridges
    return bridges
Пример #6
0
def generateFakeBridges(n=500):
    """Generate a set of **n** :class:`~bridgedb.bridges.Bridges` with random
    data.
    """
    from bridgedb.bridges import Bridge
    from bridgedb.bridges import PluggableTransport

    global _FAKE_BRIDGES

    if _FAKE_BRIDGES:
        return _FAKE_BRIDGES

    bridges = []

    for i in range(n):
        addr = randomValidIPv4String()
        nick = 'bridge-%d' % i
        port = randomHighPort()
        # Real tor currently only supports one extra ORAddress, and it can
        # only be IPv6.
        addrs = [(randomValidIPv6(), randomHighPort(), 6)]
        fpr = "".join(random.choice('abcdef0123456789') for _ in xrange(40))

        # We only support the ones without PT args, because they're easier to fake.
        supported = ["obfs2", "obfs3", "fte"]
        transports = []
        for j, method in zip(range(1, len(supported) + 1), supported):
            pt = PluggableTransport(fpr, method, addr, port - j, {})
            transports.append(pt)

        bridge = Bridge(nick, addr, port, fpr)
        bridge.flags.update("Running Stable")
        bridge.transports = transports
        bridge.orAddresses = addrs
        bridges.append(bridge)

    _FAKE_BRIDGES = bridges
    return bridges
Пример #7
0
class FiltersTests(unittest.TestCase):
    """Tests for :mod:`bridgedb.filters`."""
    def setUp(self):
        """Create a Bridge whose address is 1.1.1.1, orPort is 1111, and
        fingerprint is 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'.  Also,
        create an HMAC function whose key is 'plasma'.
        """
        self.bridge = Bridge()
        self.bridge.address = '1.1.1.1'
        self.bridge.orPort = 1111
        self.bridge.fingerprint = 'a' * 40

        self.hmac = getHMACFunc('plasma')

    def addIPv4VoltronPT(self):
        pt = PluggableTransport('a' * 40, 'voltron', '1.1.1.1', 1111, {})
        self.bridge.transports.append(pt)

    def addIPv6VoltronPT(self):
        pt = PluggableTransport('a' * 40, 'voltron', '2006:2222::2222', 1111,
                                {})
        self.bridge.transports.append(pt)

    def test_bySubring_1_of_2(self):
        """A Bridge with fingerprint 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'
        should be assigned to sub-hashring 1-of-2 (in this case, using a
        particular HMAC key), and therefore filters.bySubring(HMAC, 1, 2)
        should return that Bridge (because it is in the sub-hashring we asked
        for).
        """
        filtre = filters.bySubring(self.hmac, 1, 2)
        self.assertTrue(filtre(self.bridge))

    def test_bySubring_2_of_2(self):
        """A Bridge with fingerprint 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'
        should be assigned to sub-hashring 1-of-2 (in this case, using a
        particular HMAC key), and therefore filters.bySubring(HMAC, 2, 2)
        should *not* return that Bridge (because it is in sub-hashring 1-of-2
        and we asked for Bridges which are in sub-hashring 2-of-2).
        """
        filtre = filters.bySubring(self.hmac, 2, 2)
        self.assertFalse(filtre(self.bridge))

    def test_byFilters_bySubring_byTransport_correct_subhashring_with_transport(
            self):
        """Filtering byTransport('voltron') and bySubring(HMAC, 1, 2) when the
        Bridge has a voltron transport and is assigned to sub-hashring 1-of-2
        should return True.
        """
        self.addIPv4VoltronPT()
        filtre = filters.byFilters([
            filters.bySubring(self.hmac, 1, 2),
            filters.byTransport('voltron')
        ])
        self.assertTrue(filtre(self.bridge))

    def test_byFilters_bySubring_byTransport_wrong_subhashring_with_transport(
            self):
        """Filtering byTransport('voltron') and bySubring(HMAC, 2, 2) when the
        Bridge has a voltron transport and is assigned to sub-hashring 1-of-2
        should return False.
        """
        self.addIPv4VoltronPT()
        filtre = filters.byFilters([
            filters.bySubring(self.hmac, 2, 2),
            filters.byTransport('voltron')
        ])
        self.assertFalse(filtre(self.bridge))

    def test_byFilters_bySubring_byTransport_correct_subhashring_no_transport(
            self):
        """Filtering byTransport('voltron') and bySubring(HMAC, 1, 2) when the
        Bridge has no transports and is assigned to sub-hashring 1-of-2
        should return False.
        """
        filtre = filters.byFilters([
            filters.bySubring(self.hmac, 1, 2),
            filters.byTransport('voltron')
        ])
        self.assertFalse(filtre(self.bridge))

    def test_byFilters_bySubring_byTransport_wrong_subhashring_no_transport(
            self):
        """Filtering byTransport('voltron') and bySubring(HMAC, 2, 2) when the
        Bridge has no transports and is assigned to sub-hashring 1-of-2
        should return False.
        """
        filtre = filters.byFilters([
            filters.bySubring(self.hmac, 2, 2),
            filters.byTransport('voltron')
        ])
        self.assertFalse(filtre(self.bridge))

    def test_byFilters_no_filters(self):
        self.addIPv4VoltronPT()
        filtre = filters.byFilters([])
        self.assertTrue(filtre(self.bridge))

    def test_byIPv_ipv5(self):
        """Calling byIPv(ipVersion=5) should default to filterint by IPv4."""
        filtre = filters.byIPv(5)
        self.assertTrue(filtre(self.bridge))

    def test_byIPv4_address(self):
        """A bridge with an IPv4 address for its main orPort address should
        cause filters.byIPv4() to return True.
        """
        self.assertTrue(filters.byIPv4(self.bridge))

    def test_byIPv4_orAddress(self):
        """A bridge with an IPv4 address in its orAddresses address should
        cause filters.byIPv4() to return True.
        """
        self.bridge.address = '2006:2222::2222'
        self.bridge.orAddresses = [(ipaddr.IPv4Address('2.2.2.2'), 2222, 4)]
        self.assertTrue(filters.byIPv4(self.bridge))

    def test_byIPv4_none(self):
        """A bridge with no IPv4 addresses should cause filters.byIPv4() to
        return False.
        """
        self.bridge.address = ipaddr.IPv6Address('2006:2222::2222')
        self.bridge.orAddresses = [(ipaddr.IPv6Address('2006:3333::3333'),
                                    3333, 6)]
        self.assertFalse(filters.byIPv4(self.bridge))

    def test_byIPv6_address(self):
        """A bridge with an IPv6 address for its main orPort address should
        cause filters.byIPv6() to return True.
        """
        self.bridge.address = '2006:2222::2222'
        self.assertTrue(filters.byIPv6(self.bridge))

    def test_byIPv6_orAddress(self):
        """A bridge with an IPv6 address in its orAddresses address should
        cause filters.byIPv6() to return True.
        """
        self.bridge.orAddresses = [(ipaddr.IPv6Address('2006:3333::3333'),
                                    3333, 6)]
        self.assertTrue(filters.byIPv6(self.bridge))

    def test_byIPv6_none(self):
        """A bridge with no IPv6 addresses should cause filters.byIPv6() to
        return False.
        """
        self.assertFalse(filters.byIPv6(self.bridge))

    def test_byTransport_with_transport_ipv4(self):
        """A bridge with an IPv4 voltron transport should cause
        byTransport('voltron') to return True.
        """
        self.addIPv4VoltronPT()
        filtre = filters.byTransport('voltron')
        self.assertTrue(filtre(self.bridge))

    def test_byTransport_with_transport_ipv6(self):
        """A bridge with an IPv6 voltron transport should cause
        byTransport('voltron', ipVersion=6) to return True.
        """
        self.addIPv6VoltronPT()
        filtre = filters.byTransport('voltron', ipVersion=6)
        self.assertTrue(filtre(self.bridge))

    def test_byTransport_with_transport_ipv6_filtering_by_ipv4(self):
        """A bridge with an IPv6 voltron transport should cause
        byTransport('voltron') to return True.
        """
        self.addIPv6VoltronPT()
        filtre = filters.byTransport('voltron')
        self.assertFalse(filtre(self.bridge))

    def test_byTransport_no_transports(self):
        """A bridge without any transports should cause
        byTransport('voltron') to return False.
        """
        filtre = filters.byTransport('voltron')
        self.assertFalse(filtre(self.bridge))

    def test_byTransport_vanilla_ipv4(self):
        """byTransport() without namimg a transport to filter by should just
        return the bridge's IPv4 address.
        """
        filtre = filters.byTransport()
        self.assertTrue(filtre(self.bridge))

    def test_byTransport_vanilla_ipv6(self):
        """byTranspfort(ipVersion=6) without namimg a transport to filter by
        should just return the bridge's IPv4 address.
        """
        self.bridge.orAddresses = [(ipaddr.IPv6Address('2006:3333::3333'),
                                    3333, 6)]
        filtre = filters.byTransport(ipVersion=6)
        self.assertTrue(filtre(self.bridge))

    def test_byTransport_wrong_transport(self):
        """A bridge with only a Voltron transport should cause
        byTransport('obfs3') to return False.
        """
        self.addIPv4VoltronPT()
        filtre = filters.byTransport('obfs3')
        self.assertFalse(filtre(self.bridge))

    def test_byNotBlockedIn_no_countryCode_with_transport_ipv4(self):
        """A bridge with an IPv4 voltron transport should cause
        byNotBlockedIn('voltron') to return True (because it calls
        filters.byTransport).
        """
        self.addIPv4VoltronPT()
        filtre = filters.byNotBlockedIn(None, methodname='voltron')
        self.assertTrue(filtre(self.bridge))

    def test_byNotBlockedIn_no_countryCode_with_transport_ipv6(self):
        """A bridge with an IPv6 voltron transport should cause
        byNotBlockedIn('voltron') to return True (because it calls
        filters.byTransport).
        """
        self.addIPv6VoltronPT()
        filtre = filters.byNotBlockedIn(None,
                                        methodname='voltron',
                                        ipVersion=6)
        self.assertTrue(filtre(self.bridge))

    def test_byNotBlockedIn_with_transport_ipv4(self):
        """A bridge with an IPv4 voltron transport should cause
        byNotBlockedIn('voltron') to return True.
        """
        self.addIPv4VoltronPT()
        filtre = filters.byNotBlockedIn('CN', methodname='voltron')
        self.assertTrue(filtre(self.bridge))

    def test_byNotBlockedIn_with_transport_ipv4_blocked(self):
        """A bridge with an IPv4 voltron transport which is blocked should
        cause byNotBlockedIn('voltron') to return False.
        """
        self.addIPv4VoltronPT()
        self.bridge.setBlockedIn('CN')
        filtre = filters.byNotBlockedIn('CN', methodname='voltron')
        self.assertFalse(filtre(self.bridge))

    def test_byNotBlockedIn_with_transport_ipv6(self):
        """A bridge with an IPv6 voltron transport should cause
        byNotBlockedIn('voltron') to return True.
        """
        self.addIPv6VoltronPT()
        filtre = filters.byNotBlockedIn('cn', 'voltron', ipVersion=6)
        self.assertTrue(filtre(self.bridge))

    def test_byNotBlockedIn_with_transport_ipv4_not_blocked_ipv4(self):
        """A bridge with an IPv6 voltron transport which is not blocked in China
        should cause byNotBlockedIn('cn', 'voltron') to return False, because
        the IP version is wrong.
        """
        self.addIPv6VoltronPT()
        filtre = filters.byNotBlockedIn('cn', 'voltron')
        self.assertFalse(filtre(self.bridge))

    def test_byNotBlockedIn_with_transport_ipv6_blocked(self):
        """A bridge with an IPv6 voltron transport which is blocked should
        cause byNotBlockedIn('voltron') to return False.
        """
        self.addIPv6VoltronPT()
        self.bridge.setBlockedIn('CN')
        filtre = filters.byNotBlockedIn('cn', 'voltron', ipVersion=6)
        self.assertFalse(filtre(self.bridge))

    def test_byNotBlockedIn_no_countryCode_no_transports(self):
        """A bridge without any transports should cause
        byNotBlockedIn('voltron') to return False (because it calls
        filters.byTransport('voltron')).
        """
        filtre = filters.byNotBlockedIn(None, methodname='voltron')
        self.assertFalse(filtre(self.bridge))

    def test_byNotBlockedIn_no_transports(self):
        """A bridge without any transports should cause
        byNotBlockedIn('cn', 'voltron') to return False.
        """
        filtre = filters.byNotBlockedIn('cn', methodname='voltron')
        self.assertFalse(filtre(self.bridge))

    def test_byNotBlockedIn_no_transports_blocked(self):
        """A bridge without any transports which is also blocked should cause
        byNotBlockedIn('voltron') to return False.
        """
        self.bridge.setBlockedIn('cn')
        filtre = filters.byNotBlockedIn('cn', methodname='voltron')
        self.assertFalse(filtre(self.bridge))

    def test_byNotBlockedIn_wrong_transport(self):
        """A bridge with only a Voltron transport should cause
        byNotBlockedIn('obfs3') to return False.
        """
        self.addIPv4VoltronPT()
        filtre = filters.byNotBlockedIn('cn', methodname='obfs3')
        self.assertFalse(filtre(self.bridge))

    def test_byNotBlockedIn_ipv5(self):
        """Calling byNotBlockedIn([…], ipVersion=5) should default to IPv4."""
        self.bridge.setBlockedIn('ru')
        filtre = filters.byNotBlockedIn('cn', ipVersion=5)
        self.assertTrue(filtre(self.bridge))

    def test_byNotBlockedIn_vanilla_not_blocked(self):
        """Calling byNotBlockedIn('vanilla') should return the IPv4 vanilla
        address, if it is not blocked.
        """
        self.bridge.setBlockedIn('ru')
        filtre = filters.byNotBlockedIn('cn', methodname='vanilla')
        self.assertTrue(filtre(self.bridge))

    def test_byNotBlockedIn_vanilla_not_blocked_ipv6(self):
        """Calling byNotBlockedIn('vanilla', ipVersion=6) should not return the
        IPv4 vanilla address, even if it is not blocked, because it has the
        wrong IP version.
        """
        self.bridge.setBlockedIn('ru')
        filtre = filters.byNotBlockedIn('cn',
                                        methodname='vanilla',
                                        ipVersion=6)
        self.assertFalse(filtre(self.bridge))

    def test_byNotBlockedIn_vanilla_blocked(self):
        """Calling byNotBlockedIn('vanilla') should not return the IPv4 vanilla
        address, if it is blocked.
        """
        self.bridge.setBlockedIn('ru')
        filtre = filters.byNotBlockedIn('ru', methodname='vanilla')
        self.assertFalse(filtre(self.bridge))
Пример #8
0
class FiltersTests(unittest.TestCase):
    """Tests for :mod:`bridgedb.filters`."""

    def setUp(self):
        """Create a Bridge whose address is 1.1.1.1, orPort is 1111, and
        fingerprint is 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'.  Also,
        create an HMAC function whose key is 'plasma'.
        """
        self.bridge = Bridge()
        self.bridge.address = '1.1.1.1'
        self.bridge.orPort = 1111
        self.bridge.fingerprint = 'a' * 40

        self.hmac = getHMACFunc('plasma')

    def addIPv4VoltronPT(self):
        pt = PluggableTransport('a' * 40, 'voltron', '1.1.1.1', 1111, {})
        self.bridge.transports.append(pt)

    def addIPv6VoltronPT(self):
        pt = PluggableTransport('a' * 40, 'voltron', '2006:2222::2222', 1111, {})
        self.bridge.transports.append(pt)

    def test_bySubring_1_of_2(self):
        """A Bridge with fingerprint 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'
        should be assigned to sub-hashring 1-of-2 (in this case, using a
        particular HMAC key), and therefore filters.bySubring(HMAC, 1, 2)
        should return that Bridge (because it is in the sub-hashring we asked
        for).
        """
        filtre = filters.bySubring(self.hmac, 1, 2)
        self.assertTrue(filtre(self.bridge))

    def test_bySubring_2_of_2(self):
        """A Bridge with fingerprint 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'
        should be assigned to sub-hashring 1-of-2 (in this case, using a
        particular HMAC key), and therefore filters.bySubring(HMAC, 2, 2)
        should *not* return that Bridge (because it is in sub-hashring 1-of-2
        and we asked for Bridges which are in sub-hashring 2-of-2).
        """
        filtre = filters.bySubring(self.hmac, 2, 2)
        self.assertFalse(filtre(self.bridge))

    def test_byFilters_bySubring_byTransport_correct_subhashring_with_transport(self):
        """Filtering byTransport('voltron') and bySubring(HMAC, 1, 2) when the
        Bridge has a voltron transport and is assigned to sub-hashring 1-of-2
        should return True.
        """
        self.addIPv4VoltronPT()
        filtre = filters.byFilters([filters.bySubring(self.hmac, 1, 2),
                                    filters.byTransport('voltron')])
        self.assertTrue(filtre(self.bridge))

    def test_byFilters_bySubring_byTransport_wrong_subhashring_with_transport(self):
        """Filtering byTransport('voltron') and bySubring(HMAC, 2, 2) when the
        Bridge has a voltron transport and is assigned to sub-hashring 1-of-2
        should return False.
        """
        self.addIPv4VoltronPT()
        filtre = filters.byFilters([filters.bySubring(self.hmac, 2, 2),
                                    filters.byTransport('voltron')])
        self.assertFalse(filtre(self.bridge))

    def test_byFilters_bySubring_byTransport_correct_subhashring_no_transport(self):
        """Filtering byTransport('voltron') and bySubring(HMAC, 1, 2) when the
        Bridge has no transports and is assigned to sub-hashring 1-of-2
        should return False.
        """
        filtre = filters.byFilters([filters.bySubring(self.hmac, 1, 2),
                                    filters.byTransport('voltron')])
        self.assertFalse(filtre(self.bridge))

    def test_byFilters_bySubring_byTransport_wrong_subhashring_no_transport(self):
        """Filtering byTransport('voltron') and bySubring(HMAC, 2, 2) when the
        Bridge has no transports and is assigned to sub-hashring 1-of-2
        should return False.
        """
        filtre = filters.byFilters([filters.bySubring(self.hmac, 2, 2),
                                    filters.byTransport('voltron')])
        self.assertFalse(filtre(self.bridge))

    def test_byFilters_no_filters(self):
        self.addIPv4VoltronPT()
        filtre = filters.byFilters([])
        self.assertTrue(filtre(self.bridge))

    def test_byIPv_ipv5(self):
        """Calling byIPv(ipVersion=5) should default to filterint by IPv4."""
        filtre = filters.byIPv(5)
        self.assertTrue(filtre(self.bridge))

    def test_byIPv4_address(self):
        """A bridge with an IPv4 address for its main orPort address should
        cause filters.byIPv4() to return True.
        """
        self.assertTrue(filters.byIPv4(self.bridge))

    def test_byIPv4_orAddress(self):
        """A bridge with an IPv4 address in its orAddresses address should
        cause filters.byIPv4() to return True.
        """
        self.bridge.address = '2006:2222::2222'
        self.bridge.orAddresses = [(ipaddr.IPv4Address('2.2.2.2'), 2222, 4)]
        self.assertTrue(filters.byIPv4(self.bridge))

    def test_byIPv4_none(self):
        """A bridge with no IPv4 addresses should cause filters.byIPv4() to
        return False.
        """
        self.bridge.address = ipaddr.IPv6Address('2006:2222::2222')
        self.bridge.orAddresses = [(ipaddr.IPv6Address('2006:3333::3333'), 3333, 6)]
        self.assertFalse(filters.byIPv4(self.bridge))

    def test_byIPv6_address(self):
        """A bridge with an IPv6 address for its main orPort address should
        cause filters.byIPv6() to return True.
        """
        self.bridge.address = '2006:2222::2222'
        self.assertTrue(filters.byIPv6(self.bridge))

    def test_byIPv6_orAddress(self):
        """A bridge with an IPv6 address in its orAddresses address should
        cause filters.byIPv6() to return True.
        """
        self.bridge.orAddresses = [(ipaddr.IPv6Address('2006:3333::3333'), 3333, 6)]
        self.assertTrue(filters.byIPv6(self.bridge))

    def test_byIPv6_none(self):
        """A bridge with no IPv6 addresses should cause filters.byIPv6() to
        return False.
        """
        self.assertFalse(filters.byIPv6(self.bridge))

    def test_byTransport_with_transport_ipv4(self):
        """A bridge with an IPv4 voltron transport should cause
        byTransport('voltron') to return True.
        """
        self.addIPv4VoltronPT()
        filtre = filters.byTransport('voltron')
        self.assertTrue(filtre(self.bridge))

    def test_byTransport_with_transport_ipv6(self):
        """A bridge with an IPv6 voltron transport should cause
        byTransport('voltron', ipVersion=6) to return True.
        """
        self.addIPv6VoltronPT()
        filtre = filters.byTransport('voltron', ipVersion=6)
        self.assertTrue(filtre(self.bridge))

    def test_byTransport_with_transport_ipv6_filtering_by_ipv4(self):
        """A bridge with an IPv6 voltron transport should cause
        byTransport('voltron') to return True.
        """
        self.addIPv6VoltronPT()
        filtre = filters.byTransport('voltron')
        self.assertFalse(filtre(self.bridge))

    def test_byTransport_no_transports(self):
        """A bridge without any transports should cause
        byTransport('voltron') to return False.
        """
        filtre = filters.byTransport('voltron')
        self.assertFalse(filtre(self.bridge))

    def test_byTransport_vanilla_ipv4(self):
        """byTransport() without namimg a transport to filter by should just
        return the bridge's IPv4 address.
        """
        filtre = filters.byTransport()
        self.assertTrue(filtre(self.bridge))

    def test_byTransport_vanilla_ipv6(self):
        """byTranspfort(ipVersion=6) without namimg a transport to filter by
        should just return the bridge's IPv4 address.
        """
        self.bridge.orAddresses = [(ipaddr.IPv6Address('2006:3333::3333'), 3333, 6)]
        filtre = filters.byTransport(ipVersion=6)
        self.assertTrue(filtre(self.bridge))

    def test_byTransport_wrong_transport(self):
        """A bridge with only a Voltron transport should cause
        byTransport('obfs3') to return False.
        """
        self.addIPv4VoltronPT()
        filtre = filters.byTransport('obfs3')
        self.assertFalse(filtre(self.bridge))

    def test_byNotBlockedIn_no_countryCode_with_transport_ipv4(self):
        """A bridge with an IPv4 voltron transport should cause
        byNotBlockedIn('voltron') to return True (because it calls
        filters.byTransport).
        """
        self.addIPv4VoltronPT()
        filtre = filters.byNotBlockedIn(None, methodname='voltron')
        self.assertTrue(filtre(self.bridge))

    def test_byNotBlockedIn_no_countryCode_with_transport_ipv6(self):
        """A bridge with an IPv6 voltron transport should cause
        byNotBlockedIn('voltron') to return True (because it calls
        filters.byTransport).
        """
        self.addIPv6VoltronPT()
        filtre = filters.byNotBlockedIn(None, methodname='voltron', ipVersion=6)
        self.assertTrue(filtre(self.bridge))

    def test_byNotBlockedIn_with_transport_ipv4(self):
        """A bridge with an IPv4 voltron transport should cause
        byNotBlockedIn('voltron') to return True.
        """
        self.addIPv4VoltronPT()
        filtre = filters.byNotBlockedIn('CN', methodname='voltron')
        self.assertTrue(filtre(self.bridge))

    def test_byNotBlockedIn_with_transport_ipv4_blocked(self):
        """A bridge with an IPv4 voltron transport which is blocked should
        cause byNotBlockedIn('voltron') to return False.
        """
        self.addIPv4VoltronPT()
        self.bridge.setBlockedIn('CN')
        filtre = filters.byNotBlockedIn('CN', methodname='voltron')
        self.assertFalse(filtre(self.bridge))

    def test_byNotBlockedIn_with_transport_ipv6(self):
        """A bridge with an IPv6 voltron transport should cause
        byNotBlockedIn('voltron') to return True.
        """
        self.addIPv6VoltronPT()
        filtre = filters.byNotBlockedIn('cn', 'voltron', ipVersion=6)
        self.assertTrue(filtre(self.bridge))

    def test_byNotBlockedIn_with_transport_ipv4_not_blocked_ipv4(self):
        """A bridge with an IPv6 voltron transport which is not blocked in China
        should cause byNotBlockedIn('cn', 'voltron') to return False, because
        the IP version is wrong.
        """
        self.addIPv6VoltronPT()
        filtre = filters.byNotBlockedIn('cn', 'voltron')
        self.assertFalse(filtre(self.bridge))

    def test_byNotBlockedIn_with_transport_ipv6_blocked(self):
        """A bridge with an IPv6 voltron transport which is blocked should
        cause byNotBlockedIn('voltron') to return False.
        """
        self.addIPv6VoltronPT()
        self.bridge.setBlockedIn('CN')
        filtre = filters.byNotBlockedIn('cn', 'voltron', ipVersion=6)
        self.assertFalse(filtre(self.bridge))

    def test_byNotBlockedIn_no_countryCode_no_transports(self):
        """A bridge without any transports should cause
        byNotBlockedIn('voltron') to return False (because it calls
        filters.byTransport('voltron')).
        """
        filtre = filters.byNotBlockedIn(None, methodname='voltron')
        self.assertFalse(filtre(self.bridge))

    def test_byNotBlockedIn_no_transports(self):
        """A bridge without any transports should cause
        byNotBlockedIn('cn', 'voltron') to return False.
        """
        filtre = filters.byNotBlockedIn('cn', methodname='voltron')
        self.assertFalse(filtre(self.bridge))

    def test_byNotBlockedIn_no_transports_blocked(self):
        """A bridge without any transports which is also blocked should cause
        byNotBlockedIn('voltron') to return False.
        """
        self.bridge.setBlockedIn('cn')
        filtre = filters.byNotBlockedIn('cn', methodname='voltron')
        self.assertFalse(filtre(self.bridge))

    def test_byNotBlockedIn_wrong_transport(self):
        """A bridge with only a Voltron transport should cause
        byNotBlockedIn('obfs3') to return False.
        """
        self.addIPv4VoltronPT()
        filtre = filters.byNotBlockedIn('cn', methodname='obfs3')
        self.assertFalse(filtre(self.bridge))

    def test_byNotBlockedIn_ipv5(self):
        """Calling byNotBlockedIn([…], ipVersion=5) should default to IPv4."""
        self.bridge.setBlockedIn('ru')
        filtre = filters.byNotBlockedIn('cn', ipVersion=5)
        self.assertTrue(filtre(self.bridge))

    def test_byNotBlockedIn_vanilla_not_blocked(self):
        """Calling byNotBlockedIn('vanilla') should return the IPv4 vanilla
        address, if it is not blocked.
        """
        self.bridge.setBlockedIn('ru')
        filtre = filters.byNotBlockedIn('cn', methodname='vanilla')
        self.assertTrue(filtre(self.bridge))

    def test_byNotBlockedIn_vanilla_not_blocked_ipv6(self):
        """Calling byNotBlockedIn('vanilla', ipVersion=6) should not return the
        IPv4 vanilla address, even if it is not blocked, because it has the
        wrong IP version.
        """
        self.bridge.setBlockedIn('ru')
        filtre = filters.byNotBlockedIn('cn', methodname='vanilla', ipVersion=6)
        self.assertFalse(filtre(self.bridge))

    def test_byNotBlockedIn_vanilla_blocked(self):
        """Calling byNotBlockedIn('vanilla') should not return the IPv4 vanilla
        address, if it is blocked.
        """
        self.bridge.setBlockedIn('ru')
        filtre = filters.byNotBlockedIn('ru', methodname='vanilla')
        self.assertFalse(filtre(self.bridge))
Пример #9
0
def load(state, hashring, clear=False):
    """Read and parse all descriptors, and load into a bridge hashring.

    Read all the appropriate bridge files from the saved
    :class:`~bridgedb.persistent.State`, parse and validate them, and then
    store them into our ``state.hashring`` instance. The ``state`` will be
    saved again at the end of this function.

    :type hashring: :class:`~bridgedb.bridgerings.BridgeSplitter`
    :param hashring: A class which provides a mechanism for HMACing
        Bridges in order to assign them to hashrings.
    :param boolean clear: If True, clear all previous bridges from the
        hashring before parsing for new ones.
    """
    if not state:
        logging.fatal("bridgedb.main.load() could not retrieve state!")
        sys.exit(2)

    if clear:
        logging.info("Clearing old bridges...")
        hashring.clear()

    logging.info("Loading bridges...")

    ignoreNetworkstatus = state.IGNORE_NETWORKSTATUS
    if ignoreNetworkstatus:
        logging.info("Ignoring BridgeAuthority networkstatus documents.")

    for auth in state.BRIDGE_AUTHORITY_DIRECTORIES:
        logging.info("Processing descriptors in %s directory..." % auth)

        bridges = {}
        timestamps = {}

        fn = expandBridgeAuthDir(auth, state.STATUS_FILE)
        logging.info("Opening networkstatus file: %s" % fn)
        networkstatuses = descriptors.parseNetworkStatusFile(fn)
        logging.debug("Closing networkstatus file: %s" % fn)

        logging.info("Processing networkstatus descriptors...")
        for router in networkstatuses:
            bridge = Bridge()
            bridge.updateFromNetworkStatus(router, ignoreNetworkstatus)
            try:
                bridge.assertOK()
            except MalformedBridgeInfo as error:
                logging.warn(str(error))
            else:
                bridges[bridge.fingerprint] = bridge

        for filename in state.BRIDGE_FILES:
            fn = expandBridgeAuthDir(auth, filename)
            logging.info("Opening bridge-server-descriptor file: '%s'" % fn)
            serverdescriptors = descriptors.parseServerDescriptorsFile(fn)
            logging.debug("Closing bridge-server-descriptor file: '%s'" % fn)

            for router in serverdescriptors:
                try:
                    bridge = bridges[router.fingerprint]
                except KeyError:
                    logging.warn((
                        "Received server descriptor for bridge '%s' which wasn't "
                        "in the networkstatus!") % router.fingerprint)
                    if ignoreNetworkstatus:
                        bridge = Bridge()
                    else:
                        continue

                try:
                    bridge.updateFromServerDescriptor(router,
                                                      ignoreNetworkstatus)
                except (ServerDescriptorWithoutNetworkstatus,
                        MissingServerDescriptorDigest,
                        ServerDescriptorDigestMismatch) as error:
                    logging.warn(str(error))
                    # Reject any routers whose server descriptors didn't pass
                    # :meth:`~bridges.Bridge._checkServerDescriptor`, i.e. those
                    # bridges who don't have corresponding networkstatus
                    # documents, or whose server descriptor digests don't check
                    # out:
                    bridges.pop(router.fingerprint)
                    continue

                if state.COLLECT_TIMESTAMPS:
                    # Update timestamps from server descriptors, not from network
                    # status descriptors (because networkstatus documents and
                    # descriptors aren't authenticated in any way):
                    if bridge.fingerprint in timestamps.keys():
                        timestamps[bridge.fingerprint].append(router.published)
                    else:
                        timestamps[bridge.fingerprint] = [router.published]

        eifiles = [
            expandBridgeAuthDir(auth, fn) for fn in state.EXTRA_INFO_FILES
        ]
        extrainfos = descriptors.parseExtraInfoFiles(*eifiles)
        for fingerprint, router in extrainfos.items():
            try:
                bridges[fingerprint].updateFromExtraInfoDescriptor(router)
            except MalformedBridgeInfo as error:
                logging.warn(str(error))
            except KeyError as error:
                logging.warn(
                    ("Received extrainfo descriptor for bridge '%s', "
                     "but could not find bridge with that fingerprint.") %
                    router.fingerprint)

        blacklist = parseBridgeBlacklistFile(state.NO_DISTRIBUTION_FILE)

        inserted = 0
        logging.info(
            "Trying to insert %d bridges into hashring, %d of which "
            "have the 'Running' flag..." %
            (len(bridges),
             len(list(filter(lambda b: b.flags.running, bridges.values())))))

        for fingerprint, bridge in bridges.items():
            # Skip insertion of bridges which are geolocated to be in one of the
            # NO_DISTRIBUTION_COUNTRIES, a.k.a. the countries we don't distribute
            # bridges from:
            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]))
            # Skip bridges that are running a blacklisted version of Tor.
            elif bridge.runsVersion(state.BLACKLISTED_TOR_VERSIONS):
                logging.warn(
                    "Not distributing bridge %s because it runs blacklisted "
                    "Tor version %s." % (router.fingerprint, bridge.software))
            else:
                # If the bridge is not running, then it is skipped during the
                # insertion process.
                hashring.insert(bridge)
                inserted += 1
        logging.info("Tried to insert %d bridges into hashring.  Resulting "
                     "hashring is of length %d." % (inserted, len(hashring)))

        if state.COLLECT_TIMESTAMPS:
            reactor.callInThread(updateBridgeHistory, bridges, timestamps)

        state.save()
Пример #10
0
def load(state, hashring, clear=False):
    """Read and parse all descriptors, and load into a bridge hashring.

    Read all the appropriate bridge files from the saved
    :class:`~bridgedb.persistent.State`, parse and validate them, and then
    store them into our ``state.hashring`` instance. The ``state`` will be
    saved again at the end of this function.

    :type hashring: :class:`~bridgedb.Bridges.BridgeSplitter`
    :param hashring: A class which provides a mechanism for HMACing
        Bridges in order to assign them to hashrings.
    :param boolean clear: If True, clear all previous bridges from the
        hashring before parsing for new ones.
    """
    if not state:
        logging.fatal("bridgedb.main.load() could not retrieve state!")
        sys.exit(2)

    if clear:
        logging.info("Clearing old bridges...")
        hashring.clear()

    logging.info("Loading bridges...")

    ignoreNetworkstatus = state.IGNORE_NETWORKSTATUS
    if ignoreNetworkstatus:
        logging.info("Ignoring BridgeAuthority networkstatus documents.")

    for auth in state.BRIDGE_AUTHORITY_DIRECTORIES:
        logging.info("Processing descriptors in %s directory..." % auth)

        bridges = {}
        timestamps = {}

        fn = expandBridgeAuthDir(auth, state.STATUS_FILE)
        logging.info("Opening networkstatus file: %s" % fn)
        networkstatuses = descriptors.parseNetworkStatusFile(fn)
        logging.debug("Closing networkstatus file: %s" % fn)

        logging.info("Processing networkstatus descriptors...")
        for router in networkstatuses:
            bridge = Bridge()
            bridge.updateFromNetworkStatus(router, ignoreNetworkstatus)
            try:
                bridge.assertOK()
            except MalformedBridgeInfo as error:
                logging.warn(str(error))
            else:
                bridges[bridge.fingerprint] = bridge

        for filename in state.BRIDGE_FILES:
            fn = expandBridgeAuthDir(auth, filename)
            logging.info("Opening bridge-server-descriptor file: '%s'" % fn)
            serverdescriptors = descriptors.parseServerDescriptorsFile(fn)
            logging.debug("Closing bridge-server-descriptor file: '%s'" % fn)

            for router in serverdescriptors:
                try:
                    bridge = bridges[router.fingerprint]
                except KeyError:
                    logging.warn(
                        ("Received server descriptor for bridge '%s' which wasn't "
                         "in the networkstatus!") % router.fingerprint)
                    if ignoreNetworkstatus:
                        bridge = Bridge()
                    else:
                        continue

                try:
                    bridge.updateFromServerDescriptor(router, ignoreNetworkstatus)
                except (ServerDescriptorWithoutNetworkstatus,
                        MissingServerDescriptorDigest,
                        ServerDescriptorDigestMismatch) as error:
                    logging.warn(str(error))
                    # Reject any routers whose server descriptors didn't pass
                    # :meth:`~bridges.Bridge._checkServerDescriptor`, i.e. those
                    # bridges who don't have corresponding networkstatus
                    # documents, or whose server descriptor digests don't check
                    # out:
                    bridges.pop(router.fingerprint)
                    continue

                if state.COLLECT_TIMESTAMPS:
                    # Update timestamps from server descriptors, not from network
                    # status descriptors (because networkstatus documents and
                    # descriptors aren't authenticated in any way):
                    if bridge.fingerprint in timestamps.keys():
                        timestamps[bridge.fingerprint].append(router.published)
                    else:
                        timestamps[bridge.fingerprint] = [router.published]

        eifiles = [expandBridgeAuthDir(auth, fn) for fn in state.EXTRA_INFO_FILES]
        extrainfos = descriptors.parseExtraInfoFiles(*eifiles)
        for fingerprint, router in extrainfos.items():
            try:
                bridges[fingerprint].updateFromExtraInfoDescriptor(router)
            except MalformedBridgeInfo as error:
                logging.warn(str(error))
            except KeyError as error:
                logging.warn(("Received extrainfo descriptor for bridge '%s', "
                              "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():
            # Skip insertion of bridges which are geolocated to be in one of the
            # NO_DISTRIBUTION_COUNTRIES, a.k.a. the countries we don't distribute
            # bridges from:
            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.
                hashring.insert(bridge)
                inserted += 1
        logging.info("Done inserting %d bridges into hashring." % inserted)

        if state.COLLECT_TIMESTAMPS:
            reactor.callInThread(updateBridgeHistory, bridges, timestamps)

        state.save()
Пример #11
0
def load(state, splitter, clear=False):
    """Read and parse all descriptors, and load into a bridge splitter.

    Read all the appropriate bridge files from the saved
    :class:`~bridgedb.persistent.State`, parse and validate them, and then
    store them into our ``state.splitter`` instance. The ``state`` will be
    saved again at the end of this function.

    :type splitter: :class:`BridgeSplitter <bridgedb.Bridges.BridgeHolder>`
    :param splitter: A class which provides a mechanism for HMACing
        Bridges in order to assign them to hashrings.
    :param boolean clear: If True, clear all previous bridges from the
        splitter before parsing for new ones.
    """
    if not state:
        logging.fatal("bridgedb.Main.load() could not retrieve state!")
        sys.exit(2)

    if clear:
        logging.info("Clearing old bridges...")
        splitter.clear()

    logging.info("Loading bridges...")

    ignoreNetworkstatus = state.IGNORE_NETWORKSTATUS
    if ignoreNetworkstatus:
        logging.info("Ignoring BridgeAuthority networkstatus documents.")

    bridges = {}
    timestamps = {}

    logging.info("Opening networkstatus file: %s" % state.STATUS_FILE)
    networkstatuses = descriptors.parseNetworkStatusFile(state.STATUS_FILE)
    logging.debug("Closing networkstatus file: %s" % state.STATUS_FILE)

    logging.info("Processing networkstatus descriptors...")
    for router in networkstatuses:
        bridge = Bridge()
        bridge.updateFromNetworkStatus(router, ignoreNetworkstatus)
        try:
            bridge.assertOK()
        except MalformedBridgeInfo as error:
            logging.warn(str(error))
        else:
            bridges[bridge.fingerprint] = bridge

    for filename in state.BRIDGE_FILES:
        logging.info("Opening bridge-server-descriptor file: '%s'" % filename)
        serverdescriptors = descriptors.parseServerDescriptorsFile(filename)
        logging.debug("Closing bridge-server-descriptor file: '%s'" % filename)

        for router in serverdescriptors:
            try:
                bridge = bridges[router.fingerprint]
            except KeyError:
                logging.warn(
                    ("Received server descriptor for bridge '%s' which wasn't "
                     "in the networkstatus!") % router.fingerprint)
                if ignoreNetworkstatus:
                    bridge = Bridge()
                else:
                    continue

            try:
                bridge.updateFromServerDescriptor(router, ignoreNetworkstatus)
            except (ServerDescriptorWithoutNetworkstatus,
                    MissingServerDescriptorDigest,
                    ServerDescriptorDigestMismatch) as error:
                logging.warn(str(error))
                # Reject any routers whose server descriptors didn't pass
                # :meth:`~bridges.Bridge._checkServerDescriptor`, i.e. those
                # bridges who don't have corresponding networkstatus
                # documents, or whose server descriptor digests don't check
                # out:
                bridges.pop(router.fingerprint)
                continue

            if state.COLLECT_TIMESTAMPS:
                # Update timestamps from server descriptors, not from network
                # status descriptors (because networkstatus documents and
                # descriptors aren't authenticated in any way):
                if bridge.fingerprint in timestamps.keys():
                    timestamps[bridge.fingerprint].append(router.published)
                else:
                    timestamps[bridge.fingerprint] = [router.published]

    extrainfos = descriptors.parseExtraInfoFiles(*state.EXTRA_INFO_FILES)
    for fingerprint, router in extrainfos.items():
        try:
            bridges[fingerprint].updateFromExtraInfoDescriptor(router)
        except MalformedBridgeInfo as error:
            logging.warn(str(error))
        except KeyError as error:
            logging.warn(("Received extrainfo descriptor for bridge '%s', "
                          "but could not find bridge with that fingerprint.") %
                         router.fingerprint)

    inserted = 0
    logging.info("Inserting %d bridges into splitter..." % len(bridges))
    for fingerprint, bridge in bridges.items():
        # Skip insertion of bridges which are geolocated to be in one of the
        # NO_DISTRIBUTION_COUNTRIES, a.k.a. the countries we don't distribute
        # bridges from:
        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))
        else:
            # If the bridge is not running, then it is skipped during the
            # insertion process.
            splitter.insert(bridge)
            inserted += 1
    logging.info("Done inserting %d bridges into splitter." % inserted)

    if state.COLLECT_TIMESTAMPS:
        reactor.callInThread(updateBridgeHistory, bridges, timestamps)

    state.save()