diff --git a/briar-core/src/org/briarproject/plugins/tcp/LanTcpPlugin.java b/briar-core/src/org/briarproject/plugins/tcp/LanTcpPlugin.java
index a03bd6155def5185110a1ca45bc705b012ec1f50..d67a6d22e2115ac19e6d60323380d6a3a89cd314 100644
--- a/briar-core/src/org/briarproject/plugins/tcp/LanTcpPlugin.java
+++ b/briar-core/src/org/briarproject/plugins/tcp/LanTcpPlugin.java
@@ -50,14 +50,9 @@ class LanTcpPlugin extends TcpPlugin {
 			return Collections.emptyList();
 		}
 		List<SocketAddress> addrs = new LinkedList<SocketAddress>();
-		// Accept interfaces with local IPv4 addresses
 		for(NetworkInterface iface : ifaces) {
 			for(InetAddress a : Collections.list(iface.getInetAddresses())) {
-				boolean ipv4 = a instanceof Inet4Address;
-				boolean loop = a.isLoopbackAddress();
-				boolean link = a.isLinkLocalAddress();
-				boolean site = a.isSiteLocalAddress();
-				if(ipv4 && !loop && (link || site)) {
+				if(isAcceptableAddress(a)) {
 					// If this is the old address, try to use the same port
 					if(old != null && old.getAddress().equals(a))
 						addrs.add(0, new InetSocketAddress(a, old.getPort()));
@@ -67,4 +62,38 @@ class LanTcpPlugin extends TcpPlugin {
 		}
 		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;
+	}
 }
\ No newline at end of file
diff --git a/briar-core/src/org/briarproject/plugins/tcp/TcpPlugin.java b/briar-core/src/org/briarproject/plugins/tcp/TcpPlugin.java
index ce47e0c70640e27989c58bd2e16a4cbdc8462df5..827a5098868b6ab8bed17f6e4cb89f2dce209d79 100644
--- a/briar-core/src/org/briarproject/plugins/tcp/TcpPlugin.java
+++ b/briar-core/src/org/briarproject/plugins/tcp/TcpPlugin.java
@@ -12,7 +12,6 @@ import java.net.SocketAddress;
 import java.net.UnknownHostException;
 import java.util.Collection;
 import java.util.List;
-import java.util.Map;
 import java.util.concurrent.Executor;
 import java.util.logging.Logger;
 import java.util.regex.Pattern;
@@ -46,6 +45,9 @@ abstract class TcpPlugin implements DuplexPlugin {
 	 */
 	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,
 			int maxFrameLength, long maxLatency, long pollingInterval) {
 		this.pluginExecutor = pluginExecutor;
@@ -162,40 +164,40 @@ abstract class TcpPlugin implements DuplexPlugin {
 
 	public void poll(Collection<ContactId> connected) {
 		if(!isRunning()) return;
-		Map<ContactId, TransportProperties> remote =
-				callback.getRemoteProperties();
-		for(final ContactId c : remote.keySet()) {
-			if(connected.contains(c)) continue;
-			pluginExecutor.execute(new Runnable() {
-				public void run() {
-					connectAndCallBack(c);
-				}
-			});
-		}
+		for(ContactId c : callback.getRemoteProperties().keySet())
+			if(!connected.contains(c)) connectAndCallBack(c);
 	}
 
-	private void connectAndCallBack(ContactId c) {
-		DuplexTransportConnection d = createConnection(c);
-		if(d != null) callback.outgoingConnectionCreated(c, d);
+	private void connectAndCallBack(final ContactId c) {
+		pluginExecutor.execute(new Runnable() {
+			public void run() {
+				DuplexTransportConnection d = createConnection(c);
+				if(d != null) callback.outgoingConnectionCreated(c, d);
+			}
+		});
 	}
 
 	public DuplexTransportConnection createConnection(ContactId c) {
 		if(!isRunning()) return null;
-		SocketAddress addr = getRemoteSocketAddress(c);
-		if(addr == null) return null;
+		InetSocketAddress remote = getRemoteSocketAddress(c);
+		if(remote == null) return null;
+		if(!isConnectable(remote)) {
+			if(LOG.isLoggable(INFO)) LOG.info(remote + " is not connectable");
+			return null;
+		}
 		Socket s = new Socket();
 		try {
-			if(LOG.isLoggable(INFO)) LOG.info("Connecting to " + addr);
-			s.connect(addr);
-			if(LOG.isLoggable(INFO)) LOG.info("Connected to " + addr);
+			if(LOG.isLoggable(INFO)) LOG.info("Connecting to " + remote);
+			s.connect(remote);
+			if(LOG.isLoggable(INFO)) LOG.info("Connected to " + remote);
 			return new TcpTransportConnection(this, s);
 		} 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;
 		}
 	}
 
-	private SocketAddress getRemoteSocketAddress(ContactId c) {
+	private InetSocketAddress getRemoteSocketAddress(ContactId c) {
 		TransportProperties p = callback.getRemoteProperties().get(c);
 		if(p == null) return null;
 		return parseSocketAddress(p.get("address"), p.get("port"));
diff --git a/briar-core/src/org/briarproject/plugins/tcp/WanTcpPlugin.java b/briar-core/src/org/briarproject/plugins/tcp/WanTcpPlugin.java
index 56f61ec239b0d88a2e6db33a5a6686994d5149f7..16c168c2e487c2e136a631dd20d58069da4fd7aa 100644
--- a/briar-core/src/org/briarproject/plugins/tcp/WanTcpPlugin.java
+++ b/briar-core/src/org/briarproject/plugins/tcp/WanTcpPlugin.java
@@ -56,14 +56,9 @@ class WanTcpPlugin extends TcpPlugin {
 			return Collections.emptyList();
 		}
 		List<SocketAddress> addrs = new LinkedList<SocketAddress>();
-		// Accept interfaces without global IPv4 addresses
 		for(NetworkInterface iface : ifaces) {
 			for(InetAddress a : Collections.list(iface.getInetAddresses())) {
-				boolean ipv4 = a instanceof Inet4Address;
-				boolean loop = a.isLoopbackAddress();
-				boolean link = a.isLinkLocalAddress();
-				boolean site = a.isSiteLocalAddress();
-				if(ipv4 && !loop && !link && !site) {
+				if(isAcceptableAddress(a)) {
 					// If this is the old address, try to use the same port
 					if(old != null && old.getAddress().equals(a))
 						addrs.add(0, new InetSocketAddress(a, old.getPort()));
@@ -81,10 +76,25 @@ class WanTcpPlugin extends TcpPlugin {
 		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() {
 		return 32768 + (int) (Math.random() * 32768);
 	}
 
+	@Override
+	protected boolean isConnectable(InetSocketAddress remote) {
+		if(remote.getPort() == 0) return false;
+		return isAcceptableAddress(remote.getAddress());
+	}
+
 	@Override
 	protected void setLocalSocketAddress(InetSocketAddress a) {
 		if(mappingResult != null && mappingResult.isUsable()) {
diff --git a/briar-tests/src/org/briarproject/plugins/tcp/LanTcpPluginTest.java b/briar-tests/src/org/briarproject/plugins/tcp/LanTcpPluginTest.java
index 268de984412548a014e810723772e7152750e4cd..03c2236035dfd55482077900787bd56c7c09a174 100644
--- a/briar-tests/src/org/briarproject/plugins/tcp/LanTcpPluginTest.java
+++ b/briar-tests/src/org/briarproject/plugins/tcp/LanTcpPluginTest.java
@@ -28,6 +28,49 @@ public class LanTcpPluginTest extends BriarTestCase {
 
 	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
 	public void testIncomingConnection() throws Exception {
 		Callback callback = new Callback();