From 28976a36e7d72e37189480f356a6badb5801a483 Mon Sep 17 00:00:00 2001 From: Rob Ruigrok Date: Thu, 9 Apr 2015 18:32:28 +0200 Subject: [PATCH] Fix connectability constraint on exit-node --- Tribler/Test/test_tunnel_community.py | 31 ++++++------------ Tribler/community/tunnel/tunnel_community.py | 34 +++++++++++++------- 2 files changed, 32 insertions(+), 33 deletions(-) diff --git a/Tribler/Test/test_tunnel_community.py b/Tribler/Test/test_tunnel_community.py index 87977d52288..9510537f3ee 100644 --- a/Tribler/Test/test_tunnel_community.py +++ b/Tribler/Test/test_tunnel_community.py @@ -5,8 +5,6 @@ from threading import Event from traceback import print_exc -from nose.tools import timed - from Tribler.Core.DecentralizedTracking.pymdht.core.identifier import Id from Tribler.Core.Utilities.twisted_thread import reactor from Tribler.Core.simpledefs import dlstatus_strings @@ -19,7 +17,6 @@ class TestTunnelCommunity(TestGuiAsServer): - @timed(120) def test_anon_download(self): def take_second_screenshot(): self.screenshot() @@ -66,7 +63,6 @@ def do_create_local_torrent(_): self.startTest(do_create_local_torrent) - @timed(180) def test_anon_download_without_relays(self): def take_second_screenshot(): self.screenshot() @@ -98,10 +94,8 @@ def check_progress(download, start_time): self.CallConditional(1, lambda: download.get_progress() == 0.0, lambda: on_success(download, start_time), - 'Anonymous download without relays should not have any progress (%.1f%% downloaded)' % ( - download.get_progress() * 100), - on_fail - ) + 'Anonymous download without relays should not have any progress (%.1f%% downloaded)' % + (download.get_progress() * 100), on_fail) def do_create_local_torrent(_): tf = self.setupSeeder() @@ -115,7 +109,6 @@ def do_create_local_torrent(_): self.startTest(do_create_local_torrent, nr_exitnodes=5, nr_relays=0) - @timed(180) def test_anon_download_without_exitnodes(self): def take_second_screenshot(): self.screenshot() @@ -147,10 +140,8 @@ def check_progress(download, start_time): self.CallConditional(1, lambda: download.get_progress() == 0.0, lambda: on_success(download, start_time), - 'Anonymous download without exit nodes should not have any progress (%.1f%% downloaded)' % ( - download.get_progress() * 100), - on_fail - ) + 'Anonymous download without exit nodes should not make progress (%.1f%% downloaded)' % + (download.get_progress() * 100), on_fail) def do_create_local_torrent(_): tf = self.setupSeeder() @@ -164,7 +155,6 @@ def do_create_local_torrent(_): self.startTest(do_create_local_torrent, nr_exitnodes=0, nr_relays=5) - @timed(120) def test_anon_download_exitnode_changeofmind(self): def changed_my_mind(tunnel_communities): @@ -175,7 +165,8 @@ def changed_my_mind(tunnel_communities): def compare_progress(lastprogress, download): progress = download.get_progress() self.assert_(progress == lastprogress, - "Expected no progress, but actual progress was progress=%s, lastprogress=%s" % (progress, lastprogress)) + "Expected no progress, but actual progress was progress=%s, lastprogress=%s" % (progress, + lastprogress)) self.quit() def check_progress(download, start_time): @@ -195,7 +186,6 @@ def do_create_local_torrent(tunnel_communities): self.startTest(do_create_local_torrent, nr_exitnodes=4, nr_relays=6) - @timed(120) def test_anon_tunnel(self): got_data = Event() this = self @@ -222,10 +212,10 @@ def start_test(tunnel_communities): def replace_socks(tunnel_communities): for tunnel_community in tunnel_communities: socks_server = tunnel_community.socks_server - socks_server.on_incoming_from_tunnel = lambda community, circuit, origin, data, socks_server = socks_server: on_incoming_from_tunnel( - socks_server, community, circuit, origin, data) - tunnel_community.exit_data = lambda circuit_id, sock_addr, destination, data, community = tunnel_community: exit_data( - community, circuit_id, sock_addr, destination, data) + socks_server.on_incoming_from_tunnel = lambda community, circuit, origin, data, \ + socks_server = socks_server: on_incoming_from_tunnel(socks_server, community, circuit, origin, data) + tunnel_community.exit_data = lambda circuit_id, sock_addr, destination, data, \ + community = tunnel_community: exit_data(community, circuit_id, sock_addr, destination, data) tunnel_communities[-1].circuits_needed[3] = 4 self.CallConditional(30, lambda: len(tunnel_communities[-1].active_data_circuits()) == 4, @@ -233,7 +223,6 @@ def replace_socks(tunnel_communities): self.startTest(replace_socks) - @timed(180) def test_hidden_services(self): def take_second_screenshot(): self.screenshot() diff --git a/Tribler/community/tunnel/tunnel_community.py b/Tribler/community/tunnel/tunnel_community.py index fe1baa53e43..eb7d5b1df5f 100644 --- a/Tribler/community/tunnel/tunnel_community.py +++ b/Tribler/community/tunnel/tunnel_community.py @@ -257,7 +257,7 @@ def initialize(self, tribler_session=None, settings=None): self.trsession = tribler_session self.settings = settings if settings else TunnelSettings(tribler_session=tribler_session) - self._logger.debug("TunnelCommunity: become_exitnode = %s" % settings.become_exitnode) + self._logger.debug("TunnelCommunity: setting become_exitnode = %s" % self.settings.become_exitnode) super(TunnelCommunity, self).initialize() @@ -281,6 +281,15 @@ def initialize(self, tribler_session=None, settings=None): self.notifier = Notifier.getInstance() self.trsession.lm.tunnel_community = self + def self_is_connectable(self): + return self._dispersy._connection_type == u"public" + + def candidate_is_connectable(self, candidate): + return candidate.connection_type == u"public" + + def become_exitnode(self): + return self.settings.become_exitnode + def start_download_test(self): if self.trsession and self.trsession.get_libtorrent() and self.settings.do_test: self.libtorrent_test = LibtorrentTest(self, self.trsession) @@ -431,10 +440,7 @@ def do_remove(self): self.remove_exit_socket(circuit_id, 'traffic limit exceeded') # Remove exit_candidates that are not returned as dispersy verified candidates - current_candidates = {} - for c in self.dispersy_yield_verified_candidates(): - pubkey = c.get_member().public_key - current_candidates[pubkey] = pubkey + current_candidates = set(c.get_member().public_key for c in self.dispersy_yield_verified_candidates()) ckeys = self.exit_candidates.keys() for pubkey in ckeys: if pubkey not in current_candidates: @@ -740,28 +746,32 @@ def _ours_on_created_extended(self, circuit, message): if circuit.state == CIRCUIT_STATE_EXTENDING: become_exit = circuit.goal_hops - 1 == len(circuit.hops) + ignore_candidates = [self.crypto.key_to_bin(hop.public_key) for hop in circuit.hops] + \ + [self.my_member.public_key] + if become_exit: if circuit.required_exit: + # Set the required exit according to the circuit setting (e.g. for linking e2e circuits) host, port, pub_key = circuit.required_exit extend_hop_public_bin = pub_key extend_hop_addr = (host, port) else: + # The exit node is a verified connectable exit node peer chosen by the circuit initiator extend_hop_public_bin = None for c in self.dispersy_yield_verified_candidates(): pubkey = c.get_member().public_key exit_candidate = self.exit_candidates[pubkey] - if exit_candidate.become_exit: + if exit_candidate.become_exit and self.candidate_is_connectable(c) and pubkey not in ignore_candidates: wan = c._wan_address extend_hop_public_bin = pubkey extend_hop_addr = wan break else: + # The next candidate is chosen from the returned list of possible candidates candidate_list_enc = message.payload.candidate_list _, candidate_list = decode(self.crypto.decrypt_str( candidate_list_enc, hop.session_keys[EXIT_NODE], hop.session_keys[EXIT_NODE_SALT])) - ignore_candidates = [self.crypto.key_to_bin(hop.public_key) for hop in circuit.hops] + \ - [self.my_member.public_key] if circuit.required_exit: ignore_candidates.append(circuit.required_exit[2]) for ignore_candidate in ignore_candidates: @@ -811,7 +821,7 @@ def _ours_on_created_extended(self, circuit, message): self.notifier.notify(NTFY_TUNNEL, NTFY_CREATED if len(circuit.hops) == 1 else NTFY_EXTENDED, circuit) def on_introduction_request(self, messages): - exitnode = self.settings.become_exitnode + exitnode = self.become_exitnode() extra_payload = [exitnode] super(TunnelCommunity, self).on_introduction_request(messages, extra_payload) for message in messages: @@ -819,7 +829,7 @@ def on_introduction_request(self, messages): self.exit_candidates[pubkey] = ExitCandidate(message.payload.exitnode) def create_introduction_request(self, destination, allow_sync, forward=True, is_fast_walker=False): - exitnode = self.settings.become_exitnode + exitnode = self.become_exitnode() extra_payload = [exitnode] super(TunnelCommunity, self).create_introduction_request(destination, allow_sync, forward, is_fast_walker, extra_payload) @@ -883,7 +893,7 @@ def on_create(self, messages): pubkey = c.get_member().public_key vc = self.exit_candidates[pubkey] if vc.become_exit: - # Exit nodes are chosen by the circuit initiator, don't add them + # Exit nodes are chosen by the circuit initiator, we decided not to use exit nodes as normal relay continue candidates[pubkey] = c @@ -1120,7 +1130,7 @@ def tunnel_data_to_origin(self, circuit_id, sock_addr, source_address, data): self.send_data([Candidate(sock_addr, False)], u'data', packet) def exit_data(self, circuit_id, sock_addr, destination, data): - if not self.settings.become_exitnode: + if not self.become_exitnode(): self._logger.error("Dropping data packets, refusing to be an exit node") elif circuit_id in self.exit_sockets: if not self.exit_sockets[circuit_id].enabled: