diff --git a/briar-android/src/org/briarproject/plugins/droidtooth/DroidtoothPlugin.java b/briar-android/src/org/briarproject/plugins/droidtooth/DroidtoothPlugin.java
index 33f35f49d6d7a48b1f9dacf0973c9ea35ad012f0..b6f82ebf5ae6a75a2c36487bbae583cff65905a0 100644
--- a/briar-android/src/org/briarproject/plugins/droidtooth/DroidtoothPlugin.java
+++ b/briar-android/src/org/briarproject/plugins/droidtooth/DroidtoothPlugin.java
@@ -57,6 +57,7 @@ import static android.bluetooth.BluetoothDevice.EXTRA_DEVICE;
 import static java.util.concurrent.TimeUnit.MILLISECONDS;
 import static java.util.logging.Level.INFO;
 import static java.util.logging.Level.WARNING;
+import static org.briarproject.util.PrivacyUtils.scrubMacAddress;
 
 class DroidtoothPlugin implements DuplexPlugin {
 
@@ -172,7 +173,7 @@ class DroidtoothPlugin implements DuplexPlugin {
 				String address = AndroidUtils.getBluetoothAddress(appContext,
 						adapter);
 				if (LOG.isLoggable(INFO))
-					LOG.info("Local address " + address);
+					LOG.info("Local address " + scrubMacAddress(address));
 				if (!StringUtils.isNullOrEmpty(address)) {
 					// Advertise the Bluetooth address to contacts
 					TransportProperties p = new TransportProperties();
@@ -237,7 +238,7 @@ class DroidtoothPlugin implements DuplexPlugin {
 			}
 			if (LOG.isLoggable(INFO)) {
 				String address = s.getRemoteDevice().getAddress();
-				LOG.info("Connection from " + address);
+				LOG.info("Connection from " + scrubMacAddress(address));
 			}
 			backoff.reset();
 			callback.incomingConnectionCreated(wrapSocket(s));
@@ -307,6 +308,7 @@ class DroidtoothPlugin implements DuplexPlugin {
 		// Validate the address
 		if (!BluetoothAdapter.checkBluetoothAddress(address)) {
 			if (LOG.isLoggable(WARNING))
+				// not scrubbing here to be able to figure out the problem
 				LOG.warning("Invalid address " + address);
 			return null;
 		}
@@ -323,13 +325,15 @@ class DroidtoothPlugin implements DuplexPlugin {
 		BluetoothSocket s = null;
 		try {
 			s = d.createInsecureRfcommSocketToServiceRecord(u);
-			if (LOG.isLoggable(INFO)) LOG.info("Connecting to " + address);
+			if (LOG.isLoggable(INFO))
+				LOG.info("Connecting to " + scrubMacAddress(address));
 			s.connect();
-			if (LOG.isLoggable(INFO)) LOG.info("Connected to " + address);
+			if (LOG.isLoggable(INFO))
+				LOG.info("Connected to " + scrubMacAddress(address));
 			return s;
 		} catch (IOException e) {
 			if (LOG.isLoggable(INFO))
-				LOG.info("Failed to connect to " + address);
+				LOG.info("Failed to connect to " + scrubMacAddress(address));
 			tryToClose(s);
 			return null;
 		}
@@ -567,7 +571,8 @@ class DroidtoothPlugin implements DuplexPlugin {
 			} else if (action.equals(FOUND)) {
 				BluetoothDevice d = intent.getParcelableExtra(EXTRA_DEVICE);
 				if (LOG.isLoggable(INFO))
-					LOG.info("Discovered device: " + d.getAddress());
+					LOG.info("Discovered device: " +
+							scrubMacAddress(d.getAddress()));
 				addresses.add(d.getAddress());
 			}
 		}
diff --git a/briar-android/src/org/briarproject/plugins/tor/TorPlugin.java b/briar-android/src/org/briarproject/plugins/tor/TorPlugin.java
index c9586af6d82e0f72e2edded3e56a8a449fea4ba3..94346424f0e306d8e733e8f9f53e861b9d1a6bd8 100644
--- a/briar-android/src/org/briarproject/plugins/tor/TorPlugin.java
+++ b/briar-android/src/org/briarproject/plugins/tor/TorPlugin.java
@@ -72,6 +72,7 @@ import static java.util.logging.Level.INFO;
 import static java.util.logging.Level.WARNING;
 import static net.freehaven.tor.control.TorControlCommands.HS_ADDRESS;
 import static net.freehaven.tor.control.TorControlCommands.HS_PRIVKEY;
+import static org.briarproject.util.PrivacyUtils.scrubOnion;
 
 class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
 
@@ -405,7 +406,8 @@ class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
 		}
 		// Publish the hidden service's onion hostname in transport properties
 		String hostname = response.get(HS_ADDRESS);
-		if (LOG.isLoggable(INFO)) LOG.info("Hidden service " + hostname);
+		if (LOG.isLoggable(INFO))
+			LOG.info("Hidden service " + scrubOnion(hostname));
 		TransportProperties p = new TransportProperties();
 		p.put(PROP_ONION, hostname);
 		callback.mergeLocalProperties(p);
@@ -510,21 +512,25 @@ class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
 		String onion = p.get(PROP_ONION);
 		if (StringUtils.isNullOrEmpty(onion)) return null;
 		if (!ONION.matcher(onion).matches()) {
+			// not scrubbing this address, so we are able to find the problem
 			if (LOG.isLoggable(INFO)) LOG.info("Invalid hostname: " + onion);
 			return null;
 		}
 		try {
-			if (LOG.isLoggable(INFO)) LOG.info("Connecting to " + onion);
+			if (LOG.isLoggable(INFO))
+				LOG.info("Connecting to " + scrubOnion(onion));
 			controlConnection.forgetHiddenService(onion);
 			Socks5Proxy proxy = new Socks5Proxy("127.0.0.1", SOCKS_PORT);
 			proxy.resolveAddrLocally(false);
 			Socket s = new SocksSocket(proxy, onion + ".onion", 80);
 			s.setSoTimeout(socketTimeout);
-			if (LOG.isLoggable(INFO)) LOG.info("Connected to " + onion);
+			if (LOG.isLoggable(INFO))
+				LOG.info("Connected to " + scrubOnion(onion));
 			return new TorTransportConnection(this, s);
 		} catch (IOException e) {
 			if (LOG.isLoggable(INFO))
-				LOG.info("Could not connect to " + onion + ": " + e.toString());
+				LOG.info("Could not connect to " + scrubOnion(onion) + ": " +
+						e.toString());
 			return null;
 		}
 	}
diff --git a/briar-core/src/org/briarproject/plugins/tcp/LanTcpPlugin.java b/briar-core/src/org/briarproject/plugins/tcp/LanTcpPlugin.java
index 34de50400f325671e808ae066af2cf7bab94278c..87ba78fab88d5a8c40b11303b395ed83860bd763 100644
--- a/briar-core/src/org/briarproject/plugins/tcp/LanTcpPlugin.java
+++ b/briar-core/src/org/briarproject/plugins/tcp/LanTcpPlugin.java
@@ -29,6 +29,7 @@ import java.util.logging.Logger;
 
 import static java.util.logging.Level.INFO;
 import static java.util.logging.Level.WARNING;
+import static org.briarproject.util.PrivacyUtils.scrubSocketAddress;
 
 class LanTcpPlugin extends TcpPlugin {
 
@@ -177,7 +178,7 @@ class LanTcpPlugin extends TcpPlugin {
 				break;
 			} catch (IOException e) {
 				if (LOG.isLoggable(INFO))
-					LOG.info("Failed to bind " + addr);
+					LOG.info("Failed to bind " + scrubSocketAddress(addr));
 				tryToClose(ss);
 			}
 		}
@@ -205,20 +206,24 @@ class LanTcpPlugin extends TcpPlugin {
 		if (!isConnectable(remote)) {
 			if (LOG.isLoggable(INFO)) {
 				SocketAddress local = socket.getLocalSocketAddress();
-				LOG.info(remote + " is not connectable from " + local);
+				LOG.info(scrubSocketAddress(remote) +
+						" is not connectable from " +
+						scrubSocketAddress(local));
 			}
 			return null;
 		}
 		Socket s = new Socket();
 		try {
-			if (LOG.isLoggable(INFO)) LOG.info("Connecting to " + remote);
+			if (LOG.isLoggable(INFO))
+				LOG.info("Connecting to " + scrubSocketAddress(remote));
 			s.connect(remote);
 			s.setSoTimeout(socketTimeout);
-			if (LOG.isLoggable(INFO)) LOG.info("Connected to " + remote);
+			if (LOG.isLoggable(INFO))
+				LOG.info("Connected to " + scrubSocketAddress(remote));
 			return new TcpTransportConnection(this, s);
 		} catch (IOException e) {
 			if (LOG.isLoggable(INFO))
-				LOG.info("Could not connect to " + remote);
+				LOG.info("Could not connect to " + scrubSocketAddress(remote));
 			return null;
 		}
 	}
diff --git a/briar-core/src/org/briarproject/plugins/tcp/PortMapperImpl.java b/briar-core/src/org/briarproject/plugins/tcp/PortMapperImpl.java
index a1585b6bec60d9dbbbc91a81d5c33cbc5e5b68f8..5e135419bffc799a24049f6cd0102222430fb0e0 100644
--- a/briar-core/src/org/briarproject/plugins/tcp/PortMapperImpl.java
+++ b/briar-core/src/org/briarproject/plugins/tcp/PortMapperImpl.java
@@ -1,7 +1,9 @@
 package org.briarproject.plugins.tcp;
 
-import static java.util.logging.Level.INFO;
-import static java.util.logging.Level.WARNING;
+import org.bitlet.weupnp.GatewayDevice;
+import org.bitlet.weupnp.GatewayDiscover;
+import org.briarproject.api.lifecycle.ShutdownManager;
+import org.xml.sax.SAXException;
 
 import java.io.IOException;
 import java.net.InetAddress;
@@ -10,10 +12,9 @@ import java.util.logging.Logger;
 
 import javax.xml.parsers.ParserConfigurationException;
 
-import org.bitlet.weupnp.GatewayDevice;
-import org.bitlet.weupnp.GatewayDiscover;
-import org.briarproject.api.lifecycle.ShutdownManager;
-import org.xml.sax.SAXException;
+import static java.util.logging.Level.INFO;
+import static java.util.logging.Level.WARNING;
+import static org.briarproject.util.PrivacyUtils.scrubInetAddress;
 
 class PortMapperImpl implements PortMapper {
 
@@ -35,7 +36,7 @@ class PortMapperImpl implements PortMapper {
 		InetAddress internal = gateway.getLocalAddress();
 		if (internal == null) return null;
 		if (LOG.isLoggable(INFO))
-			LOG.info("Internal address " + getHostAddress(internal));
+			LOG.info("Internal address " + scrubInetAddress(internal));
 		boolean succeeded = false;
 		InetAddress external = null;
 		try {
@@ -50,7 +51,8 @@ class PortMapperImpl implements PortMapper {
 			}
 			String externalString = gateway.getExternalIPAddress();
 			if (LOG.isLoggable(INFO))
-				LOG.info("External address " + externalString);
+				LOG.info(
+						"External address " + scrubInetAddress(externalString));
 			if (externalString != null)
 				external = InetAddress.getByName(externalString);
 		} catch (IOException e) {
diff --git a/briar-core/src/org/briarproject/plugins/tcp/TcpPlugin.java b/briar-core/src/org/briarproject/plugins/tcp/TcpPlugin.java
index fab2a1cbb57a9f0afb91cd0098a980c65df344f5..9ba84875bd40da38467b0899af4d566d6c26df2b 100644
--- a/briar-core/src/org/briarproject/plugins/tcp/TcpPlugin.java
+++ b/briar-core/src/org/briarproject/plugins/tcp/TcpPlugin.java
@@ -30,6 +30,7 @@ import java.util.regex.Pattern;
 
 import static java.util.logging.Level.INFO;
 import static java.util.logging.Level.WARNING;
+import static org.briarproject.util.PrivacyUtils.scrubSocketAddress;
 
 abstract class TcpPlugin implements DuplexPlugin {
 
@@ -107,14 +108,15 @@ abstract class TcpPlugin implements DuplexPlugin {
 			public void run() {
 				if (!running) return;
 				ServerSocket ss = null;
-				for (SocketAddress addr : getLocalSocketAddresses()) {
+				for (InetSocketAddress addr : getLocalSocketAddresses()) {
 					try {
 						ss = new ServerSocket();
 						ss.bind(addr);
 						break;
 					} catch (IOException e) {
 						if (LOG.isLoggable(INFO))
-							LOG.info("Failed to bind " + addr);
+							LOG.info("Failed to bind " +
+									scrubSocketAddress(addr));
 						tryToClose(ss);
 					}
 				}
@@ -128,9 +130,11 @@ abstract class TcpPlugin implements DuplexPlugin {
 				}
 				socket = ss;
 				backoff.reset();
-				SocketAddress local = ss.getLocalSocketAddress();
-				setLocalSocketAddress((InetSocketAddress) local);
-				if (LOG.isLoggable(INFO)) LOG.info("Listening on " + local);
+				InetSocketAddress local =
+						(InetSocketAddress) ss.getLocalSocketAddress();
+				setLocalSocketAddress(local);
+				if (LOG.isLoggable(INFO))
+					LOG.info("Listening on " + scrubSocketAddress(local));
 				callback.transportEnabled();
 				acceptContactConnections();
 			}
@@ -166,7 +170,8 @@ abstract class TcpPlugin implements DuplexPlugin {
 				return;
 			}
 			if (LOG.isLoggable(INFO))
-				LOG.info("Connection from " + s.getRemoteSocketAddress());
+				LOG.info("Connection from " +
+						scrubSocketAddress(s.getRemoteSocketAddress()));
 			backoff.reset();
 			TcpTransportConnection conn = new TcpTransportConnection(this, s);
 			callback.incomingConnectionCreated(conn);
@@ -223,20 +228,25 @@ abstract class TcpPlugin implements DuplexPlugin {
 			if (!isConnectable(remote)) {
 				if (LOG.isLoggable(INFO)) {
 					SocketAddress local = socket.getLocalSocketAddress();
-					LOG.info(remote + " is not connectable from " + local);
+					LOG.info(scrubSocketAddress(remote) +
+							" is not connectable from " +
+							scrubSocketAddress(local));
 				}
 				continue;
 			}
 			Socket s = new Socket();
 			try {
-				if (LOG.isLoggable(INFO)) LOG.info("Connecting to " + remote);
+				if (LOG.isLoggable(INFO))
+					LOG.info("Connecting to " + scrubSocketAddress(remote));
 				s.connect(remote);
 				s.setSoTimeout(socketTimeout);
-				if (LOG.isLoggable(INFO)) LOG.info("Connected to " + remote);
+				if (LOG.isLoggable(INFO))
+					LOG.info("Connected to " + scrubSocketAddress(remote));
 				return new TcpTransportConnection(this, s);
 			} catch (IOException e) {
 				if (LOG.isLoggable(INFO))
-					LOG.info("Could not connect to " + remote);
+					LOG.info("Could not connect to " +
+							scrubSocketAddress(remote));
 			}
 		}
 		return null;
@@ -255,6 +265,7 @@ abstract class TcpPlugin implements DuplexPlugin {
 			return new InetSocketAddress(a, p);
 		} catch (UnknownHostException e) {
 			if (LOG.isLoggable(WARNING))
+				// not scrubbing to enable us to find the problem
 				LOG.warning("Invalid address: " + addr);
 			return null;
 		} catch (NumberFormatException e) {
diff --git a/briar-core/src/org/briarproject/util/PrivacyUtils.java b/briar-core/src/org/briarproject/util/PrivacyUtils.java
new file mode 100644
index 0000000000000000000000000000000000000000..247ccda3f24a69d32d55f3d465a0427ab7d74b6e
--- /dev/null
+++ b/briar-core/src/org/briarproject/util/PrivacyUtils.java
@@ -0,0 +1,57 @@
+package org.briarproject.util;
+
+import java.net.Inet4Address;
+import java.net.Inet6Address;
+import java.net.InetAddress;
+import java.net.InetSocketAddress;
+import java.net.SocketAddress;
+
+public class PrivacyUtils {
+
+	public static String scrubOnion(String onion) {
+		// keep first three characters of onion address
+		return onion.substring(0, 3) + "[_scrubbed_]";
+	}
+
+	public static String scrubMacAddress(String address) {
+		if (address == null) return null;
+		// this is a fake address we need to know about
+		if (address.equals("02:00:00:00:00:00")) return address;
+		// keep first and last octet of MAC address
+		return address.substring(0, 3) +
+				"[scrubbed]" +
+				address.substring(14, 17);
+	}
+
+	public static String scrubInetAddress(InetAddress address) {
+		// don't scrub link and site local addresses
+		if (address.isLinkLocalAddress() || address.isSiteLocalAddress())
+			return address.toString();
+		// completely scrub IPv6 addresses
+		if (address instanceof Inet6Address) return "[scrubbed]";
+		// keep first and last octet of IPv4 addresses
+		return scrubInetAddress(address.toString());
+	}
+
+	public static String scrubInetAddress(String address) {
+		if (address == null) return null;
+
+		int firstDot = address.indexOf(".");
+		if (firstDot == -1) return "[scrubbed]";
+		String prefix = address.substring(0, firstDot + 1);
+		int lastDot = address.lastIndexOf(".");
+		String suffix = address.substring(lastDot, address.length());
+		return prefix + "[scrubbed]" + suffix;
+	}
+
+	public static String scrubSocketAddress(InetSocketAddress address) {
+		InetAddress inetAddress = address.getAddress();
+		return scrubInetAddress(inetAddress);
+	}
+
+	public static String scrubSocketAddress(SocketAddress address) {
+		if (address instanceof InetSocketAddress)
+			return scrubSocketAddress((InetSocketAddress) address);
+		return scrubInetAddress(address.toString());
+	}
+}