Skip to content
This repository has been archived by the owner on Mar 2, 2022. It is now read-only.

Commit

Permalink
Merge 0c54627 into ff86b30
Browse files Browse the repository at this point in the history
  • Loading branch information
aagbsn committed Jan 24, 2018
2 parents ff86b30 + 0c54627 commit eff297d
Show file tree
Hide file tree
Showing 5 changed files with 59 additions and 60 deletions.
57 changes: 48 additions & 9 deletions bwscanner/attacher.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,11 @@

from twisted.internet import defer, reactor
from txtorcon.interface import CircuitListenerMixin, IStreamAttacher, StreamListenerMixin
from txtorcon import TorState, launch_tor
from txtorcon import TorState, launch_tor, build_tor_connection, TorConfig
from txtorcon.util import available_tcp_port
from zope.interface import implementer


FETCH_ALL_DESCRIPTOR_OPTIONS = {
'UseMicroDescriptors': 0,
'FetchUselessDescriptors': 1,
'FetchDirInfoEarly': 1,
'FetchDirInfoExtraEarly': 1,
}
from bwscanner.logger import log


@implementer(IStreamAttacher)
Expand Down Expand Up @@ -146,7 +140,16 @@ def update_tor_config(tor, config):
"""
config_pairs = [(key, value) for key, value in config.items()]
d = tor.protocol.set_conf(*itertools.chain.from_iterable(config_pairs))
return d.addCallback(lambda result: tor)
#XXX Only follow this path if we are changing config options that
# require a wait for NEWCONSENSUS
def wait_for_newconsensus(_):
got_consensus = defer.Deferred()
def got_newconsensus(evt):
got_consensus.callback(tor)
tor.protocol.remove_event_listener('NEWCONSENSUS', got_newconsensus)
tor.protocol.add_event_listener('NEWCONSENSUS', got_newconsensus)
return got_consensus
return d.addCallback(wait_for_newconsensus)


def setconf_singleport_exit(tor):
Expand All @@ -162,3 +165,39 @@ def add_single_port_exit(port):
'ExitPolicy', 'accept 127.0.0.1:{}, reject *:*'.format(port))
return port.addCallback(add_single_port_exit).addCallback(
lambda ign: tor.routers[tor.protocol.get_info("fingerprint")])


def connect_to_tor(launch_tor, circuit_build_timeout, circuit_idle_timeout, control_port=9051):
"""
Launch or connect to a Tor instance
Configure Tor with the passed options and return a Deferred
"""
# Options for spawned or running Tor to load the correct descriptors.
tor_options = {
'LearnCircuitBuildTimeout': 0, # Disable adaptive circuit timeouts.
'CircuitBuildTimeout': circuit_build_timeout,
'CircuitIdleTimeout': circuit_idle_timeout,
'UseEntryGuards': 0, # Disable UseEntryGuards to avoid PathBias warnings.
'UseMicroDescriptors': 0,
'FetchUselessDescriptors': 1,
'FetchDirInfoEarly': 1,
'FetchDirInfoExtraEarly': 1,
}

if launch_tor:
log.info("Spawning a new Tor instance.")
c = TorConfig()
# Update Tor config before launching a new Tor.
c.config.update(tor_options)
tor = start_tor(c)

else:
log.info("Trying to connect to a running Tor instance.")
tor = build_tor_connection((reactor, '127.0.0.1', control_port,))
# Update the Tor config on a running Tor.
tor.addCallback(update_tor_config, tor_options)

tor.addErrback(log.debug)

return tor
8 changes: 4 additions & 4 deletions bwscanner/fetcher.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
from bwscanner.logger import log


def get_orport_endpoint(tor_state):
def get_tor_socks_endpoint(tor_state):
proxy_endpoint = tor_state.protocol.get_conf("SocksPort")

def extract_port_value(result):
Expand Down Expand Up @@ -54,23 +54,23 @@ def __init__(self, host, port, state, path):
self.path = path
self.state = state

self.or_endpoint = get_orport_endpoint(state)
self.tor_socks_endpoint = get_tor_socks_endpoint(state)

def connect(self, protocol_factory):
"""
Implements L{IStreamClientEndpoint.connect} to connect via TCP, after
SOCKS5 negotiation and Tor circuit construction is done.
"""
proxy_factory = SOCKS5ClientFactory(self.host, self.port, protocol_factory)
self.or_endpoint.addCallback(lambda end: end.connect(proxy_factory))
self.tor_socks_endpoint.addCallback(lambda end: end.connect(proxy_factory))

def _create_circ(proto):
hp = proto.transport.getHost()
d = self.state.attacher.create_circuit(hp.host, hp.port, self.path)
d.addErrback(proxy_factory.deferred.errback)
return proxy_factory.deferred

return self.or_endpoint.addCallback(_create_circ)
return self.tor_socks_endpoint.addCallback(_create_circ)


class OnionRoutedAgent(Agent):
Expand Down
40 changes: 1 addition & 39 deletions bwscanner/scanner.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,54 +4,16 @@

import click
from twisted.internet import reactor
from txtorcon import build_local_tor_connection, TorConfig

from bwscanner.attacher import connect_to_tor
from bwscanner.logger import setup_logging, log
from bwscanner.attacher import start_tor, update_tor_config, FETCH_ALL_DESCRIPTOR_OPTIONS
from bwscanner.measurement import BwScan
from bwscanner.aggregate import write_aggregate_data


BWSCAN_VERSION = '0.0.1'


def connect_to_tor(launch_tor, circuit_build_timeout, circuit_idle_timeout):
"""
Launch or connect to a Tor instance
Configure Tor with the passed options and return a Deferred
"""
# Options for spawned or running Tor to load the correct descriptors.
tor_options = {
'LearnCircuitBuildTimeout': 0, # Disable adaptive circuit timeouts.
'CircuitBuildTimeout': circuit_build_timeout,
'CircuitIdleTimeout': circuit_idle_timeout,
'UseEntryGuards': 0, # Disable UseEntryGuards to avoid PathBias warnings.
}

def tor_status(tor):
log.info("Connected successfully to Tor.")
return tor

if launch_tor:
log.info("Spawning a new Tor instance.")
c = TorConfig()
# Update Tor config before launching a new Tor.
c.config.update(tor_options)
c.config.update(FETCH_ALL_DESCRIPTOR_OPTIONS)
tor = start_tor(c)

else:
log.info("Trying to connect to a running Tor instance.")
tor = build_local_tor_connection(reactor)
# Update the Tor config on a running Tor.
tor.addCallback(update_tor_config, tor_options)
tor.addCallback(update_tor_config, FETCH_ALL_DESCRIPTOR_OPTIONS)

tor.addCallback(tor_status)
return tor


class ScanInstance(object):
"""
Store the configuration and state for the CLI tool.
Expand Down
12 changes: 6 additions & 6 deletions test/template.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,21 @@
import random

from twisted.internet import defer, reactor
from twisted.internet.endpoints import TCP4ClientEndpoint
from twisted.trial import unittest
from txtorcon.torstate import build_tor_connection

from bwscanner import circuit
from bwscanner.attacher import SOCKSClientStreamAttacher
from bwscanner.attacher import SOCKSClientStreamAttacher, connect_to_tor


class TorTestCase(unittest.TestCase):

@defer.inlineCallbacks
def setUp(self):
self.tor = yield build_tor_connection(
TCP4ClientEndpoint(reactor, 'localhost', int(
os.environ.get('CHUTNEY_CONTROL_PORT'))))
self.tor = yield connect_to_tor(
launch_tor=False,
circuit_build_timeout=30,
circuit_idle_timeout=30,
control_port=int(os.environ.get('CHUTNEY_CONTROL_PORT')))

self.attacher = SOCKSClientStreamAttacher(self.tor)
yield self.tor.set_attacher(self.attacher, reactor)
Expand Down
2 changes: 0 additions & 2 deletions test/test_measurement.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
from twisted.web.resource import Resource
from twisted.web.server import Site
from txtorcon.util import available_tcp_port
from bwscanner.attacher import update_tor_config, FETCH_ALL_DESCRIPTOR_OPTIONS
from bwscanner.measurement import BwScan
from test.template import TorTestCase
from tempfile import mkdtemp
Expand All @@ -18,7 +17,6 @@ class TestBwscan(TorTestCase):
@defer.inlineCallbacks
def setUp(self):
yield super(TestBwscan, self).setUp()
yield update_tor_config(self.tor, FETCH_ALL_DESCRIPTOR_OPTIONS)

class DummyResource(Resource):
isLeaf = True
Expand Down

0 comments on commit eff297d

Please sign in to comment.