From 4f57da4a386ac2fe473b30f5d57036f5d40f8e50 Mon Sep 17 00:00:00 2001 From: Vahid Farid Date: Tue, 13 Feb 2024 16:28:46 +0330 Subject: [PATCH 01/14] Added fragment_packets to arrays.xml --- V2rayNG/app/src/main/res/values/arrays.xml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/V2rayNG/app/src/main/res/values/arrays.xml b/V2rayNG/app/src/main/res/values/arrays.xml index 38a20734..c64f0fb3 100644 --- a/V2rayNG/app/src/main/res/values/arrays.xml +++ b/V2rayNG/app/src/main/res/values/arrays.xml @@ -60,6 +60,10 @@ reality + + tlshello + + chrome From 826329e996073103519beb785e3b03d7c366111d Mon Sep 17 00:00:00 2001 From: Vahid Farid Date: Tue, 13 Feb 2024 16:29:39 +0330 Subject: [PATCH 02/14] Added title_pref_fragment_* to strings.xml --- V2rayNG/app/src/main/res/values/strings.xml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/V2rayNG/app/src/main/res/values/strings.xml b/V2rayNG/app/src/main/res/values/strings.xml index a518741c..c14de35c 100644 --- a/V2rayNG/app/src/main/res/values/strings.xml +++ b/V2rayNG/app/src/main/res/values/strings.xml @@ -240,6 +240,10 @@ Subscription imported Successfully Import subscription failed + Fragment Packets + Fragment Length (min-max) + Fragment Interval (min-max) + Enable Fragment QRcode From 496a0ec92c9e14498d5f1519c08f56afb49e4a53 Mon Sep 17 00:00:00 2001 From: Vahid Farid Date: Tue, 13 Feb 2024 16:37:51 +0330 Subject: [PATCH 03/14] Added PREF_FRAGMENT_* to AppConfig.kt --- V2rayNG/app/src/main/kotlin/com/v2ray/ang/AppConfig.kt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/V2rayNG/app/src/main/kotlin/com/v2ray/ang/AppConfig.kt b/V2rayNG/app/src/main/kotlin/com/v2ray/ang/AppConfig.kt index cf866b81..b21487e9 100644 --- a/V2rayNG/app/src/main/kotlin/com/v2ray/ang/AppConfig.kt +++ b/V2rayNG/app/src/main/kotlin/com/v2ray/ang/AppConfig.kt @@ -44,6 +44,10 @@ object AppConfig { const val PREF_MUX_CONCURRENCY = "pref_mux_concurency" const val PREF_MUX_XUDP_CONCURRENCY = "pref_mux_xudp_concurency" const val PREF_MUX_XUDP_QUIC = "pref_mux_xudp_quic" + const val PREF_FRAGMENT_ENABLED = "pref_fragment_enabled" + const val PREF_FRAGMENT_PACKETS = "pref_fragment_packets" + const val PREF_FRAGMENT_LENGTH = "pref_fragment_length" + const val PREF_FRAGMENT_INTERVAL = "pref_fragment_interval" const val HTTP_PROTOCOL: String = "http://" const val HTTPS_PROTOCOL: String = "https://" From 6eaac2d7e9ef309ee127e12e8c19cd6611d41a9b Mon Sep 17 00:00:00 2001 From: Vahid Farid Date: Tue, 13 Feb 2024 16:38:27 +0330 Subject: [PATCH 04/14] Added getFragmentOutbound function to ServerConfig.kt --- V2rayNG/app/src/main/kotlin/com/v2ray/ang/dto/ServerConfig.kt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/V2rayNG/app/src/main/kotlin/com/v2ray/ang/dto/ServerConfig.kt b/V2rayNG/app/src/main/kotlin/com/v2ray/ang/dto/ServerConfig.kt index b4cd3e16..6a60654d 100644 --- a/V2rayNG/app/src/main/kotlin/com/v2ray/ang/dto/ServerConfig.kt +++ b/V2rayNG/app/src/main/kotlin/com/v2ray/ang/dto/ServerConfig.kt @@ -56,6 +56,10 @@ data class ServerConfig( return fullConfig?.getProxyOutbound() } + fun getFragmentOutbound(): V2rayConfig.OutboundBean? { + return fullConfig?.getProxyOutbound() + } + fun getAllOutboundTags(): MutableList { if (configType != EConfigType.CUSTOM) { return mutableListOf(TAG_AGENT, TAG_DIRECT, TAG_BLOCKED) From 0d77a65bbb1df7c08a0eb80c99649bd623a4a0bb Mon Sep 17 00:00:00 2001 From: Vahid Farid Date: Tue, 13 Feb 2024 16:43:29 +0330 Subject: [PATCH 05/14] Make tag, mux & sockopt writable in V2rayConfig.kt --- .../app/src/main/kotlin/com/v2ray/ang/dto/V2rayConfig.kt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/V2rayNG/app/src/main/kotlin/com/v2ray/ang/dto/V2rayConfig.kt b/V2rayNG/app/src/main/kotlin/com/v2ray/ang/dto/V2rayConfig.kt index f554e6ca..15374923 100644 --- a/V2rayNG/app/src/main/kotlin/com/v2ray/ang/dto/V2rayConfig.kt +++ b/V2rayNG/app/src/main/kotlin/com/v2ray/ang/dto/V2rayConfig.kt @@ -61,13 +61,13 @@ data class V2rayConfig( val metadataOnly: Boolean? = null) } - data class OutboundBean(val tag: String = "proxy", + data class OutboundBean(var tag: String = "proxy", var protocol: String, var settings: OutSettingsBean? = null, var streamSettings: StreamSettingsBean? = null, val proxySettings: Any? = null, val sendThrough: String? = null, - val mux: MuxBean? = MuxBean(false)) { + var mux: MuxBean? = MuxBean(false)) { data class OutSettingsBean(var vnext: List? = null, var fragment: FragmentBean? = null, @@ -141,7 +141,7 @@ data class V2rayConfig( var realitySettings: TlsSettingsBean? = null, var grpcSettings: GrpcSettingsBean? = null, val dsSettings: Any? = null, - val sockopt: SockoptBean? = null + var sockopt: SockoptBean? = null ) { data class TcpSettingsBean(var header: HeaderBean = HeaderBean(), From 32741ed7ab538978d0c62550e751be5161be7956 Mon Sep 17 00:00:00 2001 From: Vahid Farid Date: Tue, 13 Feb 2024 16:44:17 +0330 Subject: [PATCH 06/14] Added PREF_FRAGMENT_* to SettingsViewModel.kt --- .../main/kotlin/com/v2ray/ang/viewmodel/SettingsViewModel.kt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/V2rayNG/app/src/main/kotlin/com/v2ray/ang/viewmodel/SettingsViewModel.kt b/V2rayNG/app/src/main/kotlin/com/v2ray/ang/viewmodel/SettingsViewModel.kt index 98230e61..d112dd36 100644 --- a/V2rayNG/app/src/main/kotlin/com/v2ray/ang/viewmodel/SettingsViewModel.kt +++ b/V2rayNG/app/src/main/kotlin/com/v2ray/ang/viewmodel/SettingsViewModel.kt @@ -41,6 +41,9 @@ class SettingsViewModel(application: Application) : AndroidViewModel(application AppConfig.PREF_V2RAY_ROUTING_BLOCKED, AppConfig.PREF_V2RAY_ROUTING_DIRECT, AppConfig.SUBSCRIPTION_AUTO_UPDATE_INTERVAL, + AppConfig.PREF_FRAGMENT_PACKETS, + AppConfig.PREF_FRAGMENT_LENGTH, + AppConfig.PREF_FRAGMENT_INTERVAL, AppConfig.PREF_MUX_XUDP_QUIC, -> { settingsStorage?.encode(key, sharedPreferences.getString(key, "")) } @@ -55,6 +58,7 @@ class SettingsViewModel(application: Application) : AndroidViewModel(application AppConfig.PREF_CONFIRM_REMOVE, AppConfig.PREF_START_SCAN_IMMEDIATE, AppConfig.SUBSCRIPTION_AUTO_UPDATE, + AppConfig.PREF_FRAGMENT_ENABLED, AppConfig.PREF_MUX_ENABLED, -> { settingsStorage?.encode(key, sharedPreferences.getBoolean(key, false)) } From e15eec9cff73c81ad836f0f7fd4dac1db68c76ec Mon Sep 17 00:00:00 2001 From: Vahid Farid Date: Tue, 13 Feb 2024 18:35:46 +0330 Subject: [PATCH 07/14] Added fragment fields to pref_settings.xml --- .../app/src/main/res/xml/pref_settings.xml | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/V2rayNG/app/src/main/res/xml/pref_settings.xml b/V2rayNG/app/src/main/res/xml/pref_settings.xml index b4793db9..0eb159ab 100644 --- a/V2rayNG/app/src/main/res/xml/pref_settings.xml +++ b/V2rayNG/app/src/main/res/xml/pref_settings.xml @@ -32,6 +32,28 @@ android:summary="%s" android:title="@string/title_pref_mux_xudp_quic" /> + + + + + + + + Date: Tue, 13 Feb 2024 18:36:40 +0330 Subject: [PATCH 08/14] Added relevant codes to handle fragment settings in SettingsActivity.kt --- .../com/v2ray/ang/ui/SettingsActivity.kt | 52 +++++++++++++++++-- 1 file changed, 49 insertions(+), 3 deletions(-) diff --git a/V2rayNG/app/src/main/kotlin/com/v2ray/ang/ui/SettingsActivity.kt b/V2rayNG/app/src/main/kotlin/com/v2ray/ang/ui/SettingsActivity.kt index b9e1dd04..83fa9eee 100644 --- a/V2rayNG/app/src/main/kotlin/com/v2ray/ang/ui/SettingsActivity.kt +++ b/V2rayNG/app/src/main/kotlin/com/v2ray/ang/ui/SettingsActivity.kt @@ -41,6 +41,10 @@ class SettingsActivity : BaseActivity() { private val muxXudpConcurrency by lazy { findPreference(AppConfig.PREF_MUX_XUDP_CONCURRENCY) } private val muxXudpQuic by lazy { findPreference(AppConfig.PREF_MUX_XUDP_QUIC) } + private val fragment by lazy { findPreference(AppConfig.PREF_FRAGMENT_ENABLED) } + private val fragmentPackets by lazy { findPreference(AppConfig.PREF_FRAGMENT_PACKETS) } + private val fragmentLength by lazy { findPreference(AppConfig.PREF_FRAGMENT_LENGTH) } + private val fragmentInterval by lazy { findPreference(AppConfig.PREF_FRAGMENT_INTERVAL) } // val autoRestart by lazy { findPreference(PREF_AUTO_RESTART) as CheckBoxPreference } private val remoteDns by lazy { findPreference(AppConfig.PREF_REMOTE_DNS) } @@ -168,6 +172,23 @@ class SettingsActivity : BaseActivity() { updateMuxXudpConcurrency(newValue as String) true } + + fragment?.setOnPreferenceChangeListener { _, newValue -> + updateFragment(newValue as Boolean) + true + } + fragmentPackets?.setOnPreferenceChangeListener { _, newValue -> + updateFragmentPackets(newValue as String) + true + } + fragmentLength?.setOnPreferenceChangeListener { _, newValue -> + updateFragmentLength(newValue as String) + true + } + fragmentInterval?.setOnPreferenceChangeListener { _, newValue -> + updateFragmentInterval(newValue as String) + true + } } override fun onStart() { @@ -184,6 +205,10 @@ class SettingsActivity : BaseActivity() { updateMux(defaultSharedPreferences.getBoolean(AppConfig.PREF_MUX_ENABLED, false)) muxConcurrency?.summary = defaultSharedPreferences.getString(AppConfig.PREF_MUX_CONCURRENCY, "8") muxXudpConcurrency?.summary = defaultSharedPreferences.getString(AppConfig.PREF_MUX_XUDP_CONCURRENCY, "8") + updateFragment(defaultSharedPreferences.getBoolean(AppConfig.PREF_FRAGMENT_ENABLED, false)) + fragmentPackets?.summary = defaultSharedPreferences.getString(AppConfig.PREF_FRAGMENT_PACKETS, "tlshello") + fragmentLength?.summary = defaultSharedPreferences.getString(AppConfig.PREF_FRAGMENT_LENGTH, "50-100") + fragmentInterval?.summary = defaultSharedPreferences.getString(AppConfig.PREF_FRAGMENT_INTERVAL, "10-20") autoUpdateInterval?.summary = defaultSharedPreferences.getString(AppConfig.SUBSCRIPTION_AUTO_UPDATE_INTERVAL,AppConfig.SUBSCRIPTION_DEFAULT_UPDATE_INTERVAL) autoUpdateInterval?.isEnabled = defaultSharedPreferences.getBoolean(AppConfig.SUBSCRIPTION_AUTO_UPDATE, false) @@ -261,9 +286,9 @@ class SettingsActivity : BaseActivity() { private fun updateMux(enabled: Boolean) { val defaultSharedPreferences = PreferenceManager.getDefaultSharedPreferences(requireActivity()) - muxConcurrency?.isEnabled = enabled - muxXudpConcurrency?.isEnabled = enabled - muxXudpQuic?.isEnabled = enabled + muxConcurrency?.isVisible = enabled + muxXudpConcurrency?.isVisible = enabled + muxXudpQuic?.isVisible = enabled if (enabled) { updateMuxConcurrency(defaultSharedPreferences.getString(AppConfig.PREF_MUX_CONCURRENCY, "8")) updateMuxXudpConcurrency(defaultSharedPreferences.getString(AppConfig.PREF_MUX_XUDP_CONCURRENCY, "8")) @@ -287,6 +312,27 @@ class SettingsActivity : BaseActivity() { muxXudpQuic?.isEnabled = concurrency >= 0 } } + + private fun updateFragment(enabled: Boolean) { + val defaultSharedPreferences = PreferenceManager.getDefaultSharedPreferences(requireActivity()) + fragmentPackets?.isVisible = enabled + fragmentLength?.isVisible = enabled + fragmentInterval?.isVisible = enabled + if (enabled) { + updateFragmentPackets(defaultSharedPreferences.getString(AppConfig.PREF_FRAGMENT_PACKETS, "tlshello")) + updateFragmentLength(defaultSharedPreferences.getString(AppConfig.PREF_FRAGMENT_LENGTH, "50-100")) + updateFragmentInterval(defaultSharedPreferences.getString(AppConfig.PREF_FRAGMENT_INTERVAL, "10-20")) + } + } + private fun updateFragmentPackets(value: String?) { + fragmentPackets?.summary = value.toString() + } + private fun updateFragmentLength(value: String?) { + fragmentLength?.summary = value.toString() + } + private fun updateFragmentInterval(value: String?) { + fragmentInterval?.summary = value.toString() + } } fun onModeHelpClicked(view: View) { From bab21bc8a58d665b5a36df38573f7d09c25c6519 Mon Sep 17 00:00:00 2001 From: Vahid Farid Date: Tue, 13 Feb 2024 18:37:48 +0330 Subject: [PATCH 09/14] Implemented fragment in V2rayConfigUtil.kt --- .../com/v2ray/ang/util/V2rayConfigUtil.kt | 32 ++++++++++++++++--- 1 file changed, 27 insertions(+), 5 deletions(-) diff --git a/V2rayNG/app/src/main/kotlin/com/v2ray/ang/util/V2rayConfigUtil.kt b/V2rayNG/app/src/main/kotlin/com/v2ray/ang/util/V2rayConfigUtil.kt index 84ab151e..1549ce35 100644 --- a/V2rayNG/app/src/main/kotlin/com/v2ray/ang/util/V2rayConfigUtil.kt +++ b/V2rayNG/app/src/main/kotlin/com/v2ray/ang/util/V2rayConfigUtil.kt @@ -38,7 +38,8 @@ object V2rayConfigUtil { return Result(true, customConfig) } val outbound = config.getProxyOutbound() ?: return Result(false, "") - val result = getV2rayNonCustomConfig(context, outbound) + val fragmentOutbound = config.getFragmentOutbound() ?: V2rayConfig.OutboundBean(protocol = "freedom") + val result = getV2rayNonCustomConfig(context, outbound, fragmentOutbound) //Log.d(ANG_PACKAGE, result.content) return result } catch (e: Exception) { @@ -50,7 +51,7 @@ object V2rayConfigUtil { /** * 生成v2ray的客户端配置文件 */ - private fun getV2rayNonCustomConfig(context: Context, outbound: V2rayConfig.OutboundBean): Result { + private fun getV2rayNonCustomConfig(context: Context, outbound: V2rayConfig.OutboundBean, fragmentOutbound: V2rayConfig.OutboundBean): Result { val result = Result(false, "") //取得默认配置 val assets = Utils.readTextFromAssets(context, "v2ray_config.json") @@ -66,9 +67,12 @@ object V2rayConfigUtil { inbounds(v2rayConfig) - updateOutboundWithGlobalSettings(outbound) + updateOutboundWithGlobalSettings(outbound, fragmentOutbound) v2rayConfig.outbounds[0] = outbound + if (fragmentOutbound.tag == "fragment") { + v2rayConfig.outbounds[1] = fragmentOutbound + } routing(v2rayConfig) @@ -401,7 +405,7 @@ object V2rayConfigUtil { return true } - private fun updateOutboundWithGlobalSettings(outbound: V2rayConfig.OutboundBean): Boolean { + private fun updateOutboundWithGlobalSettings(outbound: V2rayConfig.OutboundBean, fragmentOutbound: V2rayConfig.OutboundBean): Boolean { try { var muxEnabled = settingsStorage?.decodeBool(AppConfig.PREF_MUX_ENABLED, false) val protocol = outbound.protocol @@ -463,11 +467,29 @@ object V2rayConfigUtil { outbound.streamSettings?.tcpSettings?.header?.request?.headers?.Host = host!! } + if(settingsStorage?.decodeBool(AppConfig.PREF_FRAGMENT_ENABLED, false) == true) { + fragmentOutbound.tag = "fragment" + fragmentOutbound.mux = null + fragmentOutbound.settings = V2rayConfig.OutboundBean.OutSettingsBean( + fragment = V2rayConfig.OutboundBean.OutSettingsBean.FragmentBean( + packets = settingsStorage?.decodeString(AppConfig.PREF_FRAGMENT_PACKETS) ?: "tlshello", + length = settingsStorage?.decodeString(AppConfig.PREF_FRAGMENT_LENGTH) ?: "50-100", + interval = settingsStorage?.decodeString(AppConfig.PREF_FRAGMENT_INTERVAL) ?: "10-20")) + fragmentOutbound.streamSettings = V2rayConfig.OutboundBean.StreamSettingsBean( + sockopt = V2rayConfig.OutboundBean.StreamSettingsBean.SockoptBean( + TcpNoDelay = true, + mark = 255)) + } + if (fragmentOutbound.tag == "fragment") { + val sockopt = outbound.streamSettings?.sockopt ?: V2rayConfig.OutboundBean.StreamSettingsBean.SockoptBean() + sockopt.dialerProxy = "fragment" + sockopt.mark = 255 + outbound.streamSettings?.sockopt = sockopt + } } catch (e: Exception) { e.printStackTrace() return false } return true } - } From a3561ddc6c511581c68478347651bc8a76a01237 Mon Sep 17 00:00:00 2001 From: Vahid Farid Date: Wed, 14 Feb 2024 11:06:41 +0330 Subject: [PATCH 10/14] Fixed and turened off fragmentOutbound function for future use --- V2rayNG/app/src/main/kotlin/com/v2ray/ang/dto/ServerConfig.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/V2rayNG/app/src/main/kotlin/com/v2ray/ang/dto/ServerConfig.kt b/V2rayNG/app/src/main/kotlin/com/v2ray/ang/dto/ServerConfig.kt index 6a60654d..65b9a23d 100644 --- a/V2rayNG/app/src/main/kotlin/com/v2ray/ang/dto/ServerConfig.kt +++ b/V2rayNG/app/src/main/kotlin/com/v2ray/ang/dto/ServerConfig.kt @@ -57,7 +57,7 @@ data class ServerConfig( } fun getFragmentOutbound(): V2rayConfig.OutboundBean? { - return fullConfig?.getProxyOutbound() + return null // TODO: fullConfig?.getFragmentOutbound() } fun getAllOutboundTags(): MutableList { From 8d1f0d5df9f3b5a5c152029b8eace44cca202cc4 Mon Sep 17 00:00:00 2001 From: Vahid Farid Date: Wed, 14 Feb 2024 11:20:20 +0330 Subject: [PATCH 11/14] Update ServerConfig.kt --- V2rayNG/app/src/main/kotlin/com/v2ray/ang/dto/ServerConfig.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/V2rayNG/app/src/main/kotlin/com/v2ray/ang/dto/ServerConfig.kt b/V2rayNG/app/src/main/kotlin/com/v2ray/ang/dto/ServerConfig.kt index 65b9a23d..38333919 100644 --- a/V2rayNG/app/src/main/kotlin/com/v2ray/ang/dto/ServerConfig.kt +++ b/V2rayNG/app/src/main/kotlin/com/v2ray/ang/dto/ServerConfig.kt @@ -57,7 +57,7 @@ data class ServerConfig( } fun getFragmentOutbound(): V2rayConfig.OutboundBean? { - return null // TODO: fullConfig?.getFragmentOutbound() + return fullConfig?.getFragmentOutbound() } fun getAllOutboundTags(): MutableList { From 9c06412cebee1c5616e7ee9c534a79f44fe848e0 Mon Sep 17 00:00:00 2001 From: Vahid Farid Date: Wed, 14 Feb 2024 11:20:25 +0330 Subject: [PATCH 12/14] Update V2rayConfig.kt --- .../app/src/main/kotlin/com/v2ray/ang/dto/V2rayConfig.kt | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/V2rayNG/app/src/main/kotlin/com/v2ray/ang/dto/V2rayConfig.kt b/V2rayNG/app/src/main/kotlin/com/v2ray/ang/dto/V2rayConfig.kt index 15374923..19a9e792 100644 --- a/V2rayNG/app/src/main/kotlin/com/v2ray/ang/dto/V2rayConfig.kt +++ b/V2rayNG/app/src/main/kotlin/com/v2ray/ang/dto/V2rayConfig.kt @@ -475,6 +475,15 @@ data class V2rayConfig( return null } + fun getFragmentOutbound(): OutboundBean? { + outbounds.forEach { outbound -> + if (outbound.protocol == "freedom" && outbound.tag == "fragment") { + return outbound + } + } + return null + } + fun toPrettyPrinting(): String { return GsonBuilder() .setPrettyPrinting() From 3cd95fbfdb9aa3cbd5abd4d741cdd6d9e8e72d06 Mon Sep 17 00:00:00 2001 From: 2dust <31833384+2dust@users.noreply.github.com> Date: Wed, 14 Feb 2024 18:52:05 +0800 Subject: [PATCH 13/14] Improve https://github.com/2dust/v2rayNG/pull/2839 --- .../main/kotlin/com/v2ray/ang/AppConfig.kt | 6 +- .../kotlin/com/v2ray/ang/dto/ServerConfig.kt | 4 - .../kotlin/com/v2ray/ang/dto/V2rayConfig.kt | 9 - .../com/v2ray/ang/ui/UrlSchemeActivity.kt | 4 +- .../com/v2ray/ang/util/AngConfigManager.kt | 9 +- .../com/v2ray/ang/util/V2rayConfigUtil.kt | 277 ++++++++++++------ 6 files changed, 201 insertions(+), 108 deletions(-) diff --git a/V2rayNG/app/src/main/kotlin/com/v2ray/ang/AppConfig.kt b/V2rayNG/app/src/main/kotlin/com/v2ray/ang/AppConfig.kt index b21487e9..0d96ac02 100644 --- a/V2rayNG/app/src/main/kotlin/com/v2ray/ang/AppConfig.kt +++ b/V2rayNG/app/src/main/kotlin/com/v2ray/ang/AppConfig.kt @@ -49,8 +49,9 @@ object AppConfig { const val PREF_FRAGMENT_LENGTH = "pref_fragment_length" const val PREF_FRAGMENT_INTERVAL = "pref_fragment_interval" - const val HTTP_PROTOCOL: String = "http://" - const val HTTPS_PROTOCOL: String = "https://" + const val PROTOCOL_HTTP: String = "http://" + const val PROTOCOL_HTTPS: String = "https://" + const val PROTOCOL_FREEDOM: String = "freedom" const val BROADCAST_ACTION_SERVICE = "com.v2ray.ang.action.service" const val BROADCAST_ACTION_ACTIVITY = "com.v2ray.ang.action.activity" @@ -65,6 +66,7 @@ object AppConfig { const val TAG_AGENT = "proxy" const val TAG_DIRECT = "direct" const val TAG_BLOCKED = "block" + const val TAG_FRAGMENT = "fragment" const val androidpackagenamelistUrl = "https://raw.githubusercontent.com/2dust/androidpackagenamelist/master/proxy.txt" diff --git a/V2rayNG/app/src/main/kotlin/com/v2ray/ang/dto/ServerConfig.kt b/V2rayNG/app/src/main/kotlin/com/v2ray/ang/dto/ServerConfig.kt index 38333919..b4cd3e16 100644 --- a/V2rayNG/app/src/main/kotlin/com/v2ray/ang/dto/ServerConfig.kt +++ b/V2rayNG/app/src/main/kotlin/com/v2ray/ang/dto/ServerConfig.kt @@ -56,10 +56,6 @@ data class ServerConfig( return fullConfig?.getProxyOutbound() } - fun getFragmentOutbound(): V2rayConfig.OutboundBean? { - return fullConfig?.getFragmentOutbound() - } - fun getAllOutboundTags(): MutableList { if (configType != EConfigType.CUSTOM) { return mutableListOf(TAG_AGENT, TAG_DIRECT, TAG_BLOCKED) diff --git a/V2rayNG/app/src/main/kotlin/com/v2ray/ang/dto/V2rayConfig.kt b/V2rayNG/app/src/main/kotlin/com/v2ray/ang/dto/V2rayConfig.kt index 19a9e792..15374923 100644 --- a/V2rayNG/app/src/main/kotlin/com/v2ray/ang/dto/V2rayConfig.kt +++ b/V2rayNG/app/src/main/kotlin/com/v2ray/ang/dto/V2rayConfig.kt @@ -475,15 +475,6 @@ data class V2rayConfig( return null } - fun getFragmentOutbound(): OutboundBean? { - outbounds.forEach { outbound -> - if (outbound.protocol == "freedom" && outbound.tag == "fragment") { - return outbound - } - } - return null - } - fun toPrettyPrinting(): String { return GsonBuilder() .setPrettyPrinting() diff --git a/V2rayNG/app/src/main/kotlin/com/v2ray/ang/ui/UrlSchemeActivity.kt b/V2rayNG/app/src/main/kotlin/com/v2ray/ang/ui/UrlSchemeActivity.kt index 793b3c29..165c37a6 100644 --- a/V2rayNG/app/src/main/kotlin/com/v2ray/ang/ui/UrlSchemeActivity.kt +++ b/V2rayNG/app/src/main/kotlin/com/v2ray/ang/ui/UrlSchemeActivity.kt @@ -25,8 +25,8 @@ class UrlSchemeActivity : BaseActivity() { if ("text/plain" == type) { intent.getStringExtra(Intent.EXTRA_TEXT)?.let { val uri = Uri.parse(it) - if (uri.scheme?.startsWith(AppConfig.HTTPS_PROTOCOL) == true || uri.scheme?.startsWith( - AppConfig.HTTP_PROTOCOL + if (uri.scheme?.startsWith(AppConfig.PROTOCOL_HTTPS) == true || uri.scheme?.startsWith( + AppConfig.PROTOCOL_HTTP ) == true ) { val name = uri.getQueryParameter("name") ?: "Subscription" diff --git a/V2rayNG/app/src/main/kotlin/com/v2ray/ang/util/AngConfigManager.kt b/V2rayNG/app/src/main/kotlin/com/v2ray/ang/util/AngConfigManager.kt index 62e725c9..6fefd03d 100644 --- a/V2rayNG/app/src/main/kotlin/com/v2ray/ang/util/AngConfigManager.kt +++ b/V2rayNG/app/src/main/kotlin/com/v2ray/ang/util/AngConfigManager.kt @@ -11,8 +11,8 @@ import com.google.gson.GsonBuilder import com.tencent.mmkv.MMKV import com.v2ray.ang.AppConfig import com.v2ray.ang.AppConfig.ANG_CONFIG -import com.v2ray.ang.AppConfig.HTTPS_PROTOCOL -import com.v2ray.ang.AppConfig.HTTP_PROTOCOL +import com.v2ray.ang.AppConfig.PROTOCOL_HTTPS +import com.v2ray.ang.AppConfig.PROTOCOL_HTTP import com.v2ray.ang.AppConfig.WIREGUARD_LOCAL_ADDRESS_V4 import com.v2ray.ang.AppConfig.WIREGUARD_LOCAL_MTU import com.v2ray.ang.R @@ -24,7 +24,6 @@ import java.net.URI import java.util.* import com.v2ray.ang.extension.idnHost import com.v2ray.ang.extension.removeWhiteSpace -import com.v2ray.ang.extension.toast object AngConfigManager { private val mainStorage by lazy { @@ -216,8 +215,8 @@ object AngConfigManager { } //maybe sub - if (TextUtils.isEmpty(subid) && (str.startsWith(HTTP_PROTOCOL) || str.startsWith( - HTTPS_PROTOCOL + if (TextUtils.isEmpty(subid) && (str.startsWith(PROTOCOL_HTTP) || str.startsWith( + PROTOCOL_HTTPS )) ) { MmkvManager.importUrlAsSubscription(str) diff --git a/V2rayNG/app/src/main/kotlin/com/v2ray/ang/util/V2rayConfigUtil.kt b/V2rayNG/app/src/main/kotlin/com/v2ray/ang/util/V2rayConfigUtil.kt index 1549ce35..745d5af2 100644 --- a/V2rayNG/app/src/main/kotlin/com/v2ray/ang/util/V2rayConfigUtil.kt +++ b/V2rayNG/app/src/main/kotlin/com/v2ray/ang/util/V2rayConfigUtil.kt @@ -2,11 +2,12 @@ package com.v2ray.ang.util import android.content.Context import android.text.TextUtils -import android.util.Log import com.google.gson.* import com.tencent.mmkv.MMKV import com.v2ray.ang.AppConfig -import com.v2ray.ang.AppConfig.ANG_PACKAGE +import com.v2ray.ang.AppConfig.PROTOCOL_FREEDOM +import com.v2ray.ang.AppConfig.TAG_DIRECT +import com.v2ray.ang.AppConfig.TAG_FRAGMENT import com.v2ray.ang.AppConfig.WIREGUARD_LOCAL_ADDRESS_V4 import com.v2ray.ang.AppConfig.WIREGUARD_LOCAL_ADDRESS_V6 import com.v2ray.ang.dto.V2rayConfig @@ -16,8 +17,18 @@ import com.v2ray.ang.dto.V2rayConfig.Companion.DEFAULT_NETWORK import com.v2ray.ang.dto.V2rayConfig.Companion.HTTP object V2rayConfigUtil { - private val serverRawStorage by lazy { MMKV.mmkvWithID(MmkvManager.ID_SERVER_RAW, MMKV.MULTI_PROCESS_MODE) } - private val settingsStorage by lazy { MMKV.mmkvWithID(MmkvManager.ID_SETTING, MMKV.MULTI_PROCESS_MODE) } + private val serverRawStorage by lazy { + MMKV.mmkvWithID( + MmkvManager.ID_SERVER_RAW, + MMKV.MULTI_PROCESS_MODE + ) + } + private val settingsStorage by lazy { + MMKV.mmkvWithID( + MmkvManager.ID_SETTING, + MMKV.MULTI_PROCESS_MODE + ) + } data class Result(var status: Boolean, var content: String) @@ -38,8 +49,7 @@ object V2rayConfigUtil { return Result(true, customConfig) } val outbound = config.getProxyOutbound() ?: return Result(false, "") - val fragmentOutbound = config.getFragmentOutbound() ?: V2rayConfig.OutboundBean(protocol = "freedom") - val result = getV2rayNonCustomConfig(context, outbound, fragmentOutbound) + val result = getV2rayNonCustomConfig(context, outbound) //Log.d(ANG_PACKAGE, result.content) return result } catch (e: Exception) { @@ -51,7 +61,10 @@ object V2rayConfigUtil { /** * 生成v2ray的客户端配置文件 */ - private fun getV2rayNonCustomConfig(context: Context, outbound: V2rayConfig.OutboundBean, fragmentOutbound: V2rayConfig.OutboundBean): Result { + private fun getV2rayNonCustomConfig( + context: Context, + outbound: V2rayConfig.OutboundBean + ): Result { val result = Result(false, "") //取得默认配置 val assets = Utils.readTextFromAssets(context, "v2ray_config.json") @@ -63,16 +76,14 @@ object V2rayConfigUtil { val v2rayConfig = Gson().fromJson(assets, V2rayConfig::class.java) ?: return result v2rayConfig.log.loglevel = settingsStorage?.decodeString(AppConfig.PREF_LOGLEVEL) - ?: "warning" + ?: "warning" inbounds(v2rayConfig) - updateOutboundWithGlobalSettings(outbound, fragmentOutbound) - + updateOutboundWithGlobalSettings(outbound) v2rayConfig.outbounds[0] = outbound - if (fragmentOutbound.tag == "fragment") { - v2rayConfig.outbounds[1] = fragmentOutbound - } + + updateOutboundFragment(v2rayConfig) routing(v2rayConfig) @@ -97,8 +108,14 @@ object V2rayConfigUtil { */ private fun inbounds(v2rayConfig: V2rayConfig): Boolean { try { - val socksPort = Utils.parseInt(settingsStorage?.decodeString(AppConfig.PREF_SOCKS_PORT), AppConfig.PORT_SOCKS.toInt()) - val httpPort = Utils.parseInt(settingsStorage?.decodeString(AppConfig.PREF_HTTP_PORT), AppConfig.PORT_HTTP.toInt()) + val socksPort = Utils.parseInt( + settingsStorage?.decodeString(AppConfig.PREF_SOCKS_PORT), + AppConfig.PORT_SOCKS.toInt() + ) + val httpPort = Utils.parseInt( + settingsStorage?.decodeString(AppConfig.PREF_HTTP_PORT), + AppConfig.PORT_HTTP.toInt() + ) v2rayConfig.inbounds.forEach { curInbound -> if (settingsStorage?.decodeBool(AppConfig.PREF_PROXY_SHARING) != true) { @@ -108,8 +125,9 @@ object V2rayConfigUtil { } v2rayConfig.inbounds[0].port = socksPort val fakedns = settingsStorage?.decodeBool(AppConfig.PREF_FAKE_DNS_ENABLED) - ?: false - val sniffAllTlsAndHttp = settingsStorage?.decodeBool(AppConfig.PREF_SNIFFING_ENABLED, true) + ?: false + val sniffAllTlsAndHttp = + settingsStorage?.decodeBool(AppConfig.PREF_SNIFFING_ENABLED, true) ?: true v2rayConfig.inbounds[0].sniffing?.enabled = fakedns || sniffAllTlsAndHttp if (!sniffAllTlsAndHttp) { @@ -135,9 +153,10 @@ object V2rayConfigUtil { } private fun fakedns(v2rayConfig: V2rayConfig) { - if (settingsStorage?.decodeBool(AppConfig.PREF_FAKE_DNS_ENABLED) == true) { + if (settingsStorage?.decodeBool(AppConfig.PREF_LOCAL_DNS_ENABLED) == true + || settingsStorage?.decodeBool(AppConfig.PREF_FAKE_DNS_ENABLED) == true) { v2rayConfig.fakedns = listOf(V2rayConfig.FakednsBean()) - v2rayConfig.outbounds.filter { it.protocol == "freedom" }.forEach { + v2rayConfig.outbounds.filter { it.protocol == PROTOCOL_FREEDOM && it.tag == TAG_DIRECT }.forEach { it.settings?.domainStrategy = "UseIP" } } @@ -148,38 +167,49 @@ object V2rayConfigUtil { */ private fun routing(v2rayConfig: V2rayConfig): Boolean { try { - routingUserRule(settingsStorage?.decodeString(AppConfig.PREF_V2RAY_ROUTING_AGENT) - ?: "", AppConfig.TAG_AGENT, v2rayConfig) - routingUserRule(settingsStorage?.decodeString(AppConfig.PREF_V2RAY_ROUTING_DIRECT) - ?: "", AppConfig.TAG_DIRECT, v2rayConfig) - routingUserRule(settingsStorage?.decodeString(AppConfig.PREF_V2RAY_ROUTING_BLOCKED) - ?: "", AppConfig.TAG_BLOCKED, v2rayConfig) + routingUserRule( + settingsStorage?.decodeString(AppConfig.PREF_V2RAY_ROUTING_AGENT) + ?: "", AppConfig.TAG_AGENT, v2rayConfig + ) + routingUserRule( + settingsStorage?.decodeString(AppConfig.PREF_V2RAY_ROUTING_DIRECT) + ?: "", AppConfig.TAG_DIRECT, v2rayConfig + ) + routingUserRule( + settingsStorage?.decodeString(AppConfig.PREF_V2RAY_ROUTING_BLOCKED) + ?: "", AppConfig.TAG_BLOCKED, v2rayConfig + ) - v2rayConfig.routing.domainStrategy = settingsStorage?.decodeString(AppConfig.PREF_ROUTING_DOMAIN_STRATEGY) + v2rayConfig.routing.domainStrategy = + settingsStorage?.decodeString(AppConfig.PREF_ROUTING_DOMAIN_STRATEGY) ?: "IPIfNonMatch" // v2rayConfig.routing.domainMatcher = "mph" - val routingMode = settingsStorage?.decodeString(AppConfig.PREF_ROUTING_MODE) ?: ERoutingMode.GLOBAL_PROXY.value + val routingMode = settingsStorage?.decodeString(AppConfig.PREF_ROUTING_MODE) + ?: ERoutingMode.GLOBAL_PROXY.value // Hardcode googleapis.cn val googleapisRoute = V2rayConfig.RoutingBean.RulesBean( - type = "field", - outboundTag = AppConfig.TAG_AGENT, - domain = arrayListOf("domain:googleapis.cn") + type = "field", + outboundTag = AppConfig.TAG_AGENT, + domain = arrayListOf("domain:googleapis.cn") ) when (routingMode) { ERoutingMode.BYPASS_LAN.value -> { routingGeo("ip", "private", AppConfig.TAG_DIRECT, v2rayConfig) } + ERoutingMode.BYPASS_MAINLAND.value -> { routingGeo("", "cn", AppConfig.TAG_DIRECT, v2rayConfig) v2rayConfig.routing.rules.add(0, googleapisRoute) } + ERoutingMode.BYPASS_LAN_MAINLAND.value -> { routingGeo("ip", "private", AppConfig.TAG_DIRECT, v2rayConfig) routingGeo("", "cn", AppConfig.TAG_DIRECT, v2rayConfig) v2rayConfig.routing.rules.add(0, googleapisRoute) } + ERoutingMode.GLOBAL_DIRECT.value -> { val globalDirect = V2rayConfig.RoutingBean.RulesBean( type = "field", @@ -196,7 +226,12 @@ object V2rayConfigUtil { return true } - private fun routingGeo(ipOrDomain: String, code: String, tag: String, v2rayConfig: V2rayConfig) { + private fun routingGeo( + ipOrDomain: String, + code: String, + tag: String, + v2rayConfig: V2rayConfig + ) { try { if (!TextUtils.isEmpty(code)) { //IP @@ -281,51 +316,70 @@ object V2rayConfigUtil { try { if (settingsStorage?.decodeBool(AppConfig.PREF_FAKE_DNS_ENABLED) == true) { val geositeCn = arrayListOf("geosite:cn") - val proxyDomain = userRule2Domian(settingsStorage?.decodeString(AppConfig.PREF_V2RAY_ROUTING_AGENT) - ?: "") - val directDomain = userRule2Domian(settingsStorage?.decodeString(AppConfig.PREF_V2RAY_ROUTING_DIRECT) - ?: "") + val proxyDomain = userRule2Domian( + settingsStorage?.decodeString(AppConfig.PREF_V2RAY_ROUTING_AGENT) + ?: "" + ) + val directDomain = userRule2Domian( + settingsStorage?.decodeString(AppConfig.PREF_V2RAY_ROUTING_DIRECT) + ?: "" + ) // fakedns with all domains to make it always top priority - v2rayConfig.dns.servers?.add(0, - V2rayConfig.DnsBean.ServersBean(address = "fakedns", domains = geositeCn.plus(proxyDomain).plus(directDomain))) + v2rayConfig.dns.servers?.add( + 0, + V2rayConfig.DnsBean.ServersBean( + address = "fakedns", + domains = geositeCn.plus(proxyDomain).plus(directDomain) + ) + ) } // DNS inbound对象 val remoteDns = Utils.getRemoteDnsServers() if (v2rayConfig.inbounds.none { e -> e.protocol == "dokodemo-door" && e.tag == "dns-in" }) { val dnsInboundSettings = V2rayConfig.InboundBean.InSettingsBean( - address = if (Utils.isPureIpAddress(remoteDns.first())) remoteDns.first() else "1.1.1.1", - port = 53, - network = "tcp,udp") + address = if (Utils.isPureIpAddress(remoteDns.first())) remoteDns.first() else "1.1.1.1", + port = 53, + network = "tcp,udp" + ) - val localDnsPort = Utils.parseInt(settingsStorage?.decodeString(AppConfig.PREF_LOCAL_DNS_PORT), AppConfig.PORT_LOCAL_DNS.toInt()) + val localDnsPort = Utils.parseInt( + settingsStorage?.decodeString(AppConfig.PREF_LOCAL_DNS_PORT), + AppConfig.PORT_LOCAL_DNS.toInt() + ) v2rayConfig.inbounds.add( - V2rayConfig.InboundBean( - tag = "dns-in", - port = localDnsPort, - listen = "127.0.0.1", - protocol = "dokodemo-door", - settings = dnsInboundSettings, - sniffing = null)) + V2rayConfig.InboundBean( + tag = "dns-in", + port = localDnsPort, + listen = "127.0.0.1", + protocol = "dokodemo-door", + settings = dnsInboundSettings, + sniffing = null + ) + ) } // DNS outbound对象 if (v2rayConfig.outbounds.none { e -> e.protocol == "dns" && e.tag == "dns-out" }) { v2rayConfig.outbounds.add( - V2rayConfig.OutboundBean( - protocol = "dns", - tag = "dns-out", - settings = null, - streamSettings = null, - mux = null)) + V2rayConfig.OutboundBean( + protocol = "dns", + tag = "dns-out", + settings = null, + streamSettings = null, + mux = null + ) + ) } // DNS routing tag - v2rayConfig.routing.rules.add(0, V2rayConfig.RoutingBean.RulesBean( + v2rayConfig.routing.rules.add( + 0, V2rayConfig.RoutingBean.RulesBean( type = "field", inboundTag = arrayListOf("dns-in"), outboundTag = "dns-out", - domain = null) + domain = null + ) ) } catch (e: Exception) { e.printStackTrace() @@ -339,43 +393,73 @@ object V2rayConfigUtil { val hosts = mutableMapOf() val servers = ArrayList() val remoteDns = Utils.getRemoteDnsServers() - val proxyDomain = userRule2Domian(settingsStorage?.decodeString(AppConfig.PREF_V2RAY_ROUTING_AGENT) - ?: "") + val proxyDomain = userRule2Domian( + settingsStorage?.decodeString(AppConfig.PREF_V2RAY_ROUTING_AGENT) + ?: "" + ) remoteDns.forEach { servers.add(it) } if (proxyDomain.size > 0) { - servers.add(V2rayConfig.DnsBean.ServersBean(remoteDns.first(), 53, proxyDomain, null)) + servers.add( + V2rayConfig.DnsBean.ServersBean( + remoteDns.first(), + 53, + proxyDomain, + null + ) + ) } // domestic DNS - val directDomain = userRule2Domian(settingsStorage?.decodeString(AppConfig.PREF_V2RAY_ROUTING_DIRECT) - ?: "") - val routingMode = settingsStorage?.decodeString(AppConfig.PREF_ROUTING_MODE) ?: ERoutingMode.GLOBAL_PROXY.value + val directDomain = userRule2Domian( + settingsStorage?.decodeString(AppConfig.PREF_V2RAY_ROUTING_DIRECT) + ?: "" + ) + val routingMode = settingsStorage?.decodeString(AppConfig.PREF_ROUTING_MODE) + ?: ERoutingMode.GLOBAL_PROXY.value if (directDomain.size > 0 || routingMode == ERoutingMode.BYPASS_MAINLAND.value || routingMode == ERoutingMode.BYPASS_LAN_MAINLAND.value) { val domesticDns = Utils.getDomesticDnsServers() val geositeCn = arrayListOf("geosite:cn") val geoipCn = arrayListOf("geoip:cn") if (directDomain.size > 0) { - servers.add(V2rayConfig.DnsBean.ServersBean(domesticDns.first(), 53, directDomain, geoipCn)) + servers.add( + V2rayConfig.DnsBean.ServersBean( + domesticDns.first(), + 53, + directDomain, + geoipCn + ) + ) } if (routingMode == ERoutingMode.BYPASS_MAINLAND.value || routingMode == ERoutingMode.BYPASS_LAN_MAINLAND.value) { - servers.add(V2rayConfig.DnsBean.ServersBean(domesticDns.first(), 53, geositeCn, geoipCn)) + servers.add( + V2rayConfig.DnsBean.ServersBean( + domesticDns.first(), + 53, + geositeCn, + geoipCn + ) + ) } if (Utils.isPureIpAddress(domesticDns.first())) { - v2rayConfig.routing.rules.add(0, V2rayConfig.RoutingBean.RulesBean( + v2rayConfig.routing.rules.add( + 0, V2rayConfig.RoutingBean.RulesBean( type = "field", outboundTag = AppConfig.TAG_DIRECT, port = "53", ip = arrayListOf(domesticDns.first()), - domain = null) + domain = null + ) ) } } - val blkDomain = userRule2Domian(settingsStorage?.decodeString(AppConfig.PREF_V2RAY_ROUTING_BLOCKED) - ?: "") + val blkDomain = userRule2Domian( + settingsStorage?.decodeString(AppConfig.PREF_V2RAY_ROUTING_BLOCKED) + ?: "" + ) if (blkDomain.size > 0) { hosts.putAll(blkDomain.map { it to "127.0.0.1" }) } @@ -385,17 +469,20 @@ object V2rayConfigUtil { // DNS dns对象 v2rayConfig.dns = V2rayConfig.DnsBean( - servers = servers, - hosts = hosts) + servers = servers, + hosts = hosts + ) // DNS routing if (Utils.isPureIpAddress(remoteDns.first())) { - v2rayConfig.routing.rules.add(0, V2rayConfig.RoutingBean.RulesBean( + v2rayConfig.routing.rules.add( + 0, V2rayConfig.RoutingBean.RulesBean( type = "field", outboundTag = AppConfig.TAG_AGENT, port = "53", ip = arrayListOf(remoteDns.first()), - domain = null) + domain = null + ) ) } } catch (e: Exception) { @@ -405,7 +492,7 @@ object V2rayConfigUtil { return true } - private fun updateOutboundWithGlobalSettings(outbound: V2rayConfig.OutboundBean, fragmentOutbound: V2rayConfig.OutboundBean): Boolean { + private fun updateOutboundWithGlobalSettings(outbound: V2rayConfig.OutboundBean): Boolean { try { var muxEnabled = settingsStorage?.decodeBool(AppConfig.PREF_MUX_ENABLED, false) val protocol = outbound.protocol @@ -467,24 +554,42 @@ object V2rayConfigUtil { outbound.streamSettings?.tcpSettings?.header?.request?.headers?.Host = host!! } - if(settingsStorage?.decodeBool(AppConfig.PREF_FRAGMENT_ENABLED, false) == true) { - fragmentOutbound.tag = "fragment" - fragmentOutbound.mux = null + + } catch (e: Exception) { + e.printStackTrace() + return false + } + return true + } + + private fun updateOutboundFragment(v2rayConfig: V2rayConfig): Boolean { + try { + if (settingsStorage?.decodeBool(AppConfig.PREF_FRAGMENT_ENABLED, false) == true) { + val fragmentOutbound = + V2rayConfig.OutboundBean(protocol = PROTOCOL_FREEDOM, tag = TAG_FRAGMENT, mux = null) fragmentOutbound.settings = V2rayConfig.OutboundBean.OutSettingsBean( fragment = V2rayConfig.OutboundBean.OutSettingsBean.FragmentBean( - packets = settingsStorage?.decodeString(AppConfig.PREF_FRAGMENT_PACKETS) ?: "tlshello", - length = settingsStorage?.decodeString(AppConfig.PREF_FRAGMENT_LENGTH) ?: "50-100", - interval = settingsStorage?.decodeString(AppConfig.PREF_FRAGMENT_INTERVAL) ?: "10-20")) + packets = settingsStorage?.decodeString(AppConfig.PREF_FRAGMENT_PACKETS) + ?: "tlshello", + length = settingsStorage?.decodeString(AppConfig.PREF_FRAGMENT_LENGTH) + ?: "50-100", + interval = settingsStorage?.decodeString(AppConfig.PREF_FRAGMENT_INTERVAL) + ?: "10-20" + ) + ) fragmentOutbound.streamSettings = V2rayConfig.OutboundBean.StreamSettingsBean( sockopt = V2rayConfig.OutboundBean.StreamSettingsBean.SockoptBean( TcpNoDelay = true, - mark = 255)) - } - if (fragmentOutbound.tag == "fragment") { - val sockopt = outbound.streamSettings?.sockopt ?: V2rayConfig.OutboundBean.StreamSettingsBean.SockoptBean() - sockopt.dialerProxy = "fragment" - sockopt.mark = 255 - outbound.streamSettings?.sockopt = sockopt + mark = 255 + ) + ) + v2rayConfig.outbounds.add(fragmentOutbound) + + //proxy chain + v2rayConfig.outbounds[0].streamSettings?.sockopt = + V2rayConfig.OutboundBean.StreamSettingsBean.SockoptBean( + dialerProxy = TAG_FRAGMENT + ) } } catch (e: Exception) { e.printStackTrace() From 09fc20794e73ebf4753caf213fba6d9c80315c12 Mon Sep 17 00:00:00 2001 From: 2dust <31833384+2dust@users.noreply.github.com> Date: Wed, 14 Feb 2024 19:40:51 +0800 Subject: [PATCH 14/14] Improve and translate --- .../app/src/main/res/values-vi/strings.xml | 1 + .../src/main/res/values-zh-rCN/strings.xml | 15 ++- .../src/main/res/values-zh-rTW/strings.xml | 15 ++- V2rayNG/app/src/main/res/values/strings.xml | 2 + .../app/src/main/res/xml/pref_settings.xml | 98 ++++++++++--------- 5 files changed, 76 insertions(+), 55 deletions(-) diff --git a/V2rayNG/app/src/main/res/values-vi/strings.xml b/V2rayNG/app/src/main/res/values-vi/strings.xml index 0b4d8bcd..cca31901 100644 --- a/V2rayNG/app/src/main/res/values-vi/strings.xml +++ b/V2rayNG/app/src/main/res/values-vi/strings.xml @@ -103,6 +103,7 @@ Proxy Theo Ứng Dụng - Bình thường: Ứng dụng đã chọn sẽ kết nối thông qua Proxy, chưa chọn sẽ kết nối trực tiếp. \n- Chế độ Bypass: Ứng dụng đã chọn sẽ kết nối trực tiếp, chưa chọn sẽ kết nối qua Proxy. \n- Nếu bạn đang ở Trung Quốc thì vào Menu, chọn Tự động chọn ứng dụng Proxy. + Mux Settings Bật Mux Giảm độ trễ trong bước bắt tay của kết nối TCP. Mux phân phối dữ liệu từ nhiều kết nối TCP trên một kết nối TCP duy nhất. Không nên sử dụng Mux để xem video, download file hoặc chạy speedtest vì thường không hiệu quả. TCP connections (từ 1 đến 1024) diff --git a/V2rayNG/app/src/main/res/values-zh-rCN/strings.xml b/V2rayNG/app/src/main/res/values-zh-rCN/strings.xml index 00d0f539..5208b864 100644 --- a/V2rayNG/app/src/main/res/values-zh-rCN/strings.xml +++ b/V2rayNG/app/src/main/res/values-zh-rCN/strings.xml @@ -103,6 +103,7 @@ 分应用代理 常规:勾选的App被代理,未勾选的直连;\n绕行模式:勾选的App直连,未勾选的被代理.\n不明白者在菜单中选择自动选中需代理应用 + Mux 多路复用 设置 启用 Mux 多路复用 减低延时,但可能会断流,建议不要启用。\nTCP,UDP 及 QUIC 流量处理方式下方可选。 TCP 复用子链接数(可填 -1 至 1024) @@ -225,6 +226,16 @@ "已连接,点击测试连接" "未连接" + 订阅导入成功 + 导入订阅失败 + 添加 + 添加链接 + 分片(fragment) 设置 + 分片方式 + 分片包长(最小-最大) + 分片间隔(最小-最大) + 启用分片(fragment) + 二维码 导出至剪贴板 @@ -255,9 +266,5 @@ VPN 仅代理 - 订阅导入成功 - 导入订阅失败 - 添加 - 添加链接 diff --git a/V2rayNG/app/src/main/res/values-zh-rTW/strings.xml b/V2rayNG/app/src/main/res/values-zh-rTW/strings.xml index c81b140e..d865928d 100644 --- a/V2rayNG/app/src/main/res/values-zh-rTW/strings.xml +++ b/V2rayNG/app/src/main/res/values-zh-rTW/strings.xml @@ -103,6 +103,7 @@ Proxy 個別應用程式 常規:勾選的 App 啟用 Proxy,未勾選的直接連線;\n繞行模式:勾選的 App 直接連線,未勾選的啟用 Proxy。\n可在選單中選擇自動選中需 Proxy 應用 + Mux 設定 啟用 Mux 多路復用 減低延時 但可能會斷流\nTCP,UDP 及 QUIC 流量處理方式下方可選 TCP 復用子鏈接數(可填 -1 至 1024) @@ -225,6 +226,16 @@ "已連線,輕觸以檢查連線能力" "未連線" + 訂閱導入成功 + 導入訂閱失敗 + 添加 + 添加連結 + 分片(fragment) 設定 + 分片方式 + 分片包长(最小-最大) + 分片间隔(最小-最大) + 启用分片(fragment) + QR Code 匯出至剪貼簿 @@ -254,9 +265,5 @@ VPN 僅 Proxy - 訂閱導入成功 - 導入訂閱失敗 - 添加 - 添加連結 diff --git a/V2rayNG/app/src/main/res/values/strings.xml b/V2rayNG/app/src/main/res/values/strings.xml index c14de35c..287723d9 100644 --- a/V2rayNG/app/src/main/res/values/strings.xml +++ b/V2rayNG/app/src/main/res/values/strings.xml @@ -114,6 +114,7 @@ Per-app proxy General: Checked App is proxy, unchecked direct connection; \nbypass mode: checked app directly connected, unchecked proxy. \nThe option to automatically select the proxy application in the menu + Mux Settings Enable Mux Faster, but it may cause unstable connectivity\ncustomize how to handle TCP, UDP and QUIC below TCP connections(range -1 to 1024) @@ -240,6 +241,7 @@ Subscription imported Successfully Import subscription failed + Fragment Settings Fragment Packets Fragment Length (min-max) Fragment Interval (min-max) diff --git a/V2rayNG/app/src/main/res/xml/pref_settings.xml b/V2rayNG/app/src/main/res/xml/pref_settings.xml index 0eb159ab..51b2c6fd 100644 --- a/V2rayNG/app/src/main/res/xml/pref_settings.xml +++ b/V2rayNG/app/src/main/res/xml/pref_settings.xml @@ -7,53 +7,6 @@ android:summary="@string/summary_pref_sniffing_enabled" android:title="@string/title_pref_sniffing_enabled" /> - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + +