Add xray-core tun mode (#5150)

* Add xray-core tun mode

The service start-up sequence is changed:
vpn service is created first,
a file descriptor to the underlining vpn service can then be passed to xray-core,
Xray core then create the TUN inbound from it

* Remove badvpn-tun2socks
This commit is contained in:
yuhan6665
2026-01-12 01:16:44 -05:00
committed by GitHub
parent bd60224577
commit 73d1dce4db
20 changed files with 210 additions and 60 deletions
@@ -0,0 +1,117 @@
{
"stats":{},
"log": {
"loglevel": "warning"
},
"policy":{
"levels": {
"8": {
"handshake": 4,
"connIdle": 300,
"uplinkOnly": 1,
"downlinkOnly": 1
}
},
"system": {
"statsOutboundUplink": true,
"statsOutboundDownlink": true
}
},
"inbounds": [{
"tag": "socks",
"port": 10808,
"protocol": "socks",
"settings": {
"auth": "noauth",
"udp": true,
"userLevel": 8
},
"sniffing": {
"enabled": true,
"destOverride": [
"http",
"tls"
]
}
},
{
"tag": "http",
"port": 10809,
"protocol": "http",
"settings": {
"userLevel": 8
}
},
{
"tag": "tun",
"port": 0,
"protocol": "tun",
"settings": {
"name": "xray0",
"MTU": 1500,
"userLevel": 8
}
}
],
"outbounds": [{
"tag": "proxy",
"protocol": "vmess",
"settings": {
"vnext": [
{
"address": "v2ray.cool",
"port": 10086,
"users": [
{
"id": "a3482e88-686a-4a58-8126-99c9df64b7bf",
"alterId": 0,
"security": "auto",
"level": 8
}
]
}
],
"servers": [
{
"address": "v2ray.cool",
"method": "chacha20",
"ota": false,
"password": "123456",
"port": 10086,
"level": 8
}
]
},
"streamSettings": {
"network": "tcp"
},
"mux": {
"enabled": false
}
},
{
"protocol": "freedom",
"settings": {
"domainStrategy": "UseIP"
},
"tag": "direct"
},
{
"protocol": "blackhole",
"tag": "block",
"settings": {
"response": {
"type": "http"
}
}
}
],
"routing": {
"domainStrategy": "AsIs",
"rules": []
},
"dns": {
"hosts": {},
"servers": []
}
}
@@ -63,7 +63,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"
const val PREF_TUN = "pref_tun"
const val PREF_HEV_TUNNEL_LOGLEVEL = "pref_hev_tunnel_loglevel"
const val PREF_HEV_TUNNEL_RW_TIMEOUT = "pref_hev_tunnel_rw_timeout_v2"
const val PREF_AUTO_REMOVE_INVALID_AFTER_TEST = "pref_auto_remove_invalid_after_test"
@@ -175,6 +175,8 @@ object AppConfig {
/** Give a good name to this, IDK*/
const val VPN = "VPN"
const val VPN_MTU = 1500
const val TUN_hevsocks5 = "hev-socks5-tunnel"
const val TUN_xray = "xray-core"
/** hev-sock5-tunnel read-write-timeout value */
const val HEVTUN_RW_TIMEOUT = "300,60"
@@ -397,6 +397,7 @@ object SettingsManager {
ensureDefaultValue(AppConfig.PREF_MUX_XUDP_CONCURRENCY, "8")
ensureDefaultValue(AppConfig.PREF_FRAGMENT_LENGTH, "50-100")
ensureDefaultValue(AppConfig.PREF_FRAGMENT_INTERVAL, "10-20")
ensureDefaultValue(AppConfig.PREF_TUN, AppConfig.TUN_hevsocks5)
}
private fun ensureDefaultValue(key: String, default: String) {
@@ -5,6 +5,7 @@ import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.os.ParcelFileDescriptor
import android.util.Log
import androidx.core.content.ContextCompat
import com.v2ray.ang.AppConfig
@@ -123,7 +124,7 @@ object V2RayServiceManager {
* `registerReceiver(Context, BroadcastReceiver, IntentFilter, int)`.
* Starts the V2Ray core service.
*/
fun startCoreLoop(): Boolean {
fun startCoreLoop(vpnInterface: ParcelFileDescriptor?): Boolean {
if (coreController.isRunning) {
return false
}
@@ -147,9 +148,13 @@ object V2RayServiceManager {
}
currentConfig = config
var tunFd = vpnInterface?.fd ?: 0
if ((MmkvManager.decodeSettingsString(AppConfig.PREF_TUN) ?: AppConfig.TUN_hevsocks5) != AppConfig.TUN_xray) {
tunFd = 0
}
try {
coreController.startLoop(result.content)
coreController.startLoop(result.content, tunFd)
} catch (e: Exception) {
Log.e(AppConfig.TAG, "Failed to start Core loop", e)
return false
@@ -28,6 +28,7 @@ import com.v2ray.ang.util.Utils
object V2rayConfigManager {
private var initConfigCache: String? = null
private var initConfigCacheWithTun: String? = null
//region get config function
@@ -305,11 +306,20 @@ object V2rayConfigManager {
* @return V2rayConfig object parsed from the JSON configuration, or null if the configuration is empty
*/
private fun initV2rayConfig(context: Context): V2rayConfig? {
val assets = initConfigCache ?: Utils.readTextFromAssets(context, "v2ray_config.json")
if (TextUtils.isEmpty(assets)) {
return null
var assets = ""
if ((MmkvManager.decodeSettingsString(AppConfig.PREF_TUN) ?: AppConfig.TUN_hevsocks5) != AppConfig.TUN_xray) {
assets = initConfigCache ?: Utils.readTextFromAssets(context, "v2ray_config.json")
if (TextUtils.isEmpty(assets)) {
return null
}
initConfigCache = assets
} else {
assets = initConfigCacheWithTun ?: Utils.readTextFromAssets(context, "v2ray_config_with_tun.json")
if (TextUtils.isEmpty(assets)) {
return null
}
initConfigCacheWithTun = assets
}
initConfigCache = assets
val config = JsonUtil.fromJson(assets, V2rayConfig::class.java)
return config
}
@@ -479,16 +489,24 @@ object V2rayConfigManager {
)
}
// if (MmkvManager.decodeSettingsBool(AppConfig.PREF_USE_HEV_TUNNEL, true)) {
//hev-socks5-tunnel dns routing
v2rayConfig.routing.rules.add(
0, RulesBean(
inboundTag = arrayListOf("socks"),
outboundTag = "dns-out",
port = "53",
type = "field"
if (MmkvManager.decodeSettingsString(AppConfig.PREF_TUN, AppConfig.TUN_hevsocks5) == AppConfig.TUN_hevsocks5) {
//hev-socks5-tunnel dns routing
v2rayConfig.routing.rules.add(
0, RulesBean(
inboundTag = arrayListOf("socks"),
outboundTag = "dns-out",
port = "53",
)
)
)
} else {
v2rayConfig.routing.rules.add(
0, RulesBean(
inboundTag = arrayListOf("tun"),
outboundTag = "dns-out",
port = "53",
)
)
}
// DNS outbound
if (v2rayConfig.outbounds.none { e -> e.protocol == "dns" && e.tag == "dns-out" }) {
@@ -26,7 +26,7 @@ class V2RayProxyOnlyService : Service(), ServiceControl {
* @return The start mode.
*/
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
V2RayServiceManager.startCoreLoop()
V2RayServiceManager.startCoreLoop(null)
return START_STICKY
}
@@ -90,9 +90,8 @@ class V2RayVpnService : VpnService(), ServiceControl {
}
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
if (V2RayServiceManager.startCoreLoop()) {
startService()
}
setupVpnService()
startService()
return START_STICKY
//return super.onStartCommand(intent, flags, startId)
}
@@ -102,7 +101,11 @@ class V2RayVpnService : VpnService(), ServiceControl {
}
override fun startService() {
setupService()
if (mInterface == null) {
Log.e(AppConfig.TAG, "Failed to create VPN interface")
return
}
V2RayServiceManager.startCoreLoop(mInterface)
}
override fun stopService() {
@@ -124,7 +127,7 @@ class V2RayVpnService : VpnService(), ServiceControl {
* Sets up the VPN service.
* Prepares the VPN and configures it if preparation is successful.
*/
private fun setupService() {
private fun setupVpnService() {
val prepare = prepare(this)
if (prepare != null) {
return
@@ -294,13 +297,16 @@ 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() }
)
if (MmkvManager.decodeSettingsString(AppConfig.PREF_TUN, AppConfig.TUN_hevsocks5) == AppConfig.TUN_hevsocks5) {
tun2SocksService = TProxyService(
context = applicationContext,
vpnInterface = mInterface,
isRunningProvider = { isRunning },
restartCallback = { runTun2socks() }
)
} else {
tun2SocksService = null
}
tun2SocksService?.startTun2Socks()
}
@@ -66,7 +66,7 @@ class SettingsActivity : BaseActivity() {
// private val hevTunLogLevel by lazy { findPreference<ListPreference>(AppConfig.PREF_HEV_TUNNEL_LOGLEVEL) }
// private val hevTunRwTimeout by lazy { findPreference<EditTextPreference>(AppConfig.PREF_HEV_TUNNEL_RW_TIMEOUT) }
// private val useHevTun by lazy { findPreference<CheckBoxPreference>(AppConfig.PREF_USE_HEV_TUNNEL) }
// private val useTun by lazy { findPreference<ListPreference>(AppConfig.PREF_TUN) }
override fun onCreatePreferences(bundle: Bundle?, s: String?) {
// Use MMKV as the storage backend for all Preferences
@@ -190,8 +190,8 @@ class SettingsActivity : BaseActivity() {
mode?.dialogLayoutResource = R.layout.preference_with_help_link
//loglevel.summary = "LogLevel"
// useHevTun?.setOnPreferenceChangeListener { _, newValue ->
// updateHevTunSettings(newValue as Boolean)
// useTun?.setOnPreferenceChangeListener { _, newValue ->
// updateHevTunSettings(newValue as String == AppConfig.TUN_hevsocks5)
// true
// }
@@ -274,8 +274,9 @@ class SettingsActivity : BaseActivity() {
// delayTestUrl?.summary = MmkvManager.decodeSettingsString(AppConfig.PREF_DELAY_TEST_URL, AppConfig.DELAY_TEST_URL)
// ipApiUrl?.summary = MmkvManager.decodeSettingsString(AppConfig.PREF_IP_API_URL, AppConfig.IP_API_URL)
// hevTunRwTimeout?.summary = MmkvManager.decodeSettingsString(AppConfig.PREF_HEV_TUNNEL_RW_TIMEOUT, AppConfig.HEVTUN_RW_TIMEOUT)
// updateHevTunSettings(MmkvManager.decodeSettingsString(AppConfig.PREF_TUN, AppConfig.TUN_hevsocks5) == AppConfig.TUN_hevsocks5)
// initSharedPreference()
// initSharedPreference()
}
private fun initSharedPreference() {
@@ -62,7 +62,8 @@ class SettingsViewModel(application: Application) : AndroidViewModel(application
AppConfig.PREF_FRAGMENT_INTERVAL,
AppConfig.PREF_MUX_XUDP_QUIC,
AppConfig.PREF_HEV_TUNNEL_LOGLEVEL,
AppConfig.PREF_HEV_TUNNEL_RW_TIMEOUT
AppConfig.PREF_HEV_TUNNEL_RW_TIMEOUT,
AppConfig.PREF_TUN,
-> {
MmkvManager.encodeSettings(key, sharedPreferences.getString(key, ""))
}
@@ -83,18 +84,19 @@ class SettingsViewModel(application: Application) : AndroidViewModel(application
AppConfig.PREF_DOUBLE_COLUMN_DISPLAY,
AppConfig.SUBSCRIPTION_AUTO_UPDATE,
AppConfig.PREF_FRAGMENT_ENABLED,
AppConfig.PREF_MUX_ENABLED
AppConfig.PREF_MUX_ENABLED,
-> {
MmkvManager.encodeSettings(key, sharedPreferences.getBoolean(key, false))
}
AppConfig.PREF_SNIFFING_ENABLED,
AppConfig.PREF_USE_HEV_TUNNEL -> {
-> {
MmkvManager.encodeSettings(key, sharedPreferences.getBoolean(key, true))
}
AppConfig.PREF_MUX_CONCURRENCY,
AppConfig.PREF_MUX_XUDP_CONCURRENCY -> {
AppConfig.PREF_MUX_XUDP_CONCURRENCY,
-> {
MmkvManager.encodeSettings(key, sharedPreferences.getString(key, "8"))
}
}
@@ -257,8 +257,7 @@
<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_pref_tun">TUN Interface</string>
<string name="title_pref_hev_tunnel_loglevel">Hev Tun Log Level</string>
<string name="title_pref_hev_tunnel_rw_timeout">Hev Tun read/write timeout (seconds) (tcp,udp default 300,60)</string>
@@ -257,8 +257,7 @@
<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_pref_tun">TUN Interface</string>
<string name="title_pref_hev_tunnel_loglevel">Hev Tun Log Level</string>
<string name="title_pref_hev_tunnel_rw_timeout">Hev Tun read/write timeout (seconds) (tcp,udp default 300,60)</string>
@@ -257,8 +257,7 @@
<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_pref_tun">TUN Interface</string>
<string name="title_pref_hev_tunnel_loglevel">Hev Tun سئت گوزارشا</string>
<string name="title_pref_hev_tunnel_rw_timeout">زمووݩ مندیر بیڌن خوندن/هؽل کردن Hev Tun (سانیه) (پؽش فرز tcp,udp 300،60)</string>
@@ -254,8 +254,7 @@
<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_pref_tun">TUN واسط</string>
<string name="title_pref_hev_tunnel_loglevel">سطح گزارشات Hev Tun</string>
<string name="title_pref_hev_tunnel_rw_timeout">زمان انتظار خواندن/نوشتن Hev Tun (ثانیه) (پیش‌فرض tcp,udp 300،60)</string>
@@ -256,8 +256,7 @@
<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_pref_tun">TUN интерфейса</string>
<string name="title_pref_hev_tunnel_loglevel">Подробность журнала HevTun</string>
<string name="title_pref_hev_tunnel_rw_timeout">Ожидание чтения/записи HevTun (секунд, по умолчанию TCP,UDP 300,60)</string>
@@ -257,8 +257,7 @@
<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_pref_tun">TUN Interface</string>
<string name="title_pref_hev_tunnel_loglevel">Hev Tun Log Level</string>
<string name="title_pref_hev_tunnel_rw_timeout">Hev Tun read/write timeout (seconds) (tcp,udp default 300,60)</string>
@@ -254,8 +254,7 @@
<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_pref_tun">TUN 接口</string>
<string name="title_pref_hev_tunnel_loglevel">HevTun 日志级别</string>
<string name="title_pref_hev_tunnel_rw_timeout">HevTun 读写超时(秒) (tcp,udp 默认 300,60)</string>
@@ -255,8 +255,7 @@
<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_pref_tun">TUN 介面</string>
<string name="title_pref_hev_tunnel_loglevel">HevTun 日誌級別</string>
<string name="title_pref_hev_tunnel_rw_timeout">HevTun 讀寫逾時(秒) (tcp,udp 預設 300,60)</string>
@@ -118,6 +118,11 @@
<item>Proxy only</item>
</string-array>
<string-array name="tun_value" translatable="false">
<item>hev-socks5-tunnel</item>
<item>xray-core</item>
</string-array>
<string-array name="hev_tunnel_loglevel" translatable="false">
<item>error</item>
<item>warn</item>
+1 -2
View File
@@ -260,8 +260,7 @@
<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_pref_tun">TUN Interface</string>
<string name="title_pref_hev_tunnel_loglevel">Hev Tun Log Level</string>
<string name="title_pref_hev_tunnel_rw_timeout">Hev Tun read/write timeout (seconds) (tcp,udp default 300,60)</string>
@@ -100,11 +100,13 @@
android:summary="1500"
android:title="@string/title_pref_vpn_mtu" />
<!-- <CheckBoxPreference-->
<!-- android:defaultValue="true"-->
<!-- android:key="pref_use_hev_tunnel"-->
<!-- android:summary="@string/summary_pref_use_hev_tunnel"-->
<!-- android:title="@string/title_pref_use_hev_tunnel" />-->
<ListPreference
android:defaultValue="hev-socks5-tunnel"
android:entries="@array/tun_value"
android:entryValues="@array/tun_value"
android:key="pref_tun"
android:summary="%s"
android:title="@string/title_pref_tun" />
<ListPreference
android:defaultValue="warn"