From 94764b74dc26d98beea9ae3ffb20438bc4c61a86 Mon Sep 17 00:00:00 2001 From: Stas Skokov <7090stas@gmail.com> Date: Wed, 10 Jun 2026 18:46:04 +1000 Subject: [PATCH] update camouflage-tls --- app/src/main/cpp/libs/fptn | 2 +- app/src/main/cpp/src/https_client.cpp | 26 ++++++++++---- app/src/main/cpp/src/websocket_client.cpp | 36 +++++++++++++------ .../org/fptn/vpn/enums/SniSpoofingMode.java | 22 +++++++----- .../services/speedtest/SpeedTestUtils.java | 9 ++--- .../fptn/vpn/services/vpn/FptnService.java | 9 ++--- .../org/fptn/vpn/utils/token/TokenUtils.java | 2 +- .../bypassmethod/BypassMethodsActivity.java | 20 ++++++++--- app/src/main/res/values-fa-rIR/strings.xml | 10 ++++-- app/src/main/res/values-ru-rRU/strings.xml | 11 ++++-- app/src/main/res/values/strings.xml | 11 ++++-- 11 files changed, 111 insertions(+), 47 deletions(-) diff --git a/app/src/main/cpp/libs/fptn b/app/src/main/cpp/libs/fptn index a99db500..b170630c 160000 --- a/app/src/main/cpp/libs/fptn +++ b/app/src/main/cpp/libs/fptn @@ -1 +1 @@ -Subproject commit a99db500ca91e535099756f9cdd5c8057a5e0c44 +Subproject commit b170630c3461fedbe7b2bbe4dea1f7557b7a76ef diff --git a/app/src/main/cpp/src/https_client.cpp b/app/src/main/cpp/src/https_client.cpp index 7f0ac274..00eea481 100644 --- a/app/src/main/cpp/src/https_client.cpp +++ b/app/src/main/cpp/src/https_client.cpp @@ -117,7 +117,11 @@ Java_org_fptn_vpn_services_websocket_NativeHttpsClientImpl_nativeCreate( censorship_strategy = fptn::protocol::https::CensorshipStrategy::kSniRealityMode; } /* Chrome */ - else if (censorship_strategy_name == "SNI-REALITY-CHROME-147") { + else if (censorship_strategy_name == "SNI-REALITY-CHROME-149") { + censorship_strategy = fptn::protocol::https::CensorshipStrategy::kSniRealityModeChrome149; + } else if (censorship_strategy_name == "SNI-REALITY-CHROME-148") { + censorship_strategy = fptn::protocol::https::CensorshipStrategy::kSniRealityModeChrome148; + } else if (censorship_strategy_name == "SNI-REALITY-CHROME-147") { censorship_strategy = fptn::protocol::https::CensorshipStrategy::kSniRealityModeChrome147; } else if (censorship_strategy_name == "SNI-REALITY-CHROME-146") { censorship_strategy = fptn::protocol::https::CensorshipStrategy::kSniRealityModeChrome146; @@ -125,22 +129,32 @@ Java_org_fptn_vpn_services_websocket_NativeHttpsClientImpl_nativeCreate( censorship_strategy = fptn::protocol::https::CensorshipStrategy::kSniRealityModeChrome145; } /* Firefox */ - else if (censorship_strategy_name == "SNI-REALITY-FIREFOX-149") { + else if (censorship_strategy_name == "SNI-REALITY-FIREFOX-151") { + censorship_strategy = fptn::protocol::https::CensorshipStrategy::kSniRealityModeFirefox151; + } else if (censorship_strategy_name == "SNI-REALITY-FIREFOX-150") { + censorship_strategy = fptn::protocol::https::CensorshipStrategy::kSniRealityModeFirefox150; + } else if (censorship_strategy_name == "SNI-REALITY-FIREFOX-149") { censorship_strategy = fptn::protocol::https::CensorshipStrategy::kSniRealityModeFirefox149; } /* Yandex */ - else if (censorship_strategy_name == "SNI-REALITY-YANDEX-26") { - censorship_strategy = fptn::protocol::https::CensorshipStrategy::kSniRealityModeYandex26; + else if (censorship_strategy_name == "SNI-REALITY-YANDEX-26-4") { + censorship_strategy = fptn::protocol::https::CensorshipStrategy::kSniRealityModeYandex26_4; + } else if (censorship_strategy_name == "SNI-REALITY-YANDEX-26-3") { + censorship_strategy = fptn::protocol::https::CensorshipStrategy::kSniRealityModeYandex26_3; } else if (censorship_strategy_name == "SNI-REALITY-YANDEX-25") { censorship_strategy = fptn::protocol::https::CensorshipStrategy::kSniRealityModeYandex25; } else if (censorship_strategy_name == "SNI-REALITY-YANDEX-24") { censorship_strategy = fptn::protocol::https::CensorshipStrategy::kSniRealityModeYandex24; } /* Safari */ - else if (censorship_strategy_name == "SNI-REALITY-SAFARI-26") { - censorship_strategy = fptn::protocol::https::CensorshipStrategy::kSniRealityModeSafari26; + else if (censorship_strategy_name == "SNI-REALITY-SAFARI-26-5") { + censorship_strategy = fptn::protocol::https::CensorshipStrategy::kSniRealityModeSafari26_5; + } else if (censorship_strategy_name == "SNI-REALITY-SAFARI-26-4") { + censorship_strategy = fptn::protocol::https::CensorshipStrategy::kSniRealityModeSafari26_4; } + SPDLOG_INFO("HTTPS client censorship strategy: {}", censorship_strategy_name); + auto* https_client = new WrapperHttpsClient(env, global_object_ref, std::move(host), port, std::move(sni), std::move(md5_fingerprint), censorship_strategy); return reinterpret_cast(https_client); diff --git a/app/src/main/cpp/src/websocket_client.cpp b/app/src/main/cpp/src/websocket_client.cpp index e55c3ca8..ece861fa 100644 --- a/app/src/main/cpp/src/websocket_client.cpp +++ b/app/src/main/cpp/src/websocket_client.cpp @@ -88,37 +88,51 @@ Java_org_fptn_vpn_services_websocket_NativeWebSocketClientImpl_nativeCreate( fptn::protocol::https::CensorshipStrategy censorship_strategy = fptn::protocol::https::CensorshipStrategy::kSni; if (censorship_strategy_name == "SNI") { - censorship_strategy = fptn::protocol::https::CensorshipStrategy::kSni; + censorship_strategy = fptn::protocol::https::CensorshipStrategy::kSni; } else if (censorship_strategy_name == "OBFUSCATION") { censorship_strategy = fptn::protocol::https::CensorshipStrategy::kTlsObfuscator; } else if (censorship_strategy_name == "SNI-REALITY") { // deprecated - censorship_strategy = fptn::protocol::https::CensorshipStrategy::kSniRealityMode; + censorship_strategy = fptn::protocol::https::CensorshipStrategy::kSniRealityMode; } /* Chrome */ - else if (censorship_strategy_name == "SNI-REALITY-CHROME-147") { - censorship_strategy = fptn::protocol::https::CensorshipStrategy::kSniRealityModeChrome147; + else if (censorship_strategy_name == "SNI-REALITY-CHROME-149") { + censorship_strategy = fptn::protocol::https::CensorshipStrategy::kSniRealityModeChrome149; + } else if (censorship_strategy_name == "SNI-REALITY-CHROME-148") { + censorship_strategy = fptn::protocol::https::CensorshipStrategy::kSniRealityModeChrome148; + } else if (censorship_strategy_name == "SNI-REALITY-CHROME-147") { + censorship_strategy = fptn::protocol::https::CensorshipStrategy::kSniRealityModeChrome147; } else if (censorship_strategy_name == "SNI-REALITY-CHROME-146") { - censorship_strategy = fptn::protocol::https::CensorshipStrategy::kSniRealityModeChrome146; + censorship_strategy = fptn::protocol::https::CensorshipStrategy::kSniRealityModeChrome146; } else if (censorship_strategy_name == "SNI-REALITY-CHROME-145") { censorship_strategy = fptn::protocol::https::CensorshipStrategy::kSniRealityModeChrome145; } /* Firefox */ - else if (censorship_strategy_name == "SNI-REALITY-FIREFOX-149") { + else if (censorship_strategy_name == "SNI-REALITY-FIREFOX-151") { + censorship_strategy = fptn::protocol::https::CensorshipStrategy::kSniRealityModeFirefox151; + } else if (censorship_strategy_name == "SNI-REALITY-FIREFOX-150") { + censorship_strategy = fptn::protocol::https::CensorshipStrategy::kSniRealityModeFirefox150; + } else if (censorship_strategy_name == "SNI-REALITY-FIREFOX-149") { censorship_strategy = fptn::protocol::https::CensorshipStrategy::kSniRealityModeFirefox149; } /* Yandex */ - else if (censorship_strategy_name == "SNI-REALITY-YANDEX-26") { - censorship_strategy = fptn::protocol::https::CensorshipStrategy::kSniRealityModeYandex26; + else if (censorship_strategy_name == "SNI-REALITY-YANDEX-26-4") { + censorship_strategy = fptn::protocol::https::CensorshipStrategy::kSniRealityModeYandex26_4; + } else if (censorship_strategy_name == "SNI-REALITY-YANDEX-26-3") { + censorship_strategy = fptn::protocol::https::CensorshipStrategy::kSniRealityModeYandex26_3; } else if (censorship_strategy_name == "SNI-REALITY-YANDEX-25") { censorship_strategy = fptn::protocol::https::CensorshipStrategy::kSniRealityModeYandex25; } else if (censorship_strategy_name == "SNI-REALITY-YANDEX-24") { - censorship_strategy = fptn::protocol::https::CensorshipStrategy::kSniRealityModeYandex24; + censorship_strategy = fptn::protocol::https::CensorshipStrategy::kSniRealityModeYandex24; } /* Safari */ - else if (censorship_strategy_name == "SNI-REALITY-SAFARI-26") { - censorship_strategy = fptn::protocol::https::CensorshipStrategy::kSniRealityModeSafari26; + else if (censorship_strategy_name == "SNI-REALITY-SAFARI-26-5") { + censorship_strategy = fptn::protocol::https::CensorshipStrategy::kSniRealityModeSafari26_5; + } else if (censorship_strategy_name == "SNI-REALITY-SAFARI-26-4") { + censorship_strategy = fptn::protocol::https::CensorshipStrategy::kSniRealityModeSafari26_4; } + SPDLOG_INFO("Censorship strategy selected: {}", censorship_strategy_name); + jobject global_object_ref = env->NewWeakGlobalRef(thiz); auto* websocket_client = new WrapperWebsocketClient( global_object_ref, diff --git a/app/src/main/java/org/fptn/vpn/enums/SniSpoofingMode.java b/app/src/main/java/org/fptn/vpn/enums/SniSpoofingMode.java index e064c13f..da5818ef 100644 --- a/app/src/main/java/org/fptn/vpn/enums/SniSpoofingMode.java +++ b/app/src/main/java/org/fptn/vpn/enums/SniSpoofingMode.java @@ -2,16 +2,22 @@ public enum SniSpoofingMode { SNI, - /* Chrome */ - SNI_REALITY_CHROME_147, - SNI_REALITY_CHROME_146, - SNI_REALITY_CHROME_145, - /* Firefox */ - SNI_REALITY_FIREFOX_149, /* Yandex Browser */ - SNI_REALITY_YANDEX_26, + SNI_REALITY_YANDEX_26_4, + SNI_REALITY_YANDEX_26_3, SNI_REALITY_YANDEX_25, SNI_REALITY_YANDEX_24, + /* Firefox */ + SNI_REALITY_FIREFOX_151, + SNI_REALITY_FIREFOX_150, + SNI_REALITY_FIREFOX_149, /* Safari */ - SNI_REALITY_SAFARI_26 + SNI_REALITY_SAFARI_26_5, + SNI_REALITY_SAFARI_26_4, + /* Chrome */ + SNI_REALITY_CHROME_149, + SNI_REALITY_CHROME_148, + SNI_REALITY_CHROME_147, + SNI_REALITY_CHROME_146, + SNI_REALITY_CHROME_145, } diff --git a/app/src/main/java/org/fptn/vpn/services/speedtest/SpeedTestUtils.java b/app/src/main/java/org/fptn/vpn/services/speedtest/SpeedTestUtils.java index 057a24f3..1fe08a40 100644 --- a/app/src/main/java/org/fptn/vpn/services/speedtest/SpeedTestUtils.java +++ b/app/src/main/java/org/fptn/vpn/services/speedtest/SpeedTestUtils.java @@ -54,10 +54,10 @@ public static ServerEntity findFastestServer(List serverEntityList } finally { executor.shutdownNow(); } - } else { + } /* else { // Must never happen - throw new PVNClientException(ErrorCode.SERVER_LIST_NULL_OR_EMPTY); - } + // throw new PVNClientException(ErrorCode.SERVER_LIST_NULL_OR_EMPTY); + } */ return null; } @@ -92,7 +92,8 @@ public static SpeedTestResult findServerByLogin(List serverEntityL executor.shutdownNow(); } } - throw new PVNClientException(ErrorCode.SERVER_LIST_NULL_OR_EMPTY); + return null; + //throw new PVNClientException(ErrorCode.SERVER_LIST_NULL_OR_EMPTY); } private static List selectServersForTesting(List servers) { diff --git a/app/src/main/java/org/fptn/vpn/services/vpn/FptnService.java b/app/src/main/java/org/fptn/vpn/services/vpn/FptnService.java index 79b63251..e0cbd82f 100644 --- a/app/src/main/java/org/fptn/vpn/services/vpn/FptnService.java +++ b/app/src/main/java/org/fptn/vpn/services/vpn/FptnService.java @@ -479,10 +479,6 @@ private void connect(ServerEntity serverEntity, String sniHostname, String preFe } int maxReconnectCount = SharedPrefUtils.getReconnectAttemptsCount(this); int delayBetweenAttempts = SharedPrefUtils.getDelayBetweenReconnect(this); - XLog.tag(TAG).i("Connection params [bypass=%s, maxRetries=%d, retryDelay=%ds, watchIP=%b, watchNetwork=%b]", - SharedPrefUtils.getBypassCensorshipMethod(this), - maxReconnectCount, delayBetweenAttempts, - reconnectOnChangeIPEnabled, reconnectOnChangeNetworkTypeEnabled); FptnConnection connection; @@ -492,6 +488,11 @@ private void connect(ServerEntity serverEntity, String sniHostname, String preFe if (bypassCensorshipMethod == BypassCensorshipMethod.SNI_REALITY) { sniSpoofingMode = SharedPrefUtils.getSniSpoofingMode(this); } + XLog.tag(TAG).i("Connection params [bypass=%s, spoofingMode=%s, maxRetries=%d, retryDelay=%ds, watchIP=%b, watchNetwork=%b]", + bypassCensorshipMethod, + sniSpoofingMode, + maxReconnectCount, delayBetweenAttempts, + reconnectOnChangeIPEnabled, reconnectOnChangeNetworkTypeEnabled); PerAppVpnMode perAppVpnMode = SharedPrefUtils.getPerAppVPNMode(this); List appInfos = new ArrayList<>(); diff --git a/app/src/main/java/org/fptn/vpn/utils/token/TokenUtils.java b/app/src/main/java/org/fptn/vpn/utils/token/TokenUtils.java index 9bf2f0d9..966e718f 100644 --- a/app/src/main/java/org/fptn/vpn/utils/token/TokenUtils.java +++ b/app/src/main/java/org/fptn/vpn/utils/token/TokenUtils.java @@ -76,7 +76,7 @@ public List parseToken(String token) throws PVNClientException { if (serverDtoList.isEmpty()) { XLog.tag(TAG).e("Token parsed but no servers found — token may be invalid or expired"); - throw new PVNClientException(ErrorCode.SERVER_LIST_NULL_OR_EMPTY); +// throw new PVNClientException(ErrorCode.SERVER_LIST_NULL_OR_EMPTY); } return serverDtoList; diff --git a/app/src/main/java/org/fptn/vpn/views/bypassmethod/BypassMethodsActivity.java b/app/src/main/java/org/fptn/vpn/views/bypassmethod/BypassMethodsActivity.java index e838052a..1a056568 100644 --- a/app/src/main/java/org/fptn/vpn/views/bypassmethod/BypassMethodsActivity.java +++ b/app/src/main/java/org/fptn/vpn/views/bypassmethod/BypassMethodsActivity.java @@ -442,22 +442,34 @@ public void onEditSNIServer(View view) { private String getSniSpoofingModeFriendlyName(SniSpoofingMode mode) { return switch (mode) { case SNI -> getString(R.string.sni); + case SNI_REALITY_CHROME_149 -> + getString(R.string.sni_reality_radio_button_label_chrome_149); + case SNI_REALITY_CHROME_148 -> + getString(R.string.sni_reality_radio_button_label_chrome_148); case SNI_REALITY_CHROME_147 -> getString(R.string.sni_reality_radio_button_label_chrome_147); case SNI_REALITY_CHROME_146 -> getString(R.string.sni_reality_radio_button_label_chrome_146); case SNI_REALITY_CHROME_145 -> getString(R.string.sni_reality_radio_button_label_chrome_145); + case SNI_REALITY_FIREFOX_151 -> + getString(R.string.sni_reality_radio_button_label_firefox_151); + case SNI_REALITY_FIREFOX_150 -> + getString(R.string.sni_reality_radio_button_label_firefox_150); case SNI_REALITY_FIREFOX_149 -> getString(R.string.sni_reality_radio_button_label_firefox_149); - case SNI_REALITY_YANDEX_26 -> - getString(R.string.sni_reality_radio_button_label_yandex_26); + case SNI_REALITY_YANDEX_26_4 -> + getString(R.string.sni_reality_radio_button_label_yandex_26_4); + case SNI_REALITY_YANDEX_26_3 -> + getString(R.string.sni_reality_radio_button_label_yandex_26_3); case SNI_REALITY_YANDEX_25 -> getString(R.string.sni_reality_radio_button_label_yandex_25); case SNI_REALITY_YANDEX_24 -> getString(R.string.sni_reality_radio_button_label_yandex_24); - case SNI_REALITY_SAFARI_26 -> - getString(R.string.sni_reality_radio_button_label_safari_26); + case SNI_REALITY_SAFARI_26_5 -> + getString(R.string.sni_reality_radio_button_label_safari_26_5); + case SNI_REALITY_SAFARI_26_4 -> + getString(R.string.sni_reality_radio_button_label_safari_26_4); default -> mode.toString(); }; } diff --git a/app/src/main/res/values-fa-rIR/strings.xml b/app/src/main/res/values-fa-rIR/strings.xml index 7da613ec..bece96dd 100644 --- a/app/src/main/res/values-fa-rIR/strings.xml +++ b/app/src/main/res/values-fa-rIR/strings.xml @@ -163,17 +163,23 @@ https://play.google.com/store/apps/details?id=org.fptn.vpn مخفی‌سازی ترافیک (Obfuscation) جعل پیشرفتهٔ دامنه (SNI + REALITY) + (Chrome 149) جعل پیشرفتهٔ دامنه + (Chrome 148) جعل پیشرفتهٔ دامنه (Chrome 147) جعل پیشرفتهٔ دامنه (Chrome 146) جعل پیشرفتهٔ دامنه (Chrome 145) جعل پیشرفتهٔ دامنه + (Firefox 151) جعل پیشرفتهٔ دامنه + (Firefox 150) جعل پیشرفتهٔ دامنه (Firefox 149) جعل پیشرفتهٔ دامنه - (Yandex 26) جعل پیشرفتهٔ دامنه + (Yandex 26.4) جعل پیشرفتهٔ دامنه + (Yandex 26.3) جعل پیشرفتهٔ دامنه Yandex 25) جعل پیشرفتهٔ دامنه Yandex 24) جعل پیشرفتهٔ دامنه - (Safari 26) جعل پیشرفتهٔ دامنه + (Safari 26.5) جعل پیشرفتهٔ دامنه + (Safari 26.4) جعل پیشرفتهٔ دامنه نیازمند یک دامنهٔ واقعی و فعال است (در غیر این صورت ممکن است خطا رخ دهد) diff --git a/app/src/main/res/values-ru-rRU/strings.xml b/app/src/main/res/values-ru-rRU/strings.xml index 3d76421e..51e5d84c 100644 --- a/app/src/main/res/values-ru-rRU/strings.xml +++ b/app/src/main/res/values-ru-rRU/strings.xml @@ -160,18 +160,23 @@ https://play.google.com/store/apps/details?id=org.fptn.vpn Подмена домена Маскировка трафика (обфускация) Подмена домена (SNI + REALITY) - + Подмена домена (Chrome 149) + Подмена домена (Chrome 148) Подмена домена (Chrome 147) Подмена домена (Chrome 146) Подмена домена (Chrome 145) + Подмена домена (Firefox 151) + Подмена домена (Firefox 150) Подмена домена (Firefox 149) - Подмена домена (Yandex 26) + Подмена домена (Yandex 26.4) + Подмена домена (Yandex 26.3) Подмена домена (Yandex 25) Подмена домена (Yandex 24) - Подмена домена (Safari 26) + Подмена домена (Safari 26.5) + Подмена домена (Safari 26.4) Требуется реальный существующий домен (иначе возможны ошибки) diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 8d2f1a5e..1940da87 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -242,18 +242,23 @@ https://play.google.com/store/apps/details?id=org.fptn.vpn Traffic masking (obfuscation) Domain spoofing (SNI + REALITY) + Domain spoofing (Chrome 149) + Domain spoofing (Chrome 148) Domain spoofing (Chrome 147) Domain spoofing (Chrome 146) Domain spoofing (Chrome 145) + Domain spoofing (Firefox 151) + Domain spoofing (Firefox 150) Domain spoofing (Firefox 149) - Domain spoofing (Yandex 26) + Domain spoofing (Yandex 26.4) + Domain spoofing (Yandex 26.3) Domain spoofing (Yandex 25) Domain spoofing (Yandex 24) - Domain spoofing (Safari 26) - + Domain spoofing (Safari 26.5) + Domain spoofing (Safari 26.4) Requires a real existing domain (otherwise errors may occur) Selecting the best server...