diff --git a/app/src/main/java/io/nekohasekai/sagernet/SagerNet.kt b/app/src/main/java/io/nekohasekai/sagernet/SagerNet.kt index e1d709c..91c6632 100644 --- a/app/src/main/java/io/nekohasekai/sagernet/SagerNet.kt +++ b/app/src/main/java/io/nekohasekai/sagernet/SagerNet.kt @@ -33,6 +33,7 @@ import libcore.BoxPlatformInterface import libcore.Libcore import libcore.NB4AInterface import moe.matsuri.nb4a.utils.JavaUtil +import moe.matsuri.nb4a.utils.LibcoreUtil import moe.matsuri.nb4a.utils.cleanWebview import java.net.InetSocketAddress import androidx.work.Configuration as WorkConfiguration @@ -266,7 +267,7 @@ class SagerNet : Application(), Logs.d("other selector: $selectorTag") return } - Libcore.resetAllConnections(true) + LibcoreUtil.resetAllConnections(true) DataStore.baseService?.apply { runOnDefaultDispatcher { val id = data.proxy!!.config.profileTagMap diff --git a/app/src/main/java/io/nekohasekai/sagernet/bg/BaseService.kt b/app/src/main/java/io/nekohasekai/sagernet/bg/BaseService.kt index 02dfa61..2c1594a 100644 --- a/app/src/main/java/io/nekohasekai/sagernet/bg/BaseService.kt +++ b/app/src/main/java/io/nekohasekai/sagernet/bg/BaseService.kt @@ -23,6 +23,7 @@ import kotlinx.coroutines.sync.Mutex import kotlinx.coroutines.sync.withLock import libcore.Libcore import moe.matsuri.nb4a.Protocols +import moe.matsuri.nb4a.utils.LibcoreUtil import moe.matsuri.nb4a.utils.Util import java.net.UnknownHostException @@ -52,7 +53,7 @@ class BaseService { Action.RELOAD -> service.reload() // Action.SWITCH_WAKE_LOCK -> runOnDefaultDispatcher { service.switchWakeLock() } Action.RESET_UPSTREAM_CONNECTIONS -> runOnDefaultDispatcher { - Libcore.resetAllConnections(true) + LibcoreUtil.resetAllConnections(true) runOnMainDispatcher { Util.collapseStatusBar(ctx) Toast.makeText(ctx, "Reset upstream connections done", Toast.LENGTH_SHORT) @@ -266,7 +267,7 @@ class BaseService { } if (oldName != null && upstreamInterfaceName != null && oldName != upstreamInterfaceName) { Logs.d("Network changed: $oldName -> $upstreamInterfaceName") - Libcore.resetAllConnections(true) + LibcoreUtil.resetAllConnections(true) } } } diff --git a/app/src/main/java/io/nekohasekai/sagernet/fmt/ConfigBuilder.kt b/app/src/main/java/io/nekohasekai/sagernet/fmt/ConfigBuilder.kt index 53327e5..aa9f7d6 100644 --- a/app/src/main/java/io/nekohasekai/sagernet/fmt/ConfigBuilder.kt +++ b/app/src/main/java/io/nekohasekai/sagernet/fmt/ConfigBuilder.kt @@ -443,6 +443,7 @@ fun buildConfig( // External proxy need a dokodemo-door inbound to forward the traffic // For external proxy software, their traffic must goes to v2ray-core to use protected fd. + bean.finalAddress = bean.serverAddress bean.finalPort = bean.serverPort if (bean.canMapping() && proxyEntity.needExternal()) { // With ss protect, don't use mapping diff --git a/app/src/main/java/io/nekohasekai/sagernet/fmt/tuic/TuicFmt.kt b/app/src/main/java/io/nekohasekai/sagernet/fmt/tuic/TuicFmt.kt index b36c8e7..6d3a3e9 100644 --- a/app/src/main/java/io/nekohasekai/sagernet/fmt/tuic/TuicFmt.kt +++ b/app/src/main/java/io/nekohasekai/sagernet/fmt/tuic/TuicFmt.kt @@ -30,15 +30,24 @@ fun TuicBean.buildTuicConfig(port: Int, cacheFile: (() -> File)?): String { fun TuicBean.buildTuicConfigV5(port: Int, cacheFile: (() -> File)?): JSONObject { return JSONObject().apply { put("relay", JSONObject().apply { - if (sni.isNotBlank() && !disableSNI) { + var disableSNI2 = disableSNI + + if (sni.isNotBlank()) { // domain + SNI put("server", "$sni:$finalPort") if (finalAddress.isIpAddress()) { put("ip", finalAddress) } else { throw Exception("TUIC must use IP address when you need spoof SNI.") } - } else { - put("server", serverAddress.wrapIPV6Host() + ":" + finalPort) + } else if (!serverAddress.isIpAddress()) { // domain + put("server", "$serverAddress:$finalPort") + if (finalAddress.isIpAddress()) { + put("ip", finalAddress) + } + } else { // prue IP server + put("server", "example.com:$finalPort") + put("ip", finalAddress) + disableSNI2 = true } put("uuid", uuid) @@ -55,7 +64,7 @@ fun TuicBean.buildTuicConfigV5(port: Int, cacheFile: (() -> File)?): JSONObject put("alpn", JSONArray(alpn.split("\n"))) } put("congestion_control", congestionController) - put("disable_sni", disableSNI) + put("disable_sni", disableSNI2) put("zero_rtt_handshake", reduceRTT) if (allowInsecure) put("allow_insecure", true) }) @@ -69,16 +78,26 @@ fun TuicBean.buildTuicConfigV5(port: Int, cacheFile: (() -> File)?): JSONObject fun TuicBean.buildTuicConfigV4(port: Int, cacheFile: (() -> File)?): JSONObject { return JSONObject().apply { put("relay", JSONObject().apply { - if (sni.isNotBlank() && !disableSNI) { - put("server", sni) + var disableSNI2 = disableSNI + + if (sni.isNotBlank()) { // domain + SNI + put("server", "$sni:$finalPort") if (finalAddress.isIpAddress()) { put("ip", finalAddress) } else { throw Exception("TUIC must use IP address when you need spoof SNI.") } - } else { - put("server", finalAddress) + } else if (!serverAddress.isIpAddress()) { // domain + put("server", "$serverAddress:$finalPort") + if (finalAddress.isIpAddress()) { + put("ip", finalAddress) + } + } else { // prue IP server + put("server", "example.com:$finalPort") + put("ip", finalAddress) + disableSNI2 = true } + put("port", finalPort) put("token", token) @@ -93,7 +112,7 @@ fun TuicBean.buildTuicConfigV4(port: Int, cacheFile: (() -> File)?): JSONObject put("alpn", JSONArray(alpn.split("\n"))) } put("congestion_controller", congestionController) - put("disable_sni", disableSNI) + put("disable_sni", disableSNI2) put("reduce_rtt", reduceRTT) put("max_udp_relay_packet_size", mtu) if (fastConnect) put("fast_connect", true) diff --git a/app/src/main/java/io/nekohasekai/sagernet/group/RawUpdater.kt b/app/src/main/java/io/nekohasekai/sagernet/group/RawUpdater.kt index c26ad2d..2da917b 100644 --- a/app/src/main/java/io/nekohasekai/sagernet/group/RawUpdater.kt +++ b/app/src/main/java/io/nekohasekai/sagernet/group/RawUpdater.kt @@ -502,10 +502,12 @@ object RawUpdater : GroupUpdater() { "tuic" -> { val bean = TuicBean() + var ip = "" for (opt in proxy) { when (opt.key.replace("_", "-")) { "name" -> bean.name = opt.value?.toString() - "server" -> bean.serverAddress = opt.value as String + "server" -> bean.serverAddress = opt.value.toString() + "ip" -> ip = opt.value.toString() "port" -> bean.serverPort = opt.value.toString().toInt() "token" -> { @@ -536,6 +538,14 @@ object RawUpdater : GroupUpdater() { "congestion-controller" -> bean.congestionController = opt.value.toString() + "udp-relay-mode" -> bean.udpRelayMode = opt.value.toString() + + } + } + if (ip.isNotBlank()) { + bean.serverAddress = ip + if (bean.sni.isNullOrBlank() && !bean.serverAddress.isNullOrBlank() && !bean.serverAddress.isIpAddress()) { + bean.sni = bean.serverAddress } } proxies.add(bean) diff --git a/app/src/main/java/moe/matsuri/nb4a/utils/LibcoreUtil.kt b/app/src/main/java/moe/matsuri/nb4a/utils/LibcoreUtil.kt new file mode 100644 index 0000000..a434e7f --- /dev/null +++ b/app/src/main/java/moe/matsuri/nb4a/utils/LibcoreUtil.kt @@ -0,0 +1,18 @@ +package moe.matsuri.nb4a.utils + +import io.nekohasekai.sagernet.database.DataStore +import io.nekohasekai.sagernet.database.ProxyEntity +import io.nekohasekai.sagernet.database.SagerDatabase +import libcore.Libcore + +object LibcoreUtil { + fun resetAllConnections(system: Boolean) { + if (DataStore.serviceState.started) { + val proxy = SagerDatabase.proxyDao.getById(DataStore.currentProfile) + if (proxy?.type == ProxyEntity.TYPE_TUIC) { + return + } + } + Libcore.resetAllConnections(system) + } +}