mirror of
https://github.com/onionshare/onionshare.git
synced 2025-01-14 08:49:47 -05:00
Rip out support for non-ephemeral onion services
This commit is contained in:
parent
a57703cb5a
commit
6370139d2e
@ -84,7 +84,7 @@ class OnionShare(object):
|
|||||||
return
|
return
|
||||||
|
|
||||||
if not self.onion:
|
if not self.onion:
|
||||||
self.onion = onion.Onion(self.transparent_torification, self.stealth)
|
self.onion = onion.Onion(self.stealth)
|
||||||
|
|
||||||
self.onion_host = self.onion.start(self.port)
|
self.onion_host = self.onion.start(self.port)
|
||||||
|
|
||||||
@ -178,14 +178,8 @@ def main(cwd=None):
|
|||||||
t.start()
|
t.start()
|
||||||
|
|
||||||
try: # Trap Ctrl-C
|
try: # Trap Ctrl-C
|
||||||
# wait for hs, only if using old version of tor
|
# Wait for web.generate_slug() to finish running
|
||||||
if not app.local_only and not app.onion.supports_ephemeral:
|
time.sleep(0.2)
|
||||||
ready = app.onion.wait_for_hs(app.onion_host)
|
|
||||||
if not ready:
|
|
||||||
sys.exit()
|
|
||||||
else:
|
|
||||||
# Wait for web.generate_slug() to finish running
|
|
||||||
time.sleep(0.2)
|
|
||||||
|
|
||||||
if(stealth):
|
if(stealth):
|
||||||
print(strings._("give_this_url_stealth"))
|
print(strings._("give_this_url_stealth"))
|
||||||
|
@ -83,21 +83,12 @@ class TorTooOld(Exception):
|
|||||||
class Onion(object):
|
class Onion(object):
|
||||||
"""
|
"""
|
||||||
Onion is an abstraction layer for connecting to the Tor control port and
|
Onion is an abstraction layer for connecting to the Tor control port and
|
||||||
creating onion services. OnionShare supports creating onion services
|
creating onion services. OnionShare supports creating onion services by
|
||||||
using two methods:
|
connecting to the Tor controller and using ADD_ONION, DEL_ONION.
|
||||||
|
|
||||||
- Modifying the Tor configuration through the control port is the old
|
|
||||||
method, and will be deprecated in favor of ephemeral onion services.
|
|
||||||
- Using the control port to create ephemeral onion servers is the
|
|
||||||
preferred method.
|
|
||||||
|
|
||||||
This class detects the versions of Tor and stem to determine if ephemeral
|
|
||||||
onion services are supported. If not, it falls back to modifying the
|
|
||||||
Tor configuration.
|
|
||||||
"""
|
"""
|
||||||
def __init__(self, transparent_torification=False, stealth=False, settings=False):
|
def __init__(self, stealth=False, settings=False):
|
||||||
self.transparent_torification = transparent_torification
|
|
||||||
self.stealth = stealth
|
self.stealth = stealth
|
||||||
|
self.service_id = None
|
||||||
|
|
||||||
# Either use settings that are passed in, or load them from disk
|
# Either use settings that are passed in, or load them from disk
|
||||||
if settings:
|
if settings:
|
||||||
@ -106,10 +97,6 @@ class Onion(object):
|
|||||||
self.settings = Settings()
|
self.settings = Settings()
|
||||||
self.settings.load()
|
self.settings.load()
|
||||||
|
|
||||||
# files and dirs to delete on shutdown
|
|
||||||
self.cleanup_filenames = []
|
|
||||||
self.service_id = None
|
|
||||||
|
|
||||||
# Try to connect to Tor
|
# Try to connect to Tor
|
||||||
self.c = None
|
self.c = None
|
||||||
|
|
||||||
@ -210,14 +197,14 @@ class Onion(object):
|
|||||||
except AuthenticationFailure:
|
except AuthenticationFailure:
|
||||||
raise TorErrorAuthError(strings._('settings_error_auth').format(self.settings.get('control_port_address'), self.settings.get('control_port_port')))
|
raise TorErrorAuthError(strings._('settings_error_auth').format(self.settings.get('control_port_address'), self.settings.get('control_port_port')))
|
||||||
|
|
||||||
# get the tor version
|
# Get the tor version
|
||||||
self.tor_version = self.c.get_version().version_str
|
self.tor_version = self.c.get_version().version_str
|
||||||
|
|
||||||
# do the versions of stem and tor that I'm using support ephemeral onion services?
|
# Do the versions of stem and tor that I'm using support ephemeral onion services?
|
||||||
list_ephemeral_hidden_services = getattr(self.c, "list_ephemeral_hidden_services", None)
|
list_ephemeral_hidden_services = getattr(self.c, "list_ephemeral_hidden_services", None)
|
||||||
self.supports_ephemeral = callable(list_ephemeral_hidden_services) and self.tor_version >= '0.2.7.1'
|
self.supports_ephemeral = callable(list_ephemeral_hidden_services) and self.tor_version >= '0.2.7.1'
|
||||||
|
|
||||||
# do the versions of stem and tor that I'm using support stealth onion services?
|
# Do the versions of stem and tor that I'm using support stealth onion services?
|
||||||
try:
|
try:
|
||||||
res = self.c.create_ephemeral_hidden_service({1:1}, basic_auth={'onionshare':None}, await_publication=False)
|
res = self.c.create_ephemeral_hidden_service({1:1}, basic_auth={'onionshare':None}, await_publication=False)
|
||||||
tmp_service_id = res.content()[0][2].split('=')[1]
|
tmp_service_id = res.content()[0][2].split('=')[1]
|
||||||
@ -233,181 +220,42 @@ class Onion(object):
|
|||||||
return the onion hostname.
|
return the onion hostname.
|
||||||
"""
|
"""
|
||||||
self.auth_string = None
|
self.auth_string = None
|
||||||
|
if not self.supports_ephemeral:
|
||||||
|
raise TorTooOld(strings._('error_ephemeral_not_supported'))
|
||||||
if self.stealth and not self.supports_stealth:
|
if self.stealth and not self.supports_stealth:
|
||||||
raise TorTooOld(strings._('error_stealth_not_supported'))
|
raise TorTooOld(strings._('error_stealth_not_supported'))
|
||||||
|
|
||||||
print(strings._("config_onion_service").format(int(port)))
|
print(strings._("config_onion_service").format(int(port)))
|
||||||
if self.supports_ephemeral:
|
print(strings._('using_ephemeral'))
|
||||||
print(strings._('using_ephemeral'))
|
|
||||||
|
|
||||||
if self.stealth:
|
|
||||||
basic_auth = {'onionshare':None}
|
|
||||||
else:
|
|
||||||
basic_auth = None
|
|
||||||
|
|
||||||
if basic_auth != None :
|
|
||||||
res = self.c.create_ephemeral_hidden_service({ 80: port }, await_publication=True, basic_auth=basic_auth)
|
|
||||||
else :
|
|
||||||
# if the stem interface is older than 1.5.0, basic_auth isn't a valid keyword arg
|
|
||||||
res = self.c.create_ephemeral_hidden_service({ 80: port }, await_publication=True)
|
|
||||||
|
|
||||||
self.service_id = res.content()[0][2].split('=')[1]
|
|
||||||
onion_host = self.service_id + '.onion'
|
|
||||||
|
|
||||||
if self.stealth:
|
|
||||||
auth_cookie = res.content()[2][2].split('=')[1].split(':')[1]
|
|
||||||
self.auth_string = 'HidServAuth {} {}'.format(onion_host, auth_cookie)
|
|
||||||
|
|
||||||
return onion_host
|
|
||||||
|
|
||||||
|
if self.stealth:
|
||||||
|
basic_auth = {'onionshare':None}
|
||||||
else:
|
else:
|
||||||
# come up with a onion service directory name
|
basic_auth = None
|
||||||
if helpers.get_platform() == 'Windows':
|
|
||||||
self.hidserv_dir = tempfile.mkdtemp()
|
|
||||||
self.hidserv_dir = self.hidserv_dir.replace('\\', '/')
|
|
||||||
|
|
||||||
else:
|
if basic_auth != None :
|
||||||
self.hidserv_dir = tempfile.mkdtemp(suffix='onionshare',dir='/tmp')
|
res = self.c.create_ephemeral_hidden_service({ 80: port }, await_publication=True, basic_auth=basic_auth)
|
||||||
|
else :
|
||||||
|
# if the stem interface is older than 1.5.0, basic_auth isn't a valid keyword arg
|
||||||
|
res = self.c.create_ephemeral_hidden_service({ 80: port }, await_publication=True)
|
||||||
|
|
||||||
self.cleanup_filenames.append(self.hidserv_dir)
|
self.service_id = res.content()[0][2].split('=')[1]
|
||||||
|
onion_host = self.service_id + '.onion'
|
||||||
|
|
||||||
# set up onion service
|
if self.stealth:
|
||||||
hsdic = self.c.get_conf_map('HiddenServiceOptions') or {
|
auth_cookie = res.content()[2][2].split('=')[1].split(':')[1]
|
||||||
'HiddenServiceDir': [], 'HiddenServicePort': []
|
self.auth_string = 'HidServAuth {} {}'.format(onion_host, auth_cookie)
|
||||||
}
|
|
||||||
if self.hidserv_dir in hsdic.get('HiddenServiceDir', []):
|
|
||||||
# Maybe a stale service with the wrong local port
|
|
||||||
dropme = hsdic['HiddenServiceDir'].index(self.hidserv_dir)
|
|
||||||
del hsdic['HiddenServiceDir'][dropme]
|
|
||||||
del hsdic['HiddenServicePort'][dropme]
|
|
||||||
hsdic['HiddenServiceDir'] = hsdic.get('HiddenServiceDir', [])+[self.hidserv_dir]
|
|
||||||
hsdic['HiddenServicePort'] = hsdic.get('HiddenServicePort', [])+[
|
|
||||||
'80 127.0.0.1:{0:d}'.format(port)]
|
|
||||||
|
|
||||||
self.c.set_options(self._hsdic2list(hsdic))
|
return onion_host
|
||||||
|
|
||||||
# figure out the .onion hostname
|
|
||||||
hostname_file = '{0:s}/hostname'.format(self.hidserv_dir)
|
|
||||||
onion_host = open(hostname_file, 'r').read().strip()
|
|
||||||
return onion_host
|
|
||||||
|
|
||||||
def wait_for_hs(self, onion_host):
|
|
||||||
"""
|
|
||||||
This function is only required when using non-ephemeral onion services. After
|
|
||||||
creating a onion service, continually attempt to connect to it until it
|
|
||||||
successfully connects.
|
|
||||||
"""
|
|
||||||
# legacy only, this function is no longer required with ephemeral onion services
|
|
||||||
print(strings._('wait_for_hs'))
|
|
||||||
|
|
||||||
ready = False
|
|
||||||
while not ready:
|
|
||||||
try:
|
|
||||||
sys.stdout.write('{0:s} '.format(strings._('wait_for_hs_trying')))
|
|
||||||
sys.stdout.flush()
|
|
||||||
|
|
||||||
if self.transparent_torification:
|
|
||||||
# no need to set the socks5 proxy
|
|
||||||
urllib.request.urlopen('http://{0:s}'.format(onion_host))
|
|
||||||
else:
|
|
||||||
tor_exists = False
|
|
||||||
ports = [9150, 9152, 9050]
|
|
||||||
for port in ports:
|
|
||||||
try:
|
|
||||||
s = socks.socksocket()
|
|
||||||
s.setproxy(socks.PROXY_TYPE_SOCKS5, '127.0.0.1', port)
|
|
||||||
s.connect((onion_host, 80))
|
|
||||||
s.close()
|
|
||||||
tor_exists = True
|
|
||||||
break
|
|
||||||
except socks.ProxyConnectionError:
|
|
||||||
pass
|
|
||||||
if not tor_exists:
|
|
||||||
raise NoTor(strings._("cant_connect_socksport").format(str(ports)))
|
|
||||||
ready = True
|
|
||||||
|
|
||||||
sys.stdout.write('{0:s}\n'.format(strings._('wait_for_hs_yup')))
|
|
||||||
except socks.GeneralProxyError:
|
|
||||||
sys.stdout.write('{0:s}\n'.format(strings._('wait_for_hs_nope')))
|
|
||||||
sys.stdout.flush()
|
|
||||||
except socks.SOCKS5Error:
|
|
||||||
sys.stdout.write('{0:s}\n'.format(strings._('wait_for_hs_nope')))
|
|
||||||
sys.stdout.flush()
|
|
||||||
except urllib.error.HTTPError: # torification error
|
|
||||||
sys.stdout.write('{0:s}\n'.format(strings._('wait_for_hs_nope')))
|
|
||||||
sys.stdout.flush()
|
|
||||||
except KeyboardInterrupt:
|
|
||||||
return False
|
|
||||||
return True
|
|
||||||
|
|
||||||
def cleanup(self):
|
def cleanup(self):
|
||||||
"""
|
"""
|
||||||
Stop onion services that were created earlier, and delete any temporary
|
Stop onion services that were created earlier.
|
||||||
files that were created.
|
|
||||||
"""
|
"""
|
||||||
if self.supports_ephemeral:
|
# cleanup the ephemeral onion service
|
||||||
# cleanup the ephemeral onion service
|
if self.service_id:
|
||||||
if self.service_id:
|
|
||||||
try:
|
|
||||||
self.c.remove_ephemeral_hidden_service(self.service_id)
|
|
||||||
except:
|
|
||||||
pass
|
|
||||||
self.service_id = None
|
|
||||||
|
|
||||||
else:
|
|
||||||
# cleanup onion service
|
|
||||||
try:
|
try:
|
||||||
if self.controller:
|
self.c.remove_ephemeral_hidden_service(self.service_id)
|
||||||
# Get fresh onion services (maybe changed since last time)
|
|
||||||
# and remove ourselves
|
|
||||||
hsdic = self.controller.get_conf_map('HiddenServiceOptions') or {
|
|
||||||
'HiddenServiceDir': [], 'HiddenServicePort': []
|
|
||||||
}
|
|
||||||
if self.hidserv_dir and self.hidserv_dir in hsdic.get('HiddenServiceDir', []):
|
|
||||||
dropme = hsdic['HiddenServiceDir'].index(self.hidserv_dir)
|
|
||||||
del hsdic['HiddenServiceDir'][dropme]
|
|
||||||
del hsdic['HiddenServicePort'][dropme]
|
|
||||||
self.controller.set_options(self._hsdic2list(hsdic))
|
|
||||||
# Politely close the controller
|
|
||||||
self.controller.close()
|
|
||||||
except:
|
except:
|
||||||
pass
|
pass
|
||||||
|
self.service_id = None
|
||||||
# cleanup files
|
|
||||||
for filename in self.cleanup_filenames:
|
|
||||||
if os.path.isfile(filename):
|
|
||||||
os.remove(filename)
|
|
||||||
elif os.path.isdir(filename):
|
|
||||||
shutil.rmtree(filename)
|
|
||||||
self.cleanup_filenames = []
|
|
||||||
|
|
||||||
def _hsdic2list(self, dic):
|
|
||||||
"""
|
|
||||||
Convert what we get from get_conf_map to what we need for set_options.
|
|
||||||
|
|
||||||
For example, if input looks like this:
|
|
||||||
{
|
|
||||||
'HiddenServicePort': [
|
|
||||||
'80 127.0.0.1:47906',
|
|
||||||
'80 127.0.0.1:33302'
|
|
||||||
],
|
|
||||||
'HiddenServiceDir': [
|
|
||||||
'/tmp/onionsharelTfZZu',
|
|
||||||
'/tmp/onionsharechDai3'
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
Output will look like this:
|
|
||||||
[
|
|
||||||
('HiddenServiceDir', '/tmp/onionsharelTfZZu'),
|
|
||||||
('HiddenServicePort', '80 127.0.0.1:47906'),
|
|
||||||
('HiddenServiceDir', '/tmp/onionsharechDai3'),
|
|
||||||
('HiddenServicePort', '80 127.0.0.1:33302')
|
|
||||||
]
|
|
||||||
"""
|
|
||||||
l = []
|
|
||||||
for dir, port in zip(dic['HiddenServiceDir'], dic['HiddenServicePort']):
|
|
||||||
l.append(('HiddenServiceDir', dir))
|
|
||||||
l.append(('HiddenServicePort', port))
|
|
||||||
return l
|
|
||||||
|
@ -206,11 +206,6 @@ class OnionShareGui(QtWidgets.QMainWindow):
|
|||||||
self.app.cleanup_filenames.append(web.zip_filename)
|
self.app.cleanup_filenames.append(web.zip_filename)
|
||||||
self.starting_server_step3.emit()
|
self.starting_server_step3.emit()
|
||||||
|
|
||||||
# wait for hs
|
|
||||||
if not self.app.local_only and not self.app.onion.supports_ephemeral:
|
|
||||||
self.status_bar.showMessage(strings._('gui_starting_server3', True))
|
|
||||||
self.app.onion.wait_for_hs(self.app.onion_host)
|
|
||||||
|
|
||||||
# done
|
# done
|
||||||
self.start_server_finished.emit()
|
self.start_server_finished.emit()
|
||||||
|
|
||||||
|
@ -38,7 +38,6 @@
|
|||||||
"gui_copied_hidservauth": "Copied HidServAuth line to clipboard",
|
"gui_copied_hidservauth": "Copied HidServAuth line to clipboard",
|
||||||
"gui_starting_server1": "Starting Tor onion service...",
|
"gui_starting_server1": "Starting Tor onion service...",
|
||||||
"gui_starting_server2": "Crunching files...",
|
"gui_starting_server2": "Crunching files...",
|
||||||
"gui_starting_server3": "Waiting for Tor onion service...",
|
|
||||||
"gui_please_wait": "Please wait...",
|
"gui_please_wait": "Please wait...",
|
||||||
"error_hs_dir_cannot_create": "Cannot create onion service dir {0:s}",
|
"error_hs_dir_cannot_create": "Cannot create onion service dir {0:s}",
|
||||||
"error_hs_dir_not_writable": "onion service dir {0:s} is not writable",
|
"error_hs_dir_not_writable": "onion service dir {0:s} is not writable",
|
||||||
@ -53,6 +52,7 @@
|
|||||||
"error_rate_limit": "An attacker might be trying to guess your URL. To prevent this, OnionShare has automatically stopped the server. To share the files you must start it again and share the new URL.",
|
"error_rate_limit": "An attacker might be trying to guess your URL. To prevent this, OnionShare has automatically stopped the server. To share the files you must start it again and share the new URL.",
|
||||||
"zip_progress_bar_format": "Crunching files: %p%",
|
"zip_progress_bar_format": "Crunching files: %p%",
|
||||||
"error_stealth_not_supported": "To create stealth onion services, you need at least Tor 0.2.9.1-alpha (or Tor Browser 6.5) and at least python3-stem 1.5.0.",
|
"error_stealth_not_supported": "To create stealth onion services, you need at least Tor 0.2.9.1-alpha (or Tor Browser 6.5) and at least python3-stem 1.5.0.",
|
||||||
|
"error_ephemeral_not_supported": "OnionShare requires at least at least Tor 0.2.7.1 and at least python3-stem 1.4.0.",
|
||||||
"gui_advanced_options": "Advanced Options",
|
"gui_advanced_options": "Advanced Options",
|
||||||
"gui_create_stealth": "Create Stealth Onion Service",
|
"gui_create_stealth": "Create Stealth Onion Service",
|
||||||
"gui_menu_file_menu": "&File",
|
"gui_menu_file_menu": "&File",
|
||||||
|
Loading…
Reference in New Issue
Block a user