From 92ed8d9c049c433cf8a50daf8f70c2781a69203a Mon Sep 17 00:00:00 2001 From: Thomas Eizinger Date: Wed, 30 Jun 2021 18:19:43 +1000 Subject: [PATCH] Refuse to dial addresses via Tor that are almost certainly not reachable For now, this just concerns loopback addresses. --- swap/src/network/tor_transport.rs | 32 ++++++++++++++++++++++++------- 1 file changed, 25 insertions(+), 7 deletions(-) diff --git a/swap/src/network/tor_transport.rs b/swap/src/network/tor_transport.rs index 13a71420..be031900 100644 --- a/swap/src/network/tor_transport.rs +++ b/swap/src/network/tor_transport.rs @@ -35,17 +35,19 @@ impl Transport for TorDialOnlyTransport { } fn dial(self, addr: Multiaddr) -> Result> { - let tor_compatible_address = TorCompatibleAddress::from_multiaddr(Cow::Borrowed(&addr))?; + let address = TorCompatibleAddress::from_multiaddr(Cow::Borrowed(&addr))?; + + if address.is_certainly_not_reachable_via_tor_daemon() { + return Err(TransportError::MultiaddrNotSupported(addr)); + } let dial_future = async move { tracing::trace!("Connecting through Tor proxy to address: {}", addr); - let stream = Socks5Stream::connect( - (Ipv4Addr::LOCALHOST, self.socks_port), - tor_compatible_address.to_string(), - ) - .await - .map_err(|e| io::Error::new(io::ErrorKind::ConnectionRefused, e))?; + let stream = + Socks5Stream::connect((Ipv4Addr::LOCALHOST, self.socks_port), address.to_string()) + .await + .map_err(|e| io::Error::new(io::ErrorKind::ConnectionRefused, e))?; tracing::trace!("Connection through Tor established"); @@ -99,6 +101,22 @@ impl TorCompatibleAddress { _ => Err(TransportError::MultiaddrNotSupported(multi.into_owned())), } } + + /// Checks if the address is reachable via the Tor daemon. + /// + /// The Tor daemon can dial onion addresses, resolve DNS names and dial + /// IP4/IP6 addresses reachable via the public Internet. + /// We can't guarantee that an address is reachable via the Internet but we + /// can say that some addresses are almost certainly not reachable, for + /// example, loopback addresses. + fn is_certainly_not_reachable_via_tor_daemon(&self) -> bool { + match self { + TorCompatibleAddress::Onion3 { .. } => false, + TorCompatibleAddress::Dns { address, .. } => address == "localhost", + TorCompatibleAddress::Ip4 { address, .. } => address.is_loopback(), + TorCompatibleAddress::Ip6 { address, .. } => address.is_loopback(), + } + } } impl fmt::Display for TorCompatibleAddress {