Allow IPv6 connections to Bitcoin nodes

Currently bisq desktop does not accept IPv6 addresses in the settings for
custom nodes or via the --btcNodes command line option.  The separation of
address and port is handled incorrectly in core / BtcNodes::fromFullAddress.
This results in IPv6 addresses being ignored.  Where Tor is enabled for
Bitcoin connections, we need to handle the IPv6 address response
from Tor DNS lookup.

Fixes #3990
This commit is contained in:
jmacxx 2020-03-10 22:56:40 -05:00
parent 879c3f2eb2
commit b1a8d944bf
No known key found for this signature in database
GPG Key ID: 155297BABFE94A1B
2 changed files with 34 additions and 12 deletions

View File

@ -113,13 +113,32 @@ public class BtcNodes {
* @return BtcNode instance
*/
public static BtcNode fromFullAddress(String fullAddress) {
String[] parts = fullAddress.split(":");
String[] parts = fullAddress.split("]");
checkArgument(parts.length > 0);
final String host = parts[0];
String host = "";
int port = DEFAULT_PORT;
if (parts.length == 2)
port = Integer.valueOf(parts[1]);
if (parts[0].contains("[") && parts[0].contains(":")) {
// IPv6 address and optional port number
// address part delimited by square brackets e.g. [2a01:123:456:789::2]:8333
host = parts[0].replace("[", "").replace("]", "");
if (parts.length == 2)
port = Integer.parseInt(parts[1].replace(":", ""));
}
else if (parts[0].contains(":") && !parts[0].contains(".")) {
// IPv6 address only; not delimited by square brackets
host = parts[0];
}
else if (parts[0].contains(".")) {
// address and an optional port number
// e.g. 127.0.0.1:8333 or abcdef123xyz.onion:9999
parts = fullAddress.split(":");
checkArgument(parts.length > 0);
host = parts[0];
if (parts.length == 2)
port = Integer.parseInt(parts[1]);
}
checkArgument(host.length()>0, "BtcNode address format not recognised");
return host.contains(".onion") ? new BtcNode(null, host, null, port, null) : new BtcNode(null, null, host, port, null);
}

View File

@ -84,10 +84,10 @@ public class DnsLookupTor {
byte[] hostBytes = host.getBytes(Charsets.UTF_8);
buf = new byte[7 + hostBytes.length];
buf[0] = b('\u0005');
buf[1] = b('\u00f0');
buf[2] = b('\u0000');
buf[3] = b('\u0003');
buf[0] = b('\u0005'); // version SOCKS5
buf[1] = b('\u00f0'); // CMD_RESOLVE
buf[2] = b('\u0000'); // (reserved)
buf[3] = b('\u0003'); // SOCKS5_ATYPE_HOSTNAME
buf[4] = (byte) hostBytes.length;
System.arraycopy(hostBytes, 0, buf, 5, hostBytes.length);
buf[5 + hostBytes.length] = 0;
@ -113,13 +113,16 @@ public class DnsLookupTor {
throw new DnsLookupException(torStatusErrors.get(buf[1]) + "(host=" + host + ")");
}
if (buf[3] != b('\u0001'))
final char SOCKS5_ATYPE_IPV4 = '\u0001';
final char SOCKS5_ATYPE_IPV6 = '\u0004';
final byte atype = buf[3];
if (atype != b(SOCKS5_ATYPE_IPV4) && atype != b(SOCKS5_ATYPE_IPV6))
throw new DnsLookupException(torStatusErrors.get(b('\u0001')) + "(host=" + host + ")");
buf = new byte[4];
final int octets = (atype == SOCKS5_ATYPE_IPV4 ? 4 : 16);
buf = new byte[octets];
bytesRead = proxySocket.getInputStream().read(buf);
if (bytesRead != 4)
if (bytesRead != octets)
throw new DnsLookupException("Invalid Tor Address Response");
return InetAddress.getByAddress(buf);