From 4b7612f20b21a9bb8f91d2646c72139199850162 Mon Sep 17 00:00:00 2001 From: Andrey Prokopyuk Date: Wed, 21 Oct 2026 19:36:24 +0300 Subject: [PATCH] Stop automatically preferring HTTP/3 in generated profiles --- docs/ru/config-api.md | 4 ++-- docs/ru/transports.md | 10 ++++------ src/megaproxy_server/config_api.py | 2 -- src/megaproxy_server/export.py | 13 +++++++++---- tests/test_config_api.py | 4 ++-- 5 files changed, 17 insertions(+), 16 deletions(-) diff --git a/docs/ru/config-api.md b/docs/ru/config-api.md index 714172a..fe2132b 100644 --- a/docs/ru/config-api.md +++ b/docs/ru/config-api.md @@ -172,8 +172,8 @@ users: ## Контракт MegaProxyConfig Настройка генерации новых транспортов описана в [Транспортах прокси](transports.md). -`services.https.http3` включает поддержку и флаг предпочтения HTTP/3 на совместимых -HTTPS-маршрутах; отдельные MASQUE-профили требуют `masque_profiles: true`. +`services.https.http3` включает поддержку HTTP/3 без автоматического выставления +`preferHttp3`; отдельные MASQUE-профили требуют `masque_profiles: true`. SOCKS5-профили генерируются только при `socks5.enabled: true`; SOCKS5 не рекомендуется из-за отсутствия шифрования транспорта и реквизитов аутентификации. diff --git a/docs/ru/transports.md b/docs/ru/transports.md index f57451d..2e0035e 100644 --- a/docs/ru/transports.md +++ b/docs/ru/transports.md @@ -31,13 +31,11 @@ hosts: нужный UDP-порт. Контейнеру добавляется только capability `NET_BIND_SERVICE`, необходимая для привязки низких портов. -API подписок и MegaProxy JSON выставляют `proxy.preferHttp3: true` только когда -HTTPS и MASQUE доступны на одном hostname и номере порта. Android пробует QUIC, -а при поддерживаемых контрактом ошибках возвращается к HTTPS/TCP. Ошибки проверки -сертификата и аутентификации остаются отказами. +API подписок и MegaProxy JSON не выставляют `proxy.preferHttp3` автоматически. +HTTPS-профили по умолчанию используют TCP; HTTP/3-listener остаётся доступным. -`masque_profiles: true` дополнительно публикует отдельные профили `type: MASQUE`. -Этот параметр требует `http3: true`; он не нужен для HTTPS с `preferHttp3`. +`masque_profiles: true` публикует отдельные профили `type: MASQUE` +и требует `http3: true`. Отдельный MASQUE-профиль требует HTTP/3 и не переключается на HTTPS. Профили получают логин и пароль текущего авторизованного пользователя. diff --git a/src/megaproxy_server/config_api.py b/src/megaproxy_server/config_api.py index 395d1cc..653a714 100644 --- a/src/megaproxy_server/config_api.py +++ b/src/megaproxy_server/config_api.py @@ -74,8 +74,6 @@ def render_config(bundle: dict[str, Any], username: str, password: str, client: proxy = {"type": "HTTPS", "host": route["host"], "port": route["port"], "username": username, "password": password, "allowInvalidProxyCertificate": route["allow_invalid_certificate"]} - if route.get("http3_port") == route["port"]: - proxy["preferHttp3"] = True item = profile(route["title"], proxy, len(profiles), route["country_code"], identity=json.dumps(["https", route["host_name"], route["route_name"], username])) options = deepcopy(payload["https_options"][json.dumps([route["host_name"], route["route_name"]])]) diff --git a/src/megaproxy_server/export.py b/src/megaproxy_server/export.py index 35d3095..e659a07 100644 --- a/src/megaproxy_server/export.py +++ b/src/megaproxy_server/export.py @@ -5,8 +5,15 @@ from pathlib import Path from typing import Any -from .config_format import configuration, https_jump_profile, profile as _profile -from .inventory import atomic_write, https_jump_routes, https_profile_routes, https_routes, ssh_jump_routes +from .config_format import configuration, https_jump_profile +from .config_format import profile as _profile +from .inventory import ( + atomic_write, + https_jump_routes, + https_profile_routes, + https_routes, + ssh_jump_routes, +) from .models import Host, Inventory, SshUser @@ -66,8 +73,6 @@ def export_profiles(inventory: Inventory, output: Path, include_all_jumps: bool title = route["title"] name = f"{title} / {user.name}" proxy = {"type": "HTTPS", "host": route["hostname"], "port": https.port, "username": user.name, "password": user.password, "allowInvalidProxyCertificate": https.certificate == "self-signed", "sshProfile": "DEFAULT", "trustedHostKey": "", "acceptAnyHostKey": False} - if route["http3_port"] == https.port: - proxy["preferHttp3"] = True item = _profile(name, proxy, len(profiles), route["country_code"], identity=json.dumps(["https", host_name, route["name"], user.name])) resistance = route["probe_resistance"] diff --git a/tests/test_config_api.py b/tests/test_config_api.py index 7bb18f6..7c13226 100644 --- a/tests/test_config_api.py +++ b/tests/test_config_api.py @@ -83,8 +83,7 @@ def test_generated_transports_are_opt_in_and_client_compatible(inventory, tmp_pa bundle = build_bundle(inventory) document = render_config(bundle, alice.name, alice.password) https = [p["proxy"] for p in document["profiles"] if p["proxy"]["type"] == "HTTPS"] - assert https[0]["preferHttp3"] is True - assert "preferHttp3" not in https[2] # Never bypass a server-side chain via direct QUIC. + assert all("preferHttp3" not in proxy for proxy in https) assert all(p["proxy"]["type"] != "MASQUE" for p in document["profiles"]) assert sum(p["proxy"]["type"] == "SOCKS5" for p in document["profiles"]) == 1 entry.masque_profiles = True @@ -112,6 +111,7 @@ def test_generated_transports_are_opt_in_and_client_compatible(inventory, tmp_pa exported = json.loads(path.read_text()) assert exported["version"] == 8 validate_config(exported) + assert all("preferHttp3" not in p["proxy"] for p in exported["profiles"]) assert {p["proxy"]["type"] for p in exported["profiles"]} >= {"SOCKS5", "MASQUE"}