mirror of
https://github.com/onionshare/onionshare.git
synced 2025-08-11 15:50:40 -04:00
Resolve conflicts in locale
This commit is contained in:
commit
dbae142a87
38 changed files with 3114 additions and 1603 deletions
|
@ -27,13 +27,10 @@ from datetime import datetime
|
|||
from datetime import timedelta
|
||||
|
||||
from .common import Common, CannotFindTor
|
||||
from .censorship import CensorshipCircumvention
|
||||
from .meek import Meek, MeekNotRunning
|
||||
from .web import Web
|
||||
from .onion import (
|
||||
TorErrorProtocolError,
|
||||
TorTooOldEphemeral,
|
||||
TorTooOldStealth,
|
||||
Onion,
|
||||
)
|
||||
from .onion import TorErrorProtocolError, TorTooOldEphemeral, TorTooOldStealth, Onion
|
||||
from .onionshare import OnionShare
|
||||
from .mode_settings import ModeSettings
|
||||
|
||||
|
@ -94,12 +91,7 @@ def main(cwd=None):
|
|||
help="Filename of persistent session",
|
||||
)
|
||||
# General args
|
||||
parser.add_argument(
|
||||
"--title",
|
||||
metavar="TITLE",
|
||||
default=None,
|
||||
help="Set a title",
|
||||
)
|
||||
parser.add_argument("--title", metavar="TITLE", default=None, help="Set a title")
|
||||
parser.add_argument(
|
||||
"--public",
|
||||
action="store_true",
|
||||
|
@ -308,6 +300,20 @@ def main(cwd=None):
|
|||
# Create the Web object
|
||||
web = Web(common, False, mode_settings, mode)
|
||||
|
||||
# Create the Meek object and start the meek client
|
||||
# meek = Meek(common)
|
||||
# meek.start()
|
||||
|
||||
# Create the CensorshipCircumvention object to make
|
||||
# API calls to Tor over Meek
|
||||
censorship = CensorshipCircumvention(common, meek)
|
||||
# Example: request recommended bridges, pretending to be from China, using
|
||||
# domain fronting.
|
||||
# censorship_recommended_settings = censorship.request_settings(country="cn")
|
||||
# print(censorship_recommended_settings)
|
||||
# Clean up the meek subprocess once we're done working with the censorship circumvention API
|
||||
# meek.cleanup()
|
||||
|
||||
# Start the Onion object
|
||||
try:
|
||||
onion = Onion(common, use_tmp_dir=True)
|
||||
|
@ -424,7 +430,7 @@ def main(cwd=None):
|
|||
sys.exit(1)
|
||||
|
||||
# Warn about sending large files over Tor
|
||||
if web.share_mode.download_filesize >= 157286400: # 150mb
|
||||
if web.share_mode.download_filesize >= 157_286_400: # 150mb
|
||||
print("")
|
||||
print("Warning: Sending a large share could take hours")
|
||||
print("")
|
||||
|
|
169
cli/onionshare_cli/censorship.py
Normal file
169
cli/onionshare_cli/censorship.py
Normal file
|
@ -0,0 +1,169 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
OnionShare | https://onionshare.org/
|
||||
|
||||
Copyright (C) 2014-2021 Micah Lee, et al. <micah@micahflee.com>
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
"""
|
||||
import requests
|
||||
|
||||
from .meek import MeekNotRunning
|
||||
|
||||
|
||||
class CensorshipCircumvention(object):
|
||||
"""
|
||||
Connect to the Tor Moat APIs to retrieve censorship
|
||||
circumvention recommendations, over the Meek client.
|
||||
"""
|
||||
|
||||
def __init__(self, common, meek, domain_fronting=True):
|
||||
"""
|
||||
Set up the CensorshipCircumvention object to hold
|
||||
common and meek objects.
|
||||
"""
|
||||
self.common = common
|
||||
self.meek = meek
|
||||
self.common.log("CensorshipCircumvention", "__init__")
|
||||
|
||||
# Bail out if we requested domain fronting but we can't use meek
|
||||
if domain_fronting and not self.meek.meek_proxies:
|
||||
raise MeekNotRunning()
|
||||
|
||||
def request_map(self, country=False):
|
||||
"""
|
||||
Retrieves the Circumvention map from Tor Project and store it
|
||||
locally for further look-ups if required.
|
||||
|
||||
Optionally pass a country code in order to get recommended settings
|
||||
just for that country.
|
||||
|
||||
Note that this API endpoint doesn't return actual bridges,
|
||||
it just returns the recommended bridge type countries.
|
||||
"""
|
||||
endpoint = "https://bridges.torproject.org/moat/circumvention/map"
|
||||
data = {}
|
||||
if country:
|
||||
data = {"country": country}
|
||||
|
||||
r = requests.post(
|
||||
endpoint,
|
||||
json=data,
|
||||
headers={"Content-Type": "application/vnd.api+json"},
|
||||
proxies=self.meek.meek_proxies,
|
||||
)
|
||||
if r.status_code != 200:
|
||||
self.common.log(
|
||||
"CensorshipCircumvention",
|
||||
"censorship_obtain_map",
|
||||
f"status_code={r.status_code}",
|
||||
)
|
||||
return False
|
||||
|
||||
result = r.json()
|
||||
|
||||
if "errors" in result:
|
||||
self.common.log(
|
||||
"CensorshipCircumvention",
|
||||
"censorship_obtain_map",
|
||||
f"errors={result['errors']}",
|
||||
)
|
||||
return False
|
||||
|
||||
return result
|
||||
|
||||
def request_settings(self, country=False, transports=False):
|
||||
"""
|
||||
Retrieves the Circumvention Settings from Tor Project, which
|
||||
will return recommended settings based on the country code of
|
||||
the requesting IP.
|
||||
|
||||
Optionally, a country code can be specified in order to override
|
||||
the IP detection.
|
||||
|
||||
Optionally, a list of transports can be specified in order to
|
||||
return recommended settings for just that transport type.
|
||||
"""
|
||||
endpoint = "https://bridges.torproject.org/moat/circumvention/settings"
|
||||
data = {}
|
||||
if country:
|
||||
data = {"country": country}
|
||||
if transports:
|
||||
data.append({"transports": transports})
|
||||
r = requests.post(
|
||||
endpoint,
|
||||
json=data,
|
||||
headers={"Content-Type": "application/vnd.api+json"},
|
||||
proxies=self.meek.meek_proxies,
|
||||
)
|
||||
if r.status_code != 200:
|
||||
self.common.log(
|
||||
"CensorshipCircumvention",
|
||||
"censorship_obtain_settings",
|
||||
f"status_code={r.status_code}",
|
||||
)
|
||||
return False
|
||||
|
||||
result = r.json()
|
||||
|
||||
if "errors" in result:
|
||||
self.common.log(
|
||||
"CensorshipCircumvention",
|
||||
"censorship_obtain_settings",
|
||||
f"errors={result['errors']}",
|
||||
)
|
||||
return False
|
||||
|
||||
# There are no settings - perhaps this country doesn't require censorship circumvention?
|
||||
# This is not really an error, so we can just check if False and assume direct Tor
|
||||
# connection will work.
|
||||
if not "settings" in result:
|
||||
self.common.log(
|
||||
"CensorshipCircumvention",
|
||||
"censorship_obtain_settings",
|
||||
"No settings found for this country",
|
||||
)
|
||||
return False
|
||||
|
||||
return result
|
||||
|
||||
def request_builtin_bridges(self):
|
||||
"""
|
||||
Retrieves the list of built-in bridges from the Tor Project.
|
||||
"""
|
||||
endpoint = "https://bridges.torproject.org/moat/circumvention/builtin"
|
||||
r = requests.post(
|
||||
endpoint,
|
||||
headers={"Content-Type": "application/vnd.api+json"},
|
||||
proxies=self.meek.meek_proxies,
|
||||
)
|
||||
if r.status_code != 200:
|
||||
self.common.log(
|
||||
"CensorshipCircumvention",
|
||||
"censorship_obtain_builtin_bridges",
|
||||
f"status_code={r.status_code}",
|
||||
)
|
||||
return False
|
||||
|
||||
result = r.json()
|
||||
|
||||
if "errors" in result:
|
||||
self.common.log(
|
||||
"CensorshipCircumvention",
|
||||
"censorship_obtain_builtin_bridges",
|
||||
f"errors={result['errors']}",
|
||||
)
|
||||
return False
|
||||
|
||||
return result
|
|
@ -22,6 +22,7 @@ import hashlib
|
|||
import os
|
||||
import platform
|
||||
import random
|
||||
import requests
|
||||
import socket
|
||||
import sys
|
||||
import threading
|
||||
|
@ -313,6 +314,8 @@ class Common:
|
|||
if not tor_path:
|
||||
raise CannotFindTor()
|
||||
obfs4proxy_file_path = shutil.which("obfs4proxy")
|
||||
snowflake_file_path = shutil.which("snowflake-client")
|
||||
meek_client_file_path = shutil.which("meek-client")
|
||||
prefix = os.path.dirname(os.path.dirname(tor_path))
|
||||
tor_geo_ip_file_path = os.path.join(prefix, "share/tor/geoip")
|
||||
tor_geo_ipv6_file_path = os.path.join(prefix, "share/tor/geoip6")
|
||||
|
@ -320,6 +323,8 @@ class Common:
|
|||
base_path = self.get_resource_path("tor")
|
||||
tor_path = os.path.join(base_path, "Tor", "tor.exe")
|
||||
obfs4proxy_file_path = os.path.join(base_path, "Tor", "obfs4proxy.exe")
|
||||
snowflake_file_path = os.path.join(base_path, "Tor", "snowflake-client.exe")
|
||||
meek_client_file_path = os.path.join(base_path, "Tor", "meek-client.exe")
|
||||
tor_geo_ip_file_path = os.path.join(base_path, "Data", "Tor", "geoip")
|
||||
tor_geo_ipv6_file_path = os.path.join(base_path, "Data", "Tor", "geoip6")
|
||||
elif self.platform == "Darwin":
|
||||
|
@ -327,6 +332,8 @@ class Common:
|
|||
if not tor_path:
|
||||
raise CannotFindTor()
|
||||
obfs4proxy_file_path = shutil.which("obfs4proxy")
|
||||
snowflake_file_path = shutil.which("snowflake-client")
|
||||
meek_client_file_path = shutil.which("meek-client")
|
||||
prefix = os.path.dirname(os.path.dirname(tor_path))
|
||||
tor_geo_ip_file_path = os.path.join(prefix, "share/tor/geoip")
|
||||
tor_geo_ipv6_file_path = os.path.join(prefix, "share/tor/geoip6")
|
||||
|
@ -335,12 +342,16 @@ class Common:
|
|||
tor_geo_ip_file_path = "/usr/local/share/tor/geoip"
|
||||
tor_geo_ipv6_file_path = "/usr/local/share/tor/geoip6"
|
||||
obfs4proxy_file_path = "/usr/local/bin/obfs4proxy"
|
||||
snowflake_file_path = "/usr/local/bin/snowflake-client"
|
||||
meek_client_file_path = "/usr/local/bin/meek-client"
|
||||
|
||||
return (
|
||||
tor_path,
|
||||
tor_geo_ip_file_path,
|
||||
tor_geo_ipv6_file_path,
|
||||
obfs4proxy_file_path,
|
||||
snowflake_file_path,
|
||||
meek_client_file_path,
|
||||
)
|
||||
|
||||
def build_data_dir(self):
|
||||
|
|
210
cli/onionshare_cli/meek.py
Normal file
210
cli/onionshare_cli/meek.py
Normal file
|
@ -0,0 +1,210 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
OnionShare | https://onionshare.org/
|
||||
|
||||
Copyright (C) 2014-2021 Micah Lee, et al. <micah@micahflee.com>
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
"""
|
||||
import os
|
||||
import subprocess
|
||||
import time
|
||||
from queue import Queue, Empty
|
||||
from threading import Thread
|
||||
|
||||
|
||||
class Meek(object):
|
||||
"""
|
||||
The Meek object starts the meek-client as a subprocess.
|
||||
This process is used to do domain-fronting to connect to
|
||||
the Tor APIs for censorship circumvention and retrieving
|
||||
bridges, before connecting to Tor.
|
||||
"""
|
||||
|
||||
def __init__(self, common, get_tor_paths=None):
|
||||
"""
|
||||
Set up the Meek object
|
||||
"""
|
||||
|
||||
self.common = common
|
||||
self.common.log("Meek", "__init__")
|
||||
|
||||
# Set the path of the meek binary
|
||||
if not get_tor_paths:
|
||||
get_tor_paths = self.common.get_tor_paths
|
||||
(
|
||||
self.tor_path,
|
||||
self.tor_geo_ip_file_path,
|
||||
self.tor_geo_ipv6_file_path,
|
||||
self.obfs4proxy_file_path,
|
||||
self.snowflake_file_path,
|
||||
self.meek_client_file_path,
|
||||
) = get_tor_paths()
|
||||
|
||||
self.meek_proxies = {}
|
||||
self.meek_url = "https://moat.torproject.org.global.prod.fastly.net/"
|
||||
self.meek_front = "cdn.sstatic.net"
|
||||
self.meek_env = {
|
||||
"TOR_PT_MANAGED_TRANSPORT_VER": "1",
|
||||
"TOR_PT_CLIENT_TRANSPORTS": "meek",
|
||||
}
|
||||
self.meek_host = "127.0.0.1"
|
||||
self.meek_port = None
|
||||
|
||||
def start(self):
|
||||
"""
|
||||
Start the Meek Client and populate the SOCKS proxies dict
|
||||
for use with requests to the Tor Moat API.
|
||||
"""
|
||||
# Small method to read stdout from the subprocess.
|
||||
# We use this to obtain the random port that Meek
|
||||
# started on
|
||||
def enqueue_output(out, queue):
|
||||
for line in iter(out.readline, b""):
|
||||
queue.put(line)
|
||||
out.close()
|
||||
|
||||
# Abort early if we can't find the Meek client
|
||||
if self.meek_client_file_path is None or not os.path.exists(
|
||||
self.meek_client_file_path
|
||||
):
|
||||
raise MeekNotFound()
|
||||
|
||||
# Start the Meek Client as a subprocess.
|
||||
self.common.log("Meek", "start", "Starting meek client")
|
||||
|
||||
if self.common.platform == "Windows":
|
||||
env = os.environ.copy()
|
||||
for key in self.meek_env:
|
||||
env[key] = self.meek_env[key]
|
||||
|
||||
# In Windows, hide console window when opening meek-client.exe subprocess
|
||||
startupinfo = subprocess.STARTUPINFO()
|
||||
startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW
|
||||
self.meek_proc = subprocess.Popen(
|
||||
[
|
||||
self.meek_client_file_path,
|
||||
"--url",
|
||||
self.meek_url,
|
||||
"--front",
|
||||
self.meek_front,
|
||||
],
|
||||
stdout=subprocess.PIPE,
|
||||
stderr=subprocess.PIPE,
|
||||
startupinfo=startupinfo,
|
||||
bufsize=1,
|
||||
env=env,
|
||||
text=True,
|
||||
)
|
||||
else:
|
||||
self.meek_proc = subprocess.Popen(
|
||||
[
|
||||
self.meek_client_file_path,
|
||||
"--url",
|
||||
self.meek_url,
|
||||
"--front",
|
||||
self.meek_front,
|
||||
],
|
||||
stdout=subprocess.PIPE,
|
||||
stderr=subprocess.PIPE,
|
||||
bufsize=1,
|
||||
env=self.meek_env,
|
||||
text=True,
|
||||
)
|
||||
|
||||
# Queue up the stdout from the subprocess for polling later
|
||||
q = Queue()
|
||||
t = Thread(target=enqueue_output, args=(self.meek_proc.stdout, q))
|
||||
t.daemon = True # thread dies with the program
|
||||
t.start()
|
||||
|
||||
while True:
|
||||
# read stdout without blocking
|
||||
try:
|
||||
line = q.get_nowait()
|
||||
self.common.log("Meek", "start", line.strip())
|
||||
except Empty:
|
||||
# no stdout yet?
|
||||
pass
|
||||
else: # we got stdout
|
||||
if "CMETHOD meek socks5" in line:
|
||||
self.meek_host = line.split(" ")[3].split(":")[0]
|
||||
self.meek_port = line.split(" ")[3].split(":")[1]
|
||||
self.common.log(
|
||||
"Meek",
|
||||
"start",
|
||||
f"Meek running on {self.meek_host}:{self.meek_port}",
|
||||
)
|
||||
break
|
||||
|
||||
if "CMETHOD-ERROR" in line:
|
||||
self.cleanup()
|
||||
raise MeekNotRunning()
|
||||
|
||||
if self.meek_port:
|
||||
self.meek_proxies = {
|
||||
"http": f"socks5h://{self.meek_host}:{self.meek_port}",
|
||||
"https": f"socks5h://{self.meek_host}:{self.meek_port}",
|
||||
}
|
||||
else:
|
||||
self.common.log("Meek", "start", "Could not obtain the meek port")
|
||||
self.cleanup()
|
||||
raise MeekNotRunning()
|
||||
|
||||
def cleanup(self):
|
||||
"""
|
||||
Kill any meek subprocesses.
|
||||
"""
|
||||
self.common.log("Meek", "cleanup")
|
||||
|
||||
if self.meek_proc:
|
||||
self.meek_proc.terminate()
|
||||
time.sleep(0.2)
|
||||
if self.meek_proc.poll() is None:
|
||||
self.common.log(
|
||||
"Meek",
|
||||
"cleanup",
|
||||
"Tried to terminate meek-client process but it's still running",
|
||||
)
|
||||
try:
|
||||
self.meek_proc.kill()
|
||||
time.sleep(0.2)
|
||||
if self.meek_proc.poll() is None:
|
||||
self.common.log(
|
||||
"Meek",
|
||||
"cleanup",
|
||||
"Tried to kill meek-client process but it's still running",
|
||||
)
|
||||
except Exception:
|
||||
self.common.log(
|
||||
"Meek", "cleanup", "Exception while killing meek-client process"
|
||||
)
|
||||
self.meek_proc = None
|
||||
|
||||
# Reset other Meek settings
|
||||
self.meek_proxies = {}
|
||||
self.meek_port = None
|
||||
|
||||
|
||||
class MeekNotRunning(Exception):
|
||||
"""
|
||||
We were unable to start Meek or obtain the port
|
||||
number it started on, in order to do domain fronting.
|
||||
"""
|
||||
|
||||
|
||||
class MeekNotFound(Exception):
|
||||
"""
|
||||
We were unable to find the Meek Client binary.
|
||||
"""
|
|
@ -153,6 +153,8 @@ class Onion(object):
|
|||
self.tor_geo_ip_file_path,
|
||||
self.tor_geo_ipv6_file_path,
|
||||
self.obfs4proxy_file_path,
|
||||
self.snowflake_file_path,
|
||||
self.meek_client_file_path,
|
||||
) = get_tor_paths()
|
||||
|
||||
# The tor process
|
||||
|
@ -178,10 +180,10 @@ class Onion(object):
|
|||
key_bytes = bytes(key)
|
||||
key_b32 = base64.b32encode(key_bytes)
|
||||
# strip trailing ====
|
||||
assert key_b32[-4:] == b'===='
|
||||
assert key_b32[-4:] == b"===="
|
||||
key_b32 = key_b32[:-4]
|
||||
# change from b'ASDF' to ASDF
|
||||
s = key_b32.decode('utf-8')
|
||||
s = key_b32.decode("utf-8")
|
||||
return s
|
||||
|
||||
def connect(
|
||||
|
@ -198,8 +200,6 @@ class Onion(object):
|
|||
)
|
||||
return
|
||||
|
||||
self.common.log("Onion", "connect")
|
||||
|
||||
# Either use settings that are passed in, or use them from common
|
||||
if custom_settings:
|
||||
self.settings = custom_settings
|
||||
|
@ -210,6 +210,12 @@ class Onion(object):
|
|||
self.common.load_settings()
|
||||
self.settings = self.common.settings
|
||||
|
||||
self.common.log(
|
||||
"Onion",
|
||||
"connect",
|
||||
f"connection_type={self.settings.get('connection_type')}",
|
||||
)
|
||||
|
||||
# The Tor controller
|
||||
self.c = None
|
||||
|
||||
|
@ -302,43 +308,50 @@ class Onion(object):
|
|||
torrc_template = torrc_template.replace(
|
||||
"{{socks_port}}", str(self.tor_socks_port)
|
||||
)
|
||||
torrc_template = torrc_template.replace(
|
||||
"{{obfs4proxy_path}}", str(self.obfs4proxy_file_path)
|
||||
)
|
||||
torrc_template = torrc_template.replace(
|
||||
"{{snowflake_path}}", str(self.snowflake_file_path)
|
||||
)
|
||||
|
||||
with open(self.tor_torrc, "w") as f:
|
||||
f.write(torrc_template)
|
||||
|
||||
# Bridge support
|
||||
if self.settings.get("tor_bridges_use_obfs4"):
|
||||
f.write(
|
||||
f"ClientTransportPlugin obfs4 exec {self.obfs4proxy_file_path}\n"
|
||||
)
|
||||
with open(
|
||||
self.common.get_resource_path("torrc_template-obfs4")
|
||||
) as o:
|
||||
for line in o:
|
||||
f.write(line)
|
||||
elif self.settings.get("tor_bridges_use_meek_lite_azure"):
|
||||
f.write(
|
||||
f"ClientTransportPlugin meek_lite exec {self.obfs4proxy_file_path}\n"
|
||||
)
|
||||
with open(
|
||||
self.common.get_resource_path("torrc_template-meek_lite_azure")
|
||||
) as o:
|
||||
for line in o:
|
||||
f.write(line)
|
||||
if self.settings.get("bridges_enabled"):
|
||||
if self.settings.get("bridges_type") == "built-in":
|
||||
if self.settings.get("bridges_builtin_pt") == "obfs4":
|
||||
with open(
|
||||
self.common.get_resource_path("torrc_template-obfs4")
|
||||
) as o:
|
||||
f.write(o.read())
|
||||
elif self.settings.get("bridges_builtin_pt") == "meek-azure":
|
||||
with open(
|
||||
self.common.get_resource_path(
|
||||
"torrc_template-meek_lite_azure"
|
||||
)
|
||||
) as o:
|
||||
f.write(o.read())
|
||||
elif self.settings.get("bridges_builtin_pt") == "snowflake":
|
||||
with open(
|
||||
self.common.get_resource_path(
|
||||
"torrc_template-snowflake"
|
||||
)
|
||||
) as o:
|
||||
f.write(o.read())
|
||||
|
||||
if self.settings.get("tor_bridges_use_custom_bridges"):
|
||||
if "obfs4" in self.settings.get("tor_bridges_use_custom_bridges"):
|
||||
f.write(
|
||||
f"ClientTransportPlugin obfs4 exec {self.obfs4proxy_file_path}\n"
|
||||
)
|
||||
elif "meek_lite" in self.settings.get(
|
||||
"tor_bridges_use_custom_bridges"
|
||||
):
|
||||
f.write(
|
||||
f"ClientTransportPlugin meek_lite exec {self.obfs4proxy_file_path}\n"
|
||||
)
|
||||
f.write(self.settings.get("tor_bridges_use_custom_bridges"))
|
||||
f.write("\nUseBridges 1")
|
||||
elif self.settings.get("bridges_type") == "moat":
|
||||
for line in self.settings.get("bridges_moat").split("\n"):
|
||||
if line.strip() != "":
|
||||
f.write(f"Bridge {line}\n")
|
||||
f.write("\nUseBridges 1\n")
|
||||
|
||||
elif self.settings.get("bridges_type") == "custom":
|
||||
for line in self.settings.get("bridges_custom").split("\n"):
|
||||
if line.strip() != "":
|
||||
f.write(f"Bridge {line}\n")
|
||||
f.write("\nUseBridges 1\n")
|
||||
|
||||
# Execute a tor subprocess
|
||||
start_ts = time.time()
|
||||
|
@ -357,6 +370,7 @@ class Onion(object):
|
|||
[self.tor_path, "-f", self.tor_torrc],
|
||||
stdout=subprocess.PIPE,
|
||||
stderr=subprocess.PIPE,
|
||||
env={"LD_LIBRARY_PATH": os.path.dirname(self.tor_path)},
|
||||
)
|
||||
|
||||
# Wait for the tor controller to start
|
||||
|
@ -410,11 +424,7 @@ class Onion(object):
|
|||
time.sleep(0.2)
|
||||
|
||||
# If using bridges, it might take a bit longer to connect to Tor
|
||||
if (
|
||||
self.settings.get("tor_bridges_use_custom_bridges")
|
||||
or self.settings.get("tor_bridges_use_obfs4")
|
||||
or self.settings.get("tor_bridges_use_meek_lite_azure")
|
||||
):
|
||||
if self.settings.get("bridges_enabled"):
|
||||
# Only override timeout if a custom timeout has not been passed in
|
||||
if connect_timeout == 120:
|
||||
connect_timeout = 150
|
||||
|
@ -650,16 +660,24 @@ class Onion(object):
|
|||
)
|
||||
raise TorTooOldStealth()
|
||||
else:
|
||||
if key_type == "NEW" or not mode_settings.get("onion", "client_auth_priv_key"):
|
||||
if key_type == "NEW" or not mode_settings.get(
|
||||
"onion", "client_auth_priv_key"
|
||||
):
|
||||
# Generate a new key pair for Client Auth on new onions, or if
|
||||
# it's a persistent onion but for some reason we don't them
|
||||
client_auth_priv_key_raw = nacl.public.PrivateKey.generate()
|
||||
client_auth_priv_key = self.key_str(client_auth_priv_key_raw)
|
||||
client_auth_pub_key = self.key_str(client_auth_priv_key_raw.public_key)
|
||||
client_auth_pub_key = self.key_str(
|
||||
client_auth_priv_key_raw.public_key
|
||||
)
|
||||
else:
|
||||
# These should have been saved in settings from the previous run of a persistent onion
|
||||
client_auth_priv_key = mode_settings.get("onion", "client_auth_priv_key")
|
||||
client_auth_pub_key = mode_settings.get("onion", "client_auth_pub_key")
|
||||
client_auth_priv_key = mode_settings.get(
|
||||
"onion", "client_auth_priv_key"
|
||||
)
|
||||
client_auth_pub_key = mode_settings.get(
|
||||
"onion", "client_auth_pub_key"
|
||||
)
|
||||
|
||||
try:
|
||||
if not self.supports_stealth:
|
||||
|
|
|
@ -6,3 +6,7 @@ AvoidDiskWrites 1
|
|||
Log notice stdout
|
||||
GeoIPFile {{geo_ip_file}}
|
||||
GeoIPv6File {{geo_ipv6_file}}
|
||||
|
||||
# Bridge configurations
|
||||
ClientTransportPlugin meek_lite,obfs2,obfs3,obfs4,scramblesuit exec {{obfs4proxy_path}}
|
||||
ClientTransportPlugin snowflake exec {{snowflake_path}} -url https://snowflake-broker.torproject.net.global.prod.fastly.net/ -front cdn.sstatic.net -ice stun:stun.l.google.com:19302,stun:stun.voip.blackberry.com:3478,stun:stun.altar.com.pl:3478,stun:stun.antisip.com:3478,stun:stun.bluesip.net:3478,stun:stun.dus.net:3478,stun:stun.epygi.com:3478,stun:stun.sonetel.com:3478,stun:stun.sonetel.net:3478,stun:stun.stunprotocol.org:3478,stun:stun.uls.co.za:3478,stun:stun.voipgate.com:3478,stun:stun.voys.nl:3478
|
||||
|
|
|
@ -1,2 +0,0 @@
|
|||
Bridge meek_lite 0.0.2.0:2 B9E7141C594AF25699E0079C1F0146F409495296 url=https://d2cly7j4zqgua7.cloudfront.net/ front=a0.awsstatic.com
|
||||
UseBridges 1
|
|
@ -1,2 +1,3 @@
|
|||
# Enable built-in meek-azure bridge
|
||||
Bridge meek_lite 0.0.2.0:3 97700DFE9F483596DDA6264C4D7DF7641E1E39CE url=https://meek.azureedge.net/ front=ajax.aspnetcdn.com
|
||||
UseBridges 1
|
||||
UseBridges 1
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
# Enable built-in obfs4-bridge
|
||||
Bridge obfs4 192.95.36.142:443 CDF2E852BF539B82BD10E27E9115A31734E378C2 cert=qUVQ0srL1JI/vO6V6m/24anYXiJD3QP2HgzUKQtQ7GRqqUvs7P+tG43RtAqdhLOALP7DJQ iat-mode=1
|
||||
Bridge obfs4 38.229.1.78:80 C8CBDB2464FC9804A69531437BCF2BE31FDD2EE4 cert=Hmyfd2ev46gGY7NoVxA9ngrPF2zCZtzskRTzoWXbxNkzeVnGFPWmrTtILRyqCTjHR+s9dg iat-mode=1
|
||||
Bridge obfs4 38.229.33.83:80 0BAC39417268B96B9F514E7F63FA6FBA1A788955 cert=VwEFpk9F/UN9JED7XpG1XOjm/O8ZCXK80oPecgWnNDZDv5pdkhq1OpbAH0wNqOT6H6BmRQ iat-mode=1
|
||||
|
|
3
cli/onionshare_cli/resources/torrc_template-snowflake
Normal file
3
cli/onionshare_cli/resources/torrc_template-snowflake
Normal file
|
@ -0,0 +1,3 @@
|
|||
# Enable built-in snowflake bridge
|
||||
Bridge snowflake 192.0.2.3:1 2B280B23E1107BB62ABFC40DDCC8824814F80A72
|
||||
UseBridges 1
|
|
@ -105,10 +105,11 @@ class Settings(object):
|
|||
"auth_password": "",
|
||||
"use_autoupdate": True,
|
||||
"autoupdate_timestamp": None,
|
||||
"no_bridges": True,
|
||||
"tor_bridges_use_obfs4": False,
|
||||
"tor_bridges_use_meek_lite_azure": False,
|
||||
"tor_bridges_use_custom_bridges": "",
|
||||
"bridges_enabled": False,
|
||||
"bridges_type": "built-in", # "built-in", "moat", or "custom"
|
||||
"bridges_builtin_pt": "obfs4", # "obfs4", "meek-azure", or "snowflake"
|
||||
"bridges_moat": "",
|
||||
"bridges_custom": "",
|
||||
"persistent_tabs": [],
|
||||
"locale": None, # this gets defined in fill_in_defaults()
|
||||
"theme": 0,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue