mirror of
https://github.com/sparrowwallet/sparrow.git
synced 2026-09-14 00:45:08 +00:00
close remaining local dns resolution gaps when classifying hostnames and connecting via tor
This commit is contained in:
@@ -16,12 +16,14 @@ package com.sparrowwallet.sparrow.net;
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import com.google.common.net.InetAddresses;
|
||||
import com.sparrowwallet.sparrow.AppServices;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.net.InetAddress;
|
||||
import java.net.UnknownHostException;
|
||||
import java.util.Locale;
|
||||
|
||||
/**
|
||||
* Matches a request based on IP Address or subnet mask matching against the remote
|
||||
@@ -109,7 +111,18 @@ public final class IpAddressMatcher {
|
||||
|
||||
public static boolean isLocalNetworkAddress(String address) {
|
||||
try {
|
||||
return "localhost".equals(address) || "127.0.0.1".equals(address) || LOCAL_RANGE_1.matches(address) || LOCAL_RANGE_2.matches(address) || LOCAL_RANGE_3.matches(address) || LOCAL_RANGE_4.matches(address);
|
||||
if("localhost".equals(address) || "127.0.0.1".equals(address)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
//Matching a hostname against the local ranges requires resolving it, which leaks the name to (and trusts the answer of) the local DNS resolver even when a proxy is configured
|
||||
//Only IP literals and mDNS names (which RFC 6762 requires to be resolved via link-local multicast, not upstream DNS) are considered potentially local when using a proxy
|
||||
if(AppServices.isUsingProxy() && !InetAddresses.isInetAddress(address) && !address.toLowerCase(Locale.ROOT).endsWith(".local")) {
|
||||
log.info("Avoiding local DNS resolution of " + address + ", assuming it is a non-local address to be resolved by the configured proxy");
|
||||
return false;
|
||||
}
|
||||
|
||||
return LOCAL_RANGE_1.matches(address) || LOCAL_RANGE_2.matches(address) || LOCAL_RANGE_3.matches(address) || LOCAL_RANGE_4.matches(address);
|
||||
} catch(IllegalArgumentException e) {
|
||||
if(AppServices.isUsingProxy()) {
|
||||
log.info(e.getMessage() + ", assuming it is a non-local address to be resolved by the configured proxy");
|
||||
|
||||
@@ -23,6 +23,6 @@ public class TorTcpTransport extends TcpTransport {
|
||||
}
|
||||
|
||||
socket = new Socket(Tor.getDefault().getProxy());
|
||||
socket.connect(new InetSocketAddress(server.getHost(), server.getPortOrDefault(getDefaultPort())));
|
||||
socket.connect(InetSocketAddress.createUnresolved(server.getHost(), server.getPortOrDefault(getDefaultPort())));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,65 @@
|
||||
package com.sparrowwallet.sparrow.net;
|
||||
|
||||
import com.sparrowwallet.drongo.Network;
|
||||
import com.sparrowwallet.sparrow.SparrowWallet;
|
||||
import com.sparrowwallet.sparrow.io.Config;
|
||||
import org.junit.jupiter.api.AfterAll;
|
||||
import org.junit.jupiter.api.BeforeAll;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.io.TempDir;
|
||||
|
||||
import java.nio.file.Path;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
public class IpAddressMatcherTest {
|
||||
@TempDir
|
||||
private static Path tempHome;
|
||||
|
||||
@BeforeAll
|
||||
public static void setUp() {
|
||||
//Isolate Config.get() from the developer's config so the proxy setting can be changed safely
|
||||
System.setProperty(SparrowWallet.APP_HOME_PROPERTY, tempHome.toString());
|
||||
Network.set(Network.MAINNET);
|
||||
}
|
||||
|
||||
@AfterAll
|
||||
public static void tearDown() {
|
||||
Config.get().setUseProxy(false);
|
||||
System.clearProperty(SparrowWallet.APP_HOME_PROPERTY);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void classifiesAddressesWithoutProxy() {
|
||||
Config.get().setUseProxy(false);
|
||||
assertTrue(IpAddressMatcher.isLocalNetworkAddress("localhost"));
|
||||
assertTrue(IpAddressMatcher.isLocalNetworkAddress("127.0.0.1"));
|
||||
assertTrue(IpAddressMatcher.isLocalNetworkAddress("192.168.1.5"));
|
||||
assertTrue(IpAddressMatcher.isLocalNetworkAddress("10.0.0.10"));
|
||||
assertTrue(IpAddressMatcher.isLocalNetworkAddress("172.16.0.1"));
|
||||
assertTrue(IpAddressMatcher.isLocalNetworkAddress("100.64.0.1"));
|
||||
assertFalse(IpAddressMatcher.isLocalNetworkAddress("8.8.8.8"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void classifiesIpLiteralsWithProxy() {
|
||||
Config.get().setUseProxy(true);
|
||||
//IP literals classify without DNS resolution, so local network servers must still connect directly when a proxy is configured
|
||||
assertTrue(IpAddressMatcher.isLocalNetworkAddress("localhost"));
|
||||
assertTrue(IpAddressMatcher.isLocalNetworkAddress("127.0.0.1"));
|
||||
assertTrue(IpAddressMatcher.isLocalNetworkAddress("192.168.1.5"));
|
||||
assertTrue(IpAddressMatcher.isLocalNetworkAddress("10.0.0.10"));
|
||||
assertTrue(IpAddressMatcher.isLocalNetworkAddress("172.16.0.1"));
|
||||
assertTrue(IpAddressMatcher.isLocalNetworkAddress("100.64.0.1"));
|
||||
assertFalse(IpAddressMatcher.isLocalNetworkAddress("8.8.8.8"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void assumesHostnamesAreRemoteWithProxy() {
|
||||
Config.get().setUseProxy(true);
|
||||
//Hostnames are not resolved by the local DNS resolver when a proxy is configured, and are assumed to be remote addresses resolved by the proxy
|
||||
assertFalse(IpAddressMatcher.isLocalNetworkAddress("electrumx.example.com"));
|
||||
assertFalse(IpAddressMatcher.isLocalNetworkAddress("notarealhost.invalid"));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user