From 268d788ab083467247d2bd91e8ba71c0fc000e1e Mon Sep 17 00:00:00 2001 From: "Kali Kaneko (leap communications)" Date: Fri, 28 Oct 2016 10:17:38 +0200 Subject: [feature] serve UI as an hidden service you need to configure onion = True in the services config. for sure, this is gonna be more interesting when we ship pixelated. but for now I thought it can be handy for testing ui changes: no need to bundle, just use your tor browser :) still need to try to serve imap/smtp over the onion service. kudos to meejah for this super-usable library! --- src/leap/bitmask/core/_web.py | 59 ++++++++++++++++++++++++++++++----- src/leap/bitmask/core/configurable.py | 1 + src/leap/bitmask/core/service.py | 7 +++-- 3 files changed, 57 insertions(+), 10 deletions(-) (limited to 'src') diff --git a/src/leap/bitmask/core/_web.py b/src/leap/bitmask/core/_web.py index 1798e7f6..715356d3 100644 --- a/src/leap/bitmask/core/_web.py +++ b/src/leap/bitmask/core/_web.py @@ -26,6 +26,7 @@ import pkg_resources from twisted.internet import reactor from twisted.application import service +from twisted.internet import endpoints from twisted.web.resource import Resource from twisted.web.server import Site, NOT_DONE_YET from twisted.web.static import File @@ -39,6 +40,11 @@ try: except ImportError: HAS_WEB_UI = False +try: + import txtorcon +except Exception: + pass + log = Logger() @@ -46,12 +52,16 @@ class HTTPDispatcherService(service.Service): """ A Dispatcher for BitmaskCore exposing a REST API. + If the leap.bitmask_js package is available in the search path, it will + serve the UI under this same service too. """ - def __init__(self, core, port=7070, debug=False): + def __init__(self, core, port=7070, debug=False, onion=False): self._core = core self.port = port self.debug = debug + self.onion = onion + self.uri = '' def startService(self): if HAS_WEB_UI: @@ -67,14 +77,49 @@ class HTTPDispatcherService(service.Service): api = Api(CommandDispatcher(self._core)) root.putChild(u'API', api) - site = Site(root) - self.site = site + factory = Site(root) + self.site = factory + + if self.onion: + try: + import txtorcon + except ImportError: + log.error('onion is enabled, but could not find txtorcon') + return + self._start_onion_service(factory) - # TODO use endpoints instead - self.listener = reactor.listenTCP(self.port, site, - interface='127.0.0.1') + else: + interface = '127.0.0.1' + endpoint = endpoints.TCP4ServerEndpoint( + reactor, self.port, interface=interface) + self.uri = 'https://%s:%s' % (interface, self.port) + endpoint.listen(factory) + # TODO this should be set in a callback to the listen call self.running = True + def _start_onion_service(self, factory): + + def progress(percent, tag, message): + bar = int(percent / 10) + log.debug('[%s%s] %s' % ('#' * bar, '.' * (10 - bar), message)) + + def setup_complete(port): + port = txtorcon.IHiddenService(port) + self.uri = "http://%s" % (port.getHost().onion_uri) + log.info('I have set up a hidden service, advertised at: %s' + % self.uri) + log.info('locally listening on %s' % port.local_address.getHost()) + + def setup_failed(args): + log.error('onion service setup FAILED: %r' % args) + + endpoint = endpoints.serverFromString(reactor, 'onion:80') + txtorcon.IProgressProvider(endpoint).add_progress_listener(progress) + d = endpoint.listen(factory) + d.addCallback(setup_complete) + d.addErrback(setup_failed) + return d + def stopService(self): self.site.stopFactory() self.listener.stopListening() @@ -82,7 +127,7 @@ class HTTPDispatcherService(service.Service): def do_status(self): status = 'running' if self.running else 'disabled' - return {'web': status} + return {'web': status, 'uri': self.uri} class Api(Resource): diff --git a/src/leap/bitmask/core/configurable.py b/src/leap/bitmask/core/configurable.py index 8bd2ecfb..f305cc3c 100644 --- a/src/leap/bitmask/core/configurable.py +++ b/src/leap/bitmask/core/configurable.py @@ -103,5 +103,6 @@ mail = True eip = True zmq = True web = True +onion = False websockets = False """ diff --git a/src/leap/bitmask/core/service.py b/src/leap/bitmask/core/service.py index b6447ddd..9fde7889 100644 --- a/src/leap/bitmask/core/service.py +++ b/src/leap/bitmask/core/service.py @@ -74,7 +74,8 @@ class BitmaskBackend(configurable.ConfigurableService): on_start(self._init_zmq) if enabled('web'): - on_start(self._init_web) + onion = enabled('onion') + on_start(self._init_web, onion=onion) if enabled('websockets'): on_start(self._init_websockets) @@ -151,9 +152,9 @@ class BitmaskBackend(configurable.ConfigurableService): zs = _zmq.ZMQServerService(self) zs.setServiceParent(self) - def _init_web(self): + def _init_web(self, onion=False): service = _web.HTTPDispatcherService - self._maybe_init_service('web', service, self) + self._maybe_init_service('web', service, self, onion=onion) def _init_websockets(self): from leap.bitmask.core import websocket -- cgit v1.2.3