mirror of
https://github.com/onionshare/onionshare.git
synced 2025-01-25 02:32:58 -03:00
Move the ability to use Tor vs Meek into the CensorshipCircumvention class so that we can use those endpoints over Tor elsewhere later
This commit is contained in:
parent
06a3599fe1
commit
55c8ada6ef
2 changed files with 60 additions and 57 deletions
|
@ -25,21 +25,46 @@ from .meek import MeekNotRunning
|
||||||
class CensorshipCircumvention(object):
|
class CensorshipCircumvention(object):
|
||||||
"""
|
"""
|
||||||
Connect to the Tor Moat APIs to retrieve censorship
|
Connect to the Tor Moat APIs to retrieve censorship
|
||||||
circumvention recommendations, over the Meek client.
|
circumvention recommendations or the latest bridges.
|
||||||
|
|
||||||
|
We support reaching this API over Tor, or Meek
|
||||||
|
(domain fronting) if Tor is not connected.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, common, meek, domain_fronting=True):
|
def __init__(self, common, meek=None, onion=None):
|
||||||
"""
|
"""
|
||||||
Set up the CensorshipCircumvention object to hold
|
Set up the CensorshipCircumvention object to hold
|
||||||
common and meek objects.
|
common and meek objects.
|
||||||
"""
|
"""
|
||||||
self.common = common
|
self.common = common
|
||||||
self.meek = meek
|
|
||||||
self.common.log("CensorshipCircumvention", "__init__")
|
self.common.log("CensorshipCircumvention", "__init__")
|
||||||
|
self.api_proxies = {}
|
||||||
# Bail out if we requested domain fronting but we can't use meek
|
if meek:
|
||||||
if domain_fronting and not self.meek.meek_proxies:
|
self.meek = meek
|
||||||
raise MeekNotRunning()
|
if not self.meek.meek_proxies:
|
||||||
|
raise MeekNotRunning()
|
||||||
|
else:
|
||||||
|
self.common.log(
|
||||||
|
"CensorshipCircumvention",
|
||||||
|
"__init__",
|
||||||
|
"Using Meek with CensorShipCircumvention API",
|
||||||
|
)
|
||||||
|
self.api_proxies = self.meek.meek_proxies
|
||||||
|
if onion:
|
||||||
|
self.onion = onion
|
||||||
|
if not self.onion.is_authenticated:
|
||||||
|
return False
|
||||||
|
else:
|
||||||
|
self.common.log(
|
||||||
|
"CensorshipCircumvention",
|
||||||
|
"__init__",
|
||||||
|
"Using Tor with CensorShipCircumvention API",
|
||||||
|
)
|
||||||
|
(socks_address, socks_port) = self.onion.get_tor_socks_port()
|
||||||
|
self.api_proxies = {
|
||||||
|
"http": f"socks5h://{socks_address}:{socks_port}",
|
||||||
|
"https": f"socks5h://{socks_address}:{socks_port}",
|
||||||
|
}
|
||||||
|
|
||||||
def request_map(self, country=False):
|
def request_map(self, country=False):
|
||||||
"""
|
"""
|
||||||
|
@ -52,6 +77,8 @@ class CensorshipCircumvention(object):
|
||||||
Note that this API endpoint doesn't return actual bridges,
|
Note that this API endpoint doesn't return actual bridges,
|
||||||
it just returns the recommended bridge type countries.
|
it just returns the recommended bridge type countries.
|
||||||
"""
|
"""
|
||||||
|
if not self.api_proxies:
|
||||||
|
return False
|
||||||
endpoint = "https://bridges.torproject.org/moat/circumvention/map"
|
endpoint = "https://bridges.torproject.org/moat/circumvention/map"
|
||||||
data = {}
|
data = {}
|
||||||
if country:
|
if country:
|
||||||
|
@ -61,7 +88,7 @@ class CensorshipCircumvention(object):
|
||||||
endpoint,
|
endpoint,
|
||||||
json=data,
|
json=data,
|
||||||
headers={"Content-Type": "application/vnd.api+json"},
|
headers={"Content-Type": "application/vnd.api+json"},
|
||||||
proxies=self.meek.meek_proxies,
|
proxies=self.api_proxies,
|
||||||
)
|
)
|
||||||
if r.status_code != 200:
|
if r.status_code != 200:
|
||||||
self.common.log(
|
self.common.log(
|
||||||
|
@ -95,6 +122,8 @@ class CensorshipCircumvention(object):
|
||||||
Optionally, a list of transports can be specified in order to
|
Optionally, a list of transports can be specified in order to
|
||||||
return recommended settings for just that transport type.
|
return recommended settings for just that transport type.
|
||||||
"""
|
"""
|
||||||
|
if not self.api_proxies:
|
||||||
|
return False
|
||||||
endpoint = "https://bridges.torproject.org/moat/circumvention/settings"
|
endpoint = "https://bridges.torproject.org/moat/circumvention/settings"
|
||||||
data = {}
|
data = {}
|
||||||
if country:
|
if country:
|
||||||
|
@ -105,7 +134,7 @@ class CensorshipCircumvention(object):
|
||||||
endpoint,
|
endpoint,
|
||||||
json=data,
|
json=data,
|
||||||
headers={"Content-Type": "application/vnd.api+json"},
|
headers={"Content-Type": "application/vnd.api+json"},
|
||||||
proxies=self.meek.meek_proxies,
|
proxies=self.api_proxies,
|
||||||
)
|
)
|
||||||
if r.status_code != 200:
|
if r.status_code != 200:
|
||||||
self.common.log(
|
self.common.log(
|
||||||
|
@ -142,11 +171,13 @@ class CensorshipCircumvention(object):
|
||||||
"""
|
"""
|
||||||
Retrieves the list of built-in bridges from the Tor Project.
|
Retrieves the list of built-in bridges from the Tor Project.
|
||||||
"""
|
"""
|
||||||
|
if not self.api_proxies:
|
||||||
|
return False
|
||||||
endpoint = "https://bridges.torproject.org/moat/circumvention/builtin"
|
endpoint = "https://bridges.torproject.org/moat/circumvention/builtin"
|
||||||
r = requests.post(
|
r = requests.post(
|
||||||
endpoint,
|
endpoint,
|
||||||
headers={"Content-Type": "application/vnd.api+json"},
|
headers={"Content-Type": "application/vnd.api+json"},
|
||||||
proxies=self.meek.meek_proxies,
|
proxies=self.api_proxies,
|
||||||
)
|
)
|
||||||
if r.status_code != 200:
|
if r.status_code != 200:
|
||||||
self.common.log(
|
self.common.log(
|
||||||
|
|
|
@ -914,7 +914,8 @@ class Onion(object):
|
||||||
Use the CensorshipCircumvention API to fetch the latest built-in bridges
|
Use the CensorshipCircumvention API to fetch the latest built-in bridges
|
||||||
and update them in settings.
|
and update them in settings.
|
||||||
"""
|
"""
|
||||||
got_builtin_bridges = False
|
builtin_bridges = False
|
||||||
|
meek = None
|
||||||
# Try obtaining bridges over Tor, if we're connected to it.
|
# Try obtaining bridges over Tor, if we're connected to it.
|
||||||
if self.is_authenticated:
|
if self.is_authenticated:
|
||||||
self.common.log(
|
self.common.log(
|
||||||
|
@ -922,43 +923,14 @@ class Onion(object):
|
||||||
"update_builtin_bridges",
|
"update_builtin_bridges",
|
||||||
"Updating the built-in bridges. Trying over Tor first",
|
"Updating the built-in bridges. Trying over Tor first",
|
||||||
)
|
)
|
||||||
(socks_address, socks_port) = self.get_tor_socks_port()
|
self.censorship_circumvention = CensorshipCircumvention(
|
||||||
tor_proxies = {
|
self.common, None, self
|
||||||
"http": f"socks5h://{socks_address}:{socks_port}",
|
|
||||||
"https": f"socks5h://{socks_address}:{socks_port}",
|
|
||||||
}
|
|
||||||
# Request a bridge
|
|
||||||
r = requests.post(
|
|
||||||
"https://bridges.torproject.org/moat/circumvention/builtin",
|
|
||||||
headers={"Content-Type": "application/vnd.api+json"},
|
|
||||||
proxies=tor_proxies,
|
|
||||||
)
|
)
|
||||||
if r.status_code != 200:
|
builtin_bridges = self.censorship_circumvention.request_builtin_bridges()
|
||||||
self.common.log(
|
|
||||||
"Onion",
|
|
||||||
"update_builtin_bridges",
|
|
||||||
f"Trying over Tor failed: status_code={r.status_code}",
|
|
||||||
)
|
|
||||||
|
|
||||||
try:
|
if not builtin_bridges:
|
||||||
builtin_bridges = r.json()
|
# Tor was not running or it failed to hit the Tor API.
|
||||||
if "errors" in builtin_bridges:
|
# Fall back to using Meek (domain-fronting).
|
||||||
self.common.log(
|
|
||||||
"Onion",
|
|
||||||
"update_builtin_bridges",
|
|
||||||
f"Trying over Tor failed: errors={builtin_bridges['errors']}",
|
|
||||||
)
|
|
||||||
else:
|
|
||||||
got_builtin_bridges = builtin_bridges
|
|
||||||
except Exception as e:
|
|
||||||
self.common.log(
|
|
||||||
"Onion",
|
|
||||||
"update_builtin_bridges",
|
|
||||||
f"Hit exception when trying over Tor: {e}",
|
|
||||||
)
|
|
||||||
|
|
||||||
if not got_builtin_bridges:
|
|
||||||
# Fall back to using Meek, without Tor
|
|
||||||
self.common.log(
|
self.common.log(
|
||||||
"Onion",
|
"Onion",
|
||||||
"update_builtin_bridges",
|
"update_builtin_bridges",
|
||||||
|
@ -966,35 +938,35 @@ class Onion(object):
|
||||||
)
|
)
|
||||||
meek = Meek(self.common)
|
meek = Meek(self.common)
|
||||||
meek.start()
|
meek.start()
|
||||||
self.censorship_circumvention = CensorshipCircumvention(self.common, meek)
|
self.censorship_circumvention = CensorshipCircumvention(
|
||||||
got_builtin_bridges = (
|
self.common, meek, None
|
||||||
self.censorship_circumvention.request_builtin_bridges()
|
|
||||||
)
|
)
|
||||||
|
builtin_bridges = self.censorship_circumvention.request_builtin_bridges()
|
||||||
meek.cleanup()
|
meek.cleanup()
|
||||||
|
|
||||||
# If we got to this point, we have bridges
|
if builtin_bridges:
|
||||||
if got_builtin_bridges:
|
# If we got to this point, we have bridges
|
||||||
self.common.log(
|
self.common.log(
|
||||||
"Onion",
|
"Onion",
|
||||||
"update_builtin_bridges",
|
"update_builtin_bridges",
|
||||||
f"Obtained bridges: {got_builtin_bridges}",
|
f"Obtained bridges: {builtin_bridges}",
|
||||||
)
|
)
|
||||||
if got_builtin_bridges["meek"]:
|
if builtin_bridges["meek"]:
|
||||||
# Meek bridge needs to be defined as "meek_lite", not "meek",
|
# Meek bridge needs to be defined as "meek_lite", not "meek",
|
||||||
# for it to work with obfs4proxy.
|
# for it to work with obfs4proxy.
|
||||||
# We also refer to this bridge type as 'meek-azure' in our settings.
|
# We also refer to this bridge type as 'meek-azure' in our settings.
|
||||||
# So first, rename the key in the dict
|
# So first, rename the key in the dict
|
||||||
got_builtin_bridges["meek-azure"] = got_builtin_bridges.pop("meek")
|
builtin_bridges["meek-azure"] = builtin_bridges.pop("meek")
|
||||||
new_meek_bridges = []
|
new_meek_bridges = []
|
||||||
# Now replace the values. They also need the url/front params appended
|
# Now replace the values. They also need the url/front params appended
|
||||||
for item in got_builtin_bridges["meek-azure"]:
|
for item in builtin_bridges["meek-azure"]:
|
||||||
newline = item.replace("meek", "meek_lite")
|
newline = item.replace("meek", "meek_lite")
|
||||||
new_meek_bridges.append(
|
new_meek_bridges.append(
|
||||||
f"{newline} url=https://meek.azureedge.net/ front=ajax.aspnetcdn.com"
|
f"{newline} url=https://meek.azureedge.net/ front=ajax.aspnetcdn.com"
|
||||||
)
|
)
|
||||||
got_builtin_bridges["meek-azure"] = new_meek_bridges
|
builtin_bridges["meek-azure"] = new_meek_bridges
|
||||||
# Save the new settings
|
# Save the new settings
|
||||||
self.settings.set("bridges_builtin", got_builtin_bridges)
|
self.settings.set("bridges_builtin", builtin_bridges)
|
||||||
self.settings.save()
|
self.settings.save()
|
||||||
else:
|
else:
|
||||||
self.common.log(
|
self.common.log(
|
||||||
|
|
Loading…
Add table
Reference in a new issue