def main(reactor): tor = yield txtorcon.connect( reactor, UNIXClientEndpoint(reactor, "/var/run/tor/control") ) print("Connected to Tor version {}".format(tor.version)) url = 'https://www.torproject.org:443' print("Downloading {}".format(url)) resp = yield treq.get(url, agent=tor.web_agent()) print(" {} bytes".format(resp.length)) data = yield resp.text() print("Got {} bytes:\n{}\n[...]{}".format( len(data), data[:120], data[-120:], )) print("Creating a circuit") state = yield tor.create_state() circ = yield state.build_circuit() yield circ.when_built() print(" path: {}".format(" -> ".join([r.ip for r in circ.path]))) print("Downloading meejah's public key via above circuit...") config = yield tor.get_config() resp = yield treq.get( 'https://meejah.ca/meejah.asc', agent=circ.web_agent(reactor, config.socks_endpoint(reactor)), ) data = yield resp.text() print(data)
def main(reactor): tor = yield txtorcon.connect( reactor, UNIXClientEndpoint(reactor, "/var/run/tor/control")) print("Connected to Tor version {}".format(tor.version)) url = 'https://www.torproject.org:443' print("Downloading {}".format(url)) resp = yield treq.get(url, agent=tor.web_agent()) print(" {} bytes".format(resp.length)) data = yield resp.text() print("Got {} bytes:\n{}\n[...]{}".format( len(data), data[:120], data[-120:], )) print("Creating a circuit") state = yield tor.create_state() circ = yield state.build_circuit() yield circ.when_built() print(" path: {}".format(" -> ".join([r.ip for r in circ.path]))) print("Downloading meejah's public key via above circuit...") resp = yield treq.get( 'https://meejah.ca/meejah.asc', agent=circ.web_agent(reactor, tor.config.socks_endpoint(reactor)), ) data = yield resp.text() print(data)
def main(reactor): tor = yield txtorcon.connect( reactor, endpoints.TCP4ClientEndpoint(reactor, "localhost", 9251), ) ep = tor.create_authenticated_onion_endpoint( 80, auth=AuthBasic([ ("alice", "0GaFhnbunp0TxZuBhejhxg"), "bob", ]), ) def on_progress(percent, tag, msg): print('%03d: %s' % (percent, msg)) txtorcon.IProgressProvider(ep).add_progress_listener(on_progress) print("Note: descriptor upload can take several minutes") port = yield ep.listen(server.Site(Simple())) print("Private key:\n{}".format(port.getHost().onion_key)) hs = port.onion_service print("Clients:") for name in hs.client_names(): print(" {}: username={} token={}".format( hs.get_client(name).hostname, name, hs.get_client(name).auth_token), ) print("hs {}".format(hs)) print(type(hs)) print(dir(hs)) yield defer.Deferred() # wait forever
def listen(self, proto_factory): # we don't care which local TCP port we listen on, but # we do need to know it local_ep = TCP4ServerEndpoint(reactor, 0, interface=u"127.0.0.1") target_port = yield local_ep.listen(proto_factory) tor = yield txtorcon.connect( reactor, tor_control_ep, ) # create and add the service hs = txtorcon.EphemeralHiddenService( ports=["{} 127.0.0.1:{}".format(port, target_port.getHost().port)], key_blob_or_type=private_key if private_key else "NEW:BEST", ) log.info("Uploading descriptors can take more than 30s") yield hs.add_to_tor(tor.protocol) # if it's new, store our private key # XXX better "if private_key is None"? if not exists(private_key_fname): with open(private_key_fname, 'w') as f: f.write(hs.private_key) log.info("Wrote private key to '{fname}'", fname=private_key_fname) addr = txtorcon.TorOnionAddress(hs.hostname, port) log.info( "Listening on Tor onion service {addr.onion_uri}:{addr.onion_port}" " with local port {local_port}", addr=addr, local_port=target_port.getHost().port, ) defer.returnValue(addr)
def main(reactor): # For the "single_hop=True" below to work, the Tor we're # connecting to must have the following options set: # SocksPort 0 # HiddenServiceSingleHopMode 1 # HiddenServiceNonAnonymousMode 1 tor = yield txtorcon.connect( reactor, endpoints.TCP4ClientEndpoint(reactor, "localhost", 9351), ) if False: ep = tor.create_onion_endpoint( 80, version=3, single_hop=True, ) else: ep = endpoints.serverFromString(reactor, "onion:80:version=3:singleHop=true") def on_progress(percent, tag, msg): print('%03d: %s' % (percent, msg)) txtorcon.IProgressProvider(ep).add_progress_listener(on_progress) port = yield ep.listen(server.Site(Simple())) print("Private key:\n{}".format(port.getHost().onion_key)) hs = port.onion_service print("Site on http://{}".format(hs.hostname)) yield defer.Deferred() # wait forever
def main(reactor): # use port 9051 for system tor instances, or: # ep = UNIXClientEndpoint(reactor, '/var/run/tor/control') # ep = UNIXClientEndpoint(reactor, '/var/run/tor/control') ep = TCP4ClientEndpoint(reactor, '127.0.0.1', default_control_port()) tor = yield txtorcon.connect(reactor, ep) print("Connected to {tor} via localhost:{port}".format( tor=tor, port=default_control_port(), )) # create a web.Agent that will talk via Tor. If the socks port # given isn't yet configured, this will do so. It may also be # None, which means "the first configured SOCKSPort" # agent = tor.web_agent(u'9999') agent = tor.web_agent() uri = b'http://surely-this-has-not-been-registered-and-is-invalid.com' uri = b'https://www.torproject.org' uri = b'http://timaq4ygg2iegci7.onion/' # txtorcon documentation print("Downloading {}".format(uri)) resp = yield agent.request(b'GET', uri) print("Response has {} bytes".format(resp.length)) body = yield readBody(resp) print("received body ({} bytes)".format(len(body))) print("{}\n[...]\n{}\n".format(body[:200], body[-200:]))
def test_connect_defaults(self, fake_cfg, fake_unix, fake_tcp): """ happy-path test, ensuring there are no exceptions """ transport = Mock() reactor = FakeReactor(self, transport, lambda: None) yield connect(reactor)
def main(reactor): tor = yield txtorcon.connect( reactor, endpoints.TCP4ClientEndpoint(reactor, "localhost", 9251), ) ep = tor.create_authenticated_onion_endpoint( 80, auth=AuthBasic([ ("alice", "0GaFhnbunp0TxZuBhejhxg"), "bob", ]), ) def on_progress(percent, tag, msg): print('%03d: %s' % (percent, msg)) txtorcon.IProgressProvider(ep).add_progress_listener(on_progress) print("Note: descriptor upload can take several minutes") port = yield ep.listen(server.Site(Simple())) print("Private key:\n{}".format(port.getHost().onion_key)) hs = port.onion_service print("Clients:") for name in hs.client_names(): print( " {}: username={} token={}".format( hs.get_client(name).hostname, name, hs.get_client(name).auth_token), ) print("hs {}".format(hs)) print(type(hs)) print(dir(hs)) yield defer.Deferred() # wait forever
def test_connect_provide_endpoint(self, fake_cfg): transport = Mock() reactor = FakeReactor(self, transport, lambda: None) ep = Mock() with self.assertRaises(ValueError) as ctx: yield connect(reactor, ep) self.assertTrue('IStreamClientEndpoint' in str(ctx.exception))
def listen(self, proto_factory): # we don't care which local TCP port we listen on, but # we do need to know it local_ep = TCP4ServerEndpoint(reactor, 0, interface=u"127.0.0.1") target_port = yield local_ep.listen(proto_factory) tor = yield txtorcon.connect( reactor, tor_control_ep, ) log.info("Creating onion service (descriptor upload can take 30s or more)") hs = yield tor.create_onion_service( ports=[ (port, target_port.getHost().port), ], private_key=private_key, version=version, ) # if it's new, store our private key # XXX better "if private_key is None"? if not exists(private_key_fname): with open(private_key_fname, 'w') as f: f.write(hs.private_key) log.info("Wrote private key to '{fname}'", fname=private_key_fname) log.info( "Listening on Tor onion service {hs.hostname} " " with ports: {ports}", hs=hs, ports=" ".join(hs.ports), ) defer.returnValue(target_port)
def start_tor(self): """ This function executes the workflow of starting the hidden service and returning its hostname """ self.info_callback("Attempting to start onion service on port: {} " "...".format(self.virtual_port)) if self.hidden_service_dir == "": if str(self.tor_control_host).startswith('unix:'): control_endpoint = UNIXClientEndpoint( reactor, self.tor_control_host[5:]) else: control_endpoint = TCP4ClientEndpoint(reactor, self.tor_control_host, self.tor_control_port) d = txtorcon.connect(reactor, control_endpoint) d.addCallback(self.create_onion_ep) d.addErrback(self.setup_failed) # TODO: add errbacks to the next two calls in # the chain: d.addCallback(self.onion_listen) d.addCallback(self.print_host) else: ep = "onion:" + str(self.virtual_port) + ":localPort=" ep += str(self.serving_port) # endpoints.TCPHiddenServiceEndpoint creates version 2 by # default for backwards compat (err, txtorcon needs to update that ...) ep += ":version=3" ep += ":hiddenServiceDir=" + self.hidden_service_dir onion_endpoint = serverFromString(reactor, ep) d = onion_endpoint.listen(self.proto_factory) d.addCallback(self.print_host_filesystem)
def start_tor(self): """ This function executes the workflow of starting the hidden service. """ if not self.local_port: control_host = jm_single().config.get("PAYJOIN", "tor_control_host") control_port = int(jm_single().config.get("PAYJOIN", "tor_control_port")) if str(control_host).startswith('unix:'): control_endpoint = UNIXClientEndpoint(reactor, control_host[5:]) else: control_endpoint = TCP4ClientEndpoint(reactor, control_host, control_port) d = txtorcon.connect(reactor, control_endpoint) d.addCallback(self.create_onion_ep) d.addErrback(self.setup_failed) else: d = Deferred() d.callback(None) d.addCallback(self.create_onion_ep) # TODO: add errbacks to the next two calls in # the chain: d.addCallback(self.onion_listen) d.addCallback(self.print_host)
def main(reactor): # use port 9051 for system tor instances, or: # ep = UNIXClientEndpoint(reactor, '/var/run/tor/control') ep = TCP4ClientEndpoint(reactor, '127.0.0.1', default_control_port()) tor = yield txtorcon.connect(reactor, ep) print("Connected:", tor) state = yield tor.create_state() socks = tor.config.socks_endpoint(reactor) # create a custom circuit; in this case we're just letting Tor # decide the path but you *can* select a path (again: for advanced # use cases that will probably de-anonymize you) circ = yield state.build_circuit() print("Building a circuit:", circ) # at this point, the circuit will be "under way" but may not yet # be in BUILT state -- and hence usable. So, we wait. yield circ.when_built() print("Circuit is ready:", circ) if True: # create a web.Agent that will use this circuit (or fail) agent = circ.web_agent(reactor, socks) uri = 'https://www.torproject.org' print("Downloading {}".format(uri)) resp = yield agent.request('GET', uri) print("Response has {} bytes".format(resp.length)) body = yield readBody(resp) print("received body ({} bytes)".format(len(body))) print("{}\n[...]\n{}\n".format(body[:200], body[-200:])) if True: # make a plain TCP connection to a thing ep = circ.stream_via(reactor, 'torproject.org', 80) d = Deferred() class ToyWebRequestProtocol(Protocol): def connectionMade(self): print("Connected via {}".format(self.transport.getHost())) self.transport.write('GET http://torproject.org/ HTTP/1.1\r\n' 'Host: torproject.org\r\n' '\r\n') def dataReceived(self, d): print(" received {} bytes".format(len(d))) def connectionLost(self, reason): print("disconnected") d.callback(reason) proto = yield ep.connect(Factory.forProtocol(ToyWebRequestProtocol)) yield d print("All done, closing the circuit") yield circ.close()
def main(reactor): control_ep = clientFromString(reactor, "tcp:localhost:9051") tor = yield txtorcon.connect(reactor, control_ep) for domain in ['torproject.org', 'meejah.ca']: print("Looking up '{}' via Tor".format(domain)) ans = yield tor.dns_resolve(domain) print("...got answer: {}".format(ans)) print("Doing PTR on {}".format(ans)) ans = yield tor.dns_resolve_ptr(ans) print("...got answer: {}".format(ans))
def get_tor(reactor): # TODO: Add launch option? tor = None logging.debug("Looking for a running Tor daemon...") try: tor = yield txtorcon.connect(reactor) except RuntimeError: logging.debug("Could not connect to a running Tor daemon.") if tor: logging.debug("Connected to Tor daemon (%s)", tor.version) return tor
def main(reactor): # a simple Web site; could be any other listening service of course res = resource.Resource() res.putChild( b'', static.Data("<html>Hello, onion-service world!</html>", 'text/html')) def on_progress(percent, tag, msg): print('%03d: %s' % (percent, msg)) # We are using launch() here instead of connect() because # filesystem services are very picky about the permissions and # ownership of the directories involved. If you *do* want to # connect to e.g. a system service or Tor Browser Bundle, it's way # more likely to work to use Ephemeral services tor = yield txtorcon.connect( reactor, endpoints.TCP4ClientEndpoint(reactor, "localhost", txtorcon.util.default_control_port()), ) # NOTE: you should put these somewhere you've thought about more # and made proper permissions for the parent directory, etc. A # good choice for a system-wide Tor is /var/lib/tor/<whatever> # The parent directory must be mode 700 os.mkdir("hs_parent") os.chmod("hs_parent", 0o700) hs_dir = './hs_parent/hs_dir' print("Creating stealth-authenticated hidden-service, keys in: {}".format( hs_dir)) ep = tor.create_authenticated_filesystem_onion_endpoint( 80, hs_dir=hs_dir, auth=txtorcon.AuthStealth(['alice', 'bob']), group_readable=True, ) print("Note: descriptor upload can take several minutes") txtorcon.IProgressProvider(ep).add_progress_listener(on_progress) port = yield ep.listen(server.Site(res)) hs = port.getHost().onion_service for name in hs.client_names(): client = hs.get_client(name) print(" {}: {}".format(name, client.hostname)) print(" auth token: {}".format(client.auth_token)) print(" private key: {}..".format(client.private_key[:40])) print(" HidServAuth {} {}".format(client.hostname, client.auth_token)) yield tor.protocol.on_disconnect print("disconnected")
def _startup(reactor): ep = clientFromString(reactor, cfg.connect) tor = yield txtorcon.connect(reactor, ep) if cfg.info: info = yield tor.proto.get_info('version', 'status/version/current', 'dormant') click.echo('Connected to a Tor version "{version}" (status: ' '{status/version/current}).\n'.format(**info)) yield defer.maybeDeferred(cmd, reactor, cfg, tor, *args, **kwargs)
def main(reactor): control_ep = clientFromString(reactor, "tcp:localhost:9051") tor = yield txtorcon.connect(reactor, control_ep) print("Connected to a Tor version={version}".format( version=tor.protocol.version, )) state = yield tor.create_state() yield state.set_attacher(PortFilterAttacher(state), reactor) print("Existing streams:") for s in state.streams.values(): print(" ", s) yield Deferred()
def main(reactor): # a simple Web site; could be any other listening service of course res = resource.Resource() res.putChild( b'', static.Data("<html>Hello, onion-service world!</html>", 'text/html') ) def on_progress(percent, tag, msg): print('%03d: %s' % (percent, msg)) # We are using launch() here instead of connect() because # filesystem services are very picky about the permissions and # ownership of the directories involved. If you *do* want to # connect to e.g. a system service or Tor Browser Bundle, it's way # more likely to work to use Ephemeral services tor = yield txtorcon.connect( reactor, endpoints.TCP4ClientEndpoint(reactor, "localhost", txtorcon.util.default_control_port()), ) # NOTE: you should put these somewhere you've thought about more # and made proper permissions for the parent directory, etc. A # good choice for a system-wide Tor is /var/lib/tor/<whatever> # The parent directory must be mode 700 os.mkdir("hs_parent") os.chmod("hs_parent", 0o700) hs_dir = './hs_parent/hs_dir' print("Creating stealth-authenticated hidden-service, keys in: {}".format(hs_dir)) ep = tor.create_authenticated_filesystem_onion_endpoint( 80, hs_dir=hs_dir, auth=txtorcon.AuthStealth(['alice', 'bob']), group_readable=True, ) print("Note: descriptor upload can take several minutes") txtorcon.IProgressProvider(ep).add_progress_listener(on_progress) port = yield ep.listen(server.Site(res)) hs = port.getHost().onion_service for name in hs.client_names(): client = hs.get_client(name) print(" {}: {}".format(name, client.hostname)) print(" auth token: {}".format(client.auth_token)) print(" private key: {}..".format(client.private_key[:40])) print(" HidServAuth {} {}".format(client.hostname, client.auth_token)) yield tor.protocol.on_disconnect print("disconnected")
def main(reactor): ep = TCP4ClientEndpoint(reactor, "localhost", 9051) # or (e.g. on Debian): # ep = UNIXClientEndpoint(reactor, "/var/run/tor/control") tor = yield txtorcon.connect(reactor, ep) print("Connected to Tor {version}".format(version=tor.protocol.version)) state = yield tor.create_state() # or: # state = yield txtorcon.TorState.from_protocol(tor.protocol) print("Tor state created. Circuits:") for circuit in state.circuits.values(): print(" {circuit.id}: {circuit.path}".format(circuit=circuit))
def test_connect_multiple_endpoints_error(self, fake_cfg): transport = Mock() reactor = FakeReactor(self, transport, lambda: None) ep0 = Mock() def boom(*args, **kw): raise RuntimeError("the bad thing") ep0.connect = boom directlyProvides(ep0, IStreamClientEndpoint) with self.assertRaises(RuntimeError) as ctx: yield connect(reactor, ep0) self.assertEqual("the bad thing", str(ctx.exception))
def main(reactor): ep = UNIXClientEndpoint(reactor, '/var/run/tor/control') tor = yield txtorcon.connect(reactor, ep) def log(msg): print(msg) print("Connected to a Tor version", tor.protocol.version) for event in ['INFO', 'NOTICE', 'WARN', 'ERR']: tor.protocol.add_event_listener(event, log) is_current = yield tor.protocol.get_info('status/version/current') version = yield tor.protocol.get_info('version') print("Version '{}', is_current={}".format(version, is_current['status/version/current'])) yield defer.Deferred()
def test_connect_success(self, fake_cfg): transport = Mock() reactor = FakeReactor(self, transport, lambda: None) torcfg = Mock() fake_cfg.from_protocol = Mock(return_value=torcfg) ep0 = Mock() proto = object() torcfg.protocol = proto ep0.connect = Mock(return_value=proto) directlyProvides(ep0, IStreamClientEndpoint) ans = yield connect(reactor, [ep0]) self.assertEqual(ans.config, torcfg) self.assertEqual(ans.protocol, proto)
def main(reactor): # this will connect to TBB control_ep = endpoints.TCP4ClientEndpoint(reactor, 'localhost', 9051) tor = yield txtorcon.connect(reactor, control_ep) print("tor {}".format(tor)) state = yield tor.create_state() print("state {}".format(state)) # run all stream-attachments through our thing ns_service = _Attacher(reactor, tor) yield state.set_attacher(ns_service, reactor) # wait forever yield defer.Deferred()
def get_tor(reactor): # TODO: Add launch option? tor = None features_settings = settings.get("features") if features_settings: tor_setting = features_settings.get("tor") if tor_setting and tor_setting.lower() == "false": return tor logging.debug("Looking for a running Tor daemon...") try: tor = yield txtorcon.connect(reactor) except RuntimeError: logging.debug("Could not connect to a running Tor daemon.") if tor: logging.debug("Connected to Tor daemon (%s)", tor.version) return tor
def main(reactor): ep = UNIXClientEndpoint(reactor, '/var/run/tor/control') tor = yield txtorcon.connect(reactor, ep) def log(msg): print msg print "Connected to a Tor version", tor.protocol.version for event in ['INFO', 'NOTICE', 'WARN', 'ERR']: tor.protocol.add_event_listener(event, log) is_current = yield tor.protocol.get_info('status/version/current') version = yield tor.protocol.get_info('version') print("Version '{}', is_current={}".format( version, is_current['status/version/current'])) yield defer.Deferred()
def main(reactor): ep = TCP4ClientEndpoint(reactor, "localhost", 9051) # or (e.g. on Debian): # ep = UNIXClientEndpoint(reactor, "/var/run/tor/control") tor = yield txtorcon.connect(reactor, ep) print("Connected to Tor {version}".format(version=tor.protocol.version)) d = tor.protocol.when_disconnected() def its_gone(value): print("Connection gone") d.addCallback(its_gone) tor.protocol.transport.loseConnection() yield d
def main(reactor): tor = yield txtorcon.connect( reactor, endpoints.TCP4ClientEndpoint(reactor, "localhost", 9251), ) print(default_control_port()) ep = tor.create_filesystem_onion_endpoint(80, "./test_prop224_service", version=3) def on_progress(percent, tag, msg): print('%03d: %s' % (percent, msg)) txtorcon.IProgressProvider(ep).add_progress_listener(on_progress) print("Note: descriptor upload can take several minutes") port = yield ep.listen(server.Site(Simple())) print("Site listening: {}".format(port.getHost())) print("Private key:\n{}".format(port.getHost().onion_key)) yield defer.Deferred() # wait forever
def main(reactor): """ Close all open streams and circuits in the Tor we connect to """ control_ep = UNIXClientEndpoint(reactor, '/var/run/tor/control') tor = yield txtorcon.connect(reactor, control_ep) state = yield tor.create_state() print("Closing all circuits:") for circuit in list(state.circuits.values()): path = '->'.join(map(lambda r: r.id_hex, circuit.path)) print("Circuit {} through {}".format(circuit.id, path)) for stream in circuit.streams: print(" Stream {} to {}".format(stream.id, stream.target_host)) yield stream.close() print(" closed") yield circuit.close() print("closed") yield tor.quit()
def main(reactor): ep = TCP4ClientEndpoint(reactor, '127.0.0.1', default_control_port()) # ep = UNIXClientEndpoint(reactor, '/var/run/tor/control') tor = yield txtorcon.connect(reactor, ep) print("Connected:", tor) resp = yield treq.get( 'https://www.torproject.org:443', agent=tor.web_agent(), ) print("Retrieving {} bytes".format(resp.length)) data = yield resp.text() print("Got {} bytes:\n{}\n[...]{}".format( len(data), data[:120], data[-120:], ))
def main(reactor): tor = yield txtorcon.connect(reactor) or_nickname = "moria1" print("Trying to get decriptor information about '{}'".format(or_nickname)) # If the fingerprint is used in place of nickname then, desc/id/<OR identity> # should be used. try: descriptor_info = yield tor.protocol.get_info('desc/name/' + or_nickname) except txtorcon.TorProtocolError: print("No information found. Enable descriptor downloading by setting:") print(" UseMicrodescritors 0") print("In your torrc") raise SystemExit(1) descriptor_info = descriptor_info.values()[0] relay_info = RelayDescriptor(descriptor_info) print("The relay's fingerprint is: {}".format(relay_info.fingerprint)) print("Time in UTC when the descriptor was made: {}".format(relay_info.published))
def main(reactor): tor = yield txtorcon.connect( reactor, endpoints.TCP4ClientEndpoint(reactor, "localhost", 9251), ) print("{}".format(tor)) hs = yield tor.create_filesystem_onion_service( [(80, 8787)], "./prop224_hs", version=3, ) print("{}".format(hs)) print(dir(hs)) ep = endpoints.TCP4ServerEndpoint(reactor, 8787, interface="localhost") port = yield ep.listen(server.Site(Simple())) print("Site listening: {}".format(hs.hostname)) print("Private key:\n{}".format(hs.private_key)) yield defer.Deferred() # wait forever
def start_tor(self): """ This function executes the workflow of starting the hidden service and returning its hostname """ self.info_callback("Attempting to start onion service on port: {} " "...".format(self.port)) if str(self.tor_control_host).startswith('unix:'): control_endpoint = UNIXClientEndpoint(reactor, self.tor_control_host[5:]) else: control_endpoint = TCP4ClientEndpoint(reactor, self.tor_control_host, self.tor_control_port) d = txtorcon.connect(reactor, control_endpoint) d.addCallback(self.create_onion_ep) d.addErrback(self.setup_failed) # TODO: add errbacks to the next two calls in # the chain: d.addCallback(self.onion_listen) d.addCallback(self.print_host)
def test_connect_multiple_endpoints_many_errors(self, fake_cfg): transport = Mock() reactor = FakeReactor(self, transport, lambda: None) ep0 = Mock() ep1 = Mock() def boom0(*args, **kw): raise RuntimeError("the bad thing") def boom1(*args, **kw): raise RuntimeError("more sadness") ep0.connect = boom0 ep1.connect = boom1 directlyProvides(ep0, IStreamClientEndpoint) directlyProvides(ep1, IStreamClientEndpoint) with self.assertRaises(RuntimeError) as ctx: yield connect(reactor, [ep0, ep1]) self.assertTrue("the bad thing" in str(ctx.exception)) self.assertTrue("more sadness" in str(ctx.exception))
def listen(self, proto_factory): # we don't care which local TCP port we listen on, but # we do need to know it local_ep = TCP4ServerEndpoint(reactor, 0, interface=u"127.0.0.1") target_port = yield local_ep.listen(proto_factory) tor = yield txtorcon.connect( reactor, tor_control_ep, ) # create and add the service hs = txtorcon.EphemeralHiddenService( ports=[ "{} 127.0.0.1:{}".format(port, target_port.getHost().port) ], key_blob_or_type=private_key if private_key else "NEW:BEST", ) log.info("Uploading descriptors can take more than 30s") yield hs.add_to_tor(tor.protocol) # if it's new, store our private key # XXX better "if private_key is None"? if not exists(private_key_fname): with open(private_key_fname, 'w') as f: f.write(hs.private_key) log.info("Wrote private key to '{fname}'", fname=private_key_fname) addr = txtorcon.TorOnionAddress(hs.hostname, port) log.info( "Listening on Tor onion service {addr.onion_uri}:{addr.onion_port}" " with local port {local_port}", addr=addr, local_port=target_port.getHost().port, ) defer.returnValue(addr)
def main(reactor): tor = yield txtorcon.connect( reactor, endpoints.TCP4ClientEndpoint(reactor, "localhost", 9051), ) unix_p = abspath('./web_socket') ep = endpoints.UNIXServerEndpoint(reactor, unix_p) port = yield ep.listen(server.Site(Simple())) def on_progress(percent, tag, msg): print('%03d: %s' % (percent, msg)) print("Note: descriptor upload can take several minutes") onion = yield tor.create_onion_service( ports=[(80, 'unix:{}'.format(unix_p))], version=3, # or try version=2 if you have an older Tor progress=on_progress, ) print("Private key:\n{}".format(onion.private_key)) print("{}".format(onion.hostname)) yield defer.Deferred() # wait forever
def main(reactor): tor = yield txtorcon.connect(reactor) or_nickname = "moria1" print("Trying to get decriptor information about '{}'".format(or_nickname)) # If the fingerprint is used in place of nickname then, desc/id/<OR identity> # should be used. try: descriptor_info = yield tor.protocol.get_info('desc/name/' + or_nickname) except txtorcon.TorProtocolError: print( "No information found. Enable descriptor downloading by setting:") print(" UseMicrodescritors 0") print("In your torrc") raise SystemExit(1) descriptor_info = descriptor_info.values()[0] relay_info = RelayDescriptor(descriptor_info) print("The relay's fingerprint is: {}".format(relay_info.fingerprint)) print("Time in UTC when the descriptor was made: {}".format( relay_info.published))
def main(reactor): log.startLogging(sys.stdout) tor = yield txtorcon.connect(reactor) log.msg('Connected to a Tor version %s' % tor.protocol.version) state = yield tor.create_state() listener = StreamCircuitLogger() state.add_circuit_listener(listener) state.add_stream_listener(listener) tor.protocol.add_event_listener('STATUS_GENERAL', log.msg) tor.protocol.add_event_listener('STATUS_SERVER', log.msg) tor.protocol.add_event_listener('STATUS_CLIENT', log.msg) log.msg('Existing state when we connected:') for s in state.streams.values(): log_stream(s) log.msg('Existing circuits:') for c in state.circuits.values(): log_circuit(c) yield Deferred()
def main(reactor): # use port 9051 for system tor instances, or: # ep = UNIXClientEndpoint(reactor, '/var/run/tor/control') # ep = UNIXClientEndpoint(reactor, '/var/run/tor/control') ep = TCP4ClientEndpoint(reactor, '127.0.0.1', default_control_port()) tor = yield txtorcon.connect(reactor, ep) print("Connected to {tor} via localhost:{port}".format( tor=tor, port=default_control_port(), )) # add our client-side authentication tokens for the service. # You can create these by running the # web_onion_service_ephemeral_auth.py in a separate shell and # using either the "alice" or "bob" token in this client. token = u"0GaFhnbunp0TxZuBhejhxg" # alice's token onion_uri = b"FIXME.onion" if b'FIXME' in onion_uri: print("Please edit to the correct .onion URI") return yield tor.add_onion_authentication(onion_uri, token) try: # do the Web request as with any other agent = tor.web_agent() uri = b'http://{}/'.format(onion_uri) print("Downloading {}".format(uri)) resp = yield agent.request(b'GET', uri) print("Response has {} bytes".format(resp.length)) body = yield readBody(resp) print(body) finally: # if you're using python3, see the example that uses async # context-managers to do this more cleanly. yield tor.remove_onion_authentication(onion_uri)
def main(reactor): # use port 9051 for system tor instances, or: # ep = UNIXClientEndpoint(reactor, '/var/run/tor/control') ep = TCP4ClientEndpoint(reactor, '127.0.0.1', default_control_port()) tor = yield txtorcon.connect(reactor, ep) print("Connected:", tor) config = yield tor.get_config() state = yield tor.create_state() socks = config.socks_endpoint(reactor) # create a custom circuit; in this case we're just letting Tor # decide the path but you *can* select a path (again: for advanced # use cases that will probably de-anonymize you) circ = yield state.build_circuit() print("Building a circuit:", circ) # at this point, the circuit will be "under way" but may not yet # be in BUILT state -- and hence usable. So, we wait. (Just for # demo purposes: the underlying connect will wait too) yield circ.when_built() print("Circuit is ready:", circ) if True: # create a web.Agent that will use this circuit (or fail) agent = circ.web_agent(reactor, socks) uri = 'https://www.torproject.org' print("Downloading {}".format(uri)) resp = yield agent.request('GET', uri) print("Response has {} bytes".format(resp.length)) body = yield readBody(resp) print("received body ({} bytes)".format(len(body))) print("{}\n[...]\n{}\n".format(body[:200], body[-200:])) if True: # make a plain TCP connection to a thing ep = circ.stream_via(reactor, 'torproject.org', 80, config.socks_endpoint(reactor)) d = Deferred() class ToyWebRequestProtocol(Protocol): def connectionMade(self): print("Connected via {}".format(self.transport.getHost())) self.transport.write( 'GET http://torproject.org/ HTTP/1.1\r\n' 'Host: torproject.org\r\n' '\r\n' ) def dataReceived(self, d): print(" received {} bytes".format(len(d))) def connectionLost(self, reason): print("disconnected: {}".format(reason.value)) d.callback(None) proto = yield ep.connect(Factory.forProtocol(ToyWebRequestProtocol)) yield d print("All done, closing the circuit") yield circ.close()
def get_tor(reactor, launch_tor=False, tor_control_port=None, timing=None, stderr=sys.stderr): """ If launch_tor=True, I will try to launch a new Tor process, ask it for its SOCKS and control ports, and use those for outbound connections (and inbound onion-service listeners, if necessary). Otherwise if tor_control_port is provided, I will attempt to connect to an existing Tor's control port at the endpoint it specifies. I'll ask that Tor for its SOCKS port. With no arguments, I will try to connect to an existing Tor's control port at the usual places: [unix:/var/run/tor/control, tcp:127.0.0.1:9051, tcp:127.0.0.1:9151]. If any are successful, I'll ask that Tor for its SOCKS port. If none are successful, I'll attempt to do SOCKS to the usual places: [tcp:127.0.0.1:9050, tcp:127.0.0.1:9150]. If I am unable to make a SOCKS connection, the initial connection to the Rendezvous Server will fail, and the program will terminate. Control-port connections can only succeed if I can authenticate (by reading a cookie file named by the Tor process), so the current user must have permission to read that file (either they started Tor, e.g. TorBrowser, or they are in a unix group that's been given access, e.g. debian-tor). """ # rationale: launching a new Tor takes a long time, so only do it if # the user specifically asks for it with --launch-tor. Using an # existing Tor should be much faster, but still requires general # permission via --tor. if not txtorcon: raise errors.NoTorError() if not isinstance(launch_tor, bool): # note: False is int raise TypeError("launch_tor= must be boolean") if not isinstance(tor_control_port, (type(""), type(None))): raise TypeError("tor_control_port= must be str or None") assert tor_control_port != "" if launch_tor and tor_control_port is not None: raise ValueError("cannot combine --launch-tor and --tor-control-port=") timing = timing or DebugTiming() # Connect to an existing Tor, or create a new one. If we need to # launch an onion service, then we need a working control port (and # authentication cookie). If we're only acting as a client, we don't # need the control port. if launch_tor: print(" launching a new Tor process, this may take a while..", file=stderr) with timing.add("launch tor"): tor = yield txtorcon.launch(reactor, #data_directory=, #tor_binary=, ) elif tor_control_port: with timing.add("find tor"): control_ep = clientFromString(reactor, tor_control_port) tor = yield txtorcon.connect(reactor, control_ep) # might raise print(" using Tor via control port at %s" % tor_control_port, file=stderr) else: # Let txtorcon look through a list of usual places. If that fails, # we'll arrange to attempt the default SOCKS port with timing.add("find tor"): try: tor = yield txtorcon.connect(reactor) print(" using Tor via default control port", file=stderr) except Exception: # TODO: make this more specific. I think connect() is # likely to throw a reactor.connectTCP -type error, like # ConnectionFailed or ConnectionRefused or something print(" unable to find default Tor control port, using SOCKS", file=stderr) tor = SocksOnlyTor(reactor) directlyProvides(tor, _interfaces.ITorManager) returnValue(tor)