Skip to content

Commit

Permalink
Fix connectability constraint on exit-node
Browse files Browse the repository at this point in the history
  • Loading branch information
rjruigrok committed Apr 9, 2015
1 parent 86d4969 commit 28976a3
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 33 deletions.
31 changes: 10 additions & 21 deletions Tribler/Test/test_tunnel_community.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -19,7 +17,6 @@

class TestTunnelCommunity(TestGuiAsServer):

@timed(120)
def test_anon_download(self):
def take_second_screenshot():
self.screenshot()
Expand Down Expand Up @@ -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()
Expand Down Expand Up @@ -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()
Expand All @@ -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()
Expand Down Expand Up @@ -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()
Expand All @@ -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):
Expand All @@ -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):
Expand All @@ -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
Expand All @@ -222,18 +212,17 @@ 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,
lambda: start_test(tunnel_communities))

self.startTest(replace_socks)

@timed(180)
def test_hidden_services(self):
def take_second_screenshot():
self.screenshot()
Expand Down
34 changes: 22 additions & 12 deletions Tribler/community/tunnel/tunnel_community.py
Original file line number Diff line number Diff line change
Expand Up @@ -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()

Expand All @@ -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)
Expand Down Expand Up @@ -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:
Expand Down Expand Up @@ -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:
Expand Down Expand Up @@ -811,15 +821,15 @@ 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:
pubkey = message.candidate.get_member().public_key
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)
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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:
Expand Down

0 comments on commit 28976a3

Please sign in to comment.