Add Enable New TUN Feature option

When enabled, TUN will use hev-socks5-tunnel; otherwise, it will use badvpn-tun2socks
This commit is contained in:
2dust
2025-08-04 18:32:16 +08:00
parent b60423d1c0
commit 15de18b736
21 changed files with 176 additions and 25 deletions

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -62,6 +62,7 @@ object AppConfig {
const val PREF_IS_BOOTED = "pref_is_booted"
const val PREF_CHECK_UPDATE_PRE_RELEASE = "pref_check_update_pre_release"
const val PREF_GEO_FILES_SOURCES = "pref_geo_files_sources"
const val PREF_USE_HEV_TUNNEL = "pref_use_hev_tunnel"
/** Cache keys. */
const val CACHE_SUBSCRIPTION_ID = "cache_subscription_id"

View File

@@ -0,0 +1,96 @@
package com.v2ray.ang.service
import android.content.Context
import android.os.ParcelFileDescriptor
import android.util.Log
import com.v2ray.ang.AppConfig
import com.v2ray.ang.AppConfig.VPN_MTU
import com.v2ray.ang.handler.MmkvManager
import com.v2ray.ang.handler.SettingsManager
import java.io.File
/**
* Manages the tun2socks process that handles VPN traffic
*/
class TProxyService(
private val context: Context,
private val vpnInterface: ParcelFileDescriptor,
private val isRunningProvider: () -> Boolean,
private val restartCallback: () -> Unit
) : Tun2SocksControl {
companion object {
@JvmStatic
@Suppress("FunctionName")
private external fun TProxyStartService(configPath: String, fd: Int)
@JvmStatic
@Suppress("FunctionName")
private external fun TProxyStopService()
@JvmStatic
@Suppress("FunctionName")
private external fun TProxyGetStats(): LongArray?
init {
System.loadLibrary("hev-socks5-tunnel")
}
}
/**
* Starts the tun2socks process with the appropriate parameters.
*/
override fun startTun2Socks() {
Log.i(AppConfig.TAG, "Starting HevSocks5Tunnel via JNI")
val configContent = buildConfig()
val configFile = File(context.filesDir, "hev-socks5-tunnel.yaml").apply {
writeText(configContent)
}
Log.i(AppConfig.TAG, "Config file created: ${configFile.absolutePath}")
Log.d(AppConfig.TAG, "Config content:\n$configContent")
try {
Log.i(AppConfig.TAG, "TProxyStartService...")
TProxyStartService(configFile.absolutePath, vpnInterface.fd)
} catch (e: Exception) {
Log.e(AppConfig.TAG, "HevSocks5Tunnel exception: ${e.message}")
}
}
private fun buildConfig(): String {
val socksPort = SettingsManager.getSocksPort()
val vpnConfig = SettingsManager.getCurrentVpnInterfaceAddressConfig()
return buildString {
appendLine("tunnel:")
appendLine(" mtu: $VPN_MTU")
appendLine(" ipv4: ${vpnConfig.ipv4Client}")
if (MmkvManager.decodeSettingsBool(AppConfig.PREF_PREFER_IPV6) == true) {
appendLine(" ipv6: '${vpnConfig.ipv6Client}'")
}
appendLine("socks5:")
appendLine(" port: ${socksPort}")
appendLine(" address: ${AppConfig.LOOPBACK}")
appendLine(" udp: 'udp'")
MmkvManager.decodeSettingsString(AppConfig.PREF_LOGLEVEL)?.let { logPref ->
if (logPref != "none") {
val logLevel = if (logPref == "warning") "warn" else logPref
appendLine("misc:")
appendLine(" log-level: $logLevel")
}
}
}
}
/**
* Stops the tun2socks process
*/
override fun stopTun2Socks() {
try {
Log.i(AppConfig.TAG, "TProxyStopService...")
TProxyStopService()
} catch (e: Exception) {
Log.e(AppConfig.TAG, "Failed to stop hev-socks5-tunnel", e)
}
}
}

View File

@@ -0,0 +1,19 @@
package com.v2ray.ang.service
/**
* Interface that defines the control operations for tun2socks implementations.
*
* This interface is implemented by different tunnel solutions like:
*/
interface Tun2SocksControl {
/**
* Starts the tun2socks process with the appropriate parameters.
* This initializes the VPN tunnel and connects it to the SOCKS proxy.
*/
fun startTun2Socks()
/**
* Stops the tun2socks process and cleans up resources.
*/
fun stopTun2Socks()
}

View File

@@ -23,7 +23,7 @@ class Tun2SocksService(
private val vpnInterface: ParcelFileDescriptor,
private val isRunningProvider: () -> Boolean,
private val restartCallback: () -> Unit
) {
) : Tun2SocksControl {
companion object {
private const val TUN2SOCKS = "libtun2socks.so"
}
@@ -33,7 +33,7 @@ class Tun2SocksService(
/**
* Starts the tun2socks process with the appropriate parameters.
*/
fun startTun2Socks() {
override fun startTun2Socks() {
Log.i(AppConfig.TAG, "Start run $TUN2SOCKS")
val socksPort = SettingsManager.getSocksPort()
val vpnConfig = SettingsManager.getCurrentVpnInterfaceAddressConfig()
@@ -116,7 +116,7 @@ class Tun2SocksService(
/**
* Stops the tun2socks process
*/
fun stopTun2Socks() {
override fun stopTun2Socks() {
try {
Log.i(AppConfig.TAG, "$TUN2SOCKS destroy")
if (::process.isInitialized) {

View File

@@ -30,7 +30,7 @@ import java.lang.ref.SoftReference
class V2RayVpnService : VpnService(), ServiceControl {
private lateinit var mInterface: ParcelFileDescriptor
private var isRunning = false
private var tun2SocksService: Tun2SocksService? = null
private var tun2SocksService: Tun2SocksControl? = null
/**destroy
* Unfortunately registerDefaultNetworkCallback is going to return our VPN interface: https://android.googlesource.com/platform/frameworks/base/+/dda156ab0c5d66ad82bdcf76cda07cbc0a9c8a2e
@@ -296,14 +296,23 @@ class V2RayVpnService : VpnService(), ServiceControl {
* Starts the tun2socks process with the appropriate parameters.
*/
private fun runTun2socks() {
if (MmkvManager.decodeSettingsBool(AppConfig.PREF_USE_HEV_TUNNEL) == true) {
tun2SocksService = TProxyService(
context = applicationContext,
vpnInterface = mInterface,
isRunningProvider = { isRunning },
restartCallback = { runTun2socks() }
)
} else {
tun2SocksService = Tun2SocksService(
context = applicationContext,
vpnInterface = mInterface,
isRunningProvider = { isRunning },
restartCallback = { runTun2socks() }
).also {
it.startTun2Socks()
)
}
tun2SocksService?.startTun2Socks()
}
/**

View File

@@ -242,7 +242,8 @@ class SettingsActivity : BaseActivity() {
AppConfig.PREF_DOUBLE_COLUMN_DISPLAY,
AppConfig.PREF_PREFER_IPV6,
AppConfig.PREF_PROXY_SHARING,
AppConfig.PREF_ALLOW_INSECURE
AppConfig.PREF_ALLOW_INSECURE,
AppConfig.PREF_USE_HEV_TUNNEL
).forEach { key ->
findPreference<CheckBoxPreference>(key)?.isChecked =
MmkvManager.decodeSettingsBool(key, false)

View File

@@ -80,6 +80,7 @@ class SettingsViewModel(application: Application) : AndroidViewModel(application
AppConfig.SUBSCRIPTION_AUTO_UPDATE,
AppConfig.PREF_FRAGMENT_ENABLED,
AppConfig.PREF_MUX_ENABLED,
AppConfig.PREF_USE_HEV_TUNNEL
-> {
MmkvManager.encodeSettings(key, sharedPreferences.getBoolean(key, false))
}

View File

@@ -247,6 +247,8 @@
<string name="title_language">اللغة</string>
<string name="title_ui_settings">إعدادات واجهة المستخدم</string>
<string name="title_pref_ui_mode_night">إعدادات وضع واجهة المستخدم ليلاً</string>
<string name="title_pref_use_hev_tunnel">Enable New TUN Feature</string>
<string name="summary_pref_use_hev_tunnel">When enabled, TUN will use hev-socks5-tunnel; otherwise, it will use badvpn-tun2socks.</string>
<string name="title_logcat">Logcat</string>
<string name="logcat_copy">نسخ</string>

View File

@@ -248,6 +248,8 @@
<string name="title_language">ভাষা</string>
<string name="title_ui_settings">ইউআই সেটিংস</string>
<string name="title_pref_ui_mode_night">ইউআই মোড সেটিংস</string>
<string name="title_pref_use_hev_tunnel">Enable New TUN Feature</string>
<string name="summary_pref_use_hev_tunnel">When enabled, TUN will use hev-socks5-tunnel; otherwise, it will use badvpn-tun2socks.</string>
<string name="title_logcat">লগক্যাট</string>
<string name="logcat_copy">কপি করুন</string>

View File

@@ -248,6 +248,8 @@
<string name="title_language">زووݩ</string>
<string name="title_ui_settings">سامووا رابت منتوری</string>
<string name="title_pref_ui_mode_night">سامووا هالت رابت منتوری</string>
<string name="title_pref_use_hev_tunnel">Enable New TUN Feature</string>
<string name="summary_pref_use_hev_tunnel">When enabled, TUN will use hev-socks5-tunnel; otherwise, it will use badvpn-tun2socks.</string>
<string name="title_logcat">داسووا</string>
<string name="logcat_copy">لف گیری</string>

View File

@@ -245,6 +245,8 @@
<string name="title_language">زبان</string>
<string name="title_ui_settings">تنظیمات رابط کاربری</string>
<string name="title_pref_ui_mode_night">تنظیمات حالت رابط کاربری</string>
<string name="title_pref_use_hev_tunnel">Enable New TUN Feature</string>
<string name="summary_pref_use_hev_tunnel">When enabled, TUN will use hev-socks5-tunnel; otherwise, it will use badvpn-tun2socks.</string>
<string name="title_logcat">گزارشات</string>
<string name="logcat_copy">کپی</string>

View File

@@ -247,6 +247,8 @@
<string name="title_language">Язык</string>
<string name="title_ui_settings">Настройки интерфейса</string>
<string name="title_pref_ui_mode_night">Тема интерфейса</string>
<string name="title_pref_use_hev_tunnel">Enable New TUN Feature</string>
<string name="summary_pref_use_hev_tunnel">When enabled, TUN will use hev-socks5-tunnel; otherwise, it will use badvpn-tun2socks.</string>
<string name="title_logcat">Журнал</string>
<string name="logcat_copy">Копировать</string>

View File

@@ -248,6 +248,8 @@
<string name="title_language">Ngôn ngữ</string>
<string name="title_ui_settings">Cài đặt UI</string>
<string name="title_pref_ui_mode_night">Cài đặt chế độ UI</string>
<string name="title_pref_use_hev_tunnel">Enable New TUN Feature</string>
<string name="summary_pref_use_hev_tunnel">When enabled, TUN will use hev-socks5-tunnel; otherwise, it will use badvpn-tun2socks.</string>
<string name="title_logcat">Logcat</string>
<string name="logcat_copy">Sao chép</string>

View File

@@ -245,6 +245,8 @@
<string name="title_language">语言</string>
<string name="title_ui_settings">用户界面设置</string>
<string name="title_pref_ui_mode_night">界面颜色设置</string>
<string name="title_pref_use_hev_tunnel">启用新的 TUN 功能</string>
<string name="summary_pref_use_hev_tunnel">选择启用后 TUN 将使用 hev-socks5-tunnel 否则使用 badvpn-tun2socks</string>
<string name="title_logcat">Logcat</string>
<string name="logcat_copy">复制</string>

View File

@@ -246,6 +246,8 @@
<string name="title_language">語言</string>
<string name="title_ui_settings">介面顏色設定</string>
<string name="title_pref_ui_mode_night">介面顯示模式</string>
<string name="title_pref_use_hev_tunnel">啟用新 TUN 功能</string>
<string name="summary_pref_use_hev_tunnel">選擇啟用後TUN 將使用 hev-socks5-tunnel否則使用 badvpn-tun2socks。</string>
<string name="title_logcat">Logcat</string>
<string name="logcat_copy">複製</string>

View File

@@ -249,6 +249,8 @@
<string name="title_language">Language</string>
<string name="title_ui_settings">UI settings</string>
<string name="title_pref_ui_mode_night">UI mode settings</string>
<string name="title_pref_use_hev_tunnel">Enable New TUN Feature</string>
<string name="summary_pref_use_hev_tunnel">When enabled, TUN will use hev-socks5-tunnel; otherwise, it will use badvpn-tun2socks.</string>
<string name="title_logcat">Logcat</string>
<string name="logcat_copy">Copy</string>

View File

@@ -13,6 +13,7 @@
android:key="pref_route_only_enabled"
android:summary="@string/summary_pref_route_only_enabled"
android:title="@string/title_pref_route_only_enabled" />
<CheckBoxPreference
android:key="pref_is_booted"
android:summary="@string/summary_pref_is_booted"
@@ -254,6 +255,11 @@
android:key="pref_mode"
android:summary="%s"
android:title="@string/title_mode" />
<CheckBoxPreference
android:key="pref_use_hev_tunnel"
android:summary="@string/summary_pref_use_hev_tunnel"
android:title="@string/title_pref_use_hev_tunnel" />
</PreferenceCategory>