Skip to content

Instantly share code, notes, and snippets.

@suvayu
Last active July 19, 2018 22:50
Show Gist options
  • Save suvayu/57bf7f8529c0f9057879a0993ce15bb0 to your computer and use it in GitHub Desktop.
Save suvayu/57bf7f8529c0f9057879a0993ce15bb0 to your computer and use it in GitHub Desktop.
Create an ephemeral Tor hidden service to expose a daemon running on localhost
#!/usr/bin/env python3
"""Create a TOR hidden service
$ ./hidden_service.py [port]
When no argument is provided, port defaults to 22. The script creates a hidden
service where 127.0.0.1:[port] is served over Tor. The onion address and
authentication cookie are printed on standard output. The private key and the
authentication cookie are saved in a pickle file (keys.pkl) to be reused on
subsequent runs.
@author Suvayu Ali
@date 2018-07-19
"""
import os
import pickle
from stem.control import Controller
def hs_options(overrides):
"""Default ephemeral hidden service options
Options can be overridden by passing an override dictionary.
"""
opts = {
'key_type': 'NEW',
'key_content': 'BEST',
'discard_key': False,
'await_publication': True,
'basic_auth': {'bob': None},
}
opts.update(overrides)
return opts.copy()
def hs_restore(store):
"""Restore the private key and authentication credentials from disk.
On first run, the private key and authentication credentials are stored in
a pickle file on disk. `store` is the path to the pickle file.
"""
if os.path.exists(store):
with open(store, mode='br') as store:
key = pickle.load(store)
return dict(key_type=key.private_key_type,
key_content=key.private_key,
basic_auth=key.client_auth)
else:
return {}
def hs_store(key, store):
"""Save the private key and authentication credentials"""
if not os.path.exists(store):
with open(store, mode='bw') as store:
pickle.dump(key, store)
if len(sys.argv) < 2:
port = 22 # default to SSH
else:
port = sys.argv[1]
with Controller.from_port(port=9051) as ctrlr:
ctrlr.authenticate()
opts = hs_options(hs_restore('keys.pkl'))
res = ctrlr.create_ephemeral_hidden_service(port, **opts)
print('onion: {}.onion'.format(res.service_id))
print('auth: {}'.format(res.client_auth.get(
'bob', opts['basic_auth'].get('bob'))))
hs_store(res, 'keys.pkl')
try:
while True:
pass
except KeyboardInterrupt:
pass
finally:
print('Stopping hidden service')
code = ctrlr.remove_ephemeral_hidden_service(res.service_id)
print('success: {}'.format(code))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment