Allow selecting a snowflake bridge, and make it try to use the snowflake bridge

This commit is contained in:
Micah Lee 2021-10-13 21:11:56 -07:00
parent f2dbc97285
commit 39d624e923
No known key found for this signature in database
GPG key ID: 403C2657CD994F73
7 changed files with 98 additions and 32 deletions

View file

@ -312,6 +312,9 @@ class Common:
# Look in resources first # Look in resources first
base_path = self.get_resource_path("tor") base_path = self.get_resource_path("tor")
if os.path.exists(base_path): if os.path.exists(base_path):
self.log(
"Common", "get_tor_paths", f"using tor binaries in {base_path}"
)
tor_path = os.path.join(base_path, "tor") tor_path = os.path.join(base_path, "tor")
tor_geo_ip_file_path = os.path.join(base_path, "geoip") tor_geo_ip_file_path = os.path.join(base_path, "geoip")
tor_geo_ipv6_file_path = os.path.join(base_path, "geoip6") tor_geo_ipv6_file_path = os.path.join(base_path, "geoip6")
@ -319,6 +322,9 @@ class Common:
snowflake_file_path = os.path.join(base_path, "snowflake-client") snowflake_file_path = os.path.join(base_path, "snowflake-client")
else: else:
# Fallback to looking in the path # Fallback to looking in the path
self.log(
"Common", "get_tor_paths", f"using tor binaries in system path"
)
tor_path = shutil.which("tor") tor_path = shutil.which("tor")
if not tor_path: if not tor_path:
raise CannotFindTor() raise CannotFindTor()

View file

@ -326,6 +326,11 @@ class Onion(object):
) as o: ) as o:
for line in o: for line in o:
f.write(line) f.write(line)
elif self.settings.get("tor_bridges_use_snowflake"):
# Taken from: tor-browser_en-US/Browser/TorBrowser/Data/Tor/torrc-defaults
f.write(
f"ClientTransportPlugin snowflake exec {self.snowflake_file_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\n"
)
if self.settings.get("tor_bridges_use_custom_bridges"): if self.settings.get("tor_bridges_use_custom_bridges"):
if "obfs4" in self.settings.get("tor_bridges_use_custom_bridges"): if "obfs4" in self.settings.get("tor_bridges_use_custom_bridges"):

View file

@ -1,2 +0,0 @@
Bridge meek_lite 0.0.2.0:2 B9E7141C594AF25699E0079C1F0146F409495296 url=https://d2cly7j4zqgua7.cloudfront.net/ front=a0.awsstatic.com
UseBridges 1

View file

@ -108,6 +108,7 @@ class Settings(object):
"no_bridges": True, "no_bridges": True,
"tor_bridges_use_obfs4": False, "tor_bridges_use_obfs4": False,
"tor_bridges_use_meek_lite_azure": False, "tor_bridges_use_meek_lite_azure": False,
"tor_bridges_use_snowflake": False,
"tor_bridges_use_custom_bridges": "", "tor_bridges_use_custom_bridges": "",
"persistent_tabs": [], "persistent_tabs": [],
"locale": None, # this gets defined in fill_in_defaults() "locale": None, # this gets defined in fill_in_defaults()

View file

@ -405,7 +405,21 @@ class GuiCommon:
def get_tor_paths(self): def get_tor_paths(self):
if self.common.platform == "Linux": if self.common.platform == "Linux":
return self.common.get_tor_paths() base_path = self.get_resource_path("tor")
if os.path.exists(base_path):
tor_path = os.path.join(base_path, "tor")
tor_geo_ip_file_path = os.path.join(base_path, "geoip")
tor_geo_ipv6_file_path = os.path.join(base_path, "geoip6")
obfs4proxy_file_path = os.path.join(base_path, "obfs4proxy")
snowflake_file_path = os.path.join(base_path, "snowflake-client")
else:
# Fallback to looking in the path
tor_path = shutil.which("tor")
obfs4proxy_file_path = shutil.which("obfs4proxy")
snowflake_file_path = shutil.which("snowflake-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")
if self.common.platform == "Windows": if self.common.platform == "Windows":
base_path = self.get_resource_path("tor") base_path = self.get_resource_path("tor")

View file

@ -60,13 +60,13 @@
"gui_settings_authenticate_no_auth_option": "No authentication, or cookie authentication", "gui_settings_authenticate_no_auth_option": "No authentication, or cookie authentication",
"gui_settings_authenticate_password_option": "Password", "gui_settings_authenticate_password_option": "Password",
"gui_settings_password_label": "Password", "gui_settings_password_label": "Password",
"gui_settings_tor_bridges": "Would you like to Use a Tor bridge?", "gui_settings_tor_bridges": "Connect using a Tor bridge?",
"gui_settings_tor_bridges_label": "Bridges help you access the Tor Network in places where Tor is blocked. Depending on where you are, one bridge may work better than another.",
"gui_settings_tor_bridges_no_bridges_radio_option": "Don't use a bridge", "gui_settings_tor_bridges_no_bridges_radio_option": "Don't use a bridge",
"gui_settings_tor_bridges_obfs4_radio_option": "Use built-in obfs4 pluggable transports", "gui_settings_tor_bridges_obfs4_radio_option": "Use built-in obfs4 bridge",
"gui_settings_tor_bridges_obfs4_radio_option_no_obfs4proxy": "Use built-in obfs4 pluggable transports (requires obfs4proxy)", "gui_settings_tor_bridges_meek_lite_azure_radio_option": "Use built-in meek-azure bridge",
"gui_settings_tor_bridges_meek_lite_azure_radio_option": "Use built-in meek_lite (Azure) pluggable transports", "gui_settings_tor_bridges_snowflake_radio_option": "Use built-in snowflake bridge",
"gui_settings_tor_bridges_meek_lite_azure_radio_option_no_obfs4proxy": "Use built-in meek_lite (Azure) pluggable transports (requires obfs4proxy)", "gui_settings_meek_lite_expensive_warning": "Warning: The meek-azure bridges are very costly for the Tor Project to run.<br><br>Only use them if unable to connect to Tor directly, via obfs4 transports, or other normal bridges.",
"gui_settings_meek_lite_expensive_warning": "Warning: The meek_lite bridges are very costly for the Tor Project to run.<br><br>Only use them if unable to connect to Tor directly, via obfs4 transports, or other normal bridges.",
"gui_settings_tor_bridges_custom_radio_option": "Use custom bridges", "gui_settings_tor_bridges_custom_radio_option": "Use custom bridges",
"gui_settings_tor_bridges_custom_label": "You can get bridges from <a href=\"https://bridges.torproject.org/options\">https://bridges.torproject.org</a>", "gui_settings_tor_bridges_custom_label": "You can get bridges from <a href=\"https://bridges.torproject.org/options\">https://bridges.torproject.org</a>",
"gui_settings_tor_bridges_invalid": "None of the bridges you added work.\nDouble-check them or add others.", "gui_settings_tor_bridges_invalid": "None of the bridges you added work.\nDouble-check them or add others.",

View file

@ -89,6 +89,9 @@ class TorSettingsDialog(QtWidgets.QDialog):
# Bridge options for bundled tor # Bridge options for bundled tor
bridges_label = QtWidgets.QLabel(strings._("gui_settings_tor_bridges_label"))
bridges_label.setWordWrap(True)
# No bridges option radio # No bridges option radio
self.tor_bridges_no_bridges_radio = QtWidgets.QRadioButton( self.tor_bridges_no_bridges_radio = QtWidgets.QRadioButton(
strings._("gui_settings_tor_bridges_no_bridges_radio_option") strings._("gui_settings_tor_bridges_no_bridges_radio_option")
@ -107,39 +110,55 @@ class TorSettingsDialog(QtWidgets.QDialog):
# obfs4 option radio # obfs4 option radio
# if the obfs4proxy binary is missing, we can't use obfs4 transports # if the obfs4proxy binary is missing, we can't use obfs4 transports
if not self.obfs4proxy_file_path or 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")
)
self.tor_bridges_use_obfs4_radio.setEnabled(False)
else:
self.tor_bridges_use_obfs4_radio = QtWidgets.QRadioButton( self.tor_bridges_use_obfs4_radio = QtWidgets.QRadioButton(
strings._("gui_settings_tor_bridges_obfs4_radio_option") strings._("gui_settings_tor_bridges_obfs4_radio_option")
) )
self.tor_bridges_use_obfs4_radio.toggled.connect( self.tor_bridges_use_obfs4_radio.toggled.connect(
self.tor_bridges_use_obfs4_radio_toggled self.tor_bridges_use_obfs4_radio_toggled
) )
# meek_lite-azure option radio
# if the obfs4proxy binary is missing, we can't use meek_lite-azure transports
if not self.obfs4proxy_file_path or not os.path.isfile( if not self.obfs4proxy_file_path or not os.path.isfile(
self.obfs4proxy_file_path self.obfs4proxy_file_path
): ):
self.tor_bridges_use_meek_lite_azure_radio = QtWidgets.QRadioButton( self.common.log(
strings._( "TorSettingsDialog",
"gui_settings_tor_bridges_meek_lite_azure_radio_option_no_obfs4proxy" "__init__",
f"missing binary {self.obfs4proxy_file_path}, hiding obfs4 bridge",
) )
) self.tor_bridges_use_obfs4_radio.hide()
self.tor_bridges_use_meek_lite_azure_radio.setEnabled(False)
else: # meek-azure option radio
# if the obfs4proxy binary is missing, we can't use meek_lite-azure transports
self.tor_bridges_use_meek_lite_azure_radio = QtWidgets.QRadioButton( self.tor_bridges_use_meek_lite_azure_radio = QtWidgets.QRadioButton(
strings._("gui_settings_tor_bridges_meek_lite_azure_radio_option") strings._("gui_settings_tor_bridges_meek_lite_azure_radio_option")
) )
self.tor_bridges_use_meek_lite_azure_radio.toggled.connect( self.tor_bridges_use_meek_lite_azure_radio.toggled.connect(
self.tor_bridges_use_meek_lite_azure_radio_toggled self.tor_bridges_use_meek_lite_azure_radio_toggled
) )
if not self.obfs4proxy_file_path or not os.path.isfile(
self.obfs4proxy_file_path
):
self.common.log(
"TorSettingsDialog",
"__init__",
f"missing binary {self.obfs4proxy_file_path}, hiding meek-azure bridge",
)
self.tor_bridges_use_meek_lite_azure_radio.hide()
# snowflake option radio
# if the snowflake-client binary is missing, we can't use snowflake transports
self.tor_bridges_use_snowflake_radio = QtWidgets.QRadioButton(
strings._("gui_settings_tor_bridges_snowflake_radio_option")
)
self.tor_bridges_use_snowflake_radio.toggled.connect(
self.tor_bridges_use_snowflake_radio_toggled
)
if not self.snowflake_file_path or not os.path.isfile(self.snowflake_file_path):
self.common.log(
"TorSettingsDialog",
"__init__",
f"missing binary {self.snowflake_file_path}, hiding snowflake bridge",
)
self.tor_bridges_use_snowflake_radio.hide()
# Custom bridges radio and textbox # Custom bridges radio and textbox
self.tor_bridges_use_custom_radio = QtWidgets.QRadioButton( self.tor_bridges_use_custom_radio = QtWidgets.QRadioButton(
@ -178,9 +197,11 @@ class TorSettingsDialog(QtWidgets.QDialog):
# Bridges layout/widget # Bridges layout/widget
bridges_layout = QtWidgets.QVBoxLayout() bridges_layout = QtWidgets.QVBoxLayout()
bridges_layout.addWidget(bridges_label)
bridges_layout.addWidget(self.tor_bridges_no_bridges_radio) 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_obfs4_radio)
bridges_layout.addWidget(self.tor_bridges_use_meek_lite_azure_radio) bridges_layout.addWidget(self.tor_bridges_use_meek_lite_azure_radio)
bridges_layout.addWidget(self.tor_bridges_use_snowflake_radio)
bridges_layout.addWidget(self.tor_bridges_use_custom_radio) bridges_layout.addWidget(self.tor_bridges_use_custom_radio)
bridges_layout.addWidget(self.tor_bridges_use_custom_textbox_options) bridges_layout.addWidget(self.tor_bridges_use_custom_textbox_options)
@ -411,6 +432,7 @@ class TorSettingsDialog(QtWidgets.QDialog):
self.tor_bridges_no_bridges_radio.setChecked(True) self.tor_bridges_no_bridges_radio.setChecked(True)
self.tor_bridges_use_obfs4_radio.setChecked(False) self.tor_bridges_use_obfs4_radio.setChecked(False)
self.tor_bridges_use_meek_lite_azure_radio.setChecked(False) self.tor_bridges_use_meek_lite_azure_radio.setChecked(False)
self.tor_bridges_use_snowflake_radio.setChecked(False)
self.tor_bridges_use_custom_radio.setChecked(False) self.tor_bridges_use_custom_radio.setChecked(False)
else: else:
self.tor_bridges_no_bridges_radio.setChecked(False) self.tor_bridges_no_bridges_radio.setChecked(False)
@ -420,6 +442,9 @@ class TorSettingsDialog(QtWidgets.QDialog):
self.tor_bridges_use_meek_lite_azure_radio.setChecked( self.tor_bridges_use_meek_lite_azure_radio.setChecked(
self.old_settings.get("tor_bridges_use_meek_lite_azure") self.old_settings.get("tor_bridges_use_meek_lite_azure")
) )
self.tor_bridges_use_snowflake_radio.setChecked(
self.old_settings.get("tor_bridges_use_snowflake")
)
if self.old_settings.get("tor_bridges_use_custom_bridges"): if self.old_settings.get("tor_bridges_use_custom_bridges"):
self.tor_bridges_use_custom_radio.setChecked(True) self.tor_bridges_use_custom_radio.setChecked(True)
@ -473,6 +498,13 @@ class TorSettingsDialog(QtWidgets.QDialog):
QtWidgets.QMessageBox.Warning, QtWidgets.QMessageBox.Warning,
) )
def tor_bridges_use_snowflake_radio_toggled(self, checked):
"""
snowflake 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): def tor_bridges_use_custom_radio_toggled(self, checked):
""" """
Custom bridges option was toggled. If checked, show custom bridge options. Custom bridges option was toggled. If checked, show custom bridge options.
@ -712,21 +744,31 @@ class TorSettingsDialog(QtWidgets.QDialog):
settings.set("no_bridges", True) settings.set("no_bridges", True)
settings.set("tor_bridges_use_obfs4", False) settings.set("tor_bridges_use_obfs4", False)
settings.set("tor_bridges_use_meek_lite_azure", False) settings.set("tor_bridges_use_meek_lite_azure", False)
settings.set("tor_bridges_use_snowflake", False)
settings.set("tor_bridges_use_custom_bridges", "") settings.set("tor_bridges_use_custom_bridges", "")
if self.tor_bridges_use_obfs4_radio.isChecked(): if self.tor_bridges_use_obfs4_radio.isChecked():
settings.set("no_bridges", False) settings.set("no_bridges", False)
settings.set("tor_bridges_use_obfs4", True) settings.set("tor_bridges_use_obfs4", True)
settings.set("tor_bridges_use_meek_lite_azure", False) settings.set("tor_bridges_use_meek_lite_azure", False)
settings.set("tor_bridges_use_snowflake", False)
settings.set("tor_bridges_use_custom_bridges", "") settings.set("tor_bridges_use_custom_bridges", "")
if self.tor_bridges_use_meek_lite_azure_radio.isChecked(): if self.tor_bridges_use_meek_lite_azure_radio.isChecked():
settings.set("no_bridges", False) settings.set("no_bridges", False)
settings.set("tor_bridges_use_obfs4", False) settings.set("tor_bridges_use_obfs4", False)
settings.set("tor_bridges_use_meek_lite_azure", True) settings.set("tor_bridges_use_meek_lite_azure", True)
settings.set("tor_bridges_use_snowflake", False)
settings.set("tor_bridges_use_custom_bridges", "")
if self.tor_bridges_use_snowflake_radio.isChecked():
settings.set("no_bridges", False)
settings.set("tor_bridges_use_obfs4", False)
settings.set("tor_bridges_use_meek_lite_azure", False)
settings.set("tor_bridges_use_snowflake", True)
settings.set("tor_bridges_use_custom_bridges", "") settings.set("tor_bridges_use_custom_bridges", "")
if self.tor_bridges_use_custom_radio.isChecked(): if self.tor_bridges_use_custom_radio.isChecked():
settings.set("no_bridges", False) settings.set("no_bridges", False)
settings.set("tor_bridges_use_obfs4", False) settings.set("tor_bridges_use_obfs4", False)
settings.set("tor_bridges_use_meek_lite_azure", False) settings.set("tor_bridges_use_meek_lite_azure", False)
settings.set("tor_bridges_use_snowflake", False)
# Insert a 'Bridge' line at the start of each bridge. # Insert a 'Bridge' line at the start of each bridge.
# This makes it easier to copy/paste a set of bridges # This makes it easier to copy/paste a set of bridges