From 5917b90837e1b04a6646cd7223a73cc1073e2e5b Mon Sep 17 00:00:00 2001 From: Kr328 Date: Fri, 28 May 2021 11:32:21 +0800 Subject: [PATCH] Feature: add block loopback connections --- core/src/main/cpp/main.c | 6 +-- core/src/main/golang/tun/tcp.go | 9 ++-- core/src/main/golang/tun/tun.go | 45 ++++++++++++------- core/src/main/golang/tun/udp.go | 11 ++--- .../java/com/github/kr328/clash/core/Clash.kt | 4 +- .../github/kr328/clash/core/bridge/Bridge.kt | 2 +- .../clash/design/NetworkSettingsDesign.kt | 7 +++ design/src/main/res/values-zh-rHK/strings.xml | 2 + design/src/main/res/values-zh-rTW/strings.xml | 2 + design/src/main/res/values-zh/strings.xml | 2 + design/src/main/res/values/strings.xml | 2 + .../github/kr328/clash/service/TunService.kt | 8 +++- .../clash/service/clash/module/TunModule.kt | 4 +- .../kr328/clash/service/store/ServiceStore.kt | 5 +++ 14 files changed, 76 insertions(+), 33 deletions(-) diff --git a/core/src/main/cpp/main.c b/core/src/main/cpp/main.c index b4b814d2..6c1f2ece 100644 --- a/core/src/main/cpp/main.c +++ b/core/src/main/cpp/main.c @@ -98,15 +98,15 @@ Java_com_github_kr328_clash_core_bridge_Bridge_nativeNotifyInstalledAppChanged(J JNIEXPORT void JNICALL Java_com_github_kr328_clash_core_bridge_Bridge_nativeStartTun(JNIEnv *env, jobject thiz, jint fd, jint mtu, - jstring gateway, jstring dns, + jstring dns, jstring blocking, jobject cb) { TRACE_METHOD(); - scoped_string _gateway = get_string(gateway); + scoped_string _blocking = get_string(blocking); scoped_string _dns = get_string(dns); jobject _interface = new_global(cb); - startTun(fd, mtu, _gateway, _dns, _interface); + startTun(fd, mtu, _dns, _blocking, _interface); } JNIEXPORT void JNICALL diff --git a/core/src/main/golang/tun/tcp.go b/core/src/main/golang/tun/tcp.go index a072c8fb..baa34086 100644 --- a/core/src/main/golang/tun/tcp.go +++ b/core/src/main/golang/tun/tcp.go @@ -20,6 +20,7 @@ func (a *adapter) tcp() { defer log.Infoln("[ATUN] TCP listener exited") defer a.stack.Close() +accept: for { conn, err := a.stack.TCP().Accept() if err != nil { @@ -34,9 +35,11 @@ func (a *adapter) tcp() { continue } - // drop all connections connect to gateway - if a.gateway.Contains(tAddr.IP) { - continue + // drop all connections connect to blocking list + for _, b := range a.blocking { + if b.Contains(tAddr.IP) { + continue accept + } } metadata := &C.Metadata{ diff --git a/core/src/main/golang/tun/tun.go b/core/src/main/golang/tun/tun.go index 6a2c097a..d6c3a751 100644 --- a/core/src/main/golang/tun/tun.go +++ b/core/src/main/golang/tun/tun.go @@ -3,6 +3,7 @@ package tun import ( "net" "os" + "strings" "sync" "syscall" @@ -10,13 +11,13 @@ import ( ) type adapter struct { - device *os.File - stack tun2socket.Stack - gateway *net.IPNet - dns net.IP - mtu int - once sync.Once - stop func() + device *os.File + stack tun2socket.Stack + blocking []*net.IPNet + dns net.IP + mtu int + once sync.Once + stop func() } var lock sync.Mutex @@ -27,7 +28,7 @@ func (a *adapter) close() { _ = a.device.Close() } -func Start(fd, mtu int, gateway, dns string, stop func()) error { +func Start(fd, mtu int, dns string, blocking string, stop func()) error { lock.Lock() defer lock.Unlock() @@ -46,16 +47,28 @@ func Start(fd, mtu int, gateway, dns string, stop func()) error { } dn := net.ParseIP(dns) - _, gw, _ := net.ParseCIDR(gateway) + + var blk []*net.IPNet + + for _, b := range strings.Split(blocking, ";") { + _, n, err := net.ParseCIDR(b) + if err != nil { + device.Close() + + return err + } + + blk = append(blk, n) + } instance = &adapter{ - device: device, - stack: stack, - gateway: gw, - dns: dn, - mtu: mtu, - once: sync.Once{}, - stop: stop, + device: device, + stack: stack, + blocking: blk, + dns: dn, + mtu: mtu, + once: sync.Once{}, + stop: stop, } go instance.rx() diff --git a/core/src/main/golang/tun/udp.go b/core/src/main/golang/tun/udp.go index a5e26f13..535f9fa5 100644 --- a/core/src/main/golang/tun/udp.go +++ b/core/src/main/golang/tun/udp.go @@ -44,6 +44,7 @@ func (a *adapter) udp() { defer log.Infoln("[ATUN] UDP receiver exited") defer a.stack.Close() +read: for { buf := pool.Get(a.mtu) @@ -60,11 +61,11 @@ func (a *adapter) udp() { continue } - // drop all packets send to gateway - if a.gateway.Contains(tAddr.IP) { - pool.Put(buf) - - continue + // drop all packet send to blocking list + for _, b := range a.blocking { + if b.Contains(tAddr.IP) { + continue read + } } pkt := &packet{ 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 cd65a2de..eac180e1 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 @@ -61,12 +61,12 @@ object Clash { fun startTun( fd: Int, mtu: Int, - gateway: String, dns: String, + blocking: String, markSocket: (Int) -> Boolean, querySocketUid: (protocol: Int, source: InetSocketAddress, target: InetSocketAddress) -> Int ) { - Bridge.nativeStartTun(fd, mtu, gateway, dns, object : TunInterface { + Bridge.nativeStartTun(fd, mtu, dns, blocking, 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 7794cc36..a775853c 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 @@ -17,7 +17,7 @@ object Bridge { external fun nativeQueryTrafficTotal(): Long external fun nativeNotifyDnsChanged(dnsList: String) external fun nativeNotifyInstalledAppChanged(uidList: String) - external fun nativeStartTun(fd: Int, mtu: Int, gateway: String, dns: String, cb: TunInterface) + external fun nativeStartTun(fd: Int, mtu: Int, dns: String, blocking: String, 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 5dad3e4d..a2af8015 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,13 @@ class NetworkSettingsDesign( configure = vpnDependencies::add, ) + switch( + value = srvStore::blockLoopback, + title = R.string.block_loopback, + summary = R.string.block_loopback_summary, + configure = vpnDependencies::add, + ) + if (Build.VERSION.SDK_INT >= 29) { switch( value = srvStore::systemProxy, diff --git a/design/src/main/res/values-zh-rHK/strings.xml b/design/src/main/res/values-zh-rHK/strings.xml index 26686598..2c8a7c20 100644 --- a/design/src/main/res/values-zh-rHK/strings.xml +++ b/design/src/main/res/values-zh-rHK/strings.xml @@ -211,4 +211,6 @@ 源代碼 Clash 核心 Name Server 策略 + 阻止本地迴環 + 阻止本地迴環連接 \ No newline at end of file diff --git a/design/src/main/res/values-zh-rTW/strings.xml b/design/src/main/res/values-zh-rTW/strings.xml index eb7b62e4..ca70d250 100644 --- a/design/src/main/res/values-zh-rTW/strings.xml +++ b/design/src/main/res/values-zh-rTW/strings.xml @@ -211,4 +211,6 @@ 源代碼 Clash 核心 Name Server 策略 + 阻止本地迴環 + 阻止本地迴環連接 \ No newline at end of file diff --git a/design/src/main/res/values-zh/strings.xml b/design/src/main/res/values-zh/strings.xml index 9bddcbae..46c370fb 100644 --- a/design/src/main/res/values-zh/strings.xml +++ b/design/src/main/res/values-zh/strings.xml @@ -211,4 +211,6 @@ 源代码 Clash 核心 Name Server 策略 + 阻止本地回环 + 阻止本地回环连接 \ No newline at end of file diff --git a/design/src/main/res/values/strings.xml b/design/src/main/res/values/strings.xml index b2c71329..097edfc0 100644 --- a/design/src/main/res/values/strings.xml +++ b/design/src/main/res/values/strings.xml @@ -119,6 +119,8 @@ Bypass private network addresses DNS Hijacking Handle all dns packet + Block Loopback + Block loopback connections System Proxy Attach http proxy to VpnService Access Control Mode 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 93fa1e82..57900e9c 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 @@ -216,11 +216,16 @@ class TunService : VpnService(), CoroutineScope by CoroutineScope(Dispatchers.De } } + val blocking = mutableListOf("$TUN_GATEWAY/$TUN_SUBNET_PREFIX") + if (store.blockLoopback) { + blocking.add(NET_SUBNET_LOOPBACK) + } + TunModule.TunDevice( fd = establish()?.detachFd() ?: throw NullPointerException("Establish VPN rejected by system"), mtu = TUN_MTU, - gateway = "$TUN_GATEWAY/$TUN_SUBNET_PREFIX", + blocking = blocking.joinToString(";"), dns = if (store.dnsHijacking) NET_ANY else TUN_DNS, ) } @@ -234,5 +239,6 @@ class TunService : VpnService(), CoroutineScope by CoroutineScope(Dispatchers.De private const val TUN_GATEWAY = "172.19.0.1" private const val TUN_DNS = "172.19.0.2" private const val NET_ANY = "0.0.0.0" + private const val NET_SUBNET_LOOPBACK = "127.0.0.0/8" } } \ No newline at end of file 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 2e91316c..54944ee0 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 @@ -16,7 +16,7 @@ class TunModule(private val vpn: VpnService) : Module(vpn) { data class TunDevice( val fd: Int, val mtu: Int, - val gateway: String, + val blocking: String, val dns: String, ) @@ -57,8 +57,8 @@ class TunModule(private val vpn: VpnService) : Module(vpn) { Clash.startTun( fd = device.fd, mtu = device.mtu, - gateway = device.gateway, dns = device.dns, + blocking = device.blocking, 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 f1c32190..7a997d24 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 @@ -46,6 +46,11 @@ class ServiceStore(context: Context) { defaultValue = false ) + var blockLoopback by store.boolean( + key = "block_loopback", + defaultValue = true + ) + var dynamicNotification by store.boolean( key = "dynamic_notification", defaultValue = true