Skip to content

Commit f9f8319

Browse files
committed
Checking connection health via Proton URL
We we using a Mullvad service (https://am.i.mullvad.net/) to confirm that connection was working and to retrieve some GeoIP data (City, ISP and IP Address). Tests showed that in cases where connection was not working properly, Mullvad endpoint was not responding while ip.me was. Given ip.me is operated by ProtonVPN, this will allow us to live-test whether this helps with our connection issues.
1 parent 715bc66 commit f9f8319

File tree

2 files changed

+44
-2
lines changed

2 files changed

+44
-2
lines changed

backend/pyproject.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ dependencies = [
2424
"PyJWT==2.8.0",
2525
"paramiko==3.4.0",
2626
"humanfriendly==10.0",
27+
"beautifulsoup4==4.12.3",
2728
]
2829
license = {text = "GPL-3.0-or-later"}
2930
classifiers = [

worker/manager/src/mirrors_qa_manager/worker.py

Lines changed: 43 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
from urllib.parse import urlencode
1515

1616
import pycountry
17+
from bs4 import BeautifulSoup # pyright: ignore [reportMissingModuleSource]
1718
from docker.errors import APIError
1819
from docker.models.containers import Container, ExecResult
1920
from docker.types import Mount
@@ -32,6 +33,40 @@
3233
from mirrors_qa_manager.settings import Settings
3334

3435

36+
def ipme_data_from_html(html_content: str) -> dict[str, Any]:
37+
try:
38+
soup = BeautifulSoup(html_content, "html.parser")
39+
ip_address = soup.select_one(
40+
"p.ip-address"
41+
).text # pyright: ignore [reportOptionalMemberAccess]
42+
except Exception as exc:
43+
logger.error(f"Cant parse HTML or find IP: {exc}")
44+
return {}
45+
try:
46+
(
47+
_, # country
48+
city,
49+
_, # country_code
50+
_, # latitude
51+
_, # longitude
52+
_, # postal_code
53+
organization,
54+
_, # asn
55+
isp_name,
56+
) = (code.text for code in soup.select("table tr td code"))
57+
organization = isp_name or organization
58+
except Exception as exc:
59+
logger.error(f"Cant find City/Organization: {exc}")
60+
city = None
61+
organization = None
62+
63+
return {
64+
"ip": ip_address,
65+
"city": city,
66+
"organization": organization,
67+
}
68+
69+
3570
class WgInterfaceStatus(Enum):
3671
"""Status of the Wireguard interface."""
3772

@@ -73,10 +108,13 @@ def __init__(self, worker_id: str) -> None:
73108
self.wg_interface = "wg0"
74109
self.wg_healthcheck_cmd = [
75110
"curl",
111+
"--header",
112+
"User-Agent: Mozilla",
76113
"--interface",
77114
self.wg_interface,
78115
"-s",
79-
"https://am.i.mullvad.net/json",
116+
# "https://am.i.mullvad.net/json",
117+
"https://ip.me",
80118
]
81119
self.wg_interface_status = WgInterfaceStatus.DOWN
82120
# commands for bringing down/up the interface whenever a new configuration
@@ -438,7 +476,10 @@ def run(self) -> None:
438476
logger.info(
439477
f"Successfully retrieved metrics results for test {test_id}"
440478
)
441-
ip_data = json.loads(healthcheck_result.output.decode("utf-8"))
479+
# ip_data = json.loads(healthcheck_result.output.decode("utf-8"))
480+
ip_data = ipme_data_from_html(
481+
healthcheck_result.output.decode("utf-8")
482+
)
442483
payload = self.merge_data(
443484
ip_data=ip_data,
444485
metrics_data=json.loads(results),

0 commit comments

Comments
 (0)