mirror of
https://code.briarproject.org/briar/briar.git
synced 2026-02-17 13:19:52 +01:00
Don't try to connect to unreachable IP addresses.
This commit is contained in:
@@ -50,14 +50,9 @@ class LanTcpPlugin extends TcpPlugin {
|
|||||||
return Collections.emptyList();
|
return Collections.emptyList();
|
||||||
}
|
}
|
||||||
List<SocketAddress> addrs = new LinkedList<SocketAddress>();
|
List<SocketAddress> addrs = new LinkedList<SocketAddress>();
|
||||||
// Accept interfaces with local IPv4 addresses
|
|
||||||
for(NetworkInterface iface : ifaces) {
|
for(NetworkInterface iface : ifaces) {
|
||||||
for(InetAddress a : Collections.list(iface.getInetAddresses())) {
|
for(InetAddress a : Collections.list(iface.getInetAddresses())) {
|
||||||
boolean ipv4 = a instanceof Inet4Address;
|
if(isAcceptableAddress(a)) {
|
||||||
boolean loop = a.isLoopbackAddress();
|
|
||||||
boolean link = a.isLinkLocalAddress();
|
|
||||||
boolean site = a.isSiteLocalAddress();
|
|
||||||
if(ipv4 && !loop && (link || site)) {
|
|
||||||
// If this is the old address, try to use the same port
|
// If this is the old address, try to use the same port
|
||||||
if(old != null && old.getAddress().equals(a))
|
if(old != null && old.getAddress().equals(a))
|
||||||
addrs.add(0, new InetSocketAddress(a, old.getPort()));
|
addrs.add(0, new InetSocketAddress(a, old.getPort()));
|
||||||
@@ -67,4 +62,38 @@ class LanTcpPlugin extends TcpPlugin {
|
|||||||
}
|
}
|
||||||
return addrs;
|
return addrs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean isAcceptableAddress(InetAddress a) {
|
||||||
|
// Accept link-local and site-local IPv4 addresses
|
||||||
|
boolean ipv4 = a instanceof Inet4Address;
|
||||||
|
boolean loop = a.isLoopbackAddress();
|
||||||
|
boolean link = a.isLinkLocalAddress();
|
||||||
|
boolean site = a.isSiteLocalAddress();
|
||||||
|
return ipv4 && !loop && (link || site);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean isConnectable(InetSocketAddress remote) {
|
||||||
|
if(remote.getPort() == 0) return false;
|
||||||
|
if(!isAcceptableAddress(remote.getAddress())) return false;
|
||||||
|
// Try to determine whether the address is on the same LAN as us
|
||||||
|
if(socket == null) return true;
|
||||||
|
byte[] localIp = socket.getInetAddress().getAddress();
|
||||||
|
byte[] remoteIp = remote.getAddress().getAddress();
|
||||||
|
return addressesAreOnSameLan(localIp, remoteIp);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Package access for testing
|
||||||
|
boolean addressesAreOnSameLan(byte[] localIp, byte[] remoteIp) {
|
||||||
|
// 10.0.0.0/8
|
||||||
|
if(localIp[0] == 10) return remoteIp[0] == 10;
|
||||||
|
// 172.16.0.0/12
|
||||||
|
if(localIp[0] == (byte) 172 && (localIp[1] & 0xF0) == 16)
|
||||||
|
return remoteIp[0] == (byte) 172 && (remoteIp[1] & 0xF0) == 16;
|
||||||
|
// 192.168.0.0/16
|
||||||
|
if(localIp[0] == (byte) 192 && localIp[1] == (byte) 168)
|
||||||
|
return remoteIp[0] == (byte) 192 && remoteIp[1] == (byte) 168;
|
||||||
|
// Unrecognised prefix - may be compatible
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -12,7 +12,6 @@ import java.net.SocketAddress;
|
|||||||
import java.net.UnknownHostException;
|
import java.net.UnknownHostException;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
|
||||||
import java.util.concurrent.Executor;
|
import java.util.concurrent.Executor;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
@@ -46,6 +45,9 @@ abstract class TcpPlugin implements DuplexPlugin {
|
|||||||
*/
|
*/
|
||||||
protected abstract List<SocketAddress> getLocalSocketAddresses();
|
protected abstract List<SocketAddress> getLocalSocketAddresses();
|
||||||
|
|
||||||
|
/** Returns true if connections to the given address can be attempted. */
|
||||||
|
protected abstract boolean isConnectable(InetSocketAddress remote);
|
||||||
|
|
||||||
protected TcpPlugin(Executor pluginExecutor, DuplexPluginCallback callback,
|
protected TcpPlugin(Executor pluginExecutor, DuplexPluginCallback callback,
|
||||||
int maxFrameLength, long maxLatency, long pollingInterval) {
|
int maxFrameLength, long maxLatency, long pollingInterval) {
|
||||||
this.pluginExecutor = pluginExecutor;
|
this.pluginExecutor = pluginExecutor;
|
||||||
@@ -162,40 +164,40 @@ abstract class TcpPlugin implements DuplexPlugin {
|
|||||||
|
|
||||||
public void poll(Collection<ContactId> connected) {
|
public void poll(Collection<ContactId> connected) {
|
||||||
if(!isRunning()) return;
|
if(!isRunning()) return;
|
||||||
Map<ContactId, TransportProperties> remote =
|
for(ContactId c : callback.getRemoteProperties().keySet())
|
||||||
callback.getRemoteProperties();
|
if(!connected.contains(c)) connectAndCallBack(c);
|
||||||
for(final ContactId c : remote.keySet()) {
|
|
||||||
if(connected.contains(c)) continue;
|
|
||||||
pluginExecutor.execute(new Runnable() {
|
|
||||||
public void run() {
|
|
||||||
connectAndCallBack(c);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void connectAndCallBack(ContactId c) {
|
private void connectAndCallBack(final ContactId c) {
|
||||||
DuplexTransportConnection d = createConnection(c);
|
pluginExecutor.execute(new Runnable() {
|
||||||
if(d != null) callback.outgoingConnectionCreated(c, d);
|
public void run() {
|
||||||
|
DuplexTransportConnection d = createConnection(c);
|
||||||
|
if(d != null) callback.outgoingConnectionCreated(c, d);
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public DuplexTransportConnection createConnection(ContactId c) {
|
public DuplexTransportConnection createConnection(ContactId c) {
|
||||||
if(!isRunning()) return null;
|
if(!isRunning()) return null;
|
||||||
SocketAddress addr = getRemoteSocketAddress(c);
|
InetSocketAddress remote = getRemoteSocketAddress(c);
|
||||||
if(addr == null) return null;
|
if(remote == null) return null;
|
||||||
|
if(!isConnectable(remote)) {
|
||||||
|
if(LOG.isLoggable(INFO)) LOG.info(remote + " is not connectable");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
Socket s = new Socket();
|
Socket s = new Socket();
|
||||||
try {
|
try {
|
||||||
if(LOG.isLoggable(INFO)) LOG.info("Connecting to " + addr);
|
if(LOG.isLoggable(INFO)) LOG.info("Connecting to " + remote);
|
||||||
s.connect(addr);
|
s.connect(remote);
|
||||||
if(LOG.isLoggable(INFO)) LOG.info("Connected to " + addr);
|
if(LOG.isLoggable(INFO)) LOG.info("Connected to " + remote);
|
||||||
return new TcpTransportConnection(this, s);
|
return new TcpTransportConnection(this, s);
|
||||||
} catch(IOException e) {
|
} catch(IOException e) {
|
||||||
if(LOG.isLoggable(INFO)) LOG.info("Could not connect to " + addr);
|
if(LOG.isLoggable(INFO)) LOG.info("Could not connect to " + remote);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private SocketAddress getRemoteSocketAddress(ContactId c) {
|
private InetSocketAddress getRemoteSocketAddress(ContactId c) {
|
||||||
TransportProperties p = callback.getRemoteProperties().get(c);
|
TransportProperties p = callback.getRemoteProperties().get(c);
|
||||||
if(p == null) return null;
|
if(p == null) return null;
|
||||||
return parseSocketAddress(p.get("address"), p.get("port"));
|
return parseSocketAddress(p.get("address"), p.get("port"));
|
||||||
|
|||||||
@@ -56,14 +56,9 @@ class WanTcpPlugin extends TcpPlugin {
|
|||||||
return Collections.emptyList();
|
return Collections.emptyList();
|
||||||
}
|
}
|
||||||
List<SocketAddress> addrs = new LinkedList<SocketAddress>();
|
List<SocketAddress> addrs = new LinkedList<SocketAddress>();
|
||||||
// Accept interfaces without global IPv4 addresses
|
|
||||||
for(NetworkInterface iface : ifaces) {
|
for(NetworkInterface iface : ifaces) {
|
||||||
for(InetAddress a : Collections.list(iface.getInetAddresses())) {
|
for(InetAddress a : Collections.list(iface.getInetAddresses())) {
|
||||||
boolean ipv4 = a instanceof Inet4Address;
|
if(isAcceptableAddress(a)) {
|
||||||
boolean loop = a.isLoopbackAddress();
|
|
||||||
boolean link = a.isLinkLocalAddress();
|
|
||||||
boolean site = a.isSiteLocalAddress();
|
|
||||||
if(ipv4 && !loop && !link && !site) {
|
|
||||||
// If this is the old address, try to use the same port
|
// If this is the old address, try to use the same port
|
||||||
if(old != null && old.getAddress().equals(a))
|
if(old != null && old.getAddress().equals(a))
|
||||||
addrs.add(0, new InetSocketAddress(a, old.getPort()));
|
addrs.add(0, new InetSocketAddress(a, old.getPort()));
|
||||||
@@ -81,10 +76,25 @@ class WanTcpPlugin extends TcpPlugin {
|
|||||||
return addrs;
|
return addrs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean isAcceptableAddress(InetAddress a) {
|
||||||
|
// Accept global IPv4 addresses
|
||||||
|
boolean ipv4 = a instanceof Inet4Address;
|
||||||
|
boolean loop = a.isLoopbackAddress();
|
||||||
|
boolean link = a.isLinkLocalAddress();
|
||||||
|
boolean site = a.isSiteLocalAddress();
|
||||||
|
return ipv4 && !loop && !link && !site;
|
||||||
|
}
|
||||||
|
|
||||||
private int chooseEphemeralPort() {
|
private int chooseEphemeralPort() {
|
||||||
return 32768 + (int) (Math.random() * 32768);
|
return 32768 + (int) (Math.random() * 32768);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean isConnectable(InetSocketAddress remote) {
|
||||||
|
if(remote.getPort() == 0) return false;
|
||||||
|
return isAcceptableAddress(remote.getAddress());
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void setLocalSocketAddress(InetSocketAddress a) {
|
protected void setLocalSocketAddress(InetSocketAddress a) {
|
||||||
if(mappingResult != null && mappingResult.isUsable()) {
|
if(mappingResult != null && mappingResult.isUsable()) {
|
||||||
|
|||||||
@@ -28,6 +28,49 @@ public class LanTcpPluginTest extends BriarTestCase {
|
|||||||
|
|
||||||
private final ContactId contactId = new ContactId(234);
|
private final ContactId contactId = new ContactId(234);
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testAddressesAreOnSameLan() {
|
||||||
|
LanTcpPlugin plugin = new LanTcpPlugin(null, null, 0, 0, 0);
|
||||||
|
// Local and remote in 10.0.0.0/8 should return true
|
||||||
|
assertTrue(plugin.addressesAreOnSameLan(makeAddress(10, 0, 0, 0),
|
||||||
|
makeAddress(10, 255, 255, 255)));
|
||||||
|
// Local and remote in 172.16.0.0/12 should return true
|
||||||
|
assertTrue(plugin.addressesAreOnSameLan(makeAddress(172, 16, 0, 0),
|
||||||
|
makeAddress(172, 31, 255, 255)));
|
||||||
|
// Local and remote in 192.168.0.0/16 should return true
|
||||||
|
assertTrue(plugin.addressesAreOnSameLan(makeAddress(192, 168, 0, 0),
|
||||||
|
makeAddress(192, 168, 255, 255)));
|
||||||
|
// Local and remote in different recognised prefixes should return false
|
||||||
|
assertFalse(plugin.addressesAreOnSameLan(makeAddress(10, 0, 0, 0),
|
||||||
|
makeAddress(172, 31, 255, 255)));
|
||||||
|
assertFalse(plugin.addressesAreOnSameLan(makeAddress(10, 0, 0, 0),
|
||||||
|
makeAddress(192, 168, 255, 255)));
|
||||||
|
assertFalse(plugin.addressesAreOnSameLan(makeAddress(172, 16, 0, 0),
|
||||||
|
makeAddress(10, 255, 255, 255)));
|
||||||
|
assertFalse(plugin.addressesAreOnSameLan(makeAddress(172, 16, 0, 0),
|
||||||
|
makeAddress(192, 168, 255, 255)));
|
||||||
|
assertFalse(plugin.addressesAreOnSameLan(makeAddress(192, 168, 0, 0),
|
||||||
|
makeAddress(10, 255, 255, 255)));
|
||||||
|
assertFalse(plugin.addressesAreOnSameLan(makeAddress(192, 168, 0, 0),
|
||||||
|
makeAddress(172, 31, 255, 255)));
|
||||||
|
// Remote prefix unrecognised should return false
|
||||||
|
assertFalse(plugin.addressesAreOnSameLan(makeAddress(10, 0, 0, 0),
|
||||||
|
makeAddress(1, 2, 3, 4)));
|
||||||
|
assertFalse(plugin.addressesAreOnSameLan(makeAddress(172, 16, 0, 0),
|
||||||
|
makeAddress(1, 2, 3, 4)));
|
||||||
|
assertFalse(plugin.addressesAreOnSameLan(makeAddress(192, 168, 0, 0),
|
||||||
|
makeAddress(1, 2, 3, 4)));
|
||||||
|
// Both prefixes unrecognised should return true (could be link-local)
|
||||||
|
assertTrue(plugin.addressesAreOnSameLan(makeAddress(1, 2, 3, 4),
|
||||||
|
makeAddress(5, 6, 7, 8)));
|
||||||
|
}
|
||||||
|
|
||||||
|
private byte[] makeAddress(int... parts) {
|
||||||
|
byte[] b = new byte[parts.length];
|
||||||
|
for(int i = 0; i < parts.length; i++) b[i] = (byte) parts[i];
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testIncomingConnection() throws Exception {
|
public void testIncomingConnection() throws Exception {
|
||||||
Callback callback = new Callback();
|
Callback callback = new Callback();
|
||||||
|
|||||||
Reference in New Issue
Block a user