use tor hidden service instead of ed25515 as peer id
This commit is contained in:
parent
cc258fb5ee
commit
7c1e5c691a
23 changed files with 1139 additions and 324 deletions
196
oml/tor.py
Normal file
196
oml/tor.py
Normal file
|
|
@ -0,0 +1,196 @@
|
|||
import os
|
||||
import subprocess
|
||||
from threading import Thread
|
||||
import distutils
|
||||
|
||||
import stem
|
||||
from stem.control import Controller
|
||||
import settings
|
||||
|
||||
import logging
|
||||
import state
|
||||
import time
|
||||
|
||||
logger = logging.getLogger('oml.tor')
|
||||
|
||||
class TorDaemon(Thread):
|
||||
def __init__(self):
|
||||
self._status = []
|
||||
Thread.__init__(self)
|
||||
self.daemon = True
|
||||
self.start()
|
||||
|
||||
def create_torrc(self):
|
||||
defaults = os.path.join(settings.config_path, 'torrc-defaults')
|
||||
torrc = os.path.join(settings.config_path, 'torrc')
|
||||
if not os.path.exists(defaults):
|
||||
with open(defaults, 'w') as fd:
|
||||
fd.write('''
|
||||
AvoidDiskWrites 1
|
||||
# Where to send logging messages. Format is minSeverity[-maxSeverity]
|
||||
# (stderr|stdout|syslog|file FILENAME).
|
||||
Log notice stdout
|
||||
SocksPort 9830
|
||||
ControlPort 9831
|
||||
CookieAuthentication 1
|
||||
'''.strip())
|
||||
if not os.path.exists(torrc):
|
||||
with open(torrc, 'w') as fd:
|
||||
fd.write('''
|
||||
DataDirectory {base}/TorData
|
||||
DirReqStatistics 0
|
||||
'''.strip().format(base=settings.config_path))
|
||||
return defaults, torrc
|
||||
|
||||
def get_tor(self):
|
||||
def cmd_exists(cmd):
|
||||
return subprocess.call("type " + cmd, shell=True,
|
||||
stdout=subprocess.PIPE, stderr=subprocess.PIPE) == 0
|
||||
for path in (
|
||||
'/Applications/TorBrowser.app/TorBrowser/Tor/tor',
|
||||
):
|
||||
if os.path.isfile(path) and os.access(path, os.X_OK):
|
||||
return path
|
||||
start = os.path.expanduser('~/.local/share/applications/start-tor-browser.desktop')
|
||||
if os.path.exists(start):
|
||||
with open(start) as fd:
|
||||
e = [line for line in fd.read().split('\n') if line.startswith('Exec')]
|
||||
if e:
|
||||
try:
|
||||
base = os.path.dirname(e[0].split('"')[1])
|
||||
path = os.path.join(base, 'TorBrowser', 'Tor', 'tor')
|
||||
if os.path.isfile(path) and os.access(path, os.X_OK):
|
||||
return path
|
||||
except:
|
||||
pass
|
||||
return distutils.spawn.find_executable('tor')
|
||||
|
||||
def run(self):
|
||||
defaults, torrc = self.create_torrc()
|
||||
tor = self.get_tor()
|
||||
if not tor:
|
||||
self._status.append('No tor binary found. Please install TorBrowser or tor')
|
||||
else:
|
||||
cmd = [tor, '--defaults-torrc', defaults, '-f', torrc]
|
||||
self.p = subprocess.Popen(cmd, stdout=subprocess.PIPE, bufsize=1, universal_newlines=True)
|
||||
for line in self.p.stdout:
|
||||
self._status.append(line)
|
||||
self.p = None
|
||||
|
||||
def shutdown(self):
|
||||
if self.p:
|
||||
self.p.kill()
|
||||
|
||||
def status(self, max_lines=50):
|
||||
return ''.join(self._status[-max_lines:])
|
||||
|
||||
class Tor(object):
|
||||
_shutdown = False
|
||||
connected = False
|
||||
controller = None
|
||||
daemon = None
|
||||
socks_port = 9150
|
||||
|
||||
def __init__(self):
|
||||
if not self.connect():
|
||||
self.reconnect()
|
||||
|
||||
def connect(self):
|
||||
self.connected = False
|
||||
self.dir = os.path.join(settings.config_path, 'tor')
|
||||
connected = False
|
||||
for port in (9831, 9151):
|
||||
try:
|
||||
self.controller = Controller.from_port('127.0.0.1', port)
|
||||
connected = True
|
||||
break
|
||||
except stem.SocketError:
|
||||
pass
|
||||
if not connected:
|
||||
if not self.daemon:
|
||||
logger.debug("start own tor process")
|
||||
self.daemon = TorDaemon()
|
||||
logger.debug("daemon %s", self.daemon)
|
||||
return self.connect()
|
||||
logger.debug("Failed to connect to system or own tor process.")
|
||||
return False
|
||||
try:
|
||||
self.controller.authenticate()
|
||||
except stem.connection.MissingPassword:
|
||||
logger.debug("TOR requires a password")
|
||||
return False
|
||||
except stem.connection.PasswordAuthFailed:
|
||||
logger.debug("invalid tor password")
|
||||
return False
|
||||
self.controller.add_event_listener(self.event_listener)
|
||||
self.controller.add_status_listener(self.status_listener)
|
||||
self.connected = True
|
||||
self.socks_port = int(self.controller.get_conf('SocksPort').split(' ')[0])
|
||||
self.publish()
|
||||
state.online = True
|
||||
return True
|
||||
|
||||
def reconnect(self):
|
||||
if not self.connect():
|
||||
if state.main:
|
||||
state.main.call_later(1, self.reconnect)
|
||||
|
||||
def status_listener(self, controller, status, timestamp):
|
||||
if status == 'Closed':
|
||||
if not self._shutdown:
|
||||
self.connected = False
|
||||
state.online = False
|
||||
self.reconnect()
|
||||
else:
|
||||
logger.debug('unknonw change %s', status)
|
||||
|
||||
def event_listener(self, event):
|
||||
print('EVENT', event)
|
||||
|
||||
def shutdown(self):
|
||||
self._shutdown = True
|
||||
try:
|
||||
self.unpublish()
|
||||
if self.controller:
|
||||
#self.controller.remove_event_listener(self.connection_change)
|
||||
self.controller.close()
|
||||
if self.daemon:
|
||||
self.daemon.shutdown()
|
||||
except:
|
||||
logger.debug('shutdown exception', exc_info=1)
|
||||
pass
|
||||
self.connected = False
|
||||
|
||||
def publish(self):
|
||||
logger.debug("publish tor node")
|
||||
if not self.connected:
|
||||
return False
|
||||
controller = self.controller
|
||||
logger.debug("FIXME: dont remove/add service if already defined")
|
||||
controller.remove_hidden_service(self.dir)
|
||||
result = controller.create_hidden_service(
|
||||
self.dir,
|
||||
settings.server_defaults['node_port'],
|
||||
target_port=settings.server['node_port']
|
||||
)
|
||||
logger.debug('published node as https://%s:%s', result.hostname, settings.server_defaults['node_port'])
|
||||
'''
|
||||
with open(settings.ssl_key_path) as fd:
|
||||
key_content = fd.read()
|
||||
ports = {9851: settings.server['node_port']}
|
||||
response = controller.create_ephemeral_hidden_service(ports,
|
||||
key_type='RSA1024', key_content=key_content,
|
||||
detached=True, await_publication = True)
|
||||
logger.debug('published node as https://%s.onion:%s',
|
||||
settings.USER_ID, settings.server_defaults['node_port'])
|
||||
'''
|
||||
|
||||
def unpublish(self):
|
||||
if not self.connected:
|
||||
return False
|
||||
if self.controller:
|
||||
self.controller.remove_hidden_service(self.dir)
|
||||
state.online = False
|
||||
|
||||
def is_online(self):
|
||||
return self.connected and self.controller.is_alive()
|
||||
Loading…
Add table
Add a link
Reference in a new issue