From b9a2b0d19b1a6dba590e89bc1610687f3484e4eb Mon Sep 17 00:00:00 2001 From: SomberNight Date: Thu, 25 Apr 2024 22:48:56 +0000 Subject: [PATCH] network: re-detect is_proxy_tor every time we connect to a server This avoids some false negatives for is_proxy_tor. (previously we only set is_proxy_tor when the proxy settings were changed) In particular, consider scenario: - Tor browser not running - user sets "localhost:9150" as proxy - detection sets network.is_proxy_tor to False - user starts Tor browser - network, due to retries, finds proxy working and connects to some servers - network.is_proxy_tor remains False --- electrum/network.py | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/electrum/network.py b/electrum/network.py index ddef1aa8f..6ef23d57a 100644 --- a/electrum/network.py +++ b/electrum/network.py @@ -648,25 +648,28 @@ class Network(Logger, NetworkRetryManager[ServerAddr]): self.logger.info(f'setting proxy {proxy}') self.proxy = proxy + + # reset is_proxy_tor to unknown, and re-detect it: self.is_proxy_tor = None + self._detect_if_proxy_is_tor() + + util.trigger_callback('proxy_set', self.proxy) + def _detect_if_proxy_is_tor(self) -> None: def tor_probe_task(p): assert p is not None - tor_proxy = util.is_tor_socks_port(p['host'], int(p['port'])) + is_tor = util.is_tor_socks_port(p['host'], int(p['port'])) if self.proxy == p: # is this the proxy we probed? - self.logger.info(f'Proxy is {"" if tor_proxy else "not "}TOR') - self._tor_probe_done(tor_proxy) + if self.is_proxy_tor != is_tor: + self.logger.info(f'Proxy is {"" if is_tor else "not "}TOR') + self.is_proxy_tor = is_tor + util.trigger_callback('tor_probed', is_tor) + proxy = self.proxy if proxy and proxy['mode'] == 'socks5': t = threading.Thread(target=tor_probe_task, args=(proxy,), daemon=True) t.start() - util.trigger_callback('proxy_set', self.proxy) - - def _tor_probe_done(self, is_tor: bool): - self.is_proxy_tor = is_tor - util.trigger_callback('tor_probed', is_tor) - @log_exceptions async def set_parameters(self, net_params: NetworkParameters): proxy = net_params.proxy @@ -904,6 +907,9 @@ class Network(Logger, NetworkRetryManager[ServerAddr]): self._has_ever_managed_to_connect_to_server = True self._add_recent_server(server) util.trigger_callback('network_updated') + # When the proxy settings were set, the proxy (if any) might have been unreachable, + # resulting in a false-negative for Tor-detection. Given we just connected to a server, re-test now. + self._detect_if_proxy_is_tor() def check_interface_against_healthy_spread_of_connected_servers(self, iface_to_check: Interface) -> bool: # main interface is exempt. this makes switching servers easier