support set tun stack

This commit is contained in:
wwqgtxx 2024-09-11 19:41:19 +08:00
parent bb2c5283f8
commit 3cc77c7c95
10 changed files with 46 additions and 8 deletions

View File

@ -111,18 +111,20 @@ Java_com_github_kr328_clash_core_bridge_Bridge_nativeNotifyInstalledAppChanged(J
JNIEXPORT void JNICALL JNIEXPORT void JNICALL
Java_com_github_kr328_clash_core_bridge_Bridge_nativeStartTun(JNIEnv *env, jobject thiz, Java_com_github_kr328_clash_core_bridge_Bridge_nativeStartTun(JNIEnv *env, jobject thiz,
jint fd, jint fd,
jstring stack,
jstring gateway, jstring gateway,
jstring portal, jstring portal,
jstring dns, jstring dns,
jobject cb) { jobject cb) {
TRACE_METHOD(); TRACE_METHOD();
scoped_string _stack = get_string(stack);
scoped_string _gateway = get_string(gateway); scoped_string _gateway = get_string(gateway);
scoped_string _portal = get_string(portal); scoped_string _portal = get_string(portal);
scoped_string _dns = get_string(dns); scoped_string _dns = get_string(dns);
jobject _interface = new_global(cb); jobject _interface = new_global(cb);
startTun(fd, _gateway, _portal, _dns, _interface); startTun(fd, _stack, _gateway, _portal, _dns, _interface);
} }
JNIEXPORT void JNICALL JNIEXPORT void JNICALL

View File

@ -64,7 +64,7 @@ func (t *remoteTun) close() {
} }
//export startTun //export startTun
func startTun(fd C.int, gateway, portal, dns C.c_string, callback unsafe.Pointer) C.int { func startTun(fd C.int, stack, gateway, portal, dns C.c_string, callback unsafe.Pointer) C.int {
rTunLock.Lock() rTunLock.Lock()
defer rTunLock.Unlock() defer rTunLock.Unlock()
@ -74,6 +74,7 @@ func startTun(fd C.int, gateway, portal, dns C.c_string, callback unsafe.Pointer
} }
f := int(fd) f := int(fd)
s := C.GoString(stack)
g := C.GoString(gateway) g := C.GoString(gateway)
p := C.GoString(portal) p := C.GoString(portal)
d := C.GoString(dns) d := C.GoString(dns)
@ -82,7 +83,7 @@ func startTun(fd C.int, gateway, portal, dns C.c_string, callback unsafe.Pointer
app.ApplyTunContext(remote.markSocket, remote.querySocketUid) app.ApplyTunContext(remote.markSocket, remote.querySocketUid)
closer, err := tun.Start(f, g, p, d) closer, err := tun.Start(f, s, g, p, d)
if err != nil { if err != nil {
remote.close() remote.close()

View File

@ -14,8 +14,13 @@ import (
"github.com/metacubex/mihomo/tunnel" "github.com/metacubex/mihomo/tunnel"
) )
func Start(fd int, gateway, portal, dns string) (io.Closer, error) { func Start(fd int, stack, gateway, portal, dns string) (io.Closer, error) {
log.Debugln("TUN: fd = %d, gateway = %s, portal = %s, dns = %s", fd, gateway, portal, dns) log.Debugln("TUN: fd = %d, stack = %s, gateway = %s, portal = %s, dns = %s", fd, stack, gateway, portal, dns)
tunStack, ok := C.StackTypeMapping[strings.ToLower(stack)]
if !ok {
tunStack = C.TunSystem
}
var prefix4 []netip.Prefix var prefix4 []netip.Prefix
var prefix6 []netip.Prefix var prefix6 []netip.Prefix
@ -49,7 +54,7 @@ func Start(fd int, gateway, portal, dns string) (io.Closer, error) {
options := LC.Tun{ options := LC.Tun{
Enable: true, Enable: true,
Device: sing_tun.InterfaceName, Device: sing_tun.InterfaceName,
Stack: C.TunSystem, Stack: tunStack,
DNSHijack: dnsHijack, DNSHijack: dnsHijack,
Inet4Address: prefix4, Inet4Address: prefix4,
Inet6Address: prefix6, Inet6Address: prefix6,

View File

@ -64,13 +64,14 @@ object Clash {
fun startTun( fun startTun(
fd: Int, fd: Int,
stack: String,
gateway: String, gateway: String,
portal: String, portal: String,
dns: String, dns: String,
markSocket: (Int) -> Boolean, markSocket: (Int) -> Boolean,
querySocketUid: (protocol: Int, source: InetSocketAddress, target: InetSocketAddress) -> Int querySocketUid: (protocol: Int, source: InetSocketAddress, target: InetSocketAddress) -> Int
) { ) {
Bridge.nativeStartTun(fd, gateway, portal, dns, object : TunInterface { Bridge.nativeStartTun(fd, stack, gateway, portal, dns, object : TunInterface {
override fun markSocket(fd: Int) { override fun markSocket(fd: Int) {
markSocket(fd) markSocket(fd)
} }

View File

@ -19,7 +19,7 @@ object Bridge {
external fun nativeNotifyDnsChanged(dnsList: String) external fun nativeNotifyDnsChanged(dnsList: String)
external fun nativeNotifyTimeZoneChanged(name: String, offset: Int) external fun nativeNotifyTimeZoneChanged(name: String, offset: Int)
external fun nativeNotifyInstalledAppChanged(uidList: String) external fun nativeNotifyInstalledAppChanged(uidList: String)
external fun nativeStartTun(fd: Int, gateway: String, portal: String, dns: String, cb: TunInterface) external fun nativeStartTun(fd: Int, stack: String, gateway: String, portal: String, dns: String, cb: TunInterface)
external fun nativeStopTun() external fun nativeStopTun()
external fun nativeStartHttp(listenAt: String): String? external fun nativeStartHttp(listenAt: String): String?
external fun nativeStopHttp() external fun nativeStopHttp()

View File

@ -93,6 +93,22 @@ class NetworkSettingsDesign(
) )
} }
selectableList(
value = srvStore::tunStackMode,
values = arrayOf(
"system",
"gvisor",
"mixed"
),
valuesText = arrayOf(
R.string.tun_stack_system,
R.string.tun_stack_gvisor,
R.string.tun_stack_mixed
),
title = R.string.tun_stack_mode,
configure = vpnDependencies::add,
)
selectableList( selectableList(
value = srvStore::accessControlMode, value = srvStore::accessControlMode,
values = AccessControlMode.values(), values = AccessControlMode.values(),

View File

@ -232,6 +232,11 @@
<string name="always_dark">Always Dark</string> <string name="always_dark">Always Dark</string>
<string name="always_light">Always Light</string> <string name="always_light">Always Light</string>
<string name="tun_stack_mode">Stack Mode</string>
<string name="tun_stack_system">System Stack</string>
<string name="tun_stack_gvisor">Gvisor Stack</string>
<string name="tun_stack_mixed">Mixed Stack</string>
<string name="allow_all_apps">Allow all apps</string> <string name="allow_all_apps">Allow all apps</string>
<string name="allow_selected_apps">Allow selected apps</string> <string name="allow_selected_apps">Allow selected apps</string>
<string name="deny_selected_apps">Deny selected apps</string> <string name="deny_selected_apps">Deny selected apps</string>

View File

@ -218,6 +218,7 @@ class TunService : VpnService(), CoroutineScope by CoroutineScope(Dispatchers.De
TunModule.TunDevice( TunModule.TunDevice(
fd = establish()?.detachFd() fd = establish()?.detachFd()
?: throw NullPointerException("Establish VPN rejected by system"), ?: throw NullPointerException("Establish VPN rejected by system"),
stack = store.tunStackMode,
gateway = "$TUN_GATEWAY/$TUN_SUBNET_PREFIX" + if (store.allowIpv6) ",$TUN_GATEWAY6/$TUN_SUBNET_PREFIX6" else "", gateway = "$TUN_GATEWAY/$TUN_SUBNET_PREFIX" + if (store.allowIpv6) ",$TUN_GATEWAY6/$TUN_SUBNET_PREFIX6" else "",
portal = TUN_PORTAL + if (store.allowIpv6) ",$TUN_PORTAL6" else "", portal = TUN_PORTAL + if (store.allowIpv6) ",$TUN_PORTAL6" else "",
dns = if (store.dnsHijacking) NET_ANY else (TUN_DNS + if (store.allowIpv6) ",$TUN_DNS6" else ""), dns = if (store.dnsHijacking) NET_ANY else (TUN_DNS + if (store.allowIpv6) ",$TUN_DNS6" else ""),

View File

@ -15,6 +15,7 @@ import java.security.SecureRandom
class TunModule(private val vpn: VpnService) : Module<Unit>(vpn) { class TunModule(private val vpn: VpnService) : Module<Unit>(vpn) {
data class TunDevice( data class TunDevice(
val fd: Int, val fd: Int,
var stack: String,
val gateway: String, val gateway: String,
val portal: String, val portal: String,
val dns: String, val dns: String,
@ -56,6 +57,7 @@ class TunModule(private val vpn: VpnService) : Module<Unit>(vpn) {
fun attach(device: TunDevice) { fun attach(device: TunDevice) {
Clash.startTun( Clash.startTun(
fd = device.fd, fd = device.fd,
stack = device.stack,
gateway = device.gateway, gateway = device.gateway,
portal = device.portal, portal = device.portal,
dns = device.dns, dns = device.dns,

View File

@ -56,6 +56,11 @@ class ServiceStore(context: Context) {
defaultValue = false defaultValue = false
) )
var tunStackMode by store.string(
key = "tun_stack_mode",
defaultValue = "system"
)
var dynamicNotification by store.boolean( var dynamicNotification by store.boolean(
key = "dynamic_notification", key = "dynamic_notification",
defaultValue = true defaultValue = true