From d795bc6f70a12c1fd75cf07490d2373f6ac317a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=91=D0=BE=D0=B1=D1=8B=D1=80=D0=B5=D0=B2=20=D0=90=D0=BD?= =?UTF-8?q?=D0=B4=D1=80=D0=B5=D0=B9?= Date: Fri, 23 Oct 2026 11:57:13 +0300 Subject: [PATCH] =?UTF-8?q?release:=201.4.2=20=E2=80=94=20server=20obfusca?= =?UTF-8?q?tor=20settings,=20Android=201.4.3=20fix=20for=20configs=20with?= =?UTF-8?q?=20unknown=20obfuscator=20keys?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 5.5 --- .gitignore | 3 +- CHANGELOG.md | 5 ++ README.md | 4 +- VERSION | 2 +- android-client/AndroidManifest.xml | 4 +- .../src/com/pca/phobos/vpn/MainActivity.java | 5 ++ app.py | 66 ++++++++++++++++++- 7 files changed, 81 insertions(+), 8 deletions(-) diff --git a/.gitignore b/.gitignore index f3b621e..371721f 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,3 @@ __pycache__/ *.pyc -macos/ -windows/ +windows/build/ diff --git a/CHANGELOG.md b/CHANGELOG.md index 86c62d1..b1cdc0f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,6 +19,11 @@ phobos-update beta # или: phobos-update dev --- +## 1.4.2 — настройка обфускатора сервера + +- **feat:** в панели «Настройки» → «Обфускатор сервера»: masking (AUTO/STUN/NONE), max-dummy, idle — записываются во все порты сервера, обфускатор перезапускается (клиенты переподключаются за секунды). +- **fix (Android PCA Phobos VPN 1.4.3):** конфиги других сборок Phobos с лишними ключами (`obfuscate-bytes` и т. п.) больше не роняют обфускатор («обфускатор завершился, код 1»): передаются только ключи, известные wg-obfuscator v1.6. + ## 1.4.1 — резервный TCP-канал, «РФ напрямую» - **feat:** резервный канал TCP: если провайдер режет UDP, клиент сам переходит на TCP (порт 443, иначе 8443/2096/4433). Сервер: служба `phobos-tcp` (`udptcp`), ставится и включается автоматически при установке и обновлении. Проверено реальной блокировкой UDP: переключение за ~15 с, без блокировки остаётся UDP. diff --git a/README.md b/README.md index 179705b..38bafce 100644 --- a/README.md +++ b/README.md @@ -137,8 +137,8 @@ bash <(curl -fsSL https://git.bobyrev.com/PCA/PCA_Phobos/raw/branch/main/server/ ## Приложения для Android -- **PCA Phobos VPN** — клиент: включает VPN одной кнопкой, импорт `phobos://` из панели, встроенный обфускатор, **раздельный трафик** (весь / только выбранные приложения / все кроме выбранных), **российские сайты напрямую** (по умолчанию), **канал Авто/UDP/TCP** (при блокировке UDP — сам на TCP), журнал, проверка скорости. [Скачать APK](https://git.bobyrev.com/PCA/PCA_Phobos/releases/download/v1.4.1/PCA-Phobos-VPN.apk) · исходники `android-client/`. -- **PCA Phobos** (админ) — список ваших панелей, открываются в приложении. [Скачать APK](https://git.bobyrev.com/PCA/PCA_Phobos/releases/download/v1.4.1/PCA-Phobos.apk) · исходники `android/`. +- **PCA Phobos VPN** — клиент: включает VPN одной кнопкой, импорт `phobos://` из панели, встроенный обфускатор, **раздельный трафик** (весь / только выбранные приложения / все кроме выбранных), **российские сайты напрямую** (по умолчанию), **канал Авто/UDP/TCP** (при блокировке UDP — сам на TCP), журнал, проверка скорости. [Скачать APK](https://git.bobyrev.com/PCA/PCA_Phobos/releases/download/v1.4.2/PCA-Phobos-VPN.apk) · исходники `android-client/`. +- **PCA Phobos** (админ) — список ваших панелей, открываются в приложении. [Скачать APK](https://git.bobyrev.com/PCA/PCA_Phobos/releases/download/v1.4.2/PCA-Phobos.apk) · исходники `android/`. ## Клиенты для телефона diff --git a/VERSION b/VERSION index 347f583..9df886c 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -1.4.1 +1.4.2 diff --git a/android-client/AndroidManifest.xml b/android-client/AndroidManifest.xml index 495a5a3..b3ffe59 100644 --- a/android-client/AndroidManifest.xml +++ b/android-client/AndroidManifest.xml @@ -1,8 +1,8 @@ + android:versionCode="143" + android:versionName="1.4.3"> diff --git a/android-client/src/com/pca/phobos/vpn/MainActivity.java b/android-client/src/com/pca/phobos/vpn/MainActivity.java index ec76c39..5de5941 100644 --- a/android-client/src/com/pca/phobos/vpn/MainActivity.java +++ b/android-client/src/com/pca/phobos/vpn/MainActivity.java @@ -217,11 +217,16 @@ public class MainActivity extends Activity { private static String getPackageNameSafe() { return "com.pca.phobos.vpn"; } + private static final java.util.Set OBF_KEYS = new java.util.HashSet<>(java.util.Arrays.asList( + "target", "key", "masking", "idle-timeout", "max-dummy", "static-bindings", "max-clients", "target-if", "allow-clean", "in-timeout", "resolve-interval")); + private String obfPart(String conf, boolean viaTcp) { StringBuilder sb = new StringBuilder("[instance]\nsource-if = 127.0.0.1\nsource-lport = " + LPORT + "\n"); for (String ln : section(conf, "[instance]")) { String k = key(ln); if (k.equals("source-if") || k.equals("source-lport") || k.equals("verbose")) continue; + // configs from other Phobos builds carry keys our wg-obfuscator v1.6 rejects (obfuscate-bytes…) + if (!OBF_KEYS.contains(k)) continue; if (viaTcp && k.equals("target")) ln = "target = 127.0.0.1:" + TCP_LPORT; sb.append(ln).append('\n'); } diff --git a/app.py b/app.py index d04f4d0..1b65dde 100644 --- a/app.py +++ b/app.py @@ -37,7 +37,7 @@ WG_CONFIG = "/etc/wireguard/wg0.conf" # Distribution: Gitea first (GitHub account is unavailable since 23.10.2026), GitHub fallback PCA_GIT = "https://git.bobyrev.com/PCA/PCA_Phobos" PCA_GH_RAW = "https://raw.githubusercontent.com/andrey271192/PCA_Phobos" -APK_TAG = "v1.4.1" +APK_TAG = "v1.4.2" WARP_DIR = f"{PHOBOS_DIR}/server/warp" WARP_CUSTOM_PROFILE_FILE = f"{WARP_DIR}/custom-profile.conf" WARP_LICENSE_FILE = f"{WARP_DIR}/license.key" @@ -102,6 +102,44 @@ def save_settings(s): json.dump(s, f, indent=2, ensure_ascii=False) +SRV_OBF_KEYS = ("masking", "max-dummy", "idle-timeout") + + +def _srv_obf_confs(): + import glob + return sorted(glob.glob(f"{PHOBOS_DIR}/server/wg-obfuscator-*.conf")) + + +def read_server_obf(): + """Current server wg-obfuscator params (from the first instance config).""" + vals = {"masking": "AUTO", "max-dummy": "50", "idle-timeout": "300"} + confs = _srv_obf_confs() + if confs: + for ln in Path(confs[0]).read_text().splitlines(): + k, _, v = ln.partition("=") + if k.strip() in SRV_OBF_KEYS: + vals[k.strip()] = v.strip() + return vals + + +def write_server_obf(vals): + """Rewrite masking/max-dummy/idle-timeout in every server instance and restart them.""" + done = [] + for f in _srv_obf_confs(): + lines, seen = [], set() + for ln in Path(f).read_text().splitlines(): + k = ln.partition("=")[0].strip() + if k in vals: + ln = f"{k} = {vals[k]}"; seen.add(k) + lines.append(ln) + lines += [f"{k} = {v}" for k, v in vals.items() if k not in seen] + Path(f).write_text("\n".join(lines) + "\n") + port = re.search(r"wg-obfuscator-(\d+)\.conf$", f).group(1) + subprocess.run(["systemctl", "restart", f"wg-obfuscator-{port}"], timeout=30) + done.append(port) + return done + + def _load_server_env(): """Load server.env as dict for subprocess env.""" env = {} @@ -2741,6 +2779,17 @@ def settings_page(): except Exception: pass msg = f'
{tr("Параметры обфускатора сохранены и отправлены на роутеры", "Obfuscator params saved and pushed to routers")} ({pushed})
' + elif request.method == "POST" and request.form.get("action") == "save_srv_obf": + masking = request.form.get("srv_masking", "AUTO").strip().upper() + if masking not in ("AUTO", "STUN", "NONE"): + masking = "AUTO" + try: + dummy = str(min(255, max(0, int(request.form.get("srv_max_dummy", "50"))))) + idle = str(min(3600, max(10, int(request.form.get("srv_idle", "300"))))) + except ValueError: + dummy, idle = "50", "300" + ports = write_server_obf({"masking": masking, "max-dummy": dummy, "idle-timeout": idle}) + msg = f'
{tr("Серверный обфускатор перезапущен с новыми параметрами, порты", "Server obfuscator restarted with new params, ports")}: {", ".join(ports) or "—"}
' elif request.method == "POST": new_pass = request.form.get("admin_pass", "").strip() if new_pass: @@ -2758,6 +2807,7 @@ def settings_page(): custom_warp_profile = read_custom_warp_profile() warp_license_key = read_warp_license_key() warp = warp_status() + srv_obf = read_server_obf() warp_service = warp.get("service", "unknown") warp_state = tr("включён", "enabled") if warp.get("enabled") else tr("выключен", "disabled") warp_subnet = _html_attr(warp.get("subnet", server_wg_network())) @@ -2898,6 +2948,20 @@ def settings_page(): +
+

{tr("Обфускатор сервера","Server obfuscator")} {hlp("Параметры wg-obfuscator на ЭТОМ сервере (все порты). masking: AUTO принимает любой режим клиента — менять, только если знаете зачем; STUN/NONE — клиенты должны работать в том же режиме. max-dummy — мусорные байты в ответах, idle — таймаут простоя (сек). Сохранение перезапускает обфускатор: клиенты переподключатся за пару секунд.", "wg-obfuscator params on THIS server (all ports). masking: AUTO accepts any client mode — change only if you know why; with STUN/NONE clients must use the same mode. max-dummy — junk bytes in replies, idle — idle timeout (s). Saving restarts the obfuscator: clients reconnect within seconds.")}

+
+ + + + + +
+
+

{tr("Информация о сервере","Server info")}