Example #1
0
class TrackerService(object):
    def __init__(self):
        """
        Initialize the variables of the TrackerServiceMaker and the logger.
        """
        self.endpoint = None
        self.stopping = False
        self.overlay = None

    async def start_tracker(self, listen_port):
        """
        Main method to startup the tracker.
        """
        self.endpoint = UDPEndpoint(listen_port)
        await self.endpoint.open()
        self.overlay = EndpointServer(self.endpoint)

        async def signal_handler(sig):
            print("Received shut down signal %s" % sig)
            if not self.stopping:
                self.stopping = True
                await self.overlay.unload()
                self.endpoint.close()
                get_event_loop().stop()

        signal.signal(signal.SIGINT,
                      lambda sig, _: ensure_future(signal_handler(sig)))
        signal.signal(signal.SIGTERM,
                      lambda sig, _: ensure_future(signal_handler(sig)))

        print("Started tracker")
Example #2
0
    def start_tracker(self, options):
        """
        Main method to startup the tracker.
        """
        self.endpoint = UDPEndpoint(options["listen_port"])
        self.endpoint.open()
        self.overlay = EndpointServer(self.endpoint)

        def signal_handler(sig, _):
            msg("Received shut down signal %s" % sig)
            if not self.stopping:
                self.stopping = True

                def close_ep():
                    self.endpoint.close().addCallback(
                        lambda *args, **kwargs: reactor.callFromThread(reactor.
                                                                       stop))

                self.overlay.unload()
                close_ep()

        signal.signal(signal.SIGINT, signal_handler)
        signal.signal(signal.SIGTERM, signal_handler)

        msg("Started tracker")
Example #3
0
    def test_tunnel_data(self):
        """
        Check if data is correctly exited.
        """
        # Listen in on communication of the target
        self.public_endpoint = UDPEndpoint(8080)
        self.public_endpoint.open()
        ep_listener = MockEndpointListener(self.public_endpoint)

        # Build a tunnel
        self.nodes[1].overlay.settings.become_exitnode = True
        yield self.introduce_nodes()
        self.nodes[0].overlay.build_tunnels(1)
        yield self.deliver_messages()

        # Construct a data packet
        prefix = '\x00' * 23
        data = prefix + ''.join([chr(i) for i in range(256)])

        self.public_endpoint.assert_open()

        # Tunnel the data to the endpoint
        circuit = self.nodes[0].overlay.circuits.values()[0]
        self.nodes[0].overlay.send_data(
            [circuit.sock_addr], circuit.circuit_id,
            ('localhost', self.public_endpoint.get_address()[1]),
            ('0.0.0.0', 0), data)
        # This is not test communication, but actual socket communication, we can't do a smart sleep
        yield self.sleep()

        self.assertEqual(len(ep_listener.received_packets), 1)
        self.assertEqual(ep_listener.received_packets[0][1], data)
Example #4
0
class TrackerServiceMaker(object):
    implements(IServiceMaker, IPlugin)
    tapname = "tracker"
    description = "IPv8 tracker twistd plugin"
    options = Options

    def __init__(self):
        """
        Initialize the variables of the TrackerServiceMaker and the logger.
        """
        self.endpoint = None
        self.stopping = False
        self.overlay = None

    def start_tracker(self, options):
        """
        Main method to startup the tracker.
        """
        self.endpoint = UDPEndpoint(options["listen_port"])
        self.endpoint.open()
        self.overlay = EndpointServer(self.endpoint)

        def signal_handler(sig, _):
            msg("Received shut down signal %s" % sig)
            if not self.stopping:
                self.stopping = True

                def close_ep():
                    self.endpoint.close().addCallback(
                        lambda *args, **kwargs: reactor.callFromThread(reactor.
                                                                       stop))

                self.overlay.unload()
                close_ep()

        signal.signal(signal.SIGINT, signal_handler)
        signal.signal(signal.SIGTERM, signal_handler)

        msg("Started tracker")

    def makeService(self, options):
        """
        Construct a tracker service.
        """
        tracker_service = MultiService()
        tracker_service.setName("IPv8Tracker")

        reactor.callWhenRunning(self.start_tracker, options)

        return tracker_service
Example #5
0
        def __init__(self, configuration, endpoint_override=None, enable_statistics=False, extra_communities=None):
            if endpoint_override:
                self.endpoint = endpoint_override
            else:
                self.endpoint = UDPEndpoint(port=configuration['port'], ip=configuration['address'])
                self.endpoint.open()
                if enable_statistics:
                    self.endpoint = StatisticsEndpoint(self, self.endpoint)

            self.network = Network()

            # Load/generate keys
            self.keys = {}
            for key_block in configuration['keys']:
                if key_block['file'] and isfile(key_block['file']):
                    with open(key_block['file'], 'r') as f:
                        content = f.read()
                        try:
                            # IPv8 Standardized bin format
                            self.keys[key_block['alias']] = Peer(default_eccrypto.key_from_private_bin(content))
                        except ValueError:
                            try:
                                # Try old Tribler M2Crypto PEM format
                                content = b64decode(content[31:-30].replace('\n', ''))
                                peer = Peer(M2CryptoSK(keystring=content))
                                peer.mid # This will error out if the keystring is not M2Crypto
                                self.keys[key_block['alias']] = peer
                            except:
                                # Try old LibNacl format
                                content = "LibNaCLSK:" + content
                                self.keys[key_block['alias']] = Peer(default_eccrypto.key_from_private_bin(content))
                else:
                    self.keys[key_block['alias']] = Peer(default_eccrypto.generate_key(key_block['generation']))
                    if key_block['file']:
                        with open(key_block['file'], 'w') as f:
                            f.write(self.keys[key_block['alias']].key.key_to_bin())

            # Setup logging
            logging.basicConfig(**configuration['logger'])

            self.overlay_lock = RLock()
            self.strategies = []
            self.overlays = []

            for overlay in configuration['overlays']:
                overlay_class = _COMMUNITIES.get(overlay['class'], (extra_communities or {}).get(overlay['class']))
                my_peer = self.keys[overlay['key']]
                overlay_instance = overlay_class(my_peer, self.endpoint, self.network, **overlay['initialize'])
                self.overlays.append(overlay_instance)
                for walker in overlay['walkers']:
                    strategy_class = _WALKERS.get(walker['strategy'],
                                                  overlay_instance.get_available_strategies().get(walker['strategy']))
                    args = walker['init']
                    target_peers = walker['peers']
                    self.strategies.append((strategy_class(overlay_instance, **args), target_peers))
                for config in overlay['on_start']:
                    reactor.callWhenRunning(getattr(overlay_instance, config[0]), *config[1:])

            self.state_machine_lc = LoopingCall(self.on_tick)
            self.state_machine_lc.start(configuration['walker_interval'], False)
Example #6
0
    async def start_tracker(self, listen_port):
        """
        Main method to startup the tracker.
        """
        self.endpoint = UDPEndpoint(listen_port)
        await self.endpoint.open()
        self.overlay = EndpointServer(self.endpoint)

        async def signal_handler(sig):
            print("Received shut down signal %s" % sig)
            if not self.stopping:
                self.stopping = True
                await self.overlay.unload()
                self.endpoint.close()
                get_event_loop().stop()

        signal.signal(signal.SIGINT,
                      lambda sig, _: ensure_future(signal_handler(sig)))
        signal.signal(signal.SIGTERM,
                      lambda sig, _: ensure_future(signal_handler(sig)))

        print("Started tracker")
Example #7
0
 async def produce_anonymized_endpoint(self):
     base_endpoint = UDPEndpoint(port=0,
                                 ip=self.configuration['address'])
     await base_endpoint.open()
     return TunnelEndpoint(base_endpoint)
Example #8
0
class TrackerService:
    def __init__(self):
        """
        Initialize the variables of the TrackerServiceMaker and the logger.
        """
        self.endpoint = None
        self.stopping = False
        self.overlay = None
        self.site = None

    def create_endpoint_server(self):
        return EndpointServer(self.endpoint)

    async def start_tracker(self, listen_port):
        """
        Main method to startup the tracker.
        """
        self.endpoint = UDPEndpoint(listen_port)
        await self.endpoint.open()
        self.overlay = self.create_endpoint_server()

        async def signal_handler(sig):
            print("Received shut down signal %s" % sig)
            if not self.stopping:
                self.stopping = True
                await self.overlay.unload()
                self.endpoint.close()
                if self.site:
                    await self.site.stop()
                get_event_loop().stop()

        signal.signal(signal.SIGINT,
                      lambda sig, _: ensure_future(signal_handler(sig)))
        signal.signal(signal.SIGTERM,
                      lambda sig, _: ensure_future(signal_handler(sig)))

        print("Started tracker")

    async def start_api(self, listen_port, api_key, cert_file):
        ssl_context = None
        if cert_file:
            ssl_context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
            ssl_context.load_cert_chain(cert_file)

        async def get_services(_):
            services = set.union(*self.overlay.network.services_per_peer.values()) \
                if self.overlay.network.services_per_peer else set()
            return Response({
                hexlify(service).decode(): [
                    str(p) for p in self.overlay.network.get_peers_for_service(
                        service)
                ]
                for service in services
            })

        app = web.Application(middlewares=[ApiKeyMiddleware(api_key)])
        app.add_routes([web.get('/services', get_services)])
        runner = web.AppRunner(app, access_log=None)
        await runner.setup()
        self.site = web.TCPSite(runner,
                                '0.0.0.0',
                                listen_port,
                                ssl_context=ssl_context)
        await self.site.start()

        print("Started API server")
Example #9
0
class TestTunnelCommunity(TestBase):
    def setUp(self):
        super(TestTunnelCommunity, self).setUp()
        self.initialize(TunnelCommunity, 2)

        # An actual UDPEndpoint, if needed by the test (for catching exited data)
        self.public_endpoint = None

    def tearDown(self):
        super(TestTunnelCommunity, self).tearDown()

        # If an endpoint was used, close it
        if self.public_endpoint:
            self.public_endpoint.close()

    def create_node(self):
        # Initialize a TunnelCommunity without circuits or exit node functionality
        settings = TunnelSettings()
        settings.become_exitnode = False
        settings.min_circuits = 0
        settings.max_circuits = 0
        ipv8 = MockIPv8(u"curve25519", TunnelCommunity, settings=settings)
        # Then kill all automated circuit creation
        ipv8.overlay.cancel_all_pending_tasks()
        # Finally, use the proper exitnode and circuit settings for manual creation
        ipv8.overlay.settings.min_circuits = 1
        ipv8.overlay.settings.max_circuits = 1
        return ipv8

    @twisted_test
    def test_introduction_as_exit(self):
        """
        Check if introduction requests share the fact that nodes are exit nodes.
        """
        self.nodes[0].overlay.settings.become_exitnode = True
        self.nodes[1].overlay.settings.become_exitnode = False

        yield self.introduce_nodes()

        self.assertIn(self.nodes[0].my_peer.public_key.key_to_bin(),
                      self.nodes[1].overlay.exit_candidates)
        self.assertNotIn(self.nodes[1].my_peer.public_key.key_to_bin(),
                         self.nodes[0].overlay.exit_candidates)

    @twisted_test
    def test_introduction_as_exit_twoway(self):
        """
        Check if two nodes can have each other as exit nodes.
        """
        self.nodes[0].overlay.settings.become_exitnode = True
        self.nodes[1].overlay.settings.become_exitnode = True

        yield self.introduce_nodes()

        self.assertIn(self.nodes[0].my_peer.public_key.key_to_bin(),
                      self.nodes[1].overlay.exit_candidates)
        self.assertIn(self.nodes[1].my_peer.public_key.key_to_bin(),
                      self.nodes[0].overlay.exit_candidates)

    @twisted_test
    def test_introduction_as_exit_noway(self):
        """
        Check if two nodes don't advertise themselves as exit node incorrectly.
        """
        self.nodes[0].overlay.settings.become_exitnode = False
        self.nodes[1].overlay.settings.become_exitnode = False

        yield self.introduce_nodes()

        self.assertEqual(len(self.nodes[0].overlay.exit_candidates), 0)
        self.assertEqual(len(self.nodes[1].overlay.exit_candidates), 0)

    @twisted_test
    def test_create_circuit(self):
        """
        Check if 1 hop circuit creation works.
        """
        self.nodes[1].overlay.settings.become_exitnode = True
        yield self.introduce_nodes()

        # Let node 0 build tunnels of 1 hop (settings.min_circuits = settings.max_circuits = 1)
        # It should use node 1 for this
        self.nodes[0].overlay.build_tunnels(1)

        # Let the circuit creation commence
        yield self.deliver_messages()

        # Node 0 should now have all of its required 1 hop circuits (1.0/100%)
        self.assertEqual(self.nodes[0].overlay.tunnels_ready(1), 1.0)
        # Node 1 has an exit socket open
        self.assertEqual(len(self.nodes[1].overlay.exit_sockets), 1)

    @twisted_test
    def test_create_circuit_no_exit(self):
        """
        Check if 1 hop circuit creation fails without exit nodes.
        """
        self.nodes[1].overlay.settings.become_exitnode = False
        yield self.introduce_nodes()
        self.nodes[0].overlay.build_tunnels(1)

        # Attempt circuit creation
        yield self.deliver_messages()

        # Node 0 should now have no 1 hop circuits (0.0/0%)
        self.assertEqual(self.nodes[0].overlay.tunnels_ready(1), 0.0)
        # Node 1 should not have an exit socket open
        self.assertEqual(len(self.nodes[1].overlay.exit_sockets), 0)

    @twisted_test
    def test_destroy_circuit(self):
        """
        Check if a 1 hop circuit can be destroyed.
        """
        self.nodes[1].overlay.settings.become_exitnode = True
        yield self.introduce_nodes()
        self.nodes[0].overlay.build_tunnels(1)
        yield self.deliver_messages()

        # Destroy the circuit we just created using a destroy message
        self.nodes[0].overlay.remove_circuit(
            self.nodes[0].overlay.circuits.keys()[0], destroy=True)
        yield self.deliver_messages()

        # Node 0 should now have no 1 hop circuits (0.0/0%)
        self.assertEqual(self.nodes[0].overlay.tunnels_ready(1), 0.0)
        # Node 1 should not have an exit socket open
        self.assertEqual(len(self.nodes[1].overlay.exit_sockets), 0)

    @twisted_test
    def test_destroy_circuit_bad_id(self):
        """
        Check if the correct circuit gets destroyed.
        """
        self.nodes[1].overlay.settings.become_exitnode = True
        yield self.introduce_nodes()
        self.nodes[0].overlay.build_tunnels(1)
        yield self.deliver_messages()

        # Destroy a circuit which does not exist (circuit_id + 1)
        # This should not affect other circuits
        self.nodes[0].overlay.remove_circuit(
            self.nodes[0].overlay.circuits.keys()[0] + 1, destroy=True)
        yield self.deliver_messages()

        # Node 0 should still have all of its required 1 hop circuits (1.0/100%)
        self.assertEqual(self.nodes[0].overlay.tunnels_ready(1), 1.0)
        # Node 1 still has an exit socket open
        self.assertEqual(len(self.nodes[1].overlay.exit_sockets), 1)

    @twisted_test
    def test_tunnel_data(self):
        """
        Check if data is correctly exited.
        """
        # Listen in on communication of the target
        self.public_endpoint = UDPEndpoint(8080)
        self.public_endpoint.open()
        ep_listener = MockEndpointListener(self.public_endpoint)

        # Build a tunnel
        self.nodes[1].overlay.settings.become_exitnode = True
        yield self.introduce_nodes()
        self.nodes[0].overlay.build_tunnels(1)
        yield self.deliver_messages()

        # Construct a data packet
        prefix = '\x00' * 23
        data = prefix + ''.join([chr(i) for i in range(256)])

        self.public_endpoint.assert_open()

        # Tunnel the data to the endpoint
        circuit = self.nodes[0].overlay.circuits.values()[0]
        self.nodes[0].overlay.send_data(
            [circuit.sock_addr], circuit.circuit_id,
            ('localhost', self.public_endpoint.get_address()[1]),
            ('0.0.0.0', 0), data)
        # This is not test communication, but actual socket communication, we can't do a smart sleep
        yield self.sleep()

        self.assertEqual(len(ep_listener.received_packets), 1)
        self.assertEqual(ep_listener.received_packets[0][1], data)

    @twisted_test
    def test_two_hop_circuit(self):
        """
        Check if a two hop circuit is correctly created.

        Note that we avoid exit nodes in the relay path, so we explicitly set relay nodes to not be exits.
        """
        self.add_node_to_experiment(self.create_node())

        # Build a tunnel
        self.nodes[1].overlay.settings.become_exitnode = True
        yield self.introduce_nodes()
        self.nodes[0].overlay.build_tunnels(2)
        yield self.deliver_messages()

        self.assertEqual(self.nodes[0].overlay.tunnels_ready(2), 1.0)

    @twisted_test
    def test_three_hop_circuit(self):
        """
        Check if a three hop circuit is correctly created.

        Note that we avoid exit nodes in the relay path, so we explicitly set relay nodes to not be exits.
        """
        self.add_node_to_experiment(self.create_node())
        self.add_node_to_experiment(self.create_node())

        # Build a tunnel
        self.nodes[1].overlay.settings.become_exitnode = True
        yield self.introduce_nodes()
        self.nodes[0].overlay.build_tunnels(3)
        yield self.deliver_messages()

        self.assertEqual(self.nodes[0].overlay.tunnels_ready(3), 1.0)

    @twisted_test
    def test_create_two_circuit(self):
        """
        Check if multiple 1 hop circuit creation works.
        """
        self.add_node_to_experiment(self.create_node())
        self.nodes[0].overlay.settings.min_circuits = 2
        self.nodes[0].overlay.settings.max_circuits = 2
        self.nodes[1].overlay.settings.become_exitnode = True
        self.nodes[2].overlay.settings.become_exitnode = True
        yield self.introduce_nodes()

        # Let node 0 build tunnels of 1 hop (settings.min_circuits = settings.max_circuits = 2)
        # It should use node 1 and 2 for this
        self.nodes[0].overlay.build_tunnels(1)

        # Let the circuit creation commence
        yield self.deliver_messages()

        # Node 0 should now have all of its required 1 hop circuits (1.0/100%)
        self.assertEqual(self.nodes[0].overlay.tunnels_ready(1), 1.0)
        self.assertEqual(len(self.nodes[0].overlay.circuits), 2)
        # Two exit sockets are open between node 1 and 2 (NOT evenly spread)
        self.assertEqual(
            len(self.nodes[1].overlay.exit_sockets) +
            len(self.nodes[2].overlay.exit_sockets), 2)