Skip to content

Instantly share code, notes, and snippets.

@felipedau
Created February 20, 2017 09:57
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save felipedau/7c4b9bb8f9e553cf7db7013a71abbccd to your computer and use it in GitHub Desktop.
Save felipedau/7c4b9bb8f9e553cf7db7013a71abbccd to your computer and use it in GitHub Desktop.
Ephemeral hidden services with stem and txtorcon
#!/usr/bin/env python
from twisted.internet import reactor, defer
from twisted.internet.endpoints import TCP4ServerEndpoint
from twisted.web import server, resource
from twisted.internet.task import react
from stem.control import Controller
CONTROL_PORT = 9051
LISTEN_IP = '127.0.0.1'
HS_PORT = 80
SV_PORT = 8080
WAIT_TIME = 40
class Simple(resource.Resource):
isLeaf = True
def render_GET(self, request):
return ("<html>Hello, world! I'm a stem ephemeral hidden "
"service running on a non-Whonix system!</html>")
def start_site(reactor):
print "Starting site"
site = server.Site(Simple())
sv_endpoint = TCP4ServerEndpoint(reactor, SV_PORT, interface=LISTEN_IP)
return sv_endpoint.listen(site)
@defer.inlineCallbacks
def main(reactor):
yield start_site(reactor)
d = defer.Deferred()
try:
with open('key', 'r') as f:
key_info = f.readline().strip()
except IOError:
key_info = key_type = key = None
else:
key_type, key = key_info.split(':')
controller = Controller.from_port(port=CONTROL_PORT)
try:
controller.authenticate()
except Exception as e:
print e.title, e.message
else:
hs_string = '%s %s:%d' % (HS_PORT, LISTEN_IP, SV_PORT)
print "Adding ephemeral service", hs_string
print "(this can take some time; please be patient)"
response = controller.create_ephemeral_hidden_service(
ports={HS_PORT: hs_string.split()[1]},
key_type=key_type or 'NEW',
key_content=key or 'BEST',
await_publication=True)
key_type = key_type or response.private_key_type
key = key or response.private_key
if not key_info:
with open('key', 'w') as f:
f.write('{}:{}'.format(key_type, key))
service_id = response.content()[0][2].split('=')[1]
hostname = service_id + '.onion'
print "Added ephemeral HS to Tor:", hostname
def remove():
print "Removing the hiddenservice"
print 'Key type was', key_type
print "Private key was"
print key
controller.remove_ephemeral_hidden_service(service_id)
d.callback(None)
reactor.callLater(WAIT_TIME, remove)
print "waiting {} seconds".format(WAIT_TIME)
yield d
react(main)
#!/usr/bin/env python
from twisted.internet import reactor, defer
from twisted.internet.endpoints import TCP4ClientEndpoint, TCP4ServerEndpoint
from twisted.web import server, resource
from twisted.internet.task import react
import txtorcon
CONTROL_PORT = 9051
LISTEN_IP = '127.0.0.1'
HS_PORT = 80
SV_PORT = 8080
WAIT_TIME = 40
class Simple(resource.Resource):
isLeaf = True
def render_GET(self, request):
return ("<html>Hello, world! I'm a txtorcon ephemeral hidden "
"service running on a non-Whonix system!</html>")
def start_site(reactor):
print "Starting site"
site = server.Site(Simple())
sv_endpoint = TCP4ServerEndpoint(reactor, SV_PORT, interface=LISTEN_IP)
return sv_endpoint.listen(site)
@defer.inlineCallbacks
def main(reactor):
yield start_site(reactor)
d = defer.Deferred()
try:
with open('key', 'r') as f:
key_info = f.readline().strip()
except IOError:
key_info = None
ep = TCP4ClientEndpoint(reactor, '127.0.0.1', CONTROL_PORT)
tor = yield txtorcon.connect(reactor, ep)
print("Connected to {tor} via localhost:{port}".format(
tor=tor,
port=CONTROL_PORT,
))
hs_string = '%s %s:%d' % (HS_PORT, LISTEN_IP, SV_PORT)
print "Adding ephemeral service", hs_string
print "(this can take some time; please be patient)"
hs = txtorcon.EphemeralHiddenService([hs_string],
key_info or 'NEW:BEST')
yield hs.add_to_tor(tor._protocol)
print "Added ephemeral HS to Tor:", hs.hostname
if not key_info:
with open('key', 'w') as f:
f.write(hs.private_key)
@defer.inlineCallbacks
def remove():
print "Removing the hiddenservice. Private key was"
print key_info or hs.private_key
yield hs.remove_from_tor(tor._protocol)
d.callback(None)
reactor.callLater(WAIT_TIME, remove)
print "waiting {} seconds".format(WAIT_TIME)
yield d
react(main)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment