[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]
[tor-commits] [ooni-probe/master] Add support for starting Tor via txtorcon
commit a65b6ebb7e90a4350b1a214189196d11a8371eda
Author: Arturo Filastò <art@xxxxxxxxx>
Date: Mon Nov 26 22:49:14 2012 +0100
Add support for starting Tor via txtorcon
* XXX would like to be able to know if Tor is censored and add it to the
report, this can easily be done if running launch_tor with a timeout.
This is provided by this patch: https://github.com/meejah/txtorcon/pull/24
---
ooni/config.py | 10 ++++-
ooni/runner.py | 97 +++++++++++++++++++++++++++++++++++++++++++++++++----
ooni/utils/net.py | 26 ++++++++++++++
ooniprobe.conf | 9 ++++-
4 files changed, 132 insertions(+), 10 deletions(-)
diff --git a/ooni/config.py b/ooni/config.py
index 69842b6..edfb196 100644
--- a/ooni/config.py
+++ b/ooni/config.py
@@ -65,7 +65,13 @@ def loadConfigFile():
advanced = Storage()
for k, v in configuration['advanced'].items():
advanced[k] = v
- return basic, privacy, advanced
+
+ # Process the tor configuration options
+ tor = Storage()
+ for k, v in configuration['tor'].items():
+ tor[k] = v
+
+ return basic, privacy, advanced, tor
class TestFilenameNotSet(Exception):
pass
@@ -85,7 +91,7 @@ def generateReportFilenames():
if not basic:
# Here we make sure that we instance the config file attributes only once
- basic, privacy, advanced = loadConfigFile()
+ basic, privacy, advanced, tor = loadConfigFile()
if not resume_filename:
resume_filename = os.path.join(get_root_path(), 'ooniprobe.resume')
diff --git a/ooni/runner.py b/ooni/runner.py
index 6ea4a86..6940ec6 100644
--- a/ooni/runner.py
+++ b/ooni/runner.py
@@ -21,12 +21,20 @@ from twisted.internet import defer
from twisted.trial.runner import filenameToModule
from twisted.internet import reactor, threads
+from txtorcon import TorProtocolFactory, TorConfig
+from txtorcon import TorState, launch_tor
+
+from ooni import config
+
+from ooni.reporter import OONIBReporter, YAMLReporter
+from ooni.reporter import OONIBReportCreationFailed
+
from ooni.inputunit import InputUnitFactory
from ooni.nettest import NetTestCase, NoPostProcessor
-from ooni import reporter, config
-
-from ooni.utils import log, checkForRoot, NotRootError, Storage
+from ooni.utils import log, checkForRoot
+from ooni.utils import NotRootError, Storage
+from ooni.utils.net import randomFreePort
def processTest(obj):
"""
@@ -374,10 +382,10 @@ def runTestCases(test_cases, options, cmd_line_options):
if cmd_line_options['collector']:
log.msg("Using remote collector, please be patient while we create the report.")
- oreporter = reporter.OONIBReporter(cmd_line_options)
+ oreporter = OONIBReporter(cmd_line_options)
else:
log.msg("Reporting to file %s" % config.reports.yamloo)
- oreporter = reporter.YAMLReporter(cmd_line_options)
+ oreporter = YAMLReporter(cmd_line_options)
try:
input_unit_factory = InputUnitFactory(test_inputs)
@@ -386,7 +394,7 @@ def runTestCases(test_cases, options, cmd_line_options):
try:
yield oreporter.createReport(options)
- except reporter.OONIBReportCreationFailed:
+ except OONIBReportCreationFailed:
log.err("Error in creating new report")
raise
except Exception, e:
@@ -421,6 +429,63 @@ def runTestCases(test_cases, options, cmd_line_options):
except Exception:
log.exception("Problem in running test")
+class UnableToStartTor(Exception):
+ pass
+
+def startTor():
+
+ @defer.inlineCallbacks
+ def state_complete(state):
+ config.tor_state = state
+ log.msg("Successfully bootstrapped Tor")
+ log.debug("We now have the following circuits: ")
+ for circuit in state.circuits.values():
+ log.debug(" * %s" % circuit)
+ config.tor.socks_port = yield state.protocol.get_conf("SocksPort")
+ config.tor.control_port = yield state.protocol.get_conf("ControlPort")
+
+ def setup_failed(arg):
+ log.exception(arg)
+ raise UnableTorStartTor
+
+ def setup_complete(proto):
+ """
+ Called when we read from stdout that Tor has reached 100%.
+ """
+ log.debug("Building a TorState")
+ state = TorState(proto.tor_protocol)
+ state.post_bootstrap.addCallback(state_complete)
+ state.post_bootstrap.addErrback(setup_failed)
+ return state.post_bootstrap
+
+ def updates(prog, tag, summary):
+ log.msg("%d%%: %s" % (prog, summary))
+
+ tor_config = TorConfig()
+ if config.tor.control_port:
+ tor_config.ControlPort = config.tor.control_port
+ else:
+ control_port = int(randomFreePort())
+ tor_config.ControlPort = control_port
+ config.tor.control_port = control_port
+
+ if config.tor.socks_port:
+ tor_config.SocksPort = config.tor.socks_port
+ else:
+ socks_port = int(randomFreePort())
+ tor_config.SocksPort = socks_port
+ config.tor.socks_port = socks_port
+
+ tor_config.save()
+
+ log.debug("Setting control port as %s" % tor_config.ControlPort)
+ log.debug("Setting SOCKS port as %s" % tor_config.SocksPort)
+
+ d = launch_tor(tor_config, reactor, progress_updates=updates)
+ d.addCallback(setup_complete)
+ d.addErrback(setup_failed)
+ return d
+
def runTest(cmd_line_options):
config.cmd_line_options = cmd_line_options
config.generateReportFilenames()
@@ -436,6 +501,7 @@ def runTest(cmd_line_options):
classes = findTestClassesFromFile(cmd_line_options['test'])
test_cases, options = loadTestsAndOptions(classes, cmd_line_options)
+
if config.privacy.includepcap:
from ooni.utils.txscapy import ScapyFactory, ScapySniffer
try:
@@ -451,4 +517,21 @@ def runTest(cmd_line_options):
sniffer = ScapySniffer(config.reports.pcap)
config.scapyFactory.registerProtocol(sniffer)
- return runTestCases(test_cases, options, cmd_line_options)
+ # If we should start Tor then start it. Once Tor has started we will make
+ # sure. If not we assume that it is already running
+ if config.advanced.start_tor:
+ def tor_startup_failed(failure):
+ log.err(failure)
+
+ def tor_started():
+ return runTestCases(test_cases,
+ options, cmd_line_options)
+
+ d = startTor()
+ d.addCallback(tor_started)
+ d.addErrback(tor_startup_failed)
+ return d
+
+ else:
+ return runTestCases(test_cases,
+ options, cmd_line_options)
diff --git a/ooni/utils/net.py b/ooni/utils/net.py
index df98412..12d1939 100644
--- a/ooni/utils/net.py
+++ b/ooni/utils/net.py
@@ -10,6 +10,8 @@
# see attached LICENCE file
import sys
+import socket
+from random import randint
from zope.interface import implements
from twisted.internet import protocol, defer
@@ -123,6 +125,30 @@ def getIfaces(platform_name=None):
else:
raise UnsupportedPlatform
+def randomFreePort(addr="127.0.0.1"):
+ """
+ Args:
+
+ addr (str): the IP address to attempt to bind to.
+
+ Returns an int representing the free port number at the moment of calling
+
+ Note: there is no guarantee that some other application will attempt to
+ bind to this port once this function has been called.
+ """
+ free = False
+ while not free:
+ port = randint(1024, 65535)
+ s = socket.socket()
+ try:
+ s.bind((addr, port))
+ free = True
+ except:
+ pass
+ s.close()
+ return port
+
+
def checkInterfaces(ifaces=None, timeout=1):
"""
@param ifaces:
diff --git a/ooniprobe.conf b/ooniprobe.conf
index 5fa0743..6777fde 100644
--- a/ooniprobe.conf
+++ b/ooniprobe.conf
@@ -23,9 +23,16 @@ advanced:
geoip_data_dir: /usr/share/GeoIP/
debug: true
threadpool_size: 10
- tor_socksport: 9050
+
+ tor_binary: '/usr/sbin/tor'
# For auto detection
interface: auto
# Of specify a specific interface
#interface: wlan0
+ start_tor: true
+tor:
+ #socks_port: 9050
+ #control_port: 9051
+ # Specify the absolute path to the Tor bridges to use for testing
+ bridges: bridges.list
_______________________________________________
tor-commits mailing list
tor-commits@xxxxxxxxxxxxxxxxxxxx
https://lists.torproject.org/cgi-bin/mailman/listinfo/tor-commits