1#!/usr/local/bin/python3.8 2 3# Here we use some very new Tor configuration options to set up a 4# "single-hop" or "non-anonymous" onion service. These do NOT give the 5# server location-privacy, so may be appropriate for certain kinds of 6# services. Once you publish a service like this, there's no going 7# back to location-hidden. 8 9from __future__ import print_function 10from twisted.internet import defer, task, endpoints 11from twisted.web import server, resource 12 13import txtorcon 14 15 16class Simple(resource.Resource): 17 """ 18 A really simple Web site. 19 """ 20 isLeaf = True 21 22 def render_GET(self, request): 23 return b"<html>Hello, world! I'm a single-hop onion service!</html>" 24 25 26@defer.inlineCallbacks 27def main(reactor): 28 # For the "single_hop=True" below to work, the Tor we're 29 # connecting to must have the following options set: 30 # SocksPort 0 31 # HiddenServiceSingleHopMode 1 32 # HiddenServiceNonAnonymousMode 1 33 34 tor = yield txtorcon.connect( 35 reactor, 36 endpoints.TCP4ClientEndpoint(reactor, "localhost", 9351), 37 ) 38 if False: 39 ep = tor.create_onion_endpoint( 40 80, 41 version=3, 42 single_hop=True, 43 ) 44 else: 45 ep = endpoints.serverFromString(reactor, "onion:80:version=3:singleHop=true") 46 47 def on_progress(percent, tag, msg): 48 print('%03d: %s' % (percent, msg)) 49 txtorcon.IProgressProvider(ep).add_progress_listener(on_progress) 50 51 port = yield ep.listen(server.Site(Simple())) 52 print("Private key:\n{}".format(port.getHost().onion_key)) 53 hs = port.onion_service 54 print("Site on http://{}".format(hs.hostname)) 55 yield defer.Deferred() # wait forever 56 57 58task.react(main) 59