diff --git a/core/src/main/cpp/main.c b/core/src/main/cpp/main.c index 61e431c8a1..f1e4d85c81 100644 --- a/core/src/main/cpp/main.c +++ b/core/src/main/cpp/main.c @@ -116,6 +116,8 @@ Java_com_github_kr328_clash_core_bridge_Bridge_nativeStartTun(JNIEnv *env, jobje jstring gateway, jstring portal, jstring dns, + jboolean disable_icmp_forwarding, + jint icmp_timeout, jobject cb) { TRACE_METHOD(); @@ -125,7 +127,7 @@ Java_com_github_kr328_clash_core_bridge_Bridge_nativeStartTun(JNIEnv *env, jobje scoped_string _dns = get_string(dns); jobject _interface = new_global(cb); - startTun(fd, _stack, _gateway, _portal, _dns, _interface); + startTun(fd, _stack, _gateway, _portal, _dns, (int) disable_icmp_forwarding, (int) icmp_timeout, _interface); } JNIEXPORT void JNICALL diff --git a/core/src/main/golang/native/tun.go b/core/src/main/golang/native/tun.go index 860a1fdc21..36f9863170 100644 --- a/core/src/main/golang/native/tun.go +++ b/core/src/main/golang/native/tun.go @@ -64,7 +64,7 @@ func (t *remoteTun) close() { } //export startTun -func startTun(fd C.int, stack, gateway, portal, dns C.c_string, callback unsafe.Pointer) C.int { +func startTun(fd C.int, stack, gateway, portal, dns C.c_string, disableICMPForwarding C.int, icmpTimeout C.int, callback unsafe.Pointer) C.int { rTunLock.Lock() defer rTunLock.Unlock() @@ -83,7 +83,7 @@ func startTun(fd C.int, stack, gateway, portal, dns C.c_string, callback unsafe. app.ApplyTunContext(remote.markSocket, remote.querySocketUid) - closer, err := tun.Start(f, s, g, p, d) + closer, err := tun.Start(f, s, g, p, d, disableICMPForwarding != 0, int64(icmpTimeout)) if err != nil { remote.close() diff --git a/core/src/main/golang/native/tun/tun.go b/core/src/main/golang/native/tun/tun.go index ee2c2a9124..aaa52f4d69 100644 --- a/core/src/main/golang/native/tun/tun.go +++ b/core/src/main/golang/native/tun/tun.go @@ -14,7 +14,7 @@ import ( "github.com/metacubex/mihomo/tunnel" ) -func Start(fd int, stack, gateway, portal, dns string) (io.Closer, error) { +func Start(fd int, stack, gateway, portal, dns string, disableICMPForwarding bool, icmpTimeout int64) (io.Closer, error) { 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)] @@ -52,16 +52,18 @@ func Start(fd int, stack, gateway, portal, dns string) (io.Closer, error) { } options := LC.Tun{ - Enable: true, - Device: sing_tun.InterfaceName, - Stack: tunStack, - DNSHijack: dnsHijack, - AutoRoute: false, // had set route in TunService.kt - AutoDetectInterface: false, // implements by VpnService::protect - Inet4Address: prefix4, - Inet6Address: prefix6, - MTU: 9000, // private const val TUN_MTU = 9000 in TunService.kt - FileDescriptor: fd, + Enable: true, + Device: sing_tun.InterfaceName, + Stack: tunStack, + DNSHijack: dnsHijack, + AutoRoute: false, // had set route in TunService.kt + AutoDetectInterface: false, // implements by VpnService::protect + Inet4Address: prefix4, + Inet6Address: prefix6, + MTU: 9000, // private const val TUN_MTU = 9000 in TunService.kt + FileDescriptor: fd, + DisableICMPForwarding: disableICMPForwarding, + ICMPTimeout: icmpTimeout, } tunOptions, _ := json.Marshal(options) diff --git a/core/src/main/java/com/github/kr328/clash/core/Clash.kt b/core/src/main/java/com/github/kr328/clash/core/Clash.kt index edba62bed0..a0753d1917 100644 --- a/core/src/main/java/com/github/kr328/clash/core/Clash.kt +++ b/core/src/main/java/com/github/kr328/clash/core/Clash.kt @@ -70,10 +70,12 @@ object Clash { gateway: String, portal: String, dns: String, + disableIcmpForwarding: Boolean, + icmpTimeout: Int, markSocket: (Int) -> Boolean, querySocketUid: (protocol: Int, source: InetSocketAddress, target: InetSocketAddress) -> Int ) { - Bridge.nativeStartTun(fd, stack, gateway, portal, dns, object : TunInterface { + Bridge.nativeStartTun(fd, stack, gateway, portal, dns, disableIcmpForwarding, icmpTimeout, object : TunInterface { override fun markSocket(fd: Int) { markSocket(fd) } diff --git a/core/src/main/java/com/github/kr328/clash/core/bridge/Bridge.kt b/core/src/main/java/com/github/kr328/clash/core/bridge/Bridge.kt index fa3b9247ef..1e8231849f 100644 --- a/core/src/main/java/com/github/kr328/clash/core/bridge/Bridge.kt +++ b/core/src/main/java/com/github/kr328/clash/core/bridge/Bridge.kt @@ -19,7 +19,16 @@ object Bridge { external fun nativeNotifyDnsChanged(dnsList: String) external fun nativeNotifyTimeZoneChanged(name: String, offset: Int) external fun nativeNotifyInstalledAppChanged(uidList: String) - external fun nativeStartTun(fd: Int, stack: String, gateway: String, portal: String, dns: String, cb: TunInterface) + external fun nativeStartTun( + fd: Int, + stack: String, + gateway: String, + portal: String, + dns: String, + disableIcmpForwarding: Boolean, + icmpTimeout: Int, + cb: TunInterface + ) external fun nativeStopTun() external fun nativeStartHttp(listenAt: String): String? external fun nativeStopHttp() diff --git a/design/src/main/java/com/github/kr328/clash/design/NetworkSettingsDesign.kt b/design/src/main/java/com/github/kr328/clash/design/NetworkSettingsDesign.kt index 93e1ee3d07..432d31927e 100644 --- a/design/src/main/java/com/github/kr328/clash/design/NetworkSettingsDesign.kt +++ b/design/src/main/java/com/github/kr328/clash/design/NetworkSettingsDesign.kt @@ -70,6 +70,21 @@ class NetworkSettingsDesign( configure = vpnDependencies::add, ) + switch( + value = srvStore::disableIcmpForwarding, + title = R.string.disable_icmp_forwarding, + summary = R.string.disable_icmp_forwarding_summary, + configure = vpnDependencies::add, + ) + + editableText( + value = srvStore::icmpTimeout, + adapter = NullableTextAdapter.Int, + title = R.string.icmp_timeout, + empty = R.string.icmp_timeout_default, + configure = vpnDependencies::add, + ) + switch( value = srvStore::allowBypass, title = R.string.allow_bypass, diff --git a/design/src/main/java/com/github/kr328/clash/design/preference/Value.kt b/design/src/main/java/com/github/kr328/clash/design/preference/Value.kt index cf2dcb79fc..7e6ce7a708 100644 --- a/design/src/main/java/com/github/kr328/clash/design/preference/Value.kt +++ b/design/src/main/java/com/github/kr328/clash/design/preference/Value.kt @@ -19,6 +19,16 @@ interface NullableTextAdapter { } } + val Int = object : NullableTextAdapter { + override fun from(value: Int): String? { + return if (value > 0) value.toString() else "" + } + + override fun to(text: String?): Int { + return text?.trim()?.toIntOrNull()?.coerceAtLeast(0) ?: 0 + } + } + val String = object : NullableTextAdapter { override fun from(value: String?): String? { return value diff --git a/design/src/main/res/values/strings.xml b/design/src/main/res/values/strings.xml index 4e43d3fd26..d6cc8d03d4 100644 --- a/design/src/main/res/values/strings.xml +++ b/design/src/main/res/values/strings.xml @@ -135,6 +135,10 @@ Bypass private network addresses DNS Hijacking Handle all dns packet + Disable ICMP Forwarding + Reply ICMP echo requests locally instead of forwarding them + ICMP Timeout (seconds) + Default Block Loopback Block loopback connections Allow Bypass diff --git a/service/src/main/java/com/github/kr328/clash/service/TunService.kt b/service/src/main/java/com/github/kr328/clash/service/TunService.kt index 8550f8ab81..eb3a88036a 100644 --- a/service/src/main/java/com/github/kr328/clash/service/TunService.kt +++ b/service/src/main/java/com/github/kr328/clash/service/TunService.kt @@ -222,6 +222,8 @@ class TunService : VpnService(), CoroutineScope by CoroutineScope(Dispatchers.De gateway = "$TUN_GATEWAY/$TUN_SUBNET_PREFIX" + if (store.allowIpv6) ",$TUN_GATEWAY6/$TUN_SUBNET_PREFIX6" 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 ""), + disableIcmpForwarding = store.disableIcmpForwarding, + icmpTimeout = store.icmpTimeout, ) } diff --git a/service/src/main/java/com/github/kr328/clash/service/clash/module/TunModule.kt b/service/src/main/java/com/github/kr328/clash/service/clash/module/TunModule.kt index 84197d325f..ddf794143e 100644 --- a/service/src/main/java/com/github/kr328/clash/service/clash/module/TunModule.kt +++ b/service/src/main/java/com/github/kr328/clash/service/clash/module/TunModule.kt @@ -19,6 +19,8 @@ class TunModule(private val vpn: VpnService) : Module(vpn) { val gateway: String, val portal: String, val dns: String, + val disableIcmpForwarding: Boolean, + val icmpTimeout: Int, ) private val connectivity = service.getSystemService()!! @@ -61,6 +63,8 @@ class TunModule(private val vpn: VpnService) : Module(vpn) { gateway = device.gateway, portal = device.portal, dns = device.dns, + disableIcmpForwarding = device.disableIcmpForwarding, + icmpTimeout = device.icmpTimeout, markSocket = vpn::protect, querySocketUid = this::queryUid ) diff --git a/service/src/main/java/com/github/kr328/clash/service/store/ServiceStore.kt b/service/src/main/java/com/github/kr328/clash/service/store/ServiceStore.kt index d361848ff5..59a5914d41 100644 --- a/service/src/main/java/com/github/kr328/clash/service/store/ServiceStore.kt +++ b/service/src/main/java/com/github/kr328/clash/service/store/ServiceStore.kt @@ -61,6 +61,16 @@ class ServiceStore(context: Context) { defaultValue = "system" ) + var disableIcmpForwarding by store.boolean( + key = "disable_icmp_forwarding", + defaultValue = true + ) + + var icmpTimeout by store.int( + key = "icmp_timeout", + defaultValue = 0 + ) + var dynamicNotification by store.boolean( key = "dynamic_notification", defaultValue = true