[tor-commits] [ooni-probe/master] bridget is functional again, but DataDirectory still doesn't work so it takes forever and is hammering the DirAuths.
isis at torproject.org
isis at torproject.org
Thu Sep 13 13:04:15 UTC 2012
commit b49b70ebcdb1073e7a6fddf9a384f7e9d9c7398a
Author: Isis Lovecruft <isis at torproject.org>
Date: Wed Sep 12 02:22:55 2012 +0000
bridget is functional again, but DataDirectory still doesn't work so it takes forever and is hammering the DirAuths.
---
ooni/plugins/bridget.py | 229 ++++++++++++++++++++++++++++-------------------
1 files changed, 136 insertions(+), 93 deletions(-)
diff --git a/ooni/plugins/bridget.py b/ooni/plugins/bridget.py
index b57d7c1..2a7d573 100644
--- a/ooni/plugins/bridget.py
+++ b/ooni/plugins/bridget.py
@@ -34,23 +34,40 @@ from ooni.plugoo.assets import Asset
class BridgetArgs(usage.Options):
+
+ def portCheck(number):
+ number = int(number)
+ if number not in range(1024, 65535):
+ raise ValueError("Port out of range")
+ portCheck.coerceDoc = "Ports must be between 1024 and 65535"
+
optParameters = [
- ['bridges', 'b', None,
- 'List of bridges to scan (IP:ORport)'],
- ['relays', 'f', None,
- 'List of relays to scan (IP)'],
- ['socks', 's', 9049,
+ ['bridges', 'b', None,
+ 'List of bridges to scan <IP>:<ORport>'],
+ ['relays', 'f', None,
+ 'List of relays to scan <IP>'],
+ ['socks', 's', 9049, portCheck,
'Tor SocksPort to use'],
- ['control', 'c', 9052,
+ ['control', 'c', 9052, portCheck,
'Tor ControlPort to use'],
- ['random', 'x', False,
- 'Randomize control and socks ports'],
- ['tor-path', 'p', '/usr/sbin/tor',
+ ['tor-path', 'p', None,
'Path to the Tor binary to use'],
+ ['data-dir', 'd', None,
+ 'Tor DataDirectory to use'],
['transport', 't', None,
- 'Tor ClientTransportPlugin string. Requires -b.'],
- ['resume', 'r', 0,
+ 'Tor ClientTransportPlugin'],
+ ['resume', 'r', 0,
'Resume at this index']]
+ optFlags = [['random', 'x', 'Randomize control and socks ports']]
+
+ def postOptions(self):
+ if self['transport'] and not self['bridges']:
+ e = "Pluggable transport requires the bridges option"
+ raise usage.UsageError, e
+ if self['socks'] and self['control']:
+ if self['random']:
+ e = "Unable to use random and specific ports simultaneously"
+ raise usageError, e
class CustomCircuit(CircuitListenerMixin):
implements(IStreamAttacher)
@@ -158,14 +175,12 @@ class BridgetTest(OONITest):
:ivar config:
An :class:`ooni.lib.txtorcon.TorConfig` instance.
- :ivar use_bridges:
- A boolean integer [0|1].
- :ivar entry_nodes:
- A string of all provided relays to test. We have to do this
- because txtorcon.TorState().entry_guards won't build a custom
- circuit if the first hop isn't in the torrc's EntryNodes.
:ivar relay_list:
- The same as :ivar entry_nodes: but in list form.
+ A list of all provided relays to test. We have to do this because
+ txtorcon.TorState().entry_guards won't build a custom circuit if the
+ first hop isn't in the torrc's EntryNodes.
+ :ivar bridge_list:
+ A list of all provided bridges to test.
:ivar socks_port:
Integer for Tor's SocksPort.
:ivar control_port:
@@ -179,77 +194,84 @@ class BridgetTest(OONITest):
implements(IPlugin, ITest)
shortName = "bridget"
- description = "Use a Tor process to test connecting to bridges/relays"
+ description = "Use a Tor process to test connecting to bridges and relays"
requirements = None
options = BridgetArgs
blocking = False
def load_assets(self):
"""
- Load bridges from file given in user options. Bridges should be given
- in the form IP:ORport. We don't want to load relays as assets, because
- it's inefficient to test them one at a time.
+ Load bridges and/or relays from files given in user options. Bridges
+ should be given in the form IP:ORport. We don't want to load these as
+ assets, because it's inefficient to start a Tor process for each one.
"""
- assets = []
+ assets = {}
+ self.bridge_list = []
+ self.relay_list = []
+
+ ## XXX fix me
+ ## we should probably find a more memory nice way to load addresses,
+ ## in case the files are really large
if self.local_options:
if self.local_options['bridges']:
- #assets.update({'bridge':
- # BridgetAsset(self.local_options['bridges'])})
- with open(self.local_options['bridges'] as bridge_file):
+ log.msg("Loading bridge information from %s ..."
+ % self.local_options['bridges'])
+ with open(self.local_options['bridges']) as bridge_file:
for line in bridge_file.readlines():
if line.startswith('#'):
continue
else:
- bridge = line.replace('\n','')
- assets.append(bridge)
+ self.bridge_list.append(line.replace('\n',''))
+ assets.update({'bridges': self.bridge_list})
+
+ if self.local_options['relays']:
+ log.msg("Loading relay information from %s ..."
+ % self.local_options['relays'])
+ with open(options['relays']) as relay_file:
+ for line in relay_file.readlines():
+ if line.startswith('#'):
+ continue
+ else:
+ self.relay_list.append(line.replace('\n',''))
+ assets.update({'relays': self.relay_list})
return assets
def initialize(self):
"""
Extra initialization steps. We only want one child Tor process
- running, so we need to deal with the creation of the torrc only once,
- before the experiment runs.
+ running, so we need to deal with the creation of TorConfig() only
+ once, before the experiment runs.
"""
- self.relay_list = []
- ## XXX why doesn't the default set in the options work?
self.socks_port = 9049
self.control_port = 9052
+ self.tor_binary = '/usr/sbin/tor'
+ self.data_directory = None
if self.local_options:
try:
from ooni.lib.txtorcon import TorConfig
except:
- log.msg("Could not import TorConfig class from txtorcon")
- raise
+ e = "Could not import TorConfig class from txtorcon!"
+ raise ImportError, e
options = self.local_options
self.config = TorConfig()
- self.socks_port = options['socks']
- self.control_port = options['control']
if options['bridges']:
- log.msg("Using Bridges ...")
self.config.UseBridges = 1
if options['relays']:
- '''
- Stupid hack for when testing only relays (and not bridges):
- Tor doesn't use EntryNodes when UseBridges is enabled, but
- txtorcon requires config.state.entry_guards to make a custom
- circuit, so we should list them as EntryNodes anyway.
- '''
- log.msg("Using relays ...")
-
- with open(options['relays']) as relay_file:
- for line in relay_file.readlines():
- if line.startswith('#'):
- continue
- else:
- relay = line.replace('\n', '') ## not assets because
- self.relay_list.append(relay) ## we don't want to
- ## test one at a time
- self.config.EntryNodes = ','
- self.config.EntryNodes.join(relay_list)
+ ## Stupid hack for testing only relays:
+ ## Tor doesn't use EntryNodes when UseBridges is enabled, but
+ ## config.state.entry_guards needs to include the first hop to
+ ## build a custom circuit.
+ self.config.EntryNodes = ','.join(relay_list)
+
+ if options['socks']:
+ self.socks_port = options['socks']
+
+ if options['control']:
+ self.control_port = options['control']
if options['random']:
log.msg("Using randomized ControlPort and SocksPort ...")
@@ -259,14 +281,14 @@ class BridgetTest(OONITest):
if options['tor-path']:
self.tor_binary = options['tor-path']
+ if options['data-dir']:
+ self.config.DataDirectory = options['data-dir']
+
if options['transport']:
- '''
- ClientTransportPlugin transport socks4|socks5 IP:PORT
- ClientTransportPlugin transport exec path-to-binary [options]
- '''
+ ## ClientTransportPlugin transport socks4|socks5 IP:PORT
+ ## ClientTransportPlugin transport exec path-to-binary [options]
if not options['bridges']:
- e = "To test pluggable transports, you must provide a file"
- e = e+"with a list of bridge IP:ORPorts. See \'-b' option."
+ e = "You must use the bridge option to test a transport."
raise usage.UsageError("%s" % e)
log.msg("Using pluggable transport ...")
@@ -280,15 +302,22 @@ class BridgetTest(OONITest):
print self.config.create_torrc()
report = {'tor_config': self.config.config}
- return self.config
- else:
- return None
def experiment(self, args):
"""
XXX fill me in
+
+ :param args:
+ The :class:`ooni.plugoo.asset.Asset <Asset>` line currently being
+ used.
+ :meth launch_tor:
+ Returns a Deferred which callbacks with a
+ :class:`ooni.lib.txtorcon.torproto.TorProcessProtocol
+ <TorProcessProtocol>` connected to the fully-bootstrapped Tor;
+ this has a :class:`ooni.lib.txtorcon.torcontol.TorControlProtocol
+ <TorControlProtocol>` instance as .protocol.
"""
- log.msg("BridgeT: initiating test ... ")
+ log.msg("Bridget: initiating test ... ")
from ooni.lib.txtorcon import TorProtocolFactory, TorConfig, TorState
from ooni.lib.txtorcon import DEFAULT_VALUE, launch_tor
@@ -306,54 +335,54 @@ class BridgetTest(OONITest):
state.post_bootstrap.addCallback(state_complete).addErrback(setup_failed)
report.update({'success': args})
- def bootstrap(c):
+ def bootstrap(ctrl):
"""
Launch a Tor process with the TorConfig instance returned from
initialize().
-
- Returns a Deferred which callbacks with a TorProcessProtocol connected
- to the fully-bootstrapped Tor; this has a txtorcon.TorControlProtocol
- instance as .protocol.
"""
- conf = TorConfig(c)
+ conf = TorConfig(ctrl)
conf.post_bootstrap.addCallback(setup_complete).addErrback(setup_failed)
log.msg("Tor process connected, bootstrapping ...")
def updates(prog, tag, summary):
log.msg("%d%%: %s" % (prog, summary))
- def reconfigure_controller(proto, args):
+ def reconfigure_controller(conf, bridge):
## if bridges and relays, use one bridge then build a circuit
- ## from the relays
- print args
- print args['bridge']
- #d.addCallback(CustomCircuit(state))
- proto.set_conf('Bridge', args['bridge'])
-
- ## if bridges only, try one bridge at a time, but don't build
- ## circuits, just return
- ## if relays only, build circuits from relays
+ ## from three relays
+ conf.Bridge = bridge
+ ## XXX do we need a SIGHUP to restart?
- def reconfigure_failed(proto, args):
+ ## XXX see txtorcon.TorControlProtocol.add_event_listener we may not
+ ## need full CustomCircuit class
+
+ ## if bridges only, try one bridge at a time, but don't build
+ ## circuits, just return
+
+ ## if relays only, build circuits from relays
+
+ def reconfigure_failed(args):
log.msg("Reconfiguring Tor config with args %s failed" % args)
reactor.stop()
- ## XXX see txtorcon.TorControlProtocol.add_event_listener
- ## we may not need full CustomCircuit class
+ if len(self.bridge_list) >= 1:
+ for bridge in self.bridge_list:
+ try:
+ print "BRIDGE IS %s" % bridge
+ reconfigure_controller(self.config, bridge)
+ except:
+ reconfigure_failed(bridge)
## :return: a Deferred which callbacks with a TorProcessProtocol
## connected to the fully-bootstrapped Tor; this has a
## txtorcon.TorControlProtocol instance as .protocol.
-
- print args
- d = launch_tor(self.config, reactor, progress_updates=updates,
+ d = launch_tor(self.config,
+ reactor,
+ progress_updates=updates,
tor_binary=self.tor_binary)
- d.addCallback(reconfigure_controller, args)
- d.addErrback(reconfigure_failed, args)
d.addCallback(bootstrap, self.config)
d.addErrback(setup_failed)
-
- ## 4 build circuits
+ ## 4 build circuits
#print "Tor process ID: %s" % d.transport.pid
return d
@@ -362,6 +391,20 @@ class BridgetTest(OONITest):
bridget = BridgetTest(None, None, None)
## ISIS' NOTES
+## -----------
+## self.config.save() only needs to be called if Tor is already running.
##
-##
-##
+## need to add transport type to torrc Bridge line:
+## Bridge <transport> IP:ORPort <fingerprint>
+##
+## TODO:
+## o add option for any kwarg=arg self.config setting
+## o add DataDirectory option?
+## o cleanup documentation
+## o check if bridges are public relays
+## o take bridge_desc file as input, also be able to give same
+## format as output
+## o change the stupid name
+##
+## FIX:
+## data directory is not found, or permissions aren't right
More information about the tor-commits
mailing list