mirror of
https://github.com/onionshare/onionshare.git
synced 2025-01-10 03:37:28 -03:00
Fetch the built-in bridges from Tor's Censorship Circumvention API, rather than hardcode them
This commit is contained in:
parent
1d0d30458c
commit
19072503a9
8 changed files with 71 additions and 63 deletions
|
@ -18,6 +18,8 @@ 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 .censorship import CensorshipCircumvention
|
||||||
|
from .meek import Meek
|
||||||
from stem.control import Controller
|
from stem.control import Controller
|
||||||
from stem import ProtocolError, SocketClosed
|
from stem import ProtocolError, SocketClosed
|
||||||
from stem.connection import MissingPassword, UnreadableCookieFile, AuthenticationFailure
|
from stem.connection import MissingPassword, UnreadableCookieFile, AuthenticationFailure
|
||||||
|
@ -125,6 +127,13 @@ class PortNotAvailable(Exception):
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
class TorErrorGettingBridges(Exception):
|
||||||
|
"""
|
||||||
|
This exception is raised if onionshare tried to fetch bridges from the Tor
|
||||||
|
CensorshipCircumvention API, but failed to retrieve valid bridges for some reason.
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
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
|
||||||
|
@ -258,9 +267,7 @@ class Onion(object):
|
||||||
and cmdline[2] == self.tor_torrc
|
and cmdline[2] == self.tor_torrc
|
||||||
):
|
):
|
||||||
self.common.log(
|
self.common.log(
|
||||||
"Onion",
|
"Onion", "connect", "found a stale tor process, killing it"
|
||||||
"connect",
|
|
||||||
"found a stale tor process, killing it",
|
|
||||||
)
|
)
|
||||||
proc.terminate()
|
proc.terminate()
|
||||||
proc.wait()
|
proc.wait()
|
||||||
|
@ -321,45 +328,69 @@ class Onion(object):
|
||||||
|
|
||||||
# Bridge support
|
# Bridge support
|
||||||
if self.settings.get("bridges_enabled"):
|
if self.settings.get("bridges_enabled"):
|
||||||
|
f.write("\nUseBridges 1\n")
|
||||||
if self.settings.get("bridges_type") == "built-in":
|
if self.settings.get("bridges_type") == "built-in":
|
||||||
if self.settings.get("bridges_builtin_pt") == "obfs4":
|
# Use the CensorshipCircumvention API to fetch the latest built-in bridges
|
||||||
with open(
|
self.common.log(
|
||||||
self.common.get_resource_path("torrc_template-obfs4")
|
"Onion",
|
||||||
) as o:
|
"connect",
|
||||||
f.write(o.read())
|
"Trying to automatically obtain built-in bridges via Meek",
|
||||||
elif self.settings.get("bridges_builtin_pt") == "meek-azure":
|
)
|
||||||
with open(
|
meek = Meek(self.common)
|
||||||
self.common.get_resource_path(
|
meek.start()
|
||||||
"torrc_template-meek_lite_azure"
|
self.censorship_circumvention = CensorshipCircumvention(
|
||||||
)
|
self.common, meek
|
||||||
) as o:
|
)
|
||||||
f.write(o.read())
|
builtin_bridges = (
|
||||||
elif self.settings.get("bridges_builtin_pt") == "snowflake":
|
self.censorship_circumvention.request_builtin_bridges()
|
||||||
with open(
|
)
|
||||||
self.common.get_resource_path(
|
meek.cleanup()
|
||||||
"torrc_template-snowflake"
|
if builtin_bridges:
|
||||||
)
|
self.common.log(
|
||||||
) as o:
|
"Onion",
|
||||||
f.write(o.read())
|
"connect",
|
||||||
|
f"Obtained bridges: {builtin_bridges}",
|
||||||
|
)
|
||||||
|
if (
|
||||||
|
self.settings.get("bridges_builtin_pt") == "obfs4"
|
||||||
|
and "obfs4" in builtin_bridges
|
||||||
|
):
|
||||||
|
for line in builtin_bridges["obfs4"]:
|
||||||
|
f.write(f"Bridge {line}\n")
|
||||||
|
elif (
|
||||||
|
self.settings.get("bridges_builtin_pt") == "meek-azure"
|
||||||
|
and "meek" in builtin_bridges
|
||||||
|
):
|
||||||
|
for line in builtin_bridges["meek"]:
|
||||||
|
# Meek bridge needs to be defined as "meek_lite", not "meek"
|
||||||
|
line = line.replace("meek", "meek_lite")
|
||||||
|
f.write(f"Bridge {line}\n")
|
||||||
|
elif (
|
||||||
|
self.settings.get("bridges_builtin_pt") == "snowflake"
|
||||||
|
and "snowflake" in builtin_bridges
|
||||||
|
):
|
||||||
|
for line in builtin_bridges["snowflake"]:
|
||||||
|
f.write(f"Bridge {line}\n")
|
||||||
|
else:
|
||||||
|
self.common.log(
|
||||||
|
"Onion",
|
||||||
|
"connect",
|
||||||
|
"Error getting built-in bridges via Meek",
|
||||||
|
)
|
||||||
|
raise TorErrorGettingBridges()
|
||||||
|
|
||||||
elif self.settings.get("bridges_type") == "moat":
|
elif self.settings.get("bridges_type") == "moat":
|
||||||
for line in self.settings.get("bridges_moat").split("\n"):
|
for line in self.settings.get("bridges_moat").split("\n"):
|
||||||
if line.strip() != "":
|
if line.strip() != "":
|
||||||
f.write(f"Bridge {line}\n")
|
f.write(f"Bridge {line}\n")
|
||||||
f.write("\nUseBridges 1\n")
|
|
||||||
|
|
||||||
elif self.settings.get("bridges_type") == "custom":
|
elif self.settings.get("bridges_type") == "custom":
|
||||||
for line in self.settings.get("bridges_custom").split("\n"):
|
for line in self.settings.get("bridges_custom").split("\n"):
|
||||||
if line.strip() != "":
|
if line.strip() != "":
|
||||||
f.write(f"Bridge {line}\n")
|
f.write(f"Bridge {line}\n")
|
||||||
f.write("\nUseBridges 1\n")
|
|
||||||
|
|
||||||
# Execute a tor subprocess
|
# Execute a tor subprocess
|
||||||
self.common.log(
|
self.common.log("Onion", "connect", f"starting {self.tor_path} subprocess")
|
||||||
"Onion",
|
|
||||||
"connect",
|
|
||||||
f"starting {self.tor_path} subprocess",
|
|
||||||
)
|
|
||||||
start_ts = time.time()
|
start_ts = time.time()
|
||||||
if self.common.platform == "Windows":
|
if self.common.platform == "Windows":
|
||||||
# In Windows, hide console window when opening tor.exe subprocess
|
# In Windows, hide console window when opening tor.exe subprocess
|
||||||
|
@ -385,19 +416,11 @@ class Onion(object):
|
||||||
)
|
)
|
||||||
|
|
||||||
# Wait for the tor controller to start
|
# Wait for the tor controller to start
|
||||||
self.common.log(
|
self.common.log("Onion", "connect", f"tor pid: {self.tor_proc.pid}")
|
||||||
"Onion",
|
|
||||||
"connect",
|
|
||||||
f"tor pid: {self.tor_proc.pid}",
|
|
||||||
)
|
|
||||||
time.sleep(2)
|
time.sleep(2)
|
||||||
|
|
||||||
# Connect to the controller
|
# Connect to the controller
|
||||||
self.common.log(
|
self.common.log("Onion", "connect", "authenticating to tor controller")
|
||||||
"Onion",
|
|
||||||
"connect",
|
|
||||||
"authenticating to tor controller",
|
|
||||||
)
|
|
||||||
try:
|
try:
|
||||||
if (
|
if (
|
||||||
self.common.platform == "Windows"
|
self.common.platform == "Windows"
|
||||||
|
|
|
@ -1,3 +0,0 @@
|
||||||
# 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
|
|
|
@ -1,17 +0,0 @@
|
||||||
# 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
|
|
||||||
Bridge obfs4 37.218.245.14:38224 D9A82D2F9C2F65A18407B1D2B764F130847F8B5D cert=bjRaMrr1BRiAW8IE9U5z27fQaYgOhX1UCmOpg2pFpoMvo6ZgQMzLsaTzzQNTlm7hNcb+Sg iat-mode=0
|
|
||||||
Bridge obfs4 85.31.186.98:443 011F2599C0E9B27EE74B353155E244813763C3E5 cert=ayq0XzCwhpdysn5o0EyDUbmSOx3X/oTEbzDMvczHOdBJKlvIdHHLJGkZARtT4dcBFArPPg iat-mode=0
|
|
||||||
Bridge obfs4 85.31.186.26:443 91A6354697E6B02A386312F68D82CF86824D3606 cert=PBwr+S8JTVZo6MPdHnkTwXJPILWADLqfMGoVvhZClMq/Urndyd42BwX9YFJHZnBB3H0XCw iat-mode=0
|
|
||||||
Bridge obfs4 144.217.20.138:80 FB70B257C162BF1038CA669D568D76F5B7F0BABB cert=vYIV5MgrghGQvZPIi1tJwnzorMgqgmlKaB77Y3Z9Q/v94wZBOAXkW+fdx4aSxLVnKO+xNw iat-mode=0
|
|
||||||
Bridge obfs4 193.11.166.194:27015 2D82C2E354D531A68469ADF7F878FA6060C6BACA cert=4TLQPJrTSaDffMK7Nbao6LC7G9OW/NHkUwIdjLSS3KYf0Nv4/nQiiI8dY2TcsQx01NniOg iat-mode=0
|
|
||||||
Bridge obfs4 193.11.166.194:27020 86AC7B8D430DAC4117E9F42C9EAED18133863AAF cert=0LDeJH4JzMDtkJJrFphJCiPqKx7loozKN7VNfuukMGfHO0Z8OGdzHVkhVAOfo1mUdv9cMg iat-mode=0
|
|
||||||
Bridge obfs4 193.11.166.194:27025 1AE2C08904527FEA90C4C4F8C1083EA59FBC6FAF cert=ItvYZzW5tn6v3G4UnQa6Qz04Npro6e81AP70YujmK/KXwDFPTs3aHXcHp4n8Vt6w/bv8cA iat-mode=0
|
|
||||||
Bridge obfs4 209.148.46.65:443 74FAD13168806246602538555B5521A0383A1875 cert=ssH+9rP8dG2NLDN2XuFw63hIO/9MNNinLmxQDpVa+7kTOa9/m+tGWT1SmSYpQ9uTBGa6Hw iat-mode=0
|
|
||||||
Bridge obfs4 146.57.248.225:22 10A6CD36A537FCE513A322361547444B393989F0 cert=K1gDtDAIcUfeLqbstggjIw2rtgIKqdIhUlHp82XRqNSq/mtAjp1BIC9vHKJ2FAEpGssTPw iat-mode=0
|
|
||||||
Bridge obfs4 45.145.95.6:27015 C5B7CD6946FF10C5B3E89691A7D3F2C122D2117C cert=TD7PbUO0/0k6xYHMPW3vJxICfkMZNdkRrb63Zhl5j9dW3iRGiCx0A7mPhe5T2EDzQ35+Zw iat-mode=0
|
|
||||||
Bridge obfs4 [2a0c:4d80:42:702::1]:27015 C5B7CD6946FF10C5B3E89691A7D3F2C122D2117C cert=TD7PbUO0/0k6xYHMPW3vJxICfkMZNdkRrb63Zhl5j9dW3iRGiCx0A7mPhe5T2EDzQ35+Zw iat-mode=0
|
|
||||||
Bridge obfs4 51.222.13.177:80 5EDAC3B810E12B01F6FD8050D2FD3E277B289A08 cert=2uplIpLQ0q9+0qMFrK5pkaYRDOe460LL9WHBvatgkuRr/SL31wBOEupaMMJ6koRE6Ld0ew iat-mode=0
|
|
||||||
UseBridges 1
|
|
|
@ -1,3 +0,0 @@
|
||||||
# Enable built-in snowflake bridge
|
|
||||||
Bridge snowflake 192.0.2.3:1 2B280B23E1107BB62ABFC40DDCC8824814F80A72
|
|
||||||
UseBridges 1
|
|
|
@ -38,6 +38,7 @@ from onionshare_cli.onion import (
|
||||||
TorTooOldEphemeral,
|
TorTooOldEphemeral,
|
||||||
TorTooOldStealth,
|
TorTooOldStealth,
|
||||||
PortNotAvailable,
|
PortNotAvailable,
|
||||||
|
TorErrorGettingBridges,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@ -507,5 +508,7 @@ class GuiCommon:
|
||||||
return strings._("error_stealth_not_supported")
|
return strings._("error_stealth_not_supported")
|
||||||
elif type(e) is PortNotAvailable:
|
elif type(e) is PortNotAvailable:
|
||||||
return strings._("error_port_not_available")
|
return strings._("error_port_not_available")
|
||||||
|
elif type(e) is TorErrorGettingBridges:
|
||||||
|
return strings._("error_getting_bridges")
|
||||||
|
|
||||||
return None
|
return None
|
||||||
|
|
|
@ -223,6 +223,7 @@
|
||||||
"error_port_not_available": "OnionShare port not available",
|
"error_port_not_available": "OnionShare port not available",
|
||||||
"history_receive_read_message_button": "Read Message",
|
"history_receive_read_message_button": "Read Message",
|
||||||
"error_tor_protocol_error": "There was an error with Tor: {}",
|
"error_tor_protocol_error": "There was an error with Tor: {}",
|
||||||
|
"error_getting_bridges": "Could not obtain bridges from the Tor API",
|
||||||
"moat_contact_label": "Contacting BridgeDB...",
|
"moat_contact_label": "Contacting BridgeDB...",
|
||||||
"moat_captcha_label": "Solve the CAPTCHA to request a bridge.",
|
"moat_captcha_label": "Solve the CAPTCHA to request a bridge.",
|
||||||
"moat_captcha_placeholder": "Enter the characters from the image",
|
"moat_captcha_placeholder": "Enter the characters from the image",
|
||||||
|
@ -232,4 +233,4 @@
|
||||||
"moat_captcha_error": "The solution is not correct. Please try again.",
|
"moat_captcha_error": "The solution is not correct. Please try again.",
|
||||||
"moat_solution_empty_error": "You must enter the characters from the image",
|
"moat_solution_empty_error": "You must enter the characters from the image",
|
||||||
"mode_tor_not_connected_label": "OnionShare is not connected to the Tor network"
|
"mode_tor_not_connected_label": "OnionShare is not connected to the Tor network"
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,6 +37,7 @@ from onionshare_cli.onion import (
|
||||||
TorTooOldEphemeral,
|
TorTooOldEphemeral,
|
||||||
TorTooOldStealth,
|
TorTooOldStealth,
|
||||||
PortNotAvailable,
|
PortNotAvailable,
|
||||||
|
TorErrorGettingBridges,
|
||||||
)
|
)
|
||||||
|
|
||||||
from . import strings
|
from . import strings
|
||||||
|
@ -104,6 +105,7 @@ class OnionThread(QtCore.QThread):
|
||||||
TorTooOldEphemeral,
|
TorTooOldEphemeral,
|
||||||
TorTooOldStealth,
|
TorTooOldStealth,
|
||||||
PortNotAvailable,
|
PortNotAvailable,
|
||||||
|
TorErrorGettingBridges,
|
||||||
) as e:
|
) as e:
|
||||||
message = self.mode.common.gui.get_translated_tor_error(e)
|
message = self.mode.common.gui.get_translated_tor_error(e)
|
||||||
self.error.emit(message)
|
self.error.emit(message)
|
||||||
|
|
|
@ -36,6 +36,7 @@ from onionshare_cli.onion import (
|
||||||
TorTooOldEphemeral,
|
TorTooOldEphemeral,
|
||||||
TorTooOldStealth,
|
TorTooOldStealth,
|
||||||
PortNotAvailable,
|
PortNotAvailable,
|
||||||
|
TorErrorGettingBridges,
|
||||||
)
|
)
|
||||||
|
|
||||||
from . import strings
|
from . import strings
|
||||||
|
@ -310,6 +311,7 @@ class TorConnectionThread(QtCore.QThread):
|
||||||
TorTooOldEphemeral,
|
TorTooOldEphemeral,
|
||||||
TorTooOldStealth,
|
TorTooOldStealth,
|
||||||
PortNotAvailable,
|
PortNotAvailable,
|
||||||
|
TorErrorGettingBridges,
|
||||||
) as e:
|
) as e:
|
||||||
message = self.common.gui.get_translated_tor_error(e)
|
message = self.common.gui.get_translated_tor_error(e)
|
||||||
self.common.log(
|
self.common.log(
|
||||||
|
|
Loading…
Reference in a new issue