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

Commit 08bf6ad

Browse files
committed
add fetch method
1 parent 3427727 commit 08bf6ad

4 files changed

Lines changed: 18 additions & 95 deletions

File tree

bwscanner/fetcher.py

Lines changed: 8 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,18 @@
11
import warnings
22
import hashlib
33

4-
from twisted.internet import interfaces, reactor, defer, protocol
4+
from twisted.internet import reactor, defer, protocol
55
from twisted.internet.endpoints import TCP4ClientEndpoint
6-
from twisted.web.client import (SchemeNotSupported, Agent, BrowserLikePolicyForHTTPS,
7-
ResponseDone, PotentialDataLoss, PartialDownloadError)
8-
from txsocksx.client import SOCKS5ClientFactory
9-
from txsocksx.tls import TLSWrapClientEndpoint
10-
from zope.interface import implementer
6+
from twisted.web.client import (ResponseDone, PotentialDataLoss, PartialDownloadError)
117

128
from bwscanner.logger import log
139

10+
def fetch(tor_state, path, url):
11+
d = tor_state.build_circuit(path, False)
12+
sport = get_tor_socks_endpoint(tor_state)
13+
d.addCallback(lambda c: c.when_built())
14+
d.addCallback(lambda c: c.web_agent(reactor, sport))
15+
return d.addCallback(lambda a: a.request("GET", url))
1416

1517
def get_tor_socks_endpoint(tor_state):
1618
proxy_endpoint = tor_state.protocol.get_conf("SocksPort")
@@ -31,78 +33,6 @@ def extract_port_value(result):
3133
return proxy_endpoint
3234

3335

34-
@implementer(interfaces.IStreamClientEndpoint)
35-
class OnionRoutedTCPClientEndpoint(object):
36-
def __init__(self, host, port, state, path):
37-
"""
38-
@param reactor: An L{IReactorTCP} provider
39-
40-
@param host: A hostname, used when connecting
41-
@type host: str
42-
43-
@param port: The port number, used when connecting
44-
@type port: int
45-
46-
@param path: A list of relay identities.
47-
@type path: list
48-
49-
This endpoint will be routed through Tor over a circuit
50-
defined by path.
51-
"""
52-
self.host = host
53-
self.port = port
54-
self.path = path
55-
self.state = state
56-
57-
self.tor_socks_endpoint = get_tor_socks_endpoint(state)
58-
59-
def connect(self, protocol_factory):
60-
"""
61-
Implements L{IStreamClientEndpoint.connect} to connect via TCP, after
62-
SOCKS5 negotiation and Tor circuit construction is done.
63-
"""
64-
proxy_factory = SOCKS5ClientFactory(self.host, self.port, protocol_factory)
65-
self.tor_socks_endpoint.addCallback(lambda end: end.connect(proxy_factory))
66-
67-
def _create_circ(proto):
68-
hp = proto.transport.getHost()
69-
d = self.state._attacher.create_circuit(hp.host, hp.port, self.path)
70-
d.addErrback(proxy_factory.deferred.errback)
71-
return proxy_factory.deferred
72-
73-
return self.tor_socks_endpoint.addCallback(_create_circ)
74-
75-
76-
class OnionRoutedAgent(Agent):
77-
_tlsWrapper = TLSWrapClientEndpoint
78-
_policyForHTTPS = BrowserLikePolicyForHTTPS
79-
80-
def __init__(self, *args, **kw):
81-
self.path = kw.pop('path')
82-
self.state = kw.pop('state')
83-
super(OnionRoutedAgent, self).__init__(*args, **kw)
84-
85-
def _getEndpoint(self, parsedURI, host=None, port=None):
86-
try:
87-
host, port = parsedURI.host, parsedURI.port
88-
scheme = parsedURI.scheme
89-
except AttributeError:
90-
scheme = parsedURI
91-
if scheme not in ('http', 'https'):
92-
raise SchemeNotSupported('unsupported scheme', scheme)
93-
endpoint = OnionRoutedTCPClientEndpoint(host, port, self.state,
94-
self.path)
95-
if scheme == 'https':
96-
if hasattr(self, '_wrapContextFactory'):
97-
tls_policy = self._wrapContextFactory(host, port)
98-
elif hasattr(self, '_policyForHTTPS'):
99-
tls_policy = self._policyForHTTPS().creatorForNetloc(host, port)
100-
else:
101-
raise NotImplementedError("Cannot create a TLS validation policy.")
102-
endpoint = self._tlsWrapper(tls_policy, endpoint)
103-
return endpoint
104-
105-
10636
class hashingReadBodyProtocol(protocol.Protocol):
10737
"""
10838
Protocol that collects data sent to it and hashes it.

bwscanner/measurement.py

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,7 @@
77

88
from bwscanner.logger import log
99
from bwscanner.circuit import TwoHop
10-
from bwscanner.fetcher import OnionRoutedAgent
11-
from bwscanner.fetcher import get_tor_socks_endpoint, hashingReadBody
10+
from bwscanner.fetcher import get_tor_socks_endpoint, hashingReadBody, fetch
1211
from bwscanner.writer import ResultSink
1312

1413
# defer.setDebugging(True)
@@ -160,10 +159,7 @@ def gotResult(result):
160159
return result
161160
deferred.addBoth(gotResult)
162161

163-
d = self.state.build_circuit(path, False)
164-
d.addCallback(lambda c: c.when_built())
165-
d.addCallback(lambda c: c.web_agent(self.clock, self.socks))
166-
d.addCallback(lambda a: a.request("GET", url))
162+
d = fetch(self.state, path, url)
167163
d.addCallback(hashingReadBody)
168164
timeoutDeferred(d, self.request_timeout)
169165
d.addCallbacks(get_circuit_bw)

scripts/exitip.py

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,7 @@
22
import json
33
import re
44
import sys
5-
from bwscanner.attacher import SOCKSClientStreamAttacher, start_tor
6-
from bwscanner.circuit import ExitScan
7-
from bwscanner.fetcher import OnionRoutedAgent
5+
from bwscanner.attacher import start_tor
86
from twisted.internet import defer, reactor, task
97
from twisted.python import log
108
from twisted.web.client import readBody
@@ -57,20 +55,20 @@ def pop(circuits):
5755
def shutdown(ignore):
5856
reactor.stop()
5957

60-
def add_attacher(state):
61-
state.set_attacher(SOCKSClientStreamAttacher(state), reactor)
62-
return state
63-
6458
def setup_failed(failure):
6559
log.err(failure)
6660

6761
def save_results(result, outfile):
6862
outfile.write(json.dumps(dict([r[1] for r in result if r[1] != None])))
6963

64+
@defer.inlineCallbacks
65+
def socks(state):
66+
s = yield get_tor_socks_endpoint(state)
67+
defer.returnValue(s)
68+
7069
def main():
7170
log.startLogging(sys.stdout)
7271
tor = start_tor(TorConfig())
73-
tor.addCallback(add_attacher)
7472
tor.addCallback(run_scan)
7573
tor.addErrback(log.err)
7674
tor.addBoth(shutdown)

test/test_listener.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
from txtorcon.util import available_tcp_port
88

99
from bwscanner.listener import CircuitEventListener, StreamBandwidthListener
10-
from bwscanner.fetcher import OnionRoutedAgent
10+
from bwscanner.fetcher import fetch
1111
from test.template import TorTestCase
1212

1313
import random
@@ -133,9 +133,8 @@ def test_circ_avg_bw(self):
133133
def do_fetch(self):
134134
time_start = time.time()
135135
path = self.random_path()
136-
agent = OnionRoutedAgent(reactor, path=path, state=self.tor_state)
137136
url = "http://127.0.0.1:{}".format(self.port)
138-
request = yield agent.request("GET", url)
137+
request = yield fetch(self.tor_state, path, url)
139138
body = yield readBody(request)
140139
assert len(body) == self.fetch_size
141140
circ = [c for c in self.tor_state.circuits.values() if c.path == path][0]

0 commit comments

Comments
 (0)