Compare commits

...

3 Commits

Author SHA1 Message Date
akwizgran
84b3670624 Create hidden service via conf file so we can use Tor 0.2.6. 2016-08-27 08:45:01 +01:00
akwizgran
749695187e Disable verification of Tor binaries so we can use old ones. 2016-08-26 23:30:58 +01:00
akwizgran
c4db72abf2 Revert Tor performance improvements for measurement. 2016-08-26 22:22:44 +01:00
6 changed files with 59 additions and 99 deletions

View File

@@ -189,8 +189,8 @@ project.afterEvaluate {
preBuild.dependsOn { preBuild.dependsOn {
[ [
'verifyTorGeoIp', 'verifyTorGeoIp',
'verifyTorBinaryArm', // 'verifyTorBinaryArm',
'verifyTorBinaryArmPie', // 'verifyTorBinaryArmPie',
'verifyTorBinaryX86', 'verifyTorBinaryX86',
'verifyTorBinaryX86Pie' 'verifyTorBinaryX86Pie'
] ]

View File

@@ -38,7 +38,7 @@ public class AndroidPluginsModule {
DuplexPluginFactory bluetooth = new DroidtoothPluginFactory(ioExecutor, DuplexPluginFactory bluetooth = new DroidtoothPluginFactory(ioExecutor,
androidExecutor, appContext, random, backoffFactory); androidExecutor, appContext, random, backoffFactory);
DuplexPluginFactory tor = new TorPluginFactory(ioExecutor, appContext, DuplexPluginFactory tor = new TorPluginFactory(ioExecutor, appContext,
locationUtils, reporter, eventBus, backoffFactory); locationUtils, reporter, eventBus);
DuplexPluginFactory lan = new AndroidLanTcpPluginFactory(ioExecutor, DuplexPluginFactory lan = new AndroidLanTcpPluginFactory(ioExecutor,
backoffFactory, appContext); backoffFactory, appContext);
final Collection<DuplexPluginFactory> duplex = final Collection<DuplexPluginFactory> duplex =

View File

@@ -26,7 +26,6 @@ import org.briarproject.api.event.EventListener;
import org.briarproject.api.event.SettingsUpdatedEvent; import org.briarproject.api.event.SettingsUpdatedEvent;
import org.briarproject.api.keyagreement.KeyAgreementListener; import org.briarproject.api.keyagreement.KeyAgreementListener;
import org.briarproject.api.keyagreement.TransportDescriptor; import org.briarproject.api.keyagreement.TransportDescriptor;
import org.briarproject.api.plugins.Backoff;
import org.briarproject.api.plugins.duplex.DuplexPlugin; import org.briarproject.api.plugins.duplex.DuplexPlugin;
import org.briarproject.api.plugins.duplex.DuplexPluginCallback; import org.briarproject.api.plugins.duplex.DuplexPluginCallback;
import org.briarproject.api.plugins.duplex.DuplexTransportConnection; import org.briarproject.api.plugins.duplex.DuplexTransportConnection;
@@ -52,7 +51,6 @@ import java.util.Arrays;
import java.util.Collection; import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.Scanner; import java.util.Scanner;
import java.util.concurrent.CountDownLatch; import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Executor; import java.util.concurrent.Executor;
@@ -70,8 +68,6 @@ import static android.os.PowerManager.PARTIAL_WAKE_LOCK;
import static java.util.concurrent.TimeUnit.MILLISECONDS; import static java.util.concurrent.TimeUnit.MILLISECONDS;
import static java.util.logging.Level.INFO; import static java.util.logging.Level.INFO;
import static java.util.logging.Level.WARNING; 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; import static org.briarproject.util.PrivacyUtils.scrubOnion;
class TorPlugin implements DuplexPlugin, EventHandler, EventListener { class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
@@ -85,6 +81,7 @@ class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
private static final String OWNER = "__OwningControllerProcess"; private static final String OWNER = "__OwningControllerProcess";
private static final int SOCKS_PORT = 59050, CONTROL_PORT = 59051; private static final int SOCKS_PORT = 59050, CONTROL_PORT = 59051;
private static final int COOKIE_TIMEOUT = 3000; // Milliseconds private static final int COOKIE_TIMEOUT = 3000; // Milliseconds
private static final int HOSTNAME_TIMEOUT = 30 * 1000; // Milliseconds
private static final Pattern ONION = Pattern.compile("[a-z2-7]{16}"); private static final Pattern ONION = Pattern.compile("[a-z2-7]{16}");
private static final Logger LOG = private static final Logger LOG =
Logger.getLogger(TorPlugin.class.getName()); Logger.getLogger(TorPlugin.class.getName());
@@ -93,13 +90,13 @@ class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
private final Context appContext; private final Context appContext;
private final LocationUtils locationUtils; private final LocationUtils locationUtils;
private final DevReporter reporter; private final DevReporter reporter;
private final Backoff backoff;
private final DuplexPluginCallback callback; private final DuplexPluginCallback callback;
private final String architecture; private final String architecture;
private final int maxLatency, maxIdleTime, socketTimeout; private final int maxLatency, maxIdleTime, socketTimeout;
private final int pollingInterval;
private final ConnectionStatus connectionStatus; private final ConnectionStatus connectionStatus;
private final File torDirectory, torFile, geoIpFile, configFile; private final File torDirectory, torFile, geoIpFile, configFile;
private final File doneFile, cookieFile; private final File doneFile, cookieFile, hostnameFile;
private final PowerManager.WakeLock wakeLock; private final PowerManager.WakeLock wakeLock;
private final AtomicBoolean used = new AtomicBoolean(false); private final AtomicBoolean used = new AtomicBoolean(false);
@@ -110,18 +107,18 @@ class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
private volatile BroadcastReceiver networkStateReceiver = null; private volatile BroadcastReceiver networkStateReceiver = null;
TorPlugin(Executor ioExecutor, Context appContext, TorPlugin(Executor ioExecutor, Context appContext,
LocationUtils locationUtils, DevReporter reporter, Backoff backoff, LocationUtils locationUtils, DevReporter reporter,
DuplexPluginCallback callback, String architecture, int maxLatency, DuplexPluginCallback callback, String architecture, int maxLatency,
int maxIdleTime) { int maxIdleTime, int pollingInterval) {
this.ioExecutor = ioExecutor; this.ioExecutor = ioExecutor;
this.appContext = appContext; this.appContext = appContext;
this.locationUtils = locationUtils; this.locationUtils = locationUtils;
this.reporter = reporter; this.reporter = reporter;
this.backoff = backoff;
this.callback = callback; this.callback = callback;
this.architecture = architecture; this.architecture = architecture;
this.maxLatency = maxLatency; this.maxLatency = maxLatency;
this.maxIdleTime = maxIdleTime; this.maxIdleTime = maxIdleTime;
this.pollingInterval = pollingInterval;
if (maxIdleTime > Integer.MAX_VALUE / 2) if (maxIdleTime > Integer.MAX_VALUE / 2)
socketTimeout = Integer.MAX_VALUE; socketTimeout = Integer.MAX_VALUE;
else socketTimeout = maxIdleTime * 2; else socketTimeout = maxIdleTime * 2;
@@ -132,6 +129,7 @@ class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
configFile = new File(torDirectory, "torrc"); configFile = new File(torDirectory, "torrc");
doneFile = new File(torDirectory, "done"); doneFile = new File(torDirectory, "done");
cookieFile = new File(torDirectory, ".tor/control_auth_cookie"); cookieFile = new File(torDirectory, ".tor/control_auth_cookie");
hostnameFile = new File(torDirectory, "hs/hostname");
Object o = appContext.getSystemService(POWER_SERVICE); Object o = appContext.getSystemService(POWER_SERVICE);
PowerManager pm = (PowerManager) o; PowerManager pm = (PowerManager) o;
wakeLock = pm.newWakeLock(PARTIAL_WAKE_LOCK, "TorPlugin"); wakeLock = pm.newWakeLock(PARTIAL_WAKE_LOCK, "TorPlugin");
@@ -363,7 +361,6 @@ class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
publishHiddenService(localPort); publishHiddenService(localPort);
} }
}); });
backoff.reset();
// Accept incoming hidden service connections from Tor // Accept incoming hidden service connections from Tor
acceptContactConnections(ss); acceptContactConnections(ss);
} }
@@ -382,40 +379,48 @@ class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
private void publishHiddenService(String port) { private void publishHiddenService(String port) {
if (!running) return; if (!running) return;
LOG.info("Creating hidden service"); if (!hostnameFile.exists()) {
String privKey = callback.getSettings().get(HS_PRIVKEY); LOG.info("Creating hidden service");
Map<Integer, String> portLines = try {
Collections.singletonMap(80, "127.0.0.1:" + port); // Watch for the hostname file being created/updated
Map<String, String> response; File serviceDirectory = hostnameFile.getParentFile();
try { serviceDirectory.mkdirs();
// Use the control connection to set up the hidden service hostnameFile.createNewFile();
if (privKey == null) CountDownLatch latch = new CountDownLatch(1);
response = controlConnection.addOnion(portLines); FileObserver obs = new WriteObserver(hostnameFile, latch);
else response = controlConnection.addOnion(privKey, portLines); obs.startWatching();
} catch (IOException e) { // Use the control connection to update the Tor config
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e); List<String> config = Arrays.asList(
return; "HiddenServiceDir " +
} serviceDirectory.getAbsolutePath(),
if (!response.containsKey(HS_ADDRESS)) { "HiddenServicePort 80 127.0.0.1:" + port);
LOG.warning("Tor did not return a hidden service address"); controlConnection.setConf(config);
return; controlConnection.saveConf();
} // Wait for the hostname file to be created/updated
if (privKey == null && !response.containsKey(HS_PRIVKEY)) { if (!latch.await(HOSTNAME_TIMEOUT, MILLISECONDS)) {
LOG.warning("Tor did not return a private key"); LOG.warning("Hidden service not created");
return; if (LOG.isLoggable(INFO)) listFiles(torDirectory);
return;
}
if (!running) return;
} catch (IOException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
} catch (InterruptedException e) {
LOG.warning("Interrupted while creating hidden service");
Thread.currentThread().interrupt();
return;
}
} }
// Publish the hidden service's onion hostname in transport properties // Publish the hidden service's onion hostname in transport properties
String hostname = response.get(HS_ADDRESS); try {
if (LOG.isLoggable(INFO)) String hostname = new String(read(hostnameFile), "UTF-8").trim();
LOG.info("Hidden service " + scrubOnion(hostname)); if (LOG.isLoggable(INFO))
TransportProperties p = new TransportProperties(); LOG.info("Hidden service " + scrubOnion(hostname));
p.put(PROP_ONION, hostname); TransportProperties p = new TransportProperties();
callback.mergeLocalProperties(p); p.put(PROP_ONION, hostname.substring(0, 16));
if (privKey == null) { callback.mergeLocalProperties(p);
// Save the hidden service's private key for next time } catch (IOException e) {
Settings s = new Settings(); if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
s.put(HS_PRIVKEY, response.get(HS_PRIVKEY));
callback.mergeSettings(s);
} }
} }
@@ -431,7 +436,6 @@ class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
return; return;
} }
LOG.info("Connection received"); LOG.info("Connection received");
backoff.reset();
TorTransportConnection conn = new TorTransportConnection(this, s); TorTransportConnection conn = new TorTransportConnection(this, s);
callback.incomingConnectionCreated(conn); callback.incomingConnectionCreated(conn);
} }
@@ -479,14 +483,12 @@ class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
@Override @Override
public int getPollingInterval() { public int getPollingInterval() {
return backoff.getPollingInterval(); return pollingInterval;
} }
@Override @Override
public void poll(Collection<ContactId> connected) { public void poll(Collection<ContactId> connected) {
if (!isRunning()) return; if (!isRunning()) return;
backoff.increment();
// TODO: Pass properties to connectAndCallBack()
for (ContactId c : callback.getRemoteProperties().keySet()) for (ContactId c : callback.getRemoteProperties().keySet())
if (!connected.contains(c)) connectAndCallBack(c); if (!connected.contains(c)) connectAndCallBack(c);
} }
@@ -496,10 +498,7 @@ class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
@Override @Override
public void run() { public void run() {
DuplexTransportConnection d = createConnection(c); DuplexTransportConnection d = createConnection(c);
if (d != null) { if (d != null) callback.outgoingConnectionCreated(c, d);
backoff.reset();
callback.outgoingConnectionCreated(c, d);
}
} }
}); });
} }
@@ -519,7 +518,6 @@ class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
try { try {
if (LOG.isLoggable(INFO)) if (LOG.isLoggable(INFO))
LOG.info("Connecting to " + scrubOnion(onion)); LOG.info("Connecting to " + scrubOnion(onion));
controlConnection.forgetHiddenService(onion);
Socks5Proxy proxy = new Socks5Proxy("127.0.0.1", SOCKS_PORT); Socks5Proxy proxy = new Socks5Proxy("127.0.0.1", SOCKS_PORT);
proxy.resolveAddrLocally(false); proxy.resolveAddrLocally(false);
Socket s = new SocksSocket(proxy, onion + ".onion", 80); Socket s = new SocksSocket(proxy, onion + ".onion", 80);
@@ -528,9 +526,10 @@ class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
LOG.info("Connected to " + scrubOnion(onion)); LOG.info("Connected to " + scrubOnion(onion));
return new TorTransportConnection(this, s); return new TorTransportConnection(this, s);
} catch (IOException e) { } catch (IOException e) {
if (LOG.isLoggable(INFO)) if (LOG.isLoggable(INFO)) {
LOG.info("Could not connect to " + scrubOnion(onion) + ": " + LOG.info("Could not connect to " + scrubOnion(onion) + ": " +
e.toString()); e.toString());
}
return null; return null;
} }
} }
@@ -567,7 +566,6 @@ class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
if (status.equals("BUILT") && if (status.equals("BUILT") &&
connectionStatus.getAndSetCircuitBuilt()) { connectionStatus.getAndSetCircuitBuilt()) {
LOG.info("First circuit built"); LOG.info("First circuit built");
backoff.reset();
if (isRunning()) { if (isRunning()) {
sendDevReports(); sendDevReports();
callback.transportEnabled(); callback.transportEnabled();
@@ -597,7 +595,6 @@ class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
if (LOG.isLoggable(INFO)) LOG.info(severity + " " + msg); if (LOG.isLoggable(INFO)) LOG.info(severity + " " + msg);
if (severity.equals("NOTICE") && msg.startsWith("Bootstrapped 100%")) { if (severity.equals("NOTICE") && msg.startsWith("Bootstrapped 100%")) {
connectionStatus.setBootstrapped(); connectionStatus.setBootstrapped();
backoff.reset();
if (isRunning()) { if (isRunning()) {
sendDevReports(); sendDevReports();
callback.transportEnabled(); callback.transportEnabled();

View File

@@ -6,8 +6,6 @@ import android.os.Build;
import org.briarproject.android.util.AndroidUtils; import org.briarproject.android.util.AndroidUtils;
import org.briarproject.api.TransportId; import org.briarproject.api.TransportId;
import org.briarproject.api.event.EventBus; import org.briarproject.api.event.EventBus;
import org.briarproject.api.plugins.Backoff;
import org.briarproject.api.plugins.BackoffFactory;
import org.briarproject.api.plugins.duplex.DuplexPlugin; import org.briarproject.api.plugins.duplex.DuplexPlugin;
import org.briarproject.api.plugins.duplex.DuplexPluginCallback; import org.briarproject.api.plugins.duplex.DuplexPluginCallback;
import org.briarproject.api.plugins.duplex.DuplexPluginFactory; import org.briarproject.api.plugins.duplex.DuplexPluginFactory;
@@ -24,26 +22,22 @@ public class TorPluginFactory implements DuplexPluginFactory {
private static final int MAX_LATENCY = 30 * 1000; // 30 seconds private static final int MAX_LATENCY = 30 * 1000; // 30 seconds
private static final int MAX_IDLE_TIME = 30 * 1000; // 30 seconds private static final int MAX_IDLE_TIME = 30 * 1000; // 30 seconds
private static final int MIN_POLLING_INTERVAL = 60 * 1000; // 1 minute private static final int POLLING_INTERVAL = 2 * 60 * 1000; // 2 minutes
private static final int MAX_POLLING_INTERVAL = 10 * 60 * 1000; // 10 mins
private static final double BACKOFF_BASE = 1.2;
private final Executor ioExecutor; private final Executor ioExecutor;
private final Context appContext; private final Context appContext;
private final LocationUtils locationUtils; private final LocationUtils locationUtils;
private final DevReporter reporter; private final DevReporter reporter;
private final EventBus eventBus; private final EventBus eventBus;
private final BackoffFactory backoffFactory;
public TorPluginFactory(Executor ioExecutor, Context appContext, public TorPluginFactory(Executor ioExecutor, Context appContext,
LocationUtils locationUtils, DevReporter reporter, LocationUtils locationUtils, DevReporter reporter,
EventBus eventBus, BackoffFactory backoffFactory) { EventBus eventBus) {
this.ioExecutor = ioExecutor; this.ioExecutor = ioExecutor;
this.appContext = appContext; this.appContext = appContext;
this.locationUtils = locationUtils; this.locationUtils = locationUtils;
this.reporter = reporter; this.reporter = reporter;
this.eventBus = eventBus; this.eventBus = eventBus;
this.backoffFactory = backoffFactory;
} }
@Override @Override
@@ -77,11 +71,9 @@ public class TorPluginFactory implements DuplexPluginFactory {
// Use position-independent executable for SDK >= 16 // Use position-independent executable for SDK >= 16
if (Build.VERSION.SDK_INT >= 16) architecture += "-pie"; if (Build.VERSION.SDK_INT >= 16) architecture += "-pie";
Backoff backoff = backoffFactory.createBackoff(MIN_POLLING_INTERVAL,
MAX_POLLING_INTERVAL, BACKOFF_BASE);
TorPlugin plugin = new TorPlugin(ioExecutor, appContext, locationUtils, TorPlugin plugin = new TorPlugin(ioExecutor, appContext, locationUtils,
reporter, backoff, callback, architecture, MAX_LATENCY, reporter, callback, architecture, MAX_LATENCY, MAX_IDLE_TIME,
MAX_IDLE_TIME); POLLING_INTERVAL);
eventBus.addListener(plugin); eventBus.addListener(plugin);
return plugin; return plugin;
} }

View File

@@ -2,8 +2,6 @@ package org.briarproject.plugins;
import org.briarproject.api.TransportId; import org.briarproject.api.TransportId;
import org.briarproject.api.contact.ContactId; import org.briarproject.api.contact.ContactId;
import org.briarproject.api.event.ConnectionClosedEvent;
import org.briarproject.api.event.ConnectionOpenedEvent;
import org.briarproject.api.event.ContactStatusChangedEvent; import org.briarproject.api.event.ContactStatusChangedEvent;
import org.briarproject.api.event.Event; import org.briarproject.api.event.Event;
import org.briarproject.api.event.EventListener; import org.briarproject.api.event.EventListener;
@@ -71,18 +69,6 @@ class Poller implements EventListener {
// Connect to the newly activated contact // Connect to the newly activated contact
connectToContact(c.getContactId()); connectToContact(c.getContactId());
} }
} else if (e instanceof ConnectionClosedEvent) {
ConnectionClosedEvent c = (ConnectionClosedEvent) e;
// Reschedule polling, the polling interval may have decreased
reschedule(c.getTransportId());
if (!c.isIncoming()) {
// Connect to the disconnected contact
connectToContact(c.getContactId(), c.getTransportId());
}
} else if (e instanceof ConnectionOpenedEvent) {
ConnectionOpenedEvent c = (ConnectionOpenedEvent) e;
// Reschedule polling, the polling interval may have decreased
reschedule(c.getTransportId());
} else if (e instanceof TransportEnabledEvent) { } else if (e instanceof TransportEnabledEvent) {
TransportEnabledEvent t = (TransportEnabledEvent) e; TransportEnabledEvent t = (TransportEnabledEvent) e;
// Poll the newly enabled transport // Poll the newly enabled transport
@@ -97,14 +83,6 @@ class Poller implements EventListener {
if (d.shouldPoll()) connectToContact(c, d); if (d.shouldPoll()) connectToContact(c, d);
} }
private void connectToContact(ContactId c, TransportId t) {
Plugin p = pluginManager.getPlugin(t);
if (p instanceof SimplexPlugin && p.shouldPoll())
connectToContact(c, (SimplexPlugin) p);
else if (p instanceof DuplexPlugin && p.shouldPoll())
connectToContact(c, (DuplexPlugin) p);
}
private void connectToContact(final ContactId c, final SimplexPlugin p) { private void connectToContact(final ContactId c, final SimplexPlugin p) {
ioExecutor.execute(new Runnable() { ioExecutor.execute(new Runnable() {
@Override @Override
@@ -133,11 +111,6 @@ class Poller implements EventListener {
}); });
} }
private void reschedule(TransportId t) {
Plugin p = pluginManager.getPlugin(t);
if (p.shouldPoll()) schedule(p, p.getPollingInterval(), false);
}
private void pollNow(TransportId t) { private void pollNow(TransportId t) {
Plugin p = pluginManager.getPlugin(t); Plugin p = pluginManager.getPlugin(t);
// Randomise next polling interval // Randomise next polling interval

View File

@@ -1,6 +1,5 @@
package org.briarproject.util; package org.briarproject.util;
import java.net.Inet4Address;
import java.net.Inet6Address; import java.net.Inet6Address;
import java.net.InetAddress; import java.net.InetAddress;
import java.net.InetSocketAddress; import java.net.InetSocketAddress;
@@ -9,8 +8,7 @@ import java.net.SocketAddress;
public class PrivacyUtils { public class PrivacyUtils {
public static String scrubOnion(String onion) { public static String scrubOnion(String onion) {
// keep first three characters of onion address return onion;
return onion.substring(0, 3) + "[_scrubbed_]";
} }
public static String scrubMacAddress(String address) { public static String scrubMacAddress(String address) {