From c9d7b4fd154f1d19c2015f56a2095f436a0dcacc Mon Sep 17 00:00:00 2001 From: ssrlive <30760636+ssrlive@users.noreply.github.com> Date: Mon, 30 Dec 2024 18:31:39 +0800 Subject: [PATCH] dns2socks integrated --- .gitmodules | 4 + core/build.gradle | 2 +- .../com/github/shadowsocks/bg/Dns2socks.kt | 21 ++++++ .../github/shadowsocks/bg/SsrVpnService.kt | 73 ++++++++++++++++++- rust/Cargo.toml | 2 +- rust/dns2socks | 1 + 6 files changed, 98 insertions(+), 5 deletions(-) create mode 100644 core/src/main/java/com/github/shadowsocks/bg/Dns2socks.kt create mode 160000 rust/dns2socks diff --git a/.gitmodules b/.gitmodules index 9d3b3da8..b42c50d7 100644 --- a/.gitmodules +++ b/.gitmodules @@ -18,3 +18,7 @@ path = core/src/main/jni/fake-dlfcn url = https://github.com/ssrlive/fake-dlfcn.git branch = master +[submodule "rust/dns2socks"] + path = rust/dns2socks + url = https://github.com/tun2proxy/dns2socks.git + branch = master diff --git a/core/build.gradle b/core/build.gradle index 14b98c8a..141e92b0 100644 --- a/core/build.gradle +++ b/core/build.gradle @@ -62,7 +62,7 @@ cargo { profile = gradle.startParameter.taskNames.any{it.toLowerCase().contains("release")} ? "release" : "debug" prebuiltToolchains = true apiLevel = 24 - targetIncludes = ['libovertls.so', 'libtun2proxy.so'] + targetIncludes = ['libovertls.so', 'libtun2proxy.so', 'libdns2socks.so'] } preBuild.dependsOn "cargoBuild" diff --git a/core/src/main/java/com/github/shadowsocks/bg/Dns2socks.kt b/core/src/main/java/com/github/shadowsocks/bg/Dns2socks.kt new file mode 100644 index 00000000..5223aa61 --- /dev/null +++ b/core/src/main/java/com/github/shadowsocks/bg/Dns2socks.kt @@ -0,0 +1,21 @@ +package com.github.shadowsocks.bg + +object Dns2socks { + init { + System.loadLibrary("dns2socks") + } + + @JvmStatic + external fun start(listen_addr: String?, + dns_remote_server: String?, + socks5_server: String?, + username: String?, + password: String?, + force_tcp: Boolean, + cache_records: Boolean, + verbosity: Int, + timeout: Int): Int + + @JvmStatic + external fun stop(): Int +} diff --git a/core/src/main/java/com/github/shadowsocks/bg/SsrVpnService.kt b/core/src/main/java/com/github/shadowsocks/bg/SsrVpnService.kt index 8dbbd5ab..2e286a17 100644 --- a/core/src/main/java/com/github/shadowsocks/bg/SsrVpnService.kt +++ b/core/src/main/java/com/github/shadowsocks/bg/SsrVpnService.kt @@ -52,7 +52,6 @@ class SsrVpnService : VpnService(), BaseService.Interface { companion object { private const val VPN_MTU = 1500 private const val PRIVATE_VLAN4_CLIENT = "172.19.0.2" - private const val PRIVATE_VLAN4_ROUTER = "172.19.0.1" private const val PRIVATE_VLAN4_PREFIX_LENGTH = 30 private const val PRIVATE_VLAN6_CLIENT = "fdfe:dcba:9876::1" private const val PRIVATE_VLAN6_ROUTER = "fdfe:dcba:9876::2" @@ -92,6 +91,10 @@ class SsrVpnService : VpnService(), BaseService.Interface { override fun onRevoke() = stopRunner() override fun killProcesses(scope: CoroutineScope) { + dns2socksThread?.terminate() + dns2socksThread?.join() + dns2socksThread = null + tunThread?.terminate() tunThread?.join() tunThread = null @@ -126,12 +129,13 @@ class SsrVpnService : VpnService(), BaseService.Interface { private suspend fun startVpn() { val profile = data.proxy!!.profile + val localDnsSvrAddr = DataStore.localDnsSvrAddr val builder = Builder() .setConfigureIntent(Core.configureIntent(this)) .setSession(profile.formattedName) .setMtu(VPN_MTU) .addAddress(PRIVATE_VLAN4_CLIENT, PRIVATE_VLAN4_PREFIX_LENGTH) - .addDnsServer(PRIVATE_VLAN4_ROUTER) + .addDnsServer(localDnsSvrAddr) if (profile.ipv6) builder.addAddress(PRIVATE_VLAN6_CLIENT, PRIVATE_VLAN6_PREFIX_LENGTH) @@ -161,7 +165,7 @@ class SsrVpnService : VpnService(), BaseService.Interface { val subnet = Subnet.fromString(it)!! builder.addRoute(subnet.address.hostAddress!!, subnet.prefixSize) } - builder.addRoute(PRIVATE_VLAN4_ROUTER, 32) + builder.addRoute(localDnsSvrAddr, 32) // https://issuetracker.google.com/issues/149636790 if (profile.ipv6) builder.addRoute("2000::", 3) } @@ -186,6 +190,37 @@ class SsrVpnService : VpnService(), BaseService.Interface { tunThread = Tun2proxyThread(proxyUrl, tunFd, tunMtu, verbose, dnsOverTcp) tunThread?.isDaemon = true tunThread?.start() + + // FIXME: here can NOT use "${localDnsSvrAddr}:53", I think Android NOT support it yet, and "127.0.0.1:5353" is useless. + // https://stackoverflow.com/questions/79217146/how-do-i-implement-an-android-vpn-app-with-local-dns-resolver + // https://github.com/shadowsocks/shadowsocks-android/discussions/2823 + // https://github.com/shadowsocks/shadowsocks-android/issues/3122 + // + // val listenAddr = "${localDnsSvrAddr}:53" + // + val listenAddr = "127.0.0.1:5353" + val dnsRemoteServer = profile.remoteDns + val socks5Server = "${DataStore.listenAddress}:${DataStore.portProxy}" + val username = null + val password = null + val forceTcp = true + val cacheRecords = false + val verbosity = if (verbose) 5 else 3 + val timeout = 10 + + dns2socksThread = Dns2socksThread( + listenAddr, + dnsRemoteServer, + socks5Server, + username, + password, + forceTcp, + cacheRecords, + verbosity, + timeout + ) + dns2socksThread?.isDaemon = true + dns2socksThread?.start() } override fun onDestroy() { @@ -212,4 +247,36 @@ class SsrVpnService : VpnService(), BaseService.Interface { Tun2proxy.stop() } } + + private var dns2socksThread: Dns2socksThread? = null + + internal class Dns2socksThread( + private val listenAddr: String?, + private val dnsRemoteServer: String?, + private val socks5Server: String?, + private val username: String?, + private val password: String?, + private val forceTcp: Boolean, + private val cacheRecords: Boolean, + private val verbosity: Int, + private val timeout: Int + ) : Thread() { + override fun run() { + Dns2socks.start( + listenAddr, + dnsRemoteServer, + socks5Server, + username, + password, + forceTcp, + cacheRecords, + verbosity, + timeout + ) + } + + fun terminate() { + Dns2socks.stop() + } + } } diff --git a/rust/Cargo.toml b/rust/Cargo.toml index 801b51cb..88131451 100644 --- a/rust/Cargo.toml +++ b/rust/Cargo.toml @@ -1,3 +1,3 @@ [workspace] resolver = "2" -members = ["./overtls", "./tun2proxy"] +members = ["./overtls", "./tun2proxy", "./dns2socks"] diff --git a/rust/dns2socks b/rust/dns2socks new file mode 160000 index 00000000..60022e1b --- /dev/null +++ b/rust/dns2socks @@ -0,0 +1 @@ +Subproject commit 60022e1b174138434fd77a321f7c6d2fc103edcb