mirror of
https://github.com/onionshare/onionshare.git
synced 2025-06-07 14:23:01 -04:00
Merge branch '435_support_bridges' of https://github.com/mig5/onionshare into mig5-435_support_bridges
This commit is contained in:
commit
713e45084a
15 changed files with 720 additions and 506 deletions
11
BUILD.md
11
BUILD.md
|
@ -11,9 +11,9 @@ cd onionshare
|
||||||
|
|
||||||
Install the needed dependencies:
|
Install the needed dependencies:
|
||||||
|
|
||||||
For Debian-like distros: `apt install -y build-essential fakeroot python3-all python3-stdeb dh-python python3-flask python3-stem python3-pyqt5 python-nautilus python3-pytest tor`
|
For Debian-like distros: `apt install -y build-essential fakeroot python3-all python3-stdeb dh-python python3-flask python3-stem python3-pyqt5 python-nautilus python3-pytest tor obfs4proxy`
|
||||||
|
|
||||||
For Fedora-like distros: `dnf install -y rpm-build python3-flask python3-stem python3-qt5 python3-pytest nautilus-python tor`
|
For Fedora-like distros: `dnf install -y rpm-build python3-flask python3-stem python3-qt5 python3-pytest nautilus-python tor obfs4`
|
||||||
|
|
||||||
After that you can try both the CLI and the GUI version of OnionShare:
|
After that you can try both the CLI and the GUI version of OnionShare:
|
||||||
|
|
||||||
|
@ -98,11 +98,16 @@ These instructions include adding folders to the path in Windows. To do this, go
|
||||||
|
|
||||||
Download and install the 32-bit [Visual C++ Redistributable for Visual Studio 2015](https://www.microsoft.com/en-US/download/details.aspx?id=48145). I downloaded `vc_redist.x86.exe`.
|
Download and install the 32-bit [Visual C++ Redistributable for Visual Studio 2015](https://www.microsoft.com/en-US/download/details.aspx?id=48145). I downloaded `vc_redist.x86.exe`.
|
||||||
|
|
||||||
Download and install the standalone [Windows 10 SDK](https://dev.windows.com/en-us/downloads/windows-10-sdk). Note that you may not need this if you already have Visual Studio. Add the following directories to the path:
|
Download and install 7-Zip from http://70zip.org/download.html. I downloaded 7z1800.exe.
|
||||||
|
|
||||||
|
Download and install the standalone [Windows 10 SDK](https://dev.windows.com/en-us/downloads/windows-10-sdk). Note that you may not need this if you already have Visual Studio.
|
||||||
|
|
||||||
|
Add the following directories to the path:
|
||||||
|
|
||||||
* `C:\Program Files (x86)\Windows Kits\10\bin\10.0.16299.0\x86`
|
* `C:\Program Files (x86)\Windows Kits\10\bin\10.0.16299.0\x86`
|
||||||
* `C:\Program Files (x86)\Windows Kits\10\Redist\ucrt\DLLs\x86`
|
* `C:\Program Files (x86)\Windows Kits\10\Redist\ucrt\DLLs\x86`
|
||||||
* `C:\Users\user\AppData\Local\Programs\Python\Python36-32\Lib\site-packages\PyQt5\Qt\bin`
|
* `C:\Users\user\AppData\Local\Programs\Python\Python36-32\Lib\site-packages\PyQt5\Qt\bin`
|
||||||
|
* `C:\Program Files (x86)\7-Zip`
|
||||||
|
|
||||||
If you want to build the installer:
|
If you want to build the installer:
|
||||||
|
|
||||||
|
|
|
@ -9,7 +9,7 @@ VERSION=`cat share/version.txt`
|
||||||
rm -r build dist >/dev/null 2>&1
|
rm -r build dist >/dev/null 2>&1
|
||||||
|
|
||||||
# build binary package
|
# build binary package
|
||||||
python3 setup.py bdist_rpm --requires="python3-flask, python3-stem, python3-qt5, nautilus-python, tor"
|
python3 setup.py bdist_rpm --requires="python3-flask, python3-stem, python3-qt5, nautilus-python, tor, obfs4"
|
||||||
|
|
||||||
# install it
|
# install it
|
||||||
echo ""
|
echo ""
|
||||||
|
|
|
@ -84,6 +84,9 @@ def main():
|
||||||
shutil.copyfile(os.path.join(dmg_tor_path, 'MacOS', 'Tor', 'tor.real'), os.path.join(dist_path, 'MacOS', 'Tor', 'tor.real'))
|
shutil.copyfile(os.path.join(dmg_tor_path, 'MacOS', 'Tor', 'tor.real'), os.path.join(dist_path, 'MacOS', 'Tor', 'tor.real'))
|
||||||
shutil.copyfile(os.path.join(dmg_tor_path, 'MacOS', 'Tor', 'libevent-2.0.5.dylib'), os.path.join(dist_path, 'MacOS', 'Tor', 'libevent-2.0.5.dylib'))
|
shutil.copyfile(os.path.join(dmg_tor_path, 'MacOS', 'Tor', 'libevent-2.0.5.dylib'), os.path.join(dist_path, 'MacOS', 'Tor', 'libevent-2.0.5.dylib'))
|
||||||
os.chmod(os.path.join(dist_path, 'MacOS', 'Tor', 'tor.real'), 0o755)
|
os.chmod(os.path.join(dist_path, 'MacOS', 'Tor', 'tor.real'), 0o755)
|
||||||
|
# obfs4proxy binary
|
||||||
|
shutil.copyfile(os.path.join(dmg_tor_path, 'MacOS', 'Tor', 'PluggableTransports', 'obfs4proxy'), os.path.join(dist_path, 'Resources', 'Tor', 'obfs4proxy'))
|
||||||
|
os.chmod(os.path.join(dist_path, 'Resources', 'Tor', 'obfs4proxy'), 0o755)
|
||||||
|
|
||||||
# Unmount dmg
|
# Unmount dmg
|
||||||
subprocess.call(['diskutil', 'unmount', '/Volumes/Tor Browser'])
|
subprocess.call(['diskutil', 'unmount', '/Volumes/Tor Browser'])
|
||||||
|
|
|
@ -24,18 +24,17 @@ In order to avoid a Windows gnupg dependency, I manually verify the signature
|
||||||
and hard-code the sha256 hash.
|
and hard-code the sha256 hash.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import inspect, os, sys, hashlib, zipfile, io, shutil
|
import inspect, os, sys, hashlib, shutil, subprocess
|
||||||
import urllib.request
|
import urllib.request
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
zip_url = 'https://archive.torproject.org/tor-package-archive/torbrowser/7.0.11/tor-win32-0.3.1.9.zip'
|
exe_url = 'https://archive.torproject.org/tor-package-archive/torbrowser/7.0.11/torbrowser-install-7.0.11_en-US.exe'
|
||||||
zip_filename = 'tor-win32-0.3.1.9.zip'
|
exe_filename = 'torbrowser-install-7.0.11_en-US.exe'
|
||||||
expected_zip_sha256 = 'faf28efb606455842bda66ca369287a116b6d6e5ad3720ebed9337da0717f1b4'
|
expected_exe_sha256 = 'a033eb9b9ed2ad389169b36a90946a8af8f05bd0c7bbd3e37678041331096624'
|
||||||
|
|
||||||
# Build paths
|
# Build paths
|
||||||
root_path = os.path.dirname(os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe()))))
|
root_path = os.path.dirname(os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe()))))
|
||||||
working_path = os.path.join(os.path.join(root_path, 'build'), 'tor')
|
working_path = os.path.join(os.path.join(root_path, 'build'), 'tor')
|
||||||
zip_path = os.path.join(working_path, zip_filename)
|
exe_path = os.path.join(working_path, exe_filename)
|
||||||
dist_path = os.path.join(os.path.join(os.path.join(root_path, 'dist'), 'onionshare'), 'tor')
|
dist_path = os.path.join(os.path.join(os.path.join(root_path, 'dist'), 'onionshare'), 'tor')
|
||||||
|
|
||||||
# Make sure the working folder exists
|
# Make sure the working folder exists
|
||||||
|
@ -43,36 +42,35 @@ def main():
|
||||||
os.makedirs(working_path)
|
os.makedirs(working_path)
|
||||||
|
|
||||||
# Make sure the zip is downloaded
|
# Make sure the zip is downloaded
|
||||||
if not os.path.exists(zip_path):
|
if not os.path.exists(exe_path):
|
||||||
print("Downloading {}".format(zip_url))
|
print("Downloading {}".format(exe_url))
|
||||||
response = urllib.request.urlopen(zip_url)
|
response = urllib.request.urlopen(exe_url)
|
||||||
zip_data = response.read()
|
exe_data = response.read()
|
||||||
open(zip_path, 'wb').write(zip_data)
|
open(exe_path, 'wb').write(exe_data)
|
||||||
zip_sha256 = hashlib.sha256(zip_data).hexdigest()
|
exe_sha256 = hashlib.sha256(exe_data).hexdigest()
|
||||||
else:
|
else:
|
||||||
zip_data = open(zip_path, 'rb').read()
|
exe_data = open(exe_path, 'rb').read()
|
||||||
zip_sha256 = hashlib.sha256(zip_data).hexdigest()
|
exe_sha256 = hashlib.sha256(exe_data).hexdigest()
|
||||||
|
|
||||||
# Compare the hash
|
# Compare the hash
|
||||||
if zip_sha256 != expected_zip_sha256:
|
if exe_sha256 != expected_exe_sha256:
|
||||||
print("ERROR! The sha256 doesn't match:")
|
print("ERROR! The sha256 doesn't match:")
|
||||||
print("expected: {}".format(expected_zip_sha256))
|
print("expected: {}".format(expected_exe_sha256))
|
||||||
print(" actual: {}".format(zip_sha256))
|
print(" actual: {}".format(exe_sha256))
|
||||||
sys.exit(-1)
|
sys.exit(-1)
|
||||||
|
|
||||||
# Extract the zip
|
# Extract the bits we need from the exe
|
||||||
z = zipfile.ZipFile(io.BytesIO(zip_data))
|
cmd = ['7z', 'e', exe_path, 'Browser\TorBrowser\Tor', '-o%s' % os.path.join(working_path, 'Tor')]
|
||||||
z.extractall(working_path)
|
cmd2 = ['7z', 'e', exe_path, 'Browser\TorBrowser\Data\Tor\geoip*', '-o%s' % os.path.join(working_path, 'Data')]
|
||||||
|
subprocess.Popen(cmd).wait()
|
||||||
# Delete un-used files
|
subprocess.Popen(cmd2).wait()
|
||||||
os.remove(os.path.join(os.path.join(working_path, 'Tor'), 'tor-gencert.exe'))
|
|
||||||
|
|
||||||
# Copy into dist
|
# Copy into dist
|
||||||
if os.path.exists(dist_path):
|
if os.path.exists(dist_path):
|
||||||
shutil.rmtree(dist_path)
|
shutil.rmtree(dist_path)
|
||||||
os.makedirs(dist_path)
|
os.makedirs(dist_path)
|
||||||
shutil.copytree( os.path.join(working_path, 'Tor'), os.path.join(dist_path, 'Tor') )
|
shutil.copytree( os.path.join(working_path, 'Tor'), os.path.join(dist_path, 'Tor') )
|
||||||
shutil.copytree( os.path.join(working_path, 'Data'), os.path.join(dist_path, 'Data') )
|
shutil.copytree( os.path.join(working_path, 'Data'), os.path.join(dist_path, 'Data', 'Tor') )
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
main()
|
main()
|
||||||
|
|
|
@ -191,6 +191,7 @@ Section "install"
|
||||||
File "${BINPATH}\share\license.txt"
|
File "${BINPATH}\share\license.txt"
|
||||||
File "${BINPATH}\share\torrc_template"
|
File "${BINPATH}\share\torrc_template"
|
||||||
File "${BINPATH}\share\torrc_template-windows"
|
File "${BINPATH}\share\torrc_template-windows"
|
||||||
|
File "${BINPATH}\share\torrc_template-obfs4"
|
||||||
File "${BINPATH}\share\version.txt"
|
File "${BINPATH}\share\version.txt"
|
||||||
File "${BINPATH}\share\wordlist.txt"
|
File "${BINPATH}\share\wordlist.txt"
|
||||||
|
|
||||||
|
@ -235,6 +236,7 @@ Section "install"
|
||||||
File "${BINPATH}\tor\Tor\libevent_extra-2-0-5.dll"
|
File "${BINPATH}\tor\Tor\libevent_extra-2-0-5.dll"
|
||||||
File "${BINPATH}\tor\Tor\libgcc_s_sjlj-1.dll"
|
File "${BINPATH}\tor\Tor\libgcc_s_sjlj-1.dll"
|
||||||
File "${BINPATH}\tor\Tor\libssp-0.dll"
|
File "${BINPATH}\tor\Tor\libssp-0.dll"
|
||||||
|
File "${BINPATH}\tor\Tor\obfs4proxy.exe"
|
||||||
File "${BINPATH}\tor\Tor\ssleay32.dll"
|
File "${BINPATH}\tor\Tor\ssleay32.dll"
|
||||||
File "${BINPATH}\tor\Tor\tor.exe"
|
File "${BINPATH}\tor\Tor\tor.exe"
|
||||||
File "${BINPATH}\tor\Tor\zlib1.dll"
|
File "${BINPATH}\tor\Tor\zlib1.dll"
|
||||||
|
@ -401,6 +403,7 @@ FunctionEnd
|
||||||
Delete "$INSTDIR\share\locale\tr.json"
|
Delete "$INSTDIR\share\locale\tr.json"
|
||||||
Delete "$INSTDIR\share\torrc_template"
|
Delete "$INSTDIR\share\torrc_template"
|
||||||
Delete "$INSTDIR\share\torrc_template-windows"
|
Delete "$INSTDIR\share\torrc_template-windows"
|
||||||
|
Delete "$INSTDIR\share\torrc_template-obfs4"
|
||||||
Delete "$INSTDIR\share\version.txt"
|
Delete "$INSTDIR\share\version.txt"
|
||||||
Delete "$INSTDIR\share\wordlist.txt"
|
Delete "$INSTDIR\share\wordlist.txt"
|
||||||
Delete "$INSTDIR\sip.pyd"
|
Delete "$INSTDIR\sip.pyd"
|
||||||
|
@ -412,6 +415,7 @@ FunctionEnd
|
||||||
Delete "$INSTDIR\tor\Tor\libevent_extra-2-0-5.dll"
|
Delete "$INSTDIR\tor\Tor\libevent_extra-2-0-5.dll"
|
||||||
Delete "$INSTDIR\tor\Tor\libgcc_s_sjlj-1.dll"
|
Delete "$INSTDIR\tor\Tor\libgcc_s_sjlj-1.dll"
|
||||||
Delete "$INSTDIR\tor\Tor\libssp-0.dll"
|
Delete "$INSTDIR\tor\Tor\libssp-0.dll"
|
||||||
|
Delete "$INSTDIR\tor\Tor\obfs4proxy.exe"
|
||||||
Delete "$INSTDIR\tor\Tor\ssleay32.dll"
|
Delete "$INSTDIR\tor\Tor\ssleay32.dll"
|
||||||
Delete "$INSTDIR\tor\Tor\tor.exe"
|
Delete "$INSTDIR\tor\Tor\tor.exe"
|
||||||
Delete "$INSTDIR\tor\Tor\zlib1.dll"
|
Delete "$INSTDIR\tor\Tor\zlib1.dll"
|
||||||
|
|
|
@ -14,6 +14,7 @@ a = Analysis(
|
||||||
('../share/version.txt', 'share'),
|
('../share/version.txt', 'share'),
|
||||||
('../share/wordlist.txt', 'share'),
|
('../share/wordlist.txt', 'share'),
|
||||||
('../share/torrc_template', 'share'),
|
('../share/torrc_template', 'share'),
|
||||||
|
('../share/torrc_template-obfs4', 'share'),
|
||||||
('../share/torrc_template-windows', 'share'),
|
('../share/torrc_template-windows', 'share'),
|
||||||
('../share/images/*', 'share/images'),
|
('../share/images/*', 'share/images'),
|
||||||
('../share/locale/*', 'share/locale'),
|
('../share/locale/*', 'share/locale'),
|
||||||
|
|
|
@ -94,9 +94,11 @@ def get_tor_paths():
|
||||||
tor_path = '/usr/bin/tor'
|
tor_path = '/usr/bin/tor'
|
||||||
tor_geo_ip_file_path = '/usr/share/tor/geoip'
|
tor_geo_ip_file_path = '/usr/share/tor/geoip'
|
||||||
tor_geo_ipv6_file_path = '/usr/share/tor/geoip6'
|
tor_geo_ipv6_file_path = '/usr/share/tor/geoip6'
|
||||||
|
obfs4proxy_file_path = '/usr/bin/obfs4proxy'
|
||||||
elif p == 'Windows':
|
elif p == 'Windows':
|
||||||
base_path = os.path.join(os.path.dirname(os.path.dirname(get_resource_path(''))), 'tor')
|
base_path = os.path.join(os.path.dirname(os.path.dirname(get_resource_path(''))), 'tor')
|
||||||
tor_path = os.path.join(os.path.join(base_path, 'Tor'), "tor.exe")
|
tor_path = os.path.join(os.path.join(base_path, 'Tor'), 'tor.exe')
|
||||||
|
obfs4proxy_file_path = os.path.join(os.path.join(base_path, 'Tor'), 'obfs4proxy.exe')
|
||||||
tor_geo_ip_file_path = os.path.join(os.path.join(os.path.join(base_path, 'Data'), 'Tor'), 'geoip')
|
tor_geo_ip_file_path = os.path.join(os.path.join(os.path.join(base_path, 'Data'), 'Tor'), 'geoip')
|
||||||
tor_geo_ipv6_file_path = os.path.join(os.path.join(os.path.join(base_path, 'Data'), 'Tor'), 'geoip6')
|
tor_geo_ipv6_file_path = os.path.join(os.path.join(os.path.join(base_path, 'Data'), 'Tor'), 'geoip6')
|
||||||
elif p == 'Darwin':
|
elif p == 'Darwin':
|
||||||
|
@ -104,12 +106,14 @@ def get_tor_paths():
|
||||||
tor_path = os.path.join(base_path, 'Resources', 'Tor', 'tor')
|
tor_path = os.path.join(base_path, 'Resources', 'Tor', 'tor')
|
||||||
tor_geo_ip_file_path = os.path.join(base_path, 'Resources', 'Tor', 'geoip')
|
tor_geo_ip_file_path = os.path.join(base_path, 'Resources', 'Tor', 'geoip')
|
||||||
tor_geo_ipv6_file_path = os.path.join(base_path, 'Resources', 'Tor', 'geoip6')
|
tor_geo_ipv6_file_path = os.path.join(base_path, 'Resources', 'Tor', 'geoip6')
|
||||||
|
obfs4proxy_file_path = os.path.join(base_path, 'Resources', 'Tor', 'obfs4proxy')
|
||||||
elif p == 'OpenBSD' or p == 'FreeBSD':
|
elif p == 'OpenBSD' or p == 'FreeBSD':
|
||||||
tor_path = '/usr/local/bin/tor'
|
tor_path = '/usr/local/bin/tor'
|
||||||
tor_geo_ip_file_path = '/usr/local/share/tor/geoip'
|
tor_geo_ip_file_path = '/usr/local/share/tor/geoip'
|
||||||
tor_geo_ipv6_file_path = '/usr/local/share/tor/geoip6'
|
tor_geo_ipv6_file_path = '/usr/local/share/tor/geoip6'
|
||||||
|
obfs4proxy_file_path = '/usr/local/bin/obfs4proxy'
|
||||||
|
|
||||||
return (tor_path, tor_geo_ip_file_path, tor_geo_ipv6_file_path)
|
return (tor_path, tor_geo_ip_file_path, tor_geo_ipv6_file_path, obfs4proxy_file_path)
|
||||||
|
|
||||||
|
|
||||||
def get_version():
|
def get_version():
|
||||||
|
|
|
@ -140,7 +140,7 @@ class Onion(object):
|
||||||
self.bundle_tor_supported = True
|
self.bundle_tor_supported = True
|
||||||
|
|
||||||
# Set the path of the tor binary, for bundled tor
|
# Set the path of the tor binary, for bundled tor
|
||||||
(self.tor_path, self.tor_geo_ip_file_path, self.tor_geo_ipv6_file_path) = common.get_tor_paths()
|
(self.tor_path, self.tor_geo_ip_file_path, self.tor_geo_ipv6_file_path, self.obfs4proxy_file_path) = common.get_tor_paths()
|
||||||
|
|
||||||
# The tor process
|
# The tor process
|
||||||
self.tor_proc = None
|
self.tor_proc = None
|
||||||
|
@ -205,6 +205,16 @@ class Onion(object):
|
||||||
with open(self.tor_torrc, 'w') as f:
|
with open(self.tor_torrc, 'w') as f:
|
||||||
f.write(torrc_template)
|
f.write(torrc_template)
|
||||||
|
|
||||||
|
# Bridge support
|
||||||
|
if self.settings.get('tor_bridges_use_obfs4'):
|
||||||
|
f.write('ClientTransportPlugin obfs4 exec {}\n'.format(self.obfs4proxy_file_path))
|
||||||
|
with open(common.get_resource_path('torrc_template-obfs4')) as o:
|
||||||
|
for line in o:
|
||||||
|
f.write(line)
|
||||||
|
if self.settings.get('tor_bridges_use_custom_bridges'):
|
||||||
|
f.write(self.settings.get('tor_bridges_use_custom_bridges'))
|
||||||
|
f.write('\nUseBridges 1')
|
||||||
|
|
||||||
# Execute a tor subprocess
|
# Execute a tor subprocess
|
||||||
start_ts = time.time()
|
start_ts = time.time()
|
||||||
if self.system == 'Windows':
|
if self.system == 'Windows':
|
||||||
|
@ -254,8 +264,13 @@ class Onion(object):
|
||||||
break
|
break
|
||||||
time.sleep(0.2)
|
time.sleep(0.2)
|
||||||
|
|
||||||
# Timeout after 90 seconds
|
# If using bridges, it might take a bit longer to connect to Tor
|
||||||
if time.time() - start_ts > 90:
|
if self.settings.get('tor_bridges_use_custom_bridges') or self.settings.get('tor_bridges_use_obfs4'):
|
||||||
|
connect_timeout = 150
|
||||||
|
else:
|
||||||
|
# Timeout after 120 seconds
|
||||||
|
connect_timeout = 120
|
||||||
|
if time.time() - start_ts > connect_timeout:
|
||||||
print("")
|
print("")
|
||||||
self.tor_proc.terminate()
|
self.tor_proc.terminate()
|
||||||
raise BundledTorTimeout(strings._('settings_error_bundled_tor_timeout'))
|
raise BundledTorTimeout(strings._('settings_error_bundled_tor_timeout'))
|
||||||
|
|
|
@ -61,6 +61,9 @@ class Settings(object):
|
||||||
'use_stealth': False,
|
'use_stealth': False,
|
||||||
'use_autoupdate': True,
|
'use_autoupdate': True,
|
||||||
'autoupdate_timestamp': None,
|
'autoupdate_timestamp': None,
|
||||||
|
'no_bridges': True,
|
||||||
|
'tor_bridges_use_obfs4': False,
|
||||||
|
'tor_bridges_use_custom_bridges': '',
|
||||||
'save_private_key': False,
|
'save_private_key': False,
|
||||||
'private_key': '',
|
'private_key': '',
|
||||||
'slug': '',
|
'slug': '',
|
||||||
|
|
|
@ -18,7 +18,7 @@ You should have received a copy of the GNU General Public License
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
"""
|
"""
|
||||||
from PyQt5 import QtCore, QtWidgets, QtGui
|
from PyQt5 import QtCore, QtWidgets, QtGui
|
||||||
import sys, platform, datetime
|
import sys, platform, datetime, re
|
||||||
|
|
||||||
from onionshare import strings, common
|
from onionshare import strings, common
|
||||||
from onionshare.settings import Settings
|
from onionshare.settings import Settings
|
||||||
|
@ -140,6 +140,51 @@ class SettingsDialog(QtWidgets.QDialog):
|
||||||
if (system == 'Windows' or system == 'Darwin') and getattr(sys, 'onionshare_dev_mode', False):
|
if (system == 'Windows' or system == 'Darwin') and getattr(sys, 'onionshare_dev_mode', False):
|
||||||
self.connection_type_bundled_radio.setEnabled(False)
|
self.connection_type_bundled_radio.setEnabled(False)
|
||||||
|
|
||||||
|
# Bridge options for bundled tor
|
||||||
|
|
||||||
|
# No bridges option radio
|
||||||
|
self.tor_bridges_no_bridges_radio = QtWidgets.QRadioButton(strings._('gui_settings_tor_bridges_no_bridges_radio_option', True))
|
||||||
|
self.tor_bridges_no_bridges_radio.toggled.connect(self.tor_bridges_no_bridges_radio_toggled)
|
||||||
|
|
||||||
|
# obfs4 option radio
|
||||||
|
# if the obfs4proxy binary is missing, we can't use obfs4 transports
|
||||||
|
(self.tor_path, self.tor_geo_ip_file_path, self.tor_geo_ipv6_file_path, self.obfs4proxy_file_path) = common.get_tor_paths()
|
||||||
|
if not os.path.isfile(self.obfs4proxy_file_path):
|
||||||
|
self.tor_bridges_use_obfs4_radio = QtWidgets.QRadioButton(strings._('gui_settings_tor_bridges_obfs4_radio_option_no_obfs4proxy', True))
|
||||||
|
self.tor_bridges_use_obfs4_radio.setEnabled(False)
|
||||||
|
else:
|
||||||
|
self.tor_bridges_use_obfs4_radio = QtWidgets.QRadioButton(strings._('gui_settings_tor_bridges_obfs4_radio_option', True))
|
||||||
|
self.tor_bridges_use_obfs4_radio.toggled.connect(self.tor_bridges_use_obfs4_radio_toggled)
|
||||||
|
|
||||||
|
# Custom bridges radio and textbox
|
||||||
|
self.tor_bridges_use_custom_radio = QtWidgets.QRadioButton(strings._('gui_settings_tor_bridges_custom_radio_option', True))
|
||||||
|
self.tor_bridges_use_custom_radio.toggled.connect(self.tor_bridges_use_custom_radio_toggled)
|
||||||
|
|
||||||
|
self.tor_bridges_use_custom_label = QtWidgets.QLabel(strings._('gui_settings_tor_bridges_custom_label', True))
|
||||||
|
self.tor_bridges_use_custom_label.setTextInteractionFlags(QtCore.Qt.TextBrowserInteraction)
|
||||||
|
self.tor_bridges_use_custom_label.setOpenExternalLinks(True)
|
||||||
|
self.tor_bridges_use_custom_textbox = QtWidgets.QPlainTextEdit()
|
||||||
|
self.tor_bridges_use_custom_textbox.setMaximumHeight(200)
|
||||||
|
self.tor_bridges_use_custom_textbox.setPlaceholderText('[address:port] [identifier]')
|
||||||
|
|
||||||
|
tor_bridges_use_custom_textbox_options_layout = QtWidgets.QVBoxLayout()
|
||||||
|
tor_bridges_use_custom_textbox_options_layout.addWidget(self.tor_bridges_use_custom_label)
|
||||||
|
tor_bridges_use_custom_textbox_options_layout.addWidget(self.tor_bridges_use_custom_textbox)
|
||||||
|
|
||||||
|
self.tor_bridges_use_custom_textbox_options = QtWidgets.QWidget()
|
||||||
|
self.tor_bridges_use_custom_textbox_options.setLayout(tor_bridges_use_custom_textbox_options_layout)
|
||||||
|
self.tor_bridges_use_custom_textbox_options.hide()
|
||||||
|
|
||||||
|
# Bridges layout/widget
|
||||||
|
bridges_layout = QtWidgets.QVBoxLayout()
|
||||||
|
bridges_layout.addWidget(self.tor_bridges_no_bridges_radio)
|
||||||
|
bridges_layout.addWidget(self.tor_bridges_use_obfs4_radio)
|
||||||
|
bridges_layout.addWidget(self.tor_bridges_use_custom_radio)
|
||||||
|
bridges_layout.addWidget(self.tor_bridges_use_custom_textbox_options)
|
||||||
|
|
||||||
|
self.bridges = QtWidgets.QWidget()
|
||||||
|
self.bridges.setLayout(bridges_layout)
|
||||||
|
|
||||||
# Automatic
|
# Automatic
|
||||||
self.connection_type_automatic_radio = QtWidgets.QRadioButton(strings._('gui_settings_connection_type_automatic_option', True))
|
self.connection_type_automatic_radio = QtWidgets.QRadioButton(strings._('gui_settings_connection_type_automatic_option', True))
|
||||||
self.connection_type_automatic_radio.toggled.connect(self.connection_type_automatic_toggled)
|
self.connection_type_automatic_radio.toggled.connect(self.connection_type_automatic_toggled)
|
||||||
|
@ -238,6 +283,13 @@ class SettingsDialog(QtWidgets.QDialog):
|
||||||
connection_type_group = QtWidgets.QGroupBox()
|
connection_type_group = QtWidgets.QGroupBox()
|
||||||
connection_type_group.setLayout(connection_type_group_layout)
|
connection_type_group.setLayout(connection_type_group_layout)
|
||||||
|
|
||||||
|
# The Bridges options are not exclusive (enabling Bridges offers obfs4 or custom bridges)
|
||||||
|
connection_type_bridges_radio_group_layout = QtWidgets.QVBoxLayout()
|
||||||
|
connection_type_bridges_radio_group_layout.addWidget(self.bridges)
|
||||||
|
self.connection_type_bridges_radio_group = QtWidgets.QGroupBox(strings._("gui_settings_tor_bridges", True))
|
||||||
|
self.connection_type_bridges_radio_group.setLayout(connection_type_bridges_radio_group_layout)
|
||||||
|
self.connection_type_bridges_radio_group.hide()
|
||||||
|
|
||||||
# Buttons
|
# Buttons
|
||||||
self.save_button = QtWidgets.QPushButton(strings._('gui_settings_button_save', True))
|
self.save_button = QtWidgets.QPushButton(strings._('gui_settings_button_save', True))
|
||||||
self.save_button.clicked.connect(self.save_clicked)
|
self.save_button.clicked.connect(self.save_clicked)
|
||||||
|
@ -266,6 +318,7 @@ class SettingsDialog(QtWidgets.QDialog):
|
||||||
right_col_layout = QtWidgets.QVBoxLayout()
|
right_col_layout = QtWidgets.QVBoxLayout()
|
||||||
right_col_layout.addWidget(connection_type_radio_group)
|
right_col_layout.addWidget(connection_type_radio_group)
|
||||||
right_col_layout.addWidget(connection_type_group)
|
right_col_layout.addWidget(connection_type_group)
|
||||||
|
right_col_layout.addWidget(self.connection_type_bridges_radio_group)
|
||||||
right_col_layout.addWidget(self.tor_status)
|
right_col_layout.addWidget(self.tor_status)
|
||||||
right_col_layout.addStretch()
|
right_col_layout.addStretch()
|
||||||
|
|
||||||
|
@ -345,6 +398,25 @@ class SettingsDialog(QtWidgets.QDialog):
|
||||||
self.authenticate_password_radio.setChecked(True)
|
self.authenticate_password_radio.setChecked(True)
|
||||||
self.authenticate_password_extras_password.setText(self.old_settings.get('auth_password'))
|
self.authenticate_password_extras_password.setText(self.old_settings.get('auth_password'))
|
||||||
|
|
||||||
|
if self.old_settings.get('no_bridges'):
|
||||||
|
self.tor_bridges_no_bridges_radio.setChecked(True)
|
||||||
|
self.tor_bridges_use_obfs4_radio.setChecked(False)
|
||||||
|
self.tor_bridges_use_custom_radio.setChecked(False)
|
||||||
|
else:
|
||||||
|
self.tor_bridges_no_bridges_radio.setChecked(False)
|
||||||
|
self.tor_bridges_use_obfs4_radio.setChecked(self.old_settings.get('tor_bridges_use_obfs4'))
|
||||||
|
if self.old_settings.get('tor_bridges_use_custom_bridges'):
|
||||||
|
self.tor_bridges_use_custom_radio.setChecked(True)
|
||||||
|
# Remove the 'Bridge' lines at the start of each bridge.
|
||||||
|
# They are added automatically to provide compatibility with
|
||||||
|
# copying/pasting bridges provided from https://bridges.torproject.org
|
||||||
|
new_bridges = []
|
||||||
|
bridges = self.old_settings.get('tor_bridges_use_custom_bridges').split('Bridge ')
|
||||||
|
for bridge in bridges:
|
||||||
|
new_bridges.append(bridge)
|
||||||
|
new_bridges = ''.join(new_bridges)
|
||||||
|
self.tor_bridges_use_custom_textbox.setPlainText(new_bridges)
|
||||||
|
|
||||||
def connection_type_bundled_toggled(self, checked):
|
def connection_type_bundled_toggled(self, checked):
|
||||||
"""
|
"""
|
||||||
Connection type bundled was toggled. If checked, hide authentication fields.
|
Connection type bundled was toggled. If checked, hide authentication fields.
|
||||||
|
@ -353,6 +425,28 @@ class SettingsDialog(QtWidgets.QDialog):
|
||||||
if checked:
|
if checked:
|
||||||
self.authenticate_group.hide()
|
self.authenticate_group.hide()
|
||||||
self.connection_type_socks.hide()
|
self.connection_type_socks.hide()
|
||||||
|
self.connection_type_bridges_radio_group.show()
|
||||||
|
|
||||||
|
def tor_bridges_no_bridges_radio_toggled(self, checked):
|
||||||
|
"""
|
||||||
|
'No bridges' option was toggled. If checked, enable other bridge options.
|
||||||
|
"""
|
||||||
|
if checked:
|
||||||
|
self.tor_bridges_use_custom_textbox_options.hide()
|
||||||
|
|
||||||
|
def tor_bridges_use_obfs4_radio_toggled(self, checked):
|
||||||
|
"""
|
||||||
|
obfs4 bridges option was toggled. If checked, disable custom bridge options.
|
||||||
|
"""
|
||||||
|
if checked:
|
||||||
|
self.tor_bridges_use_custom_textbox_options.hide()
|
||||||
|
|
||||||
|
def tor_bridges_use_custom_radio_toggled(self, checked):
|
||||||
|
"""
|
||||||
|
Custom bridges option was toggled. If checked, show custom bridge options.
|
||||||
|
"""
|
||||||
|
if checked:
|
||||||
|
self.tor_bridges_use_custom_textbox_options.show()
|
||||||
|
|
||||||
def connection_type_automatic_toggled(self, checked):
|
def connection_type_automatic_toggled(self, checked):
|
||||||
"""
|
"""
|
||||||
|
@ -362,6 +456,7 @@ class SettingsDialog(QtWidgets.QDialog):
|
||||||
if checked:
|
if checked:
|
||||||
self.authenticate_group.hide()
|
self.authenticate_group.hide()
|
||||||
self.connection_type_socks.hide()
|
self.connection_type_socks.hide()
|
||||||
|
self.connection_type_bridges_radio_group.hide()
|
||||||
|
|
||||||
def connection_type_control_port_toggled(self, checked):
|
def connection_type_control_port_toggled(self, checked):
|
||||||
"""
|
"""
|
||||||
|
@ -373,6 +468,7 @@ class SettingsDialog(QtWidgets.QDialog):
|
||||||
self.authenticate_group.show()
|
self.authenticate_group.show()
|
||||||
self.connection_type_control_port_extras.show()
|
self.connection_type_control_port_extras.show()
|
||||||
self.connection_type_socks.show()
|
self.connection_type_socks.show()
|
||||||
|
self.connection_type_bridges_radio_group.hide()
|
||||||
else:
|
else:
|
||||||
self.connection_type_control_port_extras.hide()
|
self.connection_type_control_port_extras.hide()
|
||||||
|
|
||||||
|
@ -387,6 +483,7 @@ class SettingsDialog(QtWidgets.QDialog):
|
||||||
self.authenticate_group.show()
|
self.authenticate_group.show()
|
||||||
self.connection_type_socket_file_extras.show()
|
self.connection_type_socket_file_extras.show()
|
||||||
self.connection_type_socks.show()
|
self.connection_type_socks.show()
|
||||||
|
self.connection_type_bridges_radio_group.hide()
|
||||||
else:
|
else:
|
||||||
self.connection_type_socket_file_extras.hide()
|
self.connection_type_socket_file_extras.hide()
|
||||||
|
|
||||||
|
@ -513,7 +610,9 @@ class SettingsDialog(QtWidgets.QDialog):
|
||||||
if changed(settings, self.old_settings, [
|
if changed(settings, self.old_settings, [
|
||||||
'connection_type', 'control_port_address',
|
'connection_type', 'control_port_address',
|
||||||
'control_port_port', 'socks_address', 'socks_port',
|
'control_port_port', 'socks_address', 'socks_port',
|
||||||
'socket_file_path', 'auth_type', 'auth_password']):
|
'socket_file_path', 'auth_type', 'auth_password',
|
||||||
|
'no_bridges', 'tor_bridges_use_obfs4',
|
||||||
|
'tor_bridges_use_custom_bridges']):
|
||||||
|
|
||||||
reboot_onion = True
|
reboot_onion = True
|
||||||
|
|
||||||
|
@ -614,6 +713,38 @@ class SettingsDialog(QtWidgets.QDialog):
|
||||||
|
|
||||||
settings.set('auth_password', self.authenticate_password_extras_password.text())
|
settings.set('auth_password', self.authenticate_password_extras_password.text())
|
||||||
|
|
||||||
|
# Whether we use bridges
|
||||||
|
if self.tor_bridges_no_bridges_radio.isChecked():
|
||||||
|
settings.set('no_bridges', True)
|
||||||
|
settings.set('tor_bridges_use_obfs4', False)
|
||||||
|
settings.set('tor_bridges_use_custom_bridges', '')
|
||||||
|
if self.tor_bridges_use_obfs4_radio.isChecked():
|
||||||
|
settings.set('no_bridges', False)
|
||||||
|
settings.set('tor_bridges_use_obfs4', True)
|
||||||
|
settings.set('tor_bridges_use_custom_bridges', '')
|
||||||
|
if self.tor_bridges_use_custom_radio.isChecked():
|
||||||
|
settings.set('no_bridges', False)
|
||||||
|
settings.set('tor_bridges_use_obfs4', False)
|
||||||
|
# Insert a 'Bridge' line at the start of each bridge.
|
||||||
|
# This makes it easier to copy/paste a set of bridges
|
||||||
|
# provided from https://bridges.torproject.org
|
||||||
|
new_bridges = []
|
||||||
|
bridges = self.tor_bridges_use_custom_textbox.toPlainText().split('\n')
|
||||||
|
bridges_valid = False
|
||||||
|
for bridge in bridges:
|
||||||
|
if bridge != '':
|
||||||
|
# Check the syntax of the custom bridge to make sure it looks legitimate
|
||||||
|
pattern = re.compile("[0-9.]+:[0-9]+\s[A-Z0-9]+$")
|
||||||
|
if pattern.match(bridge):
|
||||||
|
new_bridges.append(''.join(['Bridge ', bridge, '\n']))
|
||||||
|
bridges_valid = True
|
||||||
|
if bridges_valid:
|
||||||
|
new_bridges = ''.join(new_bridges)
|
||||||
|
settings.set('tor_bridges_use_custom_bridges', new_bridges)
|
||||||
|
else:
|
||||||
|
Alert(strings._('gui_settings_tor_bridges_invalid', True))
|
||||||
|
settings.set('no_bridges', True)
|
||||||
|
|
||||||
return settings
|
return settings
|
||||||
|
|
||||||
def closeEvent(self, e):
|
def closeEvent(self, e):
|
||||||
|
|
|
@ -91,6 +91,13 @@
|
||||||
"gui_settings_authenticate_cookie_option": "Cookie",
|
"gui_settings_authenticate_cookie_option": "Cookie",
|
||||||
"gui_settings_password_label": "Password",
|
"gui_settings_password_label": "Password",
|
||||||
"gui_settings_cookie_label": "Cookie path",
|
"gui_settings_cookie_label": "Cookie path",
|
||||||
|
"gui_settings_tor_bridges": "Tor Bridge support",
|
||||||
|
"gui_settings_tor_bridges_no_bridges_radio_option": "Don't use bridges",
|
||||||
|
"gui_settings_tor_bridges_obfs4_radio_option": "Use obfs4 pluggable transports",
|
||||||
|
"gui_settings_tor_bridges_obfs4_radio_option_no_obfs4proxy": "Use obfs4 pluggable transports (requires obfs4proxy)",
|
||||||
|
"gui_settings_tor_bridges_custom_radio_option": "Use custom bridges (non-pluggable transports)",
|
||||||
|
"gui_settings_tor_bridges_custom_label": "You can get bridges from <a href=\"https://bridges.torproject.org/bridges\">https://bridges.torproject.org</a>",
|
||||||
|
"gui_settings_tor_bridges_invalid": "None of the bridges you supplied seem to be valid, so they've been ignored.\nPlease try again with valid bridges.",
|
||||||
"gui_settings_button_save": "Save",
|
"gui_settings_button_save": "Save",
|
||||||
"gui_settings_button_cancel": "Cancel",
|
"gui_settings_button_cancel": "Cancel",
|
||||||
"gui_settings_button_help": "Help",
|
"gui_settings_button_help": "Help",
|
||||||
|
|
27
share/torrc_template-obfs4
Normal file
27
share/torrc_template-obfs4
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
Bridge obfs4 154.35.22.10:80 8FB9F4319E89E5C6223052AA525A192AFBC85D55 cert=GGGS1TX4R81m3r0HBl79wKy1OtPPNR2CZUIrHjkRg65Vc2VR8fOyo64f9kmT1UAFG7j0HQ iat-mode=0
|
||||||
|
Bridge obfs4 83.212.101.3:50002 A09D536DD1752D542E1FBB3C9CE4449D51298239 cert=lPRQ/MXdD1t5SRZ9MquYQNT9m5DV757jtdXdlePmRCudUU9CFUOX1Tm7/meFSyPOsud7Cw iat-mode=0
|
||||||
|
Bridge obfs4 109.105.109.165:10527 8DFCD8FB3285E855F5A55EDDA35696C743ABFC4E cert=Bvg/itxeL4TWKLP6N1MaQzSOC6tcRIBv6q57DYAZc3b2AzuM+/TfB7mqTFEfXILCjEwzVA iat-mode=1
|
||||||
|
Bridge obfs4 154.35.22.11:80 A832D176ECD5C7C6B58825AE22FC4C90FA249637 cert=YPbQqXPiqTUBfjGFLpm9JYEFTBvnzEJDKJxXG5Sxzrr/v2qrhGU4Jls9lHjLAhqpXaEfZw iat-mode=0
|
||||||
|
Bridge obfs4 37.218.245.14:38224 D9A82D2F9C2F65A18407B1D2B764F130847F8B5D cert=bjRaMrr1BRiAW8IE9U5z27fQaYgOhX1UCmOpg2pFpoMvo6ZgQMzLsaTzzQNTlm7hNcb+Sg iat-mode=0
|
||||||
|
Bridge obfs4 154.35.22.9:443 C73ADBAC8ADFDBF0FC0F3F4E8091C0107D093716 cert=gEGKc5WN/bSjFa6UkG9hOcft1tuK+cV8hbZ0H6cqXiMPLqSbCh2Q3PHe5OOr6oMVORhoJA iat-mode=0
|
||||||
|
Bridge obfs4 154.35.22.11:443 A832D176ECD5C7C6B58825AE22FC4C90FA249637 cert=YPbQqXPiqTUBfjGFLpm9JYEFTBvnzEJDKJxXG5Sxzrr/v2qrhGU4Jls9lHjLAhqpXaEfZw iat-mode=0
|
||||||
|
Bridge obfs4 154.35.22.13:443 FE7840FE1E21FE0A0639ED176EDA00A3ECA1E34D cert=fKnzxr+m+jWXXQGCaXe4f2gGoPXMzbL+bTBbXMYXuK0tMotd+nXyS33y2mONZWU29l81CA iat-mode=0
|
||||||
|
Bridge obfs4 154.35.22.10:443 8FB9F4319E89E5C6223052AA525A192AFBC85D55 cert=GGGS1TX4R81m3r0HBl79wKy1OtPPNR2CZUIrHjkRg65Vc2VR8fOyo64f9kmT1UAFG7j0HQ iat-mode=0
|
||||||
|
Bridge obfs4 154.35.22.9:80 C73ADBAC8ADFDBF0FC0F3F4E8091C0107D093716 cert=gEGKc5WN/bSjFa6UkG9hOcft1tuK+cV8hbZ0H6cqXiMPLqSbCh2Q3PHe5OOr6oMVORhoJA iat-mode=0
|
||||||
|
Bridge obfs4 192.99.11.54:443 7B126FAB960E5AC6A629C729434FF84FB5074EC2 cert=VW5f8+IBUWpPFxF+rsiVy2wXkyTQG7vEd+rHeN2jV5LIDNu8wMNEOqZXPwHdwMVEBdqXEw iat-mode=0
|
||||||
|
Bridge obfs4 154.35.22.13:16815 FE7840FE1E21FE0A0639ED176EDA00A3ECA1E34D cert=fKnzxr+m+jWXXQGCaXe4f2gGoPXMzbL+bTBbXMYXuK0tMotd+nXyS33y2mONZWU29l81CA iat-mode=0
|
||||||
|
Bridge obfs4 85.31.186.26:443 91A6354697E6B02A386312F68D82CF86824D3606 cert=PBwr+S8JTVZo6MPdHnkTwXJPILWADLqfMGoVvhZClMq/Urndyd42BwX9YFJHZnBB3H0XCw iat-mode=0
|
||||||
|
Bridge obfs4 38.229.33.83:80 0BAC39417268B96B9F514E7F63FA6FBA1A788955 cert=VwEFpk9F/UN9JED7XpG1XOjm/O8ZCXK80oPecgWnNDZDv5pdkhq1OpbAH0wNqOT6H6BmRQ iat-mode=1
|
||||||
|
Bridge obfs4 154.35.22.11:16488 A832D176ECD5C7C6B58825AE22FC4C90FA249637 cert=YPbQqXPiqTUBfjGFLpm9JYEFTBvnzEJDKJxXG5Sxzrr/v2qrhGU4Jls9lHjLAhqpXaEfZw iat-mode=0
|
||||||
|
Bridge obfs4 154.35.22.9:12166 C73ADBAC8ADFDBF0FC0F3F4E8091C0107D093716 cert=gEGKc5WN/bSjFa6UkG9hOcft1tuK+cV8hbZ0H6cqXiMPLqSbCh2Q3PHe5OOr6oMVORhoJA iat-mode=0
|
||||||
|
Bridge obfs4 109.105.109.147:13764 BBB28DF0F201E706BE564EFE690FE9577DD8386D cert=KfMQN/tNMFdda61hMgpiMI7pbwU1T+wxjTulYnfw+4sgvG0zSH7N7fwT10BI8MUdAD7iJA iat-mode=2
|
||||||
|
Bridge obfs4 38.229.1.78:80 C8CBDB2464FC9804A69531437BCF2BE31FDD2EE4 cert=Hmyfd2ev46gGY7NoVxA9ngrPF2zCZtzskRTzoWXbxNkzeVnGFPWmrTtILRyqCTjHR+s9dg iat-mode=1
|
||||||
|
Bridge obfs4 [2001:470:b381:bfff:216:3eff:fe23:d6c3]:443 CDF2E852BF539B82BD10E27E9115A31734E378C2 cert=qUVQ0srL1JI/vO6V6m/24anYXiJD3QP2HgzUKQtQ7GRqqUvs7P+tG43RtAqdhLOALP7DJQ iat-mode=1
|
||||||
|
Bridge obfs4 85.17.30.79:443 FC259A04A328A07FED1413E9FC6526530D9FD87A cert=RutxZlu8BtyP+y0NX7bAVD41+J/qXNhHUrKjFkRSdiBAhIHIQLhKQ2HxESAKZprn/lR3KA iat-mode=0
|
||||||
|
Bridge obfs4 154.35.22.10:15937 8FB9F4319E89E5C6223052AA525A192AFBC85D55 cert=GGGS1TX4R81m3r0HBl79wKy1OtPPNR2CZUIrHjkRg65Vc2VR8fOyo64f9kmT1UAFG7j0HQ iat-mode=0
|
||||||
|
Bridge obfs4 37.218.240.34:40035 88CD36D45A35271963EF82E511C8827A24730913 cert=eGXYfWODcgqIdPJ+rRupg4GGvVGfh25FWaIXZkit206OSngsp7GAIiGIXOJJROMxEqFKJg iat-mode=1
|
||||||
|
Bridge obfs4 192.95.36.142:443 CDF2E852BF539B82BD10E27E9115A31734E378C2 cert=qUVQ0srL1JI/vO6V6m/24anYXiJD3QP2HgzUKQtQ7GRqqUvs7P+tG43RtAqdhLOALP7DJQ iat-mode=1
|
||||||
|
Bridge obfs4 154.35.22.12:80 00DC6C4FA49A65BD1472993CF6730D54F11E0DBB cert=N86E9hKXXXVz6G7w2z8wFfhIDztDAzZ/3poxVePHEYjbKDWzjkRDccFMAnhK75fc65pYSg iat-mode=0
|
||||||
|
Bridge obfs4 85.31.186.98:443 011F2599C0E9B27EE74B353155E244813763C3E5 cert=ayq0XzCwhpdysn5o0EyDUbmSOx3X/oTEbzDMvczHOdBJKlvIdHHLJGkZARtT4dcBFArPPg iat-mode=0
|
||||||
|
Bridge obfs4 154.35.22.12:4304 00DC6C4FA49A65BD1472993CF6730D54F11E0DBB cert=N86E9hKXXXVz6G7w2z8wFfhIDztDAzZ/3poxVePHEYjbKDWzjkRDccFMAnhK75fc65pYSg iat-mode=0
|
||||||
|
UseBridges 1
|
|
@ -1,6 +1,6 @@
|
||||||
[DEFAULT]
|
[DEFAULT]
|
||||||
Package3: onionshare
|
Package3: onionshare
|
||||||
Depends3: python3-flask, python3-stem, python3-pyqt5, python-nautilus, tor
|
Depends3: python3-flask, python3-stem, python3-pyqt5, python-nautilus, tor, obfs4proxy
|
||||||
Build-Depends: python3-pytest, python3-flask, python3-stem, python3-pyqt5
|
Build-Depends: python3-pytest, python3-flask, python3-stem, python3-pyqt5
|
||||||
Suite: xenial
|
Suite: xenial
|
||||||
X-Python3-Version: >= 3.4
|
X-Python3-Version: >= 3.4
|
||||||
|
|
|
@ -213,13 +213,15 @@ class TestGetTorPaths:
|
||||||
base_path, 'Resources', 'Tor', 'geoip')
|
base_path, 'Resources', 'Tor', 'geoip')
|
||||||
tor_geo_ipv6_file_path = os.path.join(
|
tor_geo_ipv6_file_path = os.path.join(
|
||||||
base_path, 'Resources', 'Tor', 'geoip6')
|
base_path, 'Resources', 'Tor', 'geoip6')
|
||||||
|
obfs4proxy_file_path = os.path.join(
|
||||||
|
base_path, 'Resources', 'Tor', 'obfs4proxy')
|
||||||
assert (common.get_tor_paths() ==
|
assert (common.get_tor_paths() ==
|
||||||
(tor_path, tor_geo_ip_file_path, tor_geo_ipv6_file_path))
|
(tor_path, tor_geo_ip_file_path, tor_geo_ipv6_file_path, obfs4proxy_file_path))
|
||||||
|
|
||||||
# @pytest.mark.skipif(sys.platform != 'Linux', reason='requires Linux') ?
|
# @pytest.mark.skipif(sys.platform != 'Linux', reason='requires Linux') ?
|
||||||
def test_get_tor_paths_linux(self, platform_linux):
|
def test_get_tor_paths_linux(self, platform_linux):
|
||||||
assert (common.get_tor_paths() ==
|
assert (common.get_tor_paths() ==
|
||||||
('/usr/bin/tor', '/usr/share/tor/geoip', '/usr/share/tor/geoip6'))
|
('/usr/bin/tor', '/usr/share/tor/geoip', '/usr/share/tor/geoip6', '/usr/bin/obfs4proxy'))
|
||||||
|
|
||||||
# @pytest.mark.skipif(sys.platform != 'Windows', reason='requires Windows') ?
|
# @pytest.mark.skipif(sys.platform != 'Windows', reason='requires Windows') ?
|
||||||
def test_get_tor_paths_windows(self, platform_windows, sys_frozen):
|
def test_get_tor_paths_windows(self, platform_windows, sys_frozen):
|
||||||
|
@ -228,7 +230,9 @@ class TestGetTorPaths:
|
||||||
os.path.dirname(
|
os.path.dirname(
|
||||||
common.get_resource_path(''))), 'tor')
|
common.get_resource_path(''))), 'tor')
|
||||||
tor_path = os.path.join(
|
tor_path = os.path.join(
|
||||||
os.path.join(base_path, 'Tor'), "tor.exe")
|
os.path.join(base_path, 'Tor'), 'tor.exe')
|
||||||
|
obfs4proxy_file_path = os.path.join(
|
||||||
|
os.path.join(base_path, 'Tor'), 'obfs4proxy.exe')
|
||||||
tor_geo_ip_file_path = os.path.join(
|
tor_geo_ip_file_path = os.path.join(
|
||||||
os.path.join(
|
os.path.join(
|
||||||
os.path.join(base_path, 'Data'), 'Tor'), 'geoip')
|
os.path.join(base_path, 'Data'), 'Tor'), 'geoip')
|
||||||
|
@ -236,7 +240,7 @@ class TestGetTorPaths:
|
||||||
os.path.join(
|
os.path.join(
|
||||||
os.path.join(base_path, 'Data'), 'Tor'), 'geoip6')
|
os.path.join(base_path, 'Data'), 'Tor'), 'geoip6')
|
||||||
assert (common.get_tor_paths() ==
|
assert (common.get_tor_paths() ==
|
||||||
(tor_path, tor_geo_ip_file_path, tor_geo_ipv6_file_path))
|
(tor_path, tor_geo_ip_file_path, tor_geo_ipv6_file_path, obfs4proxy_file_path))
|
||||||
|
|
||||||
|
|
||||||
class TestGetVersion:
|
class TestGetVersion:
|
||||||
|
|
|
@ -58,6 +58,9 @@ class TestSettings:
|
||||||
'use_stealth': False,
|
'use_stealth': False,
|
||||||
'use_autoupdate': True,
|
'use_autoupdate': True,
|
||||||
'autoupdate_timestamp': None,
|
'autoupdate_timestamp': None,
|
||||||
|
'no_bridges': True,
|
||||||
|
'tor_bridges_use_obfs4': False,
|
||||||
|
'tor_bridges_use_custom_bridges': '',
|
||||||
'save_private_key': False,
|
'save_private_key': False,
|
||||||
'private_key': '',
|
'private_key': '',
|
||||||
'slug': '',
|
'slug': '',
|
||||||
|
@ -119,6 +122,11 @@ class TestSettings:
|
||||||
assert settings_obj.get('use_stealth') is False
|
assert settings_obj.get('use_stealth') is False
|
||||||
assert settings_obj.get('use_autoupdate') is True
|
assert settings_obj.get('use_autoupdate') is True
|
||||||
assert settings_obj.get('autoupdate_timestamp') is None
|
assert settings_obj.get('autoupdate_timestamp') is None
|
||||||
|
assert settings_obj.get('autoupdate_timestamp') is None
|
||||||
|
assert settings_obj.get('no_bridges') is True
|
||||||
|
assert settings_obj.get('tor_bridges_use_obfs4') is False
|
||||||
|
assert settings_obj.get('tor_bridges_use_custom_bridges') == ''
|
||||||
|
|
||||||
|
|
||||||
def test_set_version(self, settings_obj):
|
def test_set_version(self, settings_obj):
|
||||||
settings_obj.set('version', 'CUSTOM_VERSION')
|
settings_obj.set('version', 'CUSTOM_VERSION')
|
||||||
|
@ -165,3 +173,7 @@ class TestSettings:
|
||||||
monkeypatch.setenv('APPDATA', 'C:')
|
monkeypatch.setenv('APPDATA', 'C:')
|
||||||
obj = settings.Settings()
|
obj = settings.Settings()
|
||||||
assert obj.filename == 'C:\\OnionShare\\onionshare.json'
|
assert obj.filename == 'C:\\OnionShare\\onionshare.json'
|
||||||
|
|
||||||
|
def test_set_custom_bridge(self, settings_obj):
|
||||||
|
settings_obj.set('tor_bridges_use_custom_bridges', 'Bridge 45.3.20.65:9050 21300AD88890A49C429A6CB9959CFD44490A8F6E')
|
||||||
|
assert settings_obj._settings['tor_bridges_use_custom_bridges'] == 'Bridge 45.3.20.65:9050 21300AD88890A49C429A6CB9959CFD44490A8F6E'
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue