commit 294fc29786c47fbffac62cbbebdfad3186906fe3 Author: juga0 juga@riseup.net Date: Tue Feb 2 13:07:57 2021 +0000
minor: scanner: Change logic creating the path
When the relay is not an exit, instead of choosing exits that can exit to all IPs, try with exits that can exit to some IPs, since the relay will be measured again with a different exit in other loop.
When the relay is an exit, instead of ensuring it can exit all IPs, try using it as exit if it can exit to some IPs. If it fails connecting to the Web server, then try a 2nd time using it as entry to avoid that it will fail in all loops if there is only one Web server, cause it will be used again as an exit.
Also, the helper exits don't need to be able to exit all IPs. When a helper exit fails to exit (maybe cause it can not exit to the Web sever IP), it's not a problem cause in a next loop other exit will be choosen.
This change of logic also solves the bug where non exits were being used as exits, because we were trying to measure again a relay that was used as entry, because it could not exit all IPs, which includes also the non exits.
Closes: #40041. --- sbws/core/scanner.py | 50 ++++++++++++++++++++++++------- tests/integration/lib/test_destination.py | 6 ++-- 2 files changed, 43 insertions(+), 13 deletions(-)
diff --git a/sbws/core/scanner.py b/sbws/core/scanner.py index aa17452..1499264 100644 --- a/sbws/core/scanner.py +++ b/sbws/core/scanner.py @@ -209,8 +209,14 @@ def _pick_ideal_second_hop(relay, dest, rl, cont, is_exit): destination **dest**, pick a second relay that is or is not an exit according to **is_exit**. ''' - candidates = rl.exits_not_bad_allowing_port_all_ips(dest.port) if is_exit \ - else rl.non_exits + # 40041: Instead of using exits that can exit to all IPs, to ensure that + # they can make requests to the Web servers, try with the exits that + # allow some IPs, since there're more. + # In the case that a concrete exit can't exit to the Web server, it is not + # a problem since the relay will be measured in the next loop with other + # random exit. + candidates = rl.exits_not_bad_allowing_port_some_ips(dest.port) \ + if is_exit else rl.non_exits if not len(candidates): return None min_relay_bw = rl.exit_min_bw() if is_exit else rl.non_exit_min_bw() @@ -332,20 +338,20 @@ def measure_relay(args, conf, destinations, cb, rl, relay):
# Pick a relay to help us measure the given relay. If the given relay is an # exit, then pick a non-exit. Otherwise pick an exit. - if relay.is_exit_not_bad_allowing_port_all_ips(dest.port): + # Instead of ensuring that the relay can exit to all IPs, try first with + # the relay as an exit, if it can exit to some IPs. + if relay.is_exit_not_bad_allowing_port_some_ips(dest.port): circ_fps, nicknames = create_path_relay_as_exit(relay, dest, rl, cb) else: circ_fps, nicknames = create_path_relay_as_entry(relay, dest, rl, cb)
# Build the circuit circ_id, reason = cb.build_circuit(circ_fps) - if not circ_id and relay.fingerprint == circ_fps[0]: - # We detected that some exits fail to build circuits as 1st hop. - # If that's the case, try again using them as 2nd hop. - # We could reuse the helper, but it does not need to be an exit now, - # so choose other again. - create_path_relay_as_exit(relay, dest, rl, cb) - circ_id, reason = cb.build_circuit(circ_fps) + + # If the circuit failed to get created, bad luck, it will be created again + # with other helper. + # Here we won't have the case that an exit tried to build the circuit as + # entry and failed (#40029), cause not checking that it can exit all IPs. if not circ_id: return error_no_circuit(circ_fps, nicknames, reason, relay, dest, our_nick) @@ -354,6 +360,30 @@ def measure_relay(args, conf, destinations, cb, rl, relay): # Make a connection to the destination is_usable, usable_data = connect_to_destination_over_circuit( dest, circ_id, s, cb.controller, dest._max_dl) + + # In the case that the relay was used as an exit, but could not exit + # to the Web server, try again using it as entry, to avoid that it would + # always fail when there's only one Web server. + if not is_usable and \ + relay.is_exit_not_bad_allowing_port_all_ips(dest.port): + log.info( + "Exit %s (%s) that can't exit all ips failed to connect to " + " %s via circuit %s (%s). Trying again with it as entry.", + relay.fingerprint, relay.nickname, dest, circ_fps, nicknames) + circ_fps, nicknames = create_path_relay_as_entry(relay, dest, rl, cb) + circ_id, reason = cb.build_circuit(circ_fps) + if not circ_id: + log.warning( + "Exit %s (%s) that can't exit all ips, failed to create " + " circuit as entry: %s (%s).", relay.fingerprint, + relay.nickname, circ_fps, nicknames) + return error_no_circuit(relay, circ_fps, nicknames, reason, dest, + our_nick) + + log.debug('Built circuit with path %s (%s) to measure %s (%s)', + circ_fps, nicknames, relay.fingerprint, relay.nickname) + is_usable, usable_data = connect_to_destination_over_circuit( + dest, circ_id, s, cb.controller, dest._max_dl) if not is_usable: log.debug('Destination %s unusable via circuit %s (%s), %s', dest.url, circ_fps, nicknames, usable_data) diff --git a/tests/integration/lib/test_destination.py b/tests/integration/lib/test_destination.py index 19f6617..d305b0e 100644 --- a/tests/integration/lib/test_destination.py +++ b/tests/integration/lib/test_destination.py @@ -26,7 +26,7 @@ def test_connect_to_destination_over_circuit_success(persistent_launch_tor, relay = [r for r in rl.relays if r.nickname == 'relay1mbyteMAB'][0] # Choose an exit, for this test it does not matter the bandwidth - helper = rl.exits_not_bad_allowing_port_all_ips(destination.port)[0] + helper = rl.exits_not_bad_allowing_port_some_ips(destination.port)[0] circuit_path = [relay.fingerprint, helper.fingerprint] # build a circuit circuit_id, _ = cb.build_circuit(circuit_path) @@ -46,7 +46,7 @@ def test_connect_to_destination_over_circuit_fail(persistent_launch_tor, relay = [r for r in rl.relays if r.nickname == 'relay1mbyteMAB'][0] # Choose an exit, for this test it does not matter the bandwidth - helper = rl.exits_not_bad_allowing_port_all_ips(bad_destination.port)[0] + helper = rl.exits_not_bad_allowing_port_some_ips(bad_destination.port)[0] circuit_path = [relay.fingerprint, helper.fingerprint] # Build a circuit. circuit_id, _ = cb.build_circuit(circuit_path) @@ -75,7 +75,7 @@ def test_functional_destinations(conf, cb, rl, persistent_launch_tor): relay = [r for r in rl.relays if r.nickname == 'relay1mbyteMAB'][0] # Choose an exit, for this test it does not matter the bandwidth - helper = rl.exits_not_bad_allowing_port_all_ips(bad_destination.port)[0] + helper = rl.exits_not_bad_allowing_port_some_ips(bad_destination.port)[0] circuit_path = [relay.fingerprint, helper.fingerprint] # Build a circuit. circuit_id, _ = cb.build_circuit(circuit_path)
tor-commits@lists.torproject.org