diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 000000000..de1cd37ee --- /dev/null +++ b/.gitattributes @@ -0,0 +1,2 @@ +# Mail-format patches preserve upstream context and signature whitespace. +buildScript/lib/core/patches/*.patch -whitespace diff --git a/.github/workflows/preview.yml b/.github/workflows/preview.yml index a6df3a164..63d79ac3b 100644 --- a/.github/workflows/preview.yml +++ b/.github/workflows/preview.yml @@ -24,7 +24,14 @@ jobs: if: steps.cache.outputs.cache-hit != 'true' uses: actions/setup-go@v5 with: - go-version: ^1.25 + go-version: '1.25.11' + cache-dependency-path: libcore/go.sum + - name: Set up Android SDK + if: steps.cache.outputs.cache-hit != 'true' + uses: android-actions/setup-android@v4.0.1 + - name: Install Android NDK + if: steps.cache.outputs.cache-hit != 'true' + run: sdkmanager 'ndk;29.0.14206865' - name: Native Build if: steps.cache.outputs.cache-hit != 'true' run: ./run lib core @@ -56,7 +63,6 @@ jobs: BUILD_PLUGIN: none run: | echo "sdk.dir=${ANDROID_HOME}" > local.properties - echo "ndk.dir=${ANDROID_HOME}/ndk/25.0.8775105" >> local.properties export LOCAL_PROPERTIES="${{ secrets.LOCAL_PROPERTIES }}" ./run init action gradle ./gradlew app:assemblePreviewRelease diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 7aecc1c05..1e9959894 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -33,7 +33,14 @@ jobs: if: steps.cache.outputs.cache-hit != 'true' uses: actions/setup-go@v5 with: - go-version: ^1.25 + go-version: '1.25.11' + cache-dependency-path: libcore/go.sum + - name: Set up Android SDK + if: steps.cache.outputs.cache-hit != 'true' + uses: android-actions/setup-android@v4.0.1 + - name: Install Android NDK + if: steps.cache.outputs.cache-hit != 'true' + run: sdkmanager 'ndk;29.0.14206865' - name: Native Build if: steps.cache.outputs.cache-hit != 'true' run: ./run lib core @@ -65,7 +72,6 @@ jobs: BUILD_PLUGIN: none run: | echo "sdk.dir=${ANDROID_HOME}" > local.properties - echo "ndk.dir=${ANDROID_HOME}/ndk/25.0.8775105" >> local.properties export LOCAL_PROPERTIES="${{ secrets.LOCAL_PROPERTIES }}" ./run init action gradle ./gradlew app:assembleOssRelease @@ -127,7 +133,6 @@ jobs: - name: Gradle Build run: | echo "sdk.dir=${ANDROID_HOME}" > local.properties - echo "ndk.dir=${ANDROID_HOME}/ndk/25.0.8775105" >> local.properties export LOCAL_PROPERTIES="${{ secrets.LOCAL_PROPERTIES }}" ./run init action gradle ./gradlew bundlePlayRelease diff --git a/app/src/main/java/io/nekohasekai/sagernet/SagerNet.kt b/app/src/main/java/io/nekohasekai/sagernet/SagerNet.kt index f38305d46..2b119fb5f 100644 --- a/app/src/main/java/io/nekohasekai/sagernet/SagerNet.kt +++ b/app/src/main/java/io/nekohasekai/sagernet/SagerNet.kt @@ -79,6 +79,9 @@ class SagerNet : Application(), } if (isMainProcess) { + if (DataStore.trafficSniffing == 2) { + DataStore.trafficSniffing = 1 + } Theme.apply(this) Theme.applyNightTheme() runOnDefaultDispatcher { 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 8fe0a2944..419f091df 100644 --- a/app/src/main/java/io/nekohasekai/sagernet/fmt/ConfigBuilder.kt +++ b/app/src/main/java/io/nekohasekai/sagernet/fmt/ConfigBuilder.kt @@ -22,7 +22,7 @@ import io.nekohasekai.sagernet.fmt.tuic.buildSingBoxOutboundTuicBean import io.nekohasekai.sagernet.fmt.v2ray.StandardV2RayBean import io.nekohasekai.sagernet.fmt.v2ray.buildSingBoxOutboundStandardV2RayBean import io.nekohasekai.sagernet.fmt.wireguard.WireGuardBean -import io.nekohasekai.sagernet.fmt.wireguard.buildSingBoxOutboundWireguardBean +import io.nekohasekai.sagernet.fmt.wireguard.buildSingBoxEndpointWireguardBean import io.nekohasekai.sagernet.ktx.isIpAddress import io.nekohasekai.sagernet.ktx.mkPort import io.nekohasekai.sagernet.utils.PackageCache @@ -141,7 +141,6 @@ fun buildConfig( val enableDnsRouting = DataStore.enableDnsRouting val useFakeDns = DataStore.enableFakeDns && !forTest val needSniff = DataStore.trafficSniffing > 0 - val needSniffOverride = DataStore.trafficSniffing == 2 val externalIndexMap = ArrayList() val ipv6Mode = if (forTest) IPv6Mode.ENABLE else DataStore.ipv6Mode @@ -206,21 +205,20 @@ fun buildConfig( } endpoint_independent_nat = true mtu = DataStore.mtu - domain_strategy = genDomainStrategy(DataStore.resolveDestination) - sniff = needSniff - sniff_override_destination = needSniffOverride when (ipv6Mode) { IPv6Mode.DISABLE -> { - inet4_address = listOf(VpnService.PRIVATE_VLAN4_CLIENT + "/28") + address = listOf(VpnService.PRIVATE_VLAN4_CLIENT + "/28") } IPv6Mode.ONLY -> { - inet6_address = listOf(VpnService.PRIVATE_VLAN6_CLIENT + "/126") + address = listOf(VpnService.PRIVATE_VLAN6_CLIENT + "/126") } else -> { - inet4_address = listOf(VpnService.PRIVATE_VLAN4_CLIENT + "/28") - inet6_address = listOf(VpnService.PRIVATE_VLAN6_CLIENT + "/126") + address = listOf( + VpnService.PRIVATE_VLAN4_CLIENT + "/28", + VpnService.PRIVATE_VLAN6_CLIENT + "/126", + ) } } }) @@ -229,13 +227,11 @@ fun buildConfig( tag = TAG_MIXED listen = bind listen_port = DataStore.mixedPort - domain_strategy = genDomainStrategy(DataStore.resolveDestination) - sniff = needSniff - sniff_override_destination = needSniffOverride }) } outbounds = mutableListOf() + endpoints = mutableListOf() // init routing object route = RouteOptions().apply { @@ -357,7 +353,7 @@ fun buildConfig( buildSingBoxOutboundShadowsocksBean(bean) is WireGuardBean -> - buildSingBoxOutboundWireguardBean(bean) + buildSingBoxEndpointWireguardBean(bean) is SSHBean -> buildSingBoxOutboundSSHBean(bean) @@ -449,7 +445,11 @@ fun buildConfig( } } - outbounds.add(currentOutbound) + if (currentOutbound is Endpoint_WireGuardOptions) { + endpoints.add(currentOutbound) + } else { + outbounds.add(currentOutbound) + } chainOutbounds.add(currentOutbound) pastOutbound = currentOutbound pastEntity = proxyEntity @@ -738,6 +738,30 @@ fun buildConfig( } } + // sing-box 1.13 removed legacy inbound sniff and domain strategy fields. + // Keep these actions ahead of the routing rules they affect. + if (!forTest) { + val inboundTags = buildList { + if (isVPN) add("tun-in") + add(TAG_MIXED) + } + inboundTags.asReversed().forEach { inboundTag -> + if (needSniff) { + route.rules.add(0, Rule_DefaultOptions().apply { + inbound = listOf(inboundTag) + action = "sniff" + }) + } + if (DataStore.resolveDestination) { + route.rules.add(0, Rule_DefaultOptions().apply { + inbound = listOf(inboundTag) + action = "resolve" + strategy = genDomainStrategy(true) + }) + } + } + } + if (!forTest) _hack_custom_config = DataStore.globalCustomConfig }.let { val configMap = it.asMap() diff --git a/app/src/main/java/io/nekohasekai/sagernet/fmt/wireguard/WireGuardFmt.kt b/app/src/main/java/io/nekohasekai/sagernet/fmt/wireguard/WireGuardFmt.kt index 5fa7397b0..8bd0dfef4 100644 --- a/app/src/main/java/io/nekohasekai/sagernet/fmt/wireguard/WireGuardFmt.kt +++ b/app/src/main/java/io/nekohasekai/sagernet/fmt/wireguard/WireGuardFmt.kt @@ -26,16 +26,19 @@ fun genReserved(anyStr: String): String { } } -fun buildSingBoxOutboundWireguardBean(bean: WireGuardBean): SingBoxOptions.Outbound_WireGuardOptions { - return SingBoxOptions.Outbound_WireGuardOptions().apply { +fun buildSingBoxEndpointWireguardBean(bean: WireGuardBean): SingBoxOptions.Endpoint_WireGuardOptions { + return SingBoxOptions.Endpoint_WireGuardOptions().apply { type = "wireguard" - server = bean.serverAddress - server_port = bean.serverPort - local_address = bean.localAddress.listByLineOrComma() + address = bean.localAddress.listByLineOrComma() private_key = bean.privateKey - peer_public_key = bean.peerPublicKey - pre_shared_key = bean.peerPreSharedKey mtu = bean.mtu - if (bean.reserved.isNotBlank()) reserved = genReserved(bean.reserved) + peers = listOf(SingBoxOptions.EndpointWireGuardPeer().apply { + address = bean.serverAddress + port = bean.serverPort + public_key = bean.peerPublicKey + pre_shared_key = bean.peerPreSharedKey + allowed_ips = listOf("0.0.0.0/0", "::/0") + if (bean.reserved.isNotBlank()) reserved = genReserved(bean.reserved) + }) } } diff --git a/app/src/main/java/moe/matsuri/nb4a/SingBoxOptions.java b/app/src/main/java/moe/matsuri/nb4a/SingBoxOptions.java index 05f89275f..0ea1d338c 100644 --- a/app/src/main/java/moe/matsuri/nb4a/SingBoxOptions.java +++ b/app/src/main/java/moe/matsuri/nb4a/SingBoxOptions.java @@ -113,6 +113,8 @@ public static class MyOptions extends SingBoxOption { public List outbounds; + public List endpoints; + public RouteOptions route; public ExperimentalOptions experimental; @@ -2803,6 +2805,9 @@ public static class Inbound_TunOptions extends Inbound { public Integer mtu; + // Generate note: Listable + public List address; + // Generate note: Listable public List inet4_address; @@ -3916,6 +3921,52 @@ public static class Outbound_WireGuardOptions extends Outbound { } + public static class Endpoint_WireGuardOptions extends Outbound { + + // Generate note: nested type DialerOptions + public String detour; + + public String bind_interface; + + public String protect_path; + + public Boolean tcp_fast_open; + + public String domain_strategy; + + public Boolean system; + + public String name; + + public List address; + + public String private_key; + + public List peers; + + public Integer workers; + + public Integer mtu; + + } + + public static class EndpointWireGuardPeer extends SingBoxOption { + + public String address; + + public Integer port; + + public String public_key; + + public String pre_shared_key; + + public List allowed_ips; + + // Generate note: Base64 String + public String reserved; + + } + public static class Outbound_HysteriaOptions extends Outbound { // Generate note: nested type DialerOptions @@ -4454,6 +4505,8 @@ public static class Rule_DefaultOptions extends Rule { public String action; + public String strategy; + public String outbound; } diff --git a/app/src/main/res/values/arrays.xml b/app/src/main/res/values/arrays.xml index a5da08b33..4a30226af 100644 --- a/app/src/main/res/values/arrays.xml +++ b/app/src/main/res/values/arrays.xml @@ -527,7 +527,11 @@ @string/off @string/sniff_routing - @string/sniff_override + + + + 0 + 1 diff --git a/app/src/main/res/xml/global_preferences.xml b/app/src/main/res/xml/global_preferences.xml index 64f4f7901..7ced3328c 100644 --- a/app/src/main/res/xml/global_preferences.xml +++ b/app/src/main/res/xml/global_preferences.xml @@ -112,7 +112,7 @@ &2 + exit 1 + fi +done popd #### if [ ! -d "libneko" ]; then - git clone --no-checkout https://github.com/MatsuriDayo/libneko.git + git clone --no-checkout "$REPOSITORY_LIBNEKO" fi pushd libneko +git remote set-url origin "$REPOSITORY_LIBNEKO" +git fetch origin "$COMMIT_LIBNEKO" git checkout "$COMMIT_LIBNEKO" popd diff --git a/buildScript/lib/core/get_source_env.sh b/buildScript/lib/core/get_source_env.sh index 2a369106f..392928e7c 100644 --- a/buildScript/lib/core/get_source_env.sh +++ b/buildScript/lib/core/get_source_env.sh @@ -1,2 +1,6 @@ -export COMMIT_SING_BOX="aed32ee3066cdbc7d471e3e0415c5134088962df" +export REPOSITORY_SING_BOX="https://github.com/SagerNet/sing-box.git" +export COMMIT_SING_BOX="45ca32dcb966f07f97fc888fe8586e359dbe8405" +export REPOSITORY_LIBNEKO="https://github.com/MatsuriDayo/libneko.git" export COMMIT_LIBNEKO="1c47a3af71990a7b2192e03292b4d246c308ef0b" +export REPOSITORY_GOMOBILE="https://github.com/MatsuriDayo/gomobile.git" +export COMMIT_GOMOBILE="17d6af34f6bd6d7e1e428e0c652c8b54a46bda4f" diff --git a/buildScript/lib/core/patches/0001-fix-needCacheFile.patch b/buildScript/lib/core/patches/0001-fix-needCacheFile.patch new file mode 100644 index 000000000..97e2063ba --- /dev/null +++ b/buildScript/lib/core/patches/0001-fix-needCacheFile.patch @@ -0,0 +1,29 @@ +From f1e280c415348431454b210199a84c3a50f76e5c Mon Sep 17 00:00:00 2001 +From: armv9 <48624112+arm64v8a@users.noreply.github.com> +Date: Wed, 26 Feb 2025 12:43:33 +0900 +Subject: [PATCH 1/6] fix needCacheFile + +--- + box.go | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/box.go b/box.go +index c88a9bc9a..61a2fbdb6 100644 +--- a/box.go ++++ b/box.go +@@ -131,10 +131,10 @@ func New(options Options) (*Box, error) { + var needCacheFile bool + var needClashAPI bool + var needV2RayAPI bool +- if experimentalOptions.CacheFile != nil && experimentalOptions.CacheFile.Enabled || options.PlatformLogWriter != nil { ++ if experimentalOptions.CacheFile != nil && experimentalOptions.CacheFile.Enabled { + needCacheFile = true + } +- if experimentalOptions.ClashAPI != nil || options.PlatformLogWriter != nil { ++ if experimentalOptions.ClashAPI != nil { + needClashAPI = true + } + if experimentalOptions.V2RayAPI != nil && experimentalOptions.V2RayAPI.Listen != "" { +-- +2.43.0 + diff --git a/buildScript/lib/core/patches/0002-add-boxapi.patch b/buildScript/lib/core/patches/0002-add-boxapi.patch new file mode 100644 index 000000000..a61bb90c1 --- /dev/null +++ b/buildScript/lib/core/patches/0002-add-boxapi.patch @@ -0,0 +1,275 @@ +From 06502225c6b78303d56272a3bfe197eca2217004 Mon Sep 17 00:00:00 2001 +From: armv9 <48624112+arm64v8a@users.noreply.github.com> +Date: Tue, 2 Jul 2024 10:51:00 +0900 +Subject: [PATCH 2/6] add boxapi + +--- + boxapi/go_http.go | 30 +++++++ + boxapi/go_net.go | 23 ++++++ + boxapi/v2ray_server.go | 32 ++++++++ + boxapi/v2ray_stats_service.go | 147 ++++++++++++++++++++++++++++++++++ + 4 files changed, 232 insertions(+) + create mode 100644 boxapi/go_http.go + create mode 100644 boxapi/go_net.go + create mode 100644 boxapi/v2ray_server.go + create mode 100644 boxapi/v2ray_stats_service.go + +diff --git a/boxapi/go_http.go b/boxapi/go_http.go +new file mode 100644 +index 000000000..3cba5ebce +--- /dev/null ++++ b/boxapi/go_http.go +@@ -0,0 +1,30 @@ ++package boxapi ++ ++import ( ++ "context" ++ "net" ++ "net/http" ++ "time" ++ ++ box "github.com/sagernet/sing-box" ++ "github.com/sagernet/sing-box/adapter" ++) ++ ++func CreateProxyHttpClient(box *box.Box, tracker adapter.ConnectionTracker) *http.Client { ++ transport := &http.Transport{ ++ TLSHandshakeTimeout: time.Second * 3, ++ ResponseHeaderTimeout: time.Second * 3, ++ } ++ ++ if box != nil { ++ transport.DialContext = func(ctx context.Context, network, addr string) (net.Conn, error) { ++ return DialContext(ctx, box, tracker, network, addr) ++ } ++ } ++ ++ client := &http.Client{ ++ Transport: transport, ++ } ++ ++ return client ++} +diff --git a/boxapi/go_net.go b/boxapi/go_net.go +new file mode 100644 +index 000000000..5a7637d1d +--- /dev/null ++++ b/boxapi/go_net.go +@@ -0,0 +1,23 @@ ++package boxapi ++ ++import ( ++ "context" ++ "net" ++ ++ box "github.com/sagernet/sing-box" ++ "github.com/sagernet/sing-box/adapter" ++ "github.com/sagernet/sing-box/common/dialer" ++ "github.com/sagernet/sing/common/metadata" ++) ++ ++func DialContext(ctx context.Context, box *box.Box, tracker adapter.ConnectionTracker, network, addr string) (net.Conn, error) { ++ defOutboundTag := box.Outbound().Default().Tag() ++ conn, err := dialer.NewDetour(box.Outbound(), defOutboundTag, true).DialContext(ctx, network, metadata.ParseSocksaddr(addr)) ++ if err != nil { ++ return nil, err ++ } ++ if ss, ok := tracker.(*SbStatsService); ok { ++ conn = ss.RoutedConnectionInternal("", defOutboundTag, "", conn, false) ++ } ++ return conn, nil ++} +diff --git a/boxapi/v2ray_server.go b/boxapi/v2ray_server.go +new file mode 100644 +index 000000000..a97e0af5c +--- /dev/null ++++ b/boxapi/v2ray_server.go +@@ -0,0 +1,32 @@ ++package boxapi ++ ++import ( ++ "context" ++ ++ "github.com/sagernet/sing-box/adapter" ++ "github.com/sagernet/sing-box/option" ++) ++ ++type SbV2rayServer struct { ++ ss *SbStatsService ++} ++ ++func NewSbV2rayServer(options option.V2RayStatsServiceOptions) *SbV2rayServer { ++ return &SbV2rayServer{ ++ ss: NewSbStatsService(options), ++ } ++} ++ ++func (s *SbV2rayServer) Start() error { return nil } ++func (s *SbV2rayServer) Close() error { return nil } ++func (s *SbV2rayServer) StatsService() adapter.ConnectionTracker { return s.ss } ++ ++// NekoRay style API ++ ++func (s *SbV2rayServer) QueryStats(name string) int64 { ++ value, err := s.ss.GetStats(context.TODO(), name, true) ++ if err == nil { ++ return value ++ } ++ return 0 ++} +diff --git a/boxapi/v2ray_stats_service.go b/boxapi/v2ray_stats_service.go +new file mode 100644 +index 000000000..3e96f42d4 +--- /dev/null ++++ b/boxapi/v2ray_stats_service.go +@@ -0,0 +1,147 @@ ++package boxapi ++ ++import ( ++ "context" ++ "net" ++ "sync" ++ "sync/atomic" ++ "time" ++ ++ "github.com/sagernet/sing-box/adapter" ++ "github.com/sagernet/sing-box/option" ++ "github.com/sagernet/sing/common/bufio" ++ E "github.com/sagernet/sing/common/exceptions" ++ N "github.com/sagernet/sing/common/network" ++) ++ ++type SbStatsService struct { ++ createdAt time.Time ++ inbounds map[string]bool ++ outbounds map[string]bool ++ users map[string]bool ++ access sync.Mutex ++ counters map[string]*atomic.Int64 ++} ++ ++func NewSbStatsService(options option.V2RayStatsServiceOptions) *SbStatsService { ++ if !options.Enabled { ++ return nil ++ } ++ inbounds := make(map[string]bool) ++ outbounds := make(map[string]bool) ++ users := make(map[string]bool) ++ for _, inbound := range options.Inbounds { ++ inbounds[inbound] = true ++ } ++ for _, outbound := range options.Outbounds { ++ outbounds[outbound] = true ++ } ++ for _, user := range options.Users { ++ users[user] = true ++ } ++ return &SbStatsService{ ++ createdAt: time.Now(), ++ inbounds: inbounds, ++ outbounds: outbounds, ++ users: users, ++ counters: make(map[string]*atomic.Int64), ++ } ++} ++ ++func (s *SbStatsService) RoutedConnection(ctx context.Context, conn net.Conn, metadata adapter.InboundContext, matchedRule adapter.Rule, matchOutbound adapter.Outbound) net.Conn { ++ inbound := metadata.Inbound ++ user := metadata.User ++ outbound := matchOutbound.Tag() ++ return s.RoutedConnectionInternal(inbound, outbound, user, conn, true) ++} ++ ++func (s *SbStatsService) RoutedConnectionInternal(inbound string, outbound string, user string, conn net.Conn, directIn bool) net.Conn { ++ var readCounter []*atomic.Int64 ++ var writeCounter []*atomic.Int64 ++ countInbound := inbound != "" && s.inbounds[inbound] ++ countOutbound := outbound != "" && s.outbounds[outbound] ++ countUser := user != "" && s.users[user] ++ if !countInbound && !countOutbound && !countUser { ++ return conn ++ } ++ s.access.Lock() ++ if countInbound { ++ readCounter = append(readCounter, s.loadOrCreateCounter("inbound>>>"+inbound+">>>traffic>>>uplink")) ++ writeCounter = append(writeCounter, s.loadOrCreateCounter("inbound>>>"+inbound+">>>traffic>>>downlink")) ++ } ++ if countOutbound { ++ readCounter = append(readCounter, s.loadOrCreateCounter("outbound>>>"+outbound+">>>traffic>>>uplink")) ++ writeCounter = append(writeCounter, s.loadOrCreateCounter("outbound>>>"+outbound+">>>traffic>>>downlink")) ++ } ++ if countUser { ++ readCounter = append(readCounter, s.loadOrCreateCounter("user>>>"+user+">>>traffic>>>uplink")) ++ writeCounter = append(writeCounter, s.loadOrCreateCounter("user>>>"+user+">>>traffic>>>downlink")) ++ } ++ s.access.Unlock() ++ if directIn { ++ conn = bufio.NewInt64CounterConn(conn, readCounter, writeCounter) ++ } else { ++ conn = bufio.NewInt64CounterConn(conn, writeCounter, readCounter) ++ } ++ return conn ++} ++ ++func (s *SbStatsService) RoutedPacketConnection(ctx context.Context, conn N.PacketConn, metadata adapter.InboundContext, matchedRule adapter.Rule, matchOutbound adapter.Outbound) N.PacketConn { ++ inbound := metadata.Inbound ++ user := metadata.User ++ outbound := matchOutbound.Tag() ++ var readCounter []*atomic.Int64 ++ var writeCounter []*atomic.Int64 ++ countInbound := inbound != "" && s.inbounds[inbound] ++ countOutbound := outbound != "" && s.outbounds[outbound] ++ countUser := user != "" && s.users[user] ++ if !countInbound && !countOutbound && !countUser { ++ return conn ++ } ++ s.access.Lock() ++ if countInbound { ++ readCounter = append(readCounter, s.loadOrCreateCounter("inbound>>>"+inbound+">>>traffic>>>uplink")) ++ writeCounter = append(writeCounter, s.loadOrCreateCounter("inbound>>>"+inbound+">>>traffic>>>downlink")) ++ } ++ if countOutbound { ++ readCounter = append(readCounter, s.loadOrCreateCounter("outbound>>>"+outbound+">>>traffic>>>uplink")) ++ writeCounter = append(writeCounter, s.loadOrCreateCounter("outbound>>>"+outbound+">>>traffic>>>downlink")) ++ } ++ if countUser { ++ readCounter = append(readCounter, s.loadOrCreateCounter("user>>>"+user+">>>traffic>>>uplink")) ++ writeCounter = append(writeCounter, s.loadOrCreateCounter("user>>>"+user+">>>traffic>>>downlink")) ++ } ++ s.access.Unlock() ++ return bufio.NewInt64CounterPacketConn(conn, readCounter, nil, writeCounter, nil) ++} ++ ++func (s *SbStatsService) GetStats(ctx context.Context, name string, reset bool) (int64, error) { ++ s.access.Lock() ++ counter, loaded := s.counters[name] ++ s.access.Unlock() ++ if !loaded { ++ return 0, E.New(name, " not found.") ++ } ++ var value int64 ++ if reset { ++ value = counter.Swap(0) ++ } else { ++ value = counter.Load() ++ } ++ return value, nil ++} ++ ++// QueryStats ++ ++// GetSysStats ++ ++//nolint:staticcheck ++func (s *SbStatsService) loadOrCreateCounter(name string) *atomic.Int64 { ++ counter, loaded := s.counters[name] ++ if loaded { ++ return counter ++ } ++ counter = &atomic.Int64{} ++ s.counters[name] = counter ++ return counter ++} +-- +2.43.0 + diff --git a/buildScript/lib/core/patches/0003-nekoutils-add-selector-callback.patch b/buildScript/lib/core/patches/0003-nekoutils-add-selector-callback.patch new file mode 100644 index 000000000..a851ced0f --- /dev/null +++ b/buildScript/lib/core/patches/0003-nekoutils-add-selector-callback.patch @@ -0,0 +1,45 @@ +From f3e8246622db0ec6beeb938bd9a5fbace4a381e9 Mon Sep 17 00:00:00 2001 +From: armv9 <48624112+arm64v8a@users.noreply.github.com> +Date: Sun, 23 Feb 2025 20:34:01 +0900 +Subject: [PATCH 3/6] nekoutils: add selector callback + +--- + nekoutils/callback.go | 3 +++ + protocol/group/selector.go | 4 ++++ + 2 files changed, 7 insertions(+) + create mode 100644 nekoutils/callback.go + +diff --git a/nekoutils/callback.go b/nekoutils/callback.go +new file mode 100644 +index 000000000..97f561236 +--- /dev/null ++++ b/nekoutils/callback.go +@@ -0,0 +1,3 @@ ++package nekoutils ++ ++var Selector_OnProxySelected func(selectorTag string, tag string) +diff --git a/protocol/group/selector.go b/protocol/group/selector.go +index f3f7377b6..1cb8b01a4 100644 +--- a/protocol/group/selector.go ++++ b/protocol/group/selector.go +@@ -10,6 +10,7 @@ import ( + "github.com/sagernet/sing-box/common/interrupt" + C "github.com/sagernet/sing-box/constant" + "github.com/sagernet/sing-box/log" ++ "github.com/sagernet/sing-box/nekoutils" + "github.com/sagernet/sing-box/option" + tun "github.com/sagernet/sing-tun" + "github.com/sagernet/sing/common" +@@ -137,6 +138,9 @@ func (s *Selector) SelectOutbound(tag string) bool { + } + } + s.interruptGroup.Interrupt(s.interruptExternalConnections) ++ if nekoutils.Selector_OnProxySelected != nil { ++ nekoutils.Selector_OnProxySelected(s.Tag(), tag) ++ } + return true + } + +-- +2.43.0 + diff --git a/buildScript/lib/core/patches/0004-nekoutils-add-geoip-geosite.patch b/buildScript/lib/core/patches/0004-nekoutils-add-geoip-geosite.patch new file mode 100644 index 000000000..2047c7ccc --- /dev/null +++ b/buildScript/lib/core/patches/0004-nekoutils-add-geoip-geosite.patch @@ -0,0 +1,68 @@ +From 46d231b796199635ae40e6f1fa382661bea4b5b5 Mon Sep 17 00:00:00 2001 +From: armv9 <48624112+arm64v8a@users.noreply.github.com> +Date: Wed, 26 Feb 2025 12:43:48 +0900 +Subject: [PATCH 4/6] nekoutils: add geoip geosite + +--- + nekoutils/srs.go | 7 +++++++ + route/rule/rule_set_local.go | 23 +++++++++++++++++++++++ + 2 files changed, 30 insertions(+) + create mode 100644 nekoutils/srs.go + +diff --git a/nekoutils/srs.go b/nekoutils/srs.go +new file mode 100644 +index 000000000..a86df58a7 +--- /dev/null ++++ b/nekoutils/srs.go +@@ -0,0 +1,7 @@ ++package nekoutils ++ ++import "github.com/sagernet/sing-box/option" ++ ++var GetGeoIPHeadlessRules func(name string) ([]option.HeadlessRule, error) ++ ++var GetGeoSiteHeadlessRules func(name string) ([]option.HeadlessRule, error) +diff --git a/route/rule/rule_set_local.go b/route/rule/rule_set_local.go +index ee19cc452..d713ef346 100644 +--- a/route/rule/rule_set_local.go ++++ b/route/rule/rule_set_local.go +@@ -12,6 +12,7 @@ import ( + "github.com/sagernet/sing-box/adapter" + "github.com/sagernet/sing-box/common/srs" + C "github.com/sagernet/sing-box/constant" ++ "github.com/sagernet/sing-box/nekoutils" + "github.com/sagernet/sing-box/option" + "github.com/sagernet/sing/common" + E "github.com/sagernet/sing/common/exceptions" +@@ -55,6 +56,28 @@ func NewLocalRuleSet(ctx context.Context, logger logger.Logger, options option.R + return nil, err + } + } else { ++ if strings.HasPrefix(options.LocalOptions.Path, "geoip:") { ++ rules, err := nekoutils.GetGeoIPHeadlessRules(strings.TrimPrefix(options.LocalOptions.Path, "geoip:")) ++ if err != nil { ++ return nil, err ++ } ++ err = ruleSet.reloadRules(rules) ++ if err != nil { ++ return nil, err ++ } ++ return ruleSet, nil ++ } ++ if strings.HasPrefix(options.LocalOptions.Path, "geosite:") { ++ rules, err := nekoutils.GetGeoSiteHeadlessRules(strings.TrimPrefix(options.LocalOptions.Path, "geosite:")) ++ if err != nil { ++ return nil, err ++ } ++ err = ruleSet.reloadRules(rules) ++ if err != nil { ++ return nil, err ++ } ++ return ruleSet, nil ++ } + filePath := filemanager.BasePath(ctx, options.LocalOptions.Path) + filePath, _ = filepath.Abs(filePath) + err := ruleSet.reloadFile(filePath) +-- +2.43.0 + diff --git a/buildScript/lib/core/patches/0005-dialer-add-DoNotSelectInterface.patch b/buildScript/lib/core/patches/0005-dialer-add-DoNotSelectInterface.patch new file mode 100644 index 000000000..145cec46f --- /dev/null +++ b/buildScript/lib/core/patches/0005-dialer-add-DoNotSelectInterface.patch @@ -0,0 +1,43 @@ +From 60e46b0af327b02e9ee2a6eec9dc06cd9e4bb6e8 Mon Sep 17 00:00:00 2001 +From: armv9 <48624112+arm64v8a@users.noreply.github.com> +Date: Sun, 23 Feb 2025 21:40:09 +0900 +Subject: [PATCH 5/6] dialer: add DoNotSelectInterface + +--- + common/dialer/default.go | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +diff --git a/common/dialer/default.go b/common/dialer/default.go +index ccdfbafbb..5256fe8d0 100644 +--- a/common/dialer/default.go ++++ b/common/dialer/default.go +@@ -22,6 +22,8 @@ import ( + "github.com/database64128/tfo-go/v2" + ) + ++var DoNotSelectInterface = false ++ + var ( + _ ParallelInterfaceDialer = (*DefaultDialer)(nil) + _ WireGuardListener = (*DefaultDialer)(nil) +@@ -249,7 +251,7 @@ func (d *DefaultDialer) DialContext(ctx context.Context, network string, address + } else if address.IsDomain() { + return nil, E.New("domain not resolved") + } +- if d.networkStrategy == nil { ++ if DoNotSelectInterface || d.networkStrategy == nil { + return d.trackConn(listener.ListenNetworkNamespace[net.Conn](d.netns, func() (net.Conn, error) { + switch N.NetworkName(network) { + case N.NetworkUDP: +@@ -319,7 +321,7 @@ func (d *DefaultDialer) DialParallelInterface(ctx context.Context, network strin + } + + func (d *DefaultDialer) ListenPacket(ctx context.Context, destination M.Socksaddr) (net.PacketConn, error) { +- if d.networkStrategy == nil { ++ if DoNotSelectInterface || d.networkStrategy == nil { + return d.trackPacketConn(listener.ListenNetworkNamespace[net.PacketConn](d.netns, func() (net.PacketConn, error) { + listenConfig := d.udpListener + if d.autoDetectBindFunc != nil && destination.Addr.IsValid() { +-- +2.43.0 + diff --git a/buildScript/lib/core/patches/0006-build-identify-Neko-core-as-1.13.18-neko-1.patch b/buildScript/lib/core/patches/0006-build-identify-Neko-core-as-1.13.18-neko-1.patch new file mode 100644 index 000000000..cb4657090 --- /dev/null +++ b/buildScript/lib/core/patches/0006-build-identify-Neko-core-as-1.13.18-neko-1.patch @@ -0,0 +1,21 @@ +From 1be1c8575127adf7bd19360b7973fae6cb8b2879 Mon Sep 17 00:00:00 2001 +From: honglei +Date: Sun, 16 Aug 2026 16:24:26 +0800 +Subject: [PATCH 6/6] build: identify Neko core as 1.13.18-neko-1 + +--- + constant/version.go | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/constant/version.go b/constant/version.go +index 5a816a733..9f7508db3 100644 +--- a/constant/version.go ++++ b/constant/version.go +@@ -1,3 +1,3 @@ + package constant + +-var Version = "unknown" ++var Version = "1.13.18-neko-1" +-- +2.43.0 + diff --git a/buildSrc/src/main/kotlin/Helpers.kt b/buildSrc/src/main/kotlin/Helpers.kt index 3561cdd1e..88d29cfb3 100644 --- a/buildSrc/src/main/kotlin/Helpers.kt +++ b/buildSrc/src/main/kotlin/Helpers.kt @@ -44,7 +44,7 @@ fun Project.setupCommon() { buildToolsVersion = "35.0.1" compileSdk = 35 defaultConfig { - minSdk = 21 + minSdk = 23 targetSdk = 35 } buildTypes { @@ -217,4 +217,4 @@ fun Project.setupApp() { jniLibs.srcDir("executableSo") } } -} \ No newline at end of file +} diff --git a/libcore/box.go b/libcore/box.go index 5df6d4ba0..24f6f3a0f 100644 --- a/libcore/box.go +++ b/libcore/box.go @@ -16,11 +16,9 @@ import ( "github.com/matsuridayo/libneko/speedtest" "github.com/sagernet/sing-box/adapter" "github.com/sagernet/sing-box/boxapi" - "github.com/sagernet/sing-box/experimental/libbox/platform" "github.com/sagernet/sing-box/protocol/group" box "github.com/sagernet/sing-box" - "github.com/sagernet/sing-box/common/conntrack" "github.com/sagernet/sing-box/common/dialer" "github.com/sagernet/sing-box/constant" "github.com/sagernet/sing-box/option" @@ -59,12 +57,16 @@ func VersionBox() string { } func ResetAllConnections(system bool) { - if system { - conntrack.Close() - log.Println("Reset system connections done") - } else { + if !system { log.Println("TODO: Reset user connections") + return + } + if mainInstance == nil { + log.Println("Reset system connections skipped: no active instance") + return } + mainInstance.Router().ResetNetwork() + log.Println("Reset system connections done") } type BoxInstance struct { @@ -89,7 +91,7 @@ func NewSingBoxInstance(config string, localTransport LocalDNSTransport) (b *Box nekoboxAndroidDNSTransportRegistry(localTransport), nekoboxAndroidServiceRegistry(), ) ctx = service.ContextWithDefaultRegistry(ctx) - service.MustRegister[platform.Interface](ctx, boxPlatformInterfaceInstance) + service.MustRegister[adapter.PlatformInterface](ctx, boxPlatformInterfaceInstance) // parse options var options option.Options diff --git a/libcore/box_include.go b/libcore/box_include.go index 5a95cd867..98f0f8400 100644 --- a/libcore/box_include.go +++ b/libcore/box_include.go @@ -83,8 +83,6 @@ func nekoboxAndroidOutboundRegistry() *outbound.Registry { tuic.RegisterOutbound(registry) hysteria2.RegisterOutbound(registry) - wireguard.RegisterOutbound(registry) - return registry } diff --git a/libcore/build.sh b/libcore/build.sh index 233e89d4d..9bc28aff0 100755 --- a/libcore/build.sh +++ b/libcore/build.sh @@ -1,6 +1,8 @@ #!/bin/bash -source ./env_java.sh || true +if [ -f ./env_java.sh ]; then + source ./env_java.sh +fi source ../buildScript/init/env_ndk.sh BUILD=".build" @@ -14,8 +16,8 @@ if [ -z "$GOPATH" ]; then GOPATH=$(go env GOPATH) fi -export GOBIND=gobind-matsuri -"$GOPATH"/bin/gomobile-matsuri bind -v -androidapi 21 -cache "$(realpath $BUILD)" -trimpath -ldflags='-s -w' -tags='with_conntrack,with_gvisor,with_quic,with_wireguard,with_utls,with_clash_api' . || exit 1 +export GOBIND="$GOPATH/bin/gobind-matsuri" +"$GOPATH"/bin/gomobile-matsuri bind -v -androidapi 23 -cache "$(realpath $BUILD)" -trimpath -ldflags='-s -w -checklinkname=0' -tags='with_gvisor,with_quic,with_wireguard,with_utls,with_clash_api,badlinkname,tfogo_checklinkname0' . || exit 1 rm -r libcore-sources.jar proj=../app/libs diff --git a/libcore/dns_box.go b/libcore/dns_box.go index 3f1cd5fbb..3ec25d5e9 100644 --- a/libcore/dns_box.go +++ b/libcore/dns_box.go @@ -54,6 +54,9 @@ func (p *platformLocalDNSTransport) Close() error { return nil } +func (p *platformLocalDNSTransport) Reset() { +} + func (p *platformLocalDNSTransport) Exchange(ctx context.Context, message *mDNS.Msg) (*mDNS.Msg, error) { if p.raw && rawQueryFunc != nil { // Raw - Android 10 及以上才有 diff --git a/libcore/go.mod b/libcore/go.mod index ddf89a1f6..4628b2503 100644 --- a/libcore/go.mod +++ b/libcore/go.mod @@ -1,87 +1,96 @@ module libcore -go 1.23.1 +go 1.25.0 -toolchain go1.23.6 +toolchain go1.25.11 require ( github.com/matsuridayo/libneko v1.0.0 // replaced - github.com/miekg/dns v1.1.67 + github.com/miekg/dns v1.1.72 github.com/oschwald/maxminddb-golang v1.13.1 - github.com/sagernet/quic-go v0.52.0-sing-box-mod.3 - github.com/sagernet/sing v0.7.18 + github.com/sagernet/quic-go v0.59.0-sing-box-mod.4 + github.com/sagernet/sing v0.8.12 github.com/sagernet/sing-box v1.0.0 // replaced - github.com/sagernet/sing-tun v0.7.10 + github.com/sagernet/sing-tun v0.8.12-0.20260727151122-3a09076491df github.com/ulikunitz/xz v0.5.15 - golang.org/x/mobile v0.0.0-20231108233038-35478a0c49da - golang.org/x/sys v0.35.0 + golang.org/x/mobile v0.0.0 + golang.org/x/sys v0.47.0 ) require ( github.com/ajg/form v1.5.1 // indirect github.com/andybalholm/brotli v1.1.0 // indirect github.com/anytls/sing-anytls v0.0.11 // indirect - github.com/caddyserver/certmagic v0.23.0 // indirect - github.com/caddyserver/zerossl v0.1.3 // indirect + github.com/caddyserver/certmagic v0.25.3-0.20260421143802-60d9d8b415d6 // indirect + github.com/caddyserver/zerossl v0.1.5 // indirect github.com/cretz/bine v0.2.0 // indirect - github.com/fsnotify/fsnotify v1.7.0 // indirect - github.com/go-chi/chi/v5 v5.2.2 // indirect + github.com/database64128/netx-go v0.1.1 // indirect + github.com/database64128/tfo-go/v2 v2.3.2 // indirect + github.com/florianl/go-nfqueue/v2 v2.0.2 // indirect + github.com/fsnotify/fsnotify v1.9.0 // indirect + github.com/go-chi/chi/v5 v5.2.5 // indirect github.com/go-chi/render v1.0.3 // indirect github.com/go-ole/go-ole v1.3.0 // indirect github.com/gobwas/httphead v0.1.0 // indirect github.com/gobwas/pool v0.2.1 // indirect - github.com/gofrs/uuid/v5 v5.3.2 // indirect + github.com/godbus/dbus/v5 v5.2.2 // indirect + github.com/gofrs/uuid/v5 v5.4.0 // indirect github.com/google/btree v1.1.3 // indirect github.com/google/go-cmp v0.7.0 // indirect github.com/hashicorp/yamux v0.1.2 // indirect - github.com/klauspost/compress v1.17.11 // indirect - github.com/klauspost/cpuid/v2 v2.2.10 // indirect - github.com/libdns/alidns v1.0.5-libdns.v1.beta1 // indirect - github.com/libdns/cloudflare v0.2.2-0.20250708034226-c574dccb31a6 // indirect - github.com/libdns/libdns v1.1.0 // indirect + github.com/insomniacslk/dhcp v0.0.0-20260220084031-5adc3eb26f91 // indirect + github.com/klauspost/compress v1.18.0 // indirect + github.com/klauspost/cpuid/v2 v2.3.0 // indirect + github.com/libdns/acmedns v0.5.0 // indirect + github.com/libdns/alidns v1.0.6 // indirect + github.com/libdns/cloudflare v0.2.2 // indirect + github.com/libdns/libdns v1.1.1 // indirect github.com/logrusorgru/aurora v2.0.3+incompatible // indirect - github.com/mdlayher/netlink v1.7.3-0.20250113171957-fbb4dce95f42 // indirect + github.com/mdlayher/netlink v1.9.0 // indirect github.com/mdlayher/socket v0.5.1 // indirect - github.com/metacubex/tfo-go v0.0.0-20250921095601-b102db4216c0 // indirect github.com/metacubex/utls v1.8.4 // indirect - github.com/mholt/acmez/v3 v3.1.2 // indirect - github.com/quic-go/qpack v0.5.1 // indirect + github.com/mholt/acmez/v3 v3.1.6 // indirect + github.com/pierrec/lz4/v4 v4.1.21 // indirect + github.com/quic-go/qpack v0.6.0 // indirect github.com/sagernet/bbolt v0.0.0-20231014093535-ea5cb2fe9f0a // indirect github.com/sagernet/cors v1.2.1 // indirect - github.com/sagernet/fswatch v0.1.1 // indirect - github.com/sagernet/gvisor v0.0.0-20250325023245-7a9c0f5725fb // indirect + github.com/sagernet/fswatch v0.1.2 // indirect + github.com/sagernet/gvisor v0.0.0-20250811.0-sing-box-mod.1 // indirect github.com/sagernet/netlink v0.0.0-20240612041022-b9a21c07ac6a // indirect - github.com/sagernet/nftables v0.3.0-beta.4 // indirect - github.com/sagernet/sing-mux v0.3.4 // indirect - github.com/sagernet/sing-quic v0.5.2 // indirect + github.com/sagernet/nftables v0.3.0-mod.2 // indirect + github.com/sagernet/sing-mux v0.3.5 // indirect + github.com/sagernet/sing-quic v0.6.4-0.20260803041914-d83826c306d7 // indirect github.com/sagernet/sing-shadowsocks v0.2.8 // indirect github.com/sagernet/sing-shadowsocks2 v0.2.1 // indirect - github.com/sagernet/sing-shadowtls v0.2.1-0.20250503051639-fcd445d33c11 // indirect - github.com/sagernet/sing-vmess v0.2.7 // indirect + github.com/sagernet/sing-shadowtls v0.2.1 // indirect + github.com/sagernet/sing-vmess v0.2.8-0.20250909125414-3aed155119a1 // indirect github.com/sagernet/smux v1.5.50-sing-box-mod.1 // indirect - github.com/sagernet/wireguard-go v0.0.1-beta.7 // indirect + github.com/sagernet/wireguard-go v0.0.4 // indirect github.com/sagernet/ws v0.0.0-20231204124109-acfe8907c854 // indirect + github.com/u-root/uio v0.0.0-20240224005618-d2acac8f3701 // indirect github.com/vishvananda/netns v0.0.5 // indirect github.com/zeebo/blake3 v0.2.4 // indirect go.uber.org/multierr v1.11.0 // indirect - go.uber.org/zap v1.27.0 // indirect + go.uber.org/zap v1.27.1 // indirect go.uber.org/zap/exp v0.3.0 // indirect go4.org/netipx v0.0.0-20231129151722-fdeea329fbba // indirect - golang.org/x/crypto v0.41.0 // indirect - golang.org/x/exp v0.0.0-20250506013437-ce4c2cf36ca6 // indirect - golang.org/x/mod v0.27.0 // indirect - golang.org/x/net v0.43.0 // indirect - golang.org/x/sync v0.16.0 // indirect - golang.org/x/text v0.28.0 // indirect - golang.org/x/time v0.9.0 // indirect - golang.org/x/tools v0.36.0 // indirect + golang.org/x/crypto v0.48.0 // indirect + golang.org/x/exp v0.0.0-20251219203646-944ab1f22d93 // indirect + golang.org/x/mod v0.33.0 // indirect + golang.org/x/net v0.50.0 // indirect + golang.org/x/sync v0.19.0 // indirect + golang.org/x/text v0.34.0 // indirect + golang.org/x/time v0.11.0 // indirect + golang.org/x/tools v0.42.0 // indirect golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20250324211829-b45e905df463 // indirect - google.golang.org/grpc v1.73.0 // indirect - google.golang.org/protobuf v1.36.6 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20251202230838-ff82c1b0f217 // indirect + google.golang.org/grpc v1.79.1 // indirect + google.golang.org/protobuf v1.36.11 // indirect lukechampine.com/blake3 v1.3.0 // indirect ) replace github.com/matsuridayo/libneko => ../../libneko replace github.com/sagernet/sing-box => ../../sing-box + +replace golang.org/x/mobile => ./gomobile diff --git a/libcore/go.sum b/libcore/go.sum index dcef8d1db..117132fde 100644 --- a/libcore/go.sum +++ b/libcore/go.sum @@ -1,26 +1,38 @@ +code.pfad.fr/check v1.1.0 h1:GWvjdzhSEgHvEHe2uJujDcpmZoySKuHQNrZMfzfO0bE= +code.pfad.fr/check v1.1.0/go.mod h1:NiUH13DtYsb7xp5wll0U4SXx7KhXQVCtRgdC96IPfoM= github.com/ajg/form v1.5.1 h1:t9c7v8JUKu/XxOGBU0yjNpaMloxGEJhUkqFRq0ibGeU= github.com/ajg/form v1.5.1/go.mod h1:uL1WgH+h2mgNtvBq0339dVnzXdBETtL2LeUXaIv25UY= github.com/andybalholm/brotli v1.1.0 h1:eLKJA0d02Lf0mVpIDgYnqXcUn0GqVmEFny3VuID1U3M= github.com/andybalholm/brotli v1.1.0/go.mod h1:sms7XGricyQI9K10gOSf56VKKWS4oLer58Q+mhRPtnY= github.com/anytls/sing-anytls v0.0.11 h1:w8e9Uj1oP3m4zxkyZDewPk0EcQbvVxb7Nn+rapEx4fc= github.com/anytls/sing-anytls v0.0.11/go.mod h1:7rjN6IukwysmdusYsrV51Fgu1uW6vsrdd6ctjnEAln8= -github.com/caddyserver/certmagic v0.23.0 h1:CfpZ/50jMfG4+1J/u2LV6piJq4HOfO6ppOnOf7DkFEU= -github.com/caddyserver/certmagic v0.23.0/go.mod h1:9mEZIWqqWoI+Gf+4Trh04MOVPD0tGSxtqsxg87hAIH4= -github.com/caddyserver/zerossl v0.1.3 h1:onS+pxp3M8HnHpN5MMbOMyNjmTheJyWRaZYwn+YTAyA= -github.com/caddyserver/zerossl v0.1.3/go.mod h1:CxA0acn7oEGO6//4rtrRjYgEoa4MFw/XofZnrYwGqG4= +github.com/caddyserver/certmagic v0.25.3-0.20260421143802-60d9d8b415d6 h1:LYSB6VgWzKtNrcxElw3c97BP40Oc7bizKxA9K1Vi/5k= +github.com/caddyserver/certmagic v0.25.3-0.20260421143802-60d9d8b415d6/go.mod h1:llW/CvsNmza8S6hmsuggsZeiX+uS27dkqY27wDIuBWg= +github.com/caddyserver/zerossl v0.1.5 h1:dkvOjBAEEtY6LIGAHei7sw2UgqSD6TrWweXpV7lvEvE= +github.com/caddyserver/zerossl v0.1.5/go.mod h1:CxA0acn7oEGO6//4rtrRjYgEoa4MFw/XofZnrYwGqG4= +github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= +github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cretz/bine v0.2.0 h1:8GiDRGlTgz+o8H9DSnsl+5MeBK4HsExxgl6WgzOCuZo= github.com/cretz/bine v0.2.0/go.mod h1:WU4o9QR9wWp8AVKtTM1XD5vUHkEqnf2vVSo6dBqbetI= +github.com/database64128/netx-go v0.1.1 h1:dT5LG7Gs7zFZBthFBbzWE6K8wAHjSNAaK7wCYZT7NzM= +github.com/database64128/netx-go v0.1.1/go.mod h1:LNlYVipaYkQArRFDNNJ02VkNV+My9A5XR/IGS7sIBQc= +github.com/database64128/tfo-go/v2 v2.3.2 h1:UhZMKiMq3swZGUiETkLBDzQnZBPSAeBMClpJGlnJ5Fw= +github.com/database64128/tfo-go/v2 v2.3.2/go.mod h1:GC3uB5oa4beGpCUbRb2ZOWP73bJJFmMyAVgQSO7r724= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= -github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= -github.com/go-chi/chi/v5 v5.2.2 h1:CMwsvRVTbXVytCk1Wd72Zy1LAsAh9GxMmSNWLHCG618= -github.com/go-chi/chi/v5 v5.2.2/go.mod h1:L2yAIGWB3H+phAw1NxKwWM+7eUH/lU8pOMm5hHcoops= +github.com/florianl/go-nfqueue/v2 v2.0.2 h1:FL5lQTeetgpCvac1TRwSfgaXUn0YSO7WzGvWNIp3JPE= +github.com/florianl/go-nfqueue/v2 v2.0.2/go.mod h1:VA09+iPOT43OMoCKNfXHyzujQUty2xmzyCRkBOlmabc= +github.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S9k= +github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0= +github.com/go-chi/chi/v5 v5.2.5 h1:Eg4myHZBjyvJmAFjFvWgrqDTXFyOzjj7YIm3L3mu6Ug= +github.com/go-chi/chi/v5 v5.2.5/go.mod h1:X7Gx4mteadT3eDOMTsXzmI4/rwUpOwBHLpAfupzFJP0= github.com/go-chi/render v1.0.3 h1:AsXqd2a1/INaIfUSKq3G5uA8weYx20FOsM7uSoCyyt4= github.com/go-chi/render v1.0.3/go.mod h1:/gr3hVkmYR0YlEy3LxCuVRFzEu9Ruok+gFqbIofjao0= -github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= -github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-jose/go-jose/v4 v4.1.3 h1:CVLmWDhDVRa6Mi/IgCgaopNosCaHz7zrMeF9MlZRkrs= +github.com/go-jose/go-jose/v4 v4.1.3/go.mod h1:x4oUasVrzR7071A4TnHLGSPpNOm2a21K9Kf04k1rs08= +github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI= +github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= github.com/go-ole/go-ole v1.3.0 h1:Dt6ye7+vXGIKZ7Xtk4s6/xVdGDQynvom7xCFEdWr6uE= @@ -29,8 +41,10 @@ github.com/gobwas/httphead v0.1.0 h1:exrUm0f4YX0L7EBwZHuCF4GDp8aJfVeBrlLQrs6NqWU github.com/gobwas/httphead v0.1.0/go.mod h1:O/RXo79gxV8G+RqlR/otEwx4Q36zl9rqC5u12GKvMCM= github.com/gobwas/pool v0.2.1 h1:xfeeEhW7pwmX8nuLVlqbzVc7udMDrwetjEv+TZIz1og= github.com/gobwas/pool v0.2.1/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw= -github.com/gofrs/uuid/v5 v5.3.2 h1:2jfO8j3XgSwlz/wHqemAEugfnTlikAYHhnqQ8Xh4fE0= -github.com/gofrs/uuid/v5 v5.3.2/go.mod h1:CDOjlDMVAtN56jqyRUZh58JT31Tiw7/oQyEXZV+9bD8= +github.com/godbus/dbus/v5 v5.2.2 h1:TUR3TgtSVDmjiXOgAAyaZbYmIeP3DPkld3jgKGV8mXQ= +github.com/godbus/dbus/v5 v5.2.2/go.mod h1:3AAv2+hPq5rdnr5txxxRwiGjPXamgoIHgz9FPBfOp3c= +github.com/gofrs/uuid/v5 v5.4.0 h1:EfbpCTjqMuGyq5ZJwxqzn3Cbr2d0rUZU7v5ycAk/e/0= +github.com/gofrs/uuid/v5 v5.4.0/go.mod h1:CDOjlDMVAtN56jqyRUZh58JT31Tiw7/oQyEXZV+9bD8= github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= github.com/google/btree v1.1.3 h1:CVpQJjYgC4VbzxeGVHfvZrv1ctoYCAI8vbl07Fcxlyg= @@ -41,78 +55,87 @@ github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/hashicorp/yamux v0.1.2 h1:XtB8kyFOyHXYVFnwT5C3+Bdo8gArse7j2AQ0DA0Uey8= github.com/hashicorp/yamux v0.1.2/go.mod h1:C+zze2n6e/7wshOZep2A70/aQU6QBRWJO/G6FT1wIns= -github.com/klauspost/compress v1.17.11 h1:In6xLpyWOi1+C7tXUUWv2ot1QvBjxevKAaI6IXrJmUc= -github.com/klauspost/compress v1.17.11/go.mod h1:pMDklpSncoRMuLFrf1W9Ss9KT+0rH90U12bZKk7uwG0= -github.com/klauspost/cpuid/v2 v2.2.10 h1:tBs3QSyvjDyFTq3uoc/9xFpCuOsJQFNPiAhYdw2skhE= -github.com/klauspost/cpuid/v2 v2.2.10/go.mod h1:hqwkgyIinND0mEev00jJYCxPNVRVXFQeu1XKlok6oO0= -github.com/libdns/alidns v1.0.5-libdns.v1.beta1 h1:txHK7UxDed3WFBDjrTZPuMn8X+WmhjBTTAMW5xdy5pQ= -github.com/libdns/alidns v1.0.5-libdns.v1.beta1/go.mod h1:ystHmPwcGoWjPrGpensQSMY9VoCx4cpR2hXNlwk9H/g= -github.com/libdns/cloudflare v0.2.2-0.20250708034226-c574dccb31a6 h1:3MGrVWs2COjMkQR17oUw1zMIPbm2YAzxDC3oGVZvQs8= -github.com/libdns/cloudflare v0.2.2-0.20250708034226-c574dccb31a6/go.mod h1:w9uTmRCDlAoafAsTPnn2nJ0XHK/eaUMh86DUk8BWi60= -github.com/libdns/libdns v1.0.0-beta.1/go.mod h1:4Bj9+5CQiNMVGf87wjX4CY3HQJypUHRuLvlsfsZqLWQ= -github.com/libdns/libdns v1.1.0 h1:9ze/tWvt7Df6sbhOJRB8jT33GHEHpEQXdtkE3hPthbU= -github.com/libdns/libdns v1.1.0/go.mod h1:4Bj9+5CQiNMVGf87wjX4CY3HQJypUHRuLvlsfsZqLWQ= +github.com/insomniacslk/dhcp v0.0.0-20260220084031-5adc3eb26f91 h1:u9i04mGE3iliBh0EFuWaKsmcwrLacqGmq1G3XoaM7gY= +github.com/insomniacslk/dhcp v0.0.0-20260220084031-5adc3eb26f91/go.mod h1:qfvBmyDNp+/liLEYWRvqny/PEz9hGe2Dz833eXILSmo= +github.com/klauspost/compress v1.18.0 h1:c/Cqfb0r+Yi+JtIEq73FWXVkRonBlf0CRNYc8Zttxdo= +github.com/klauspost/compress v1.18.0/go.mod h1:2Pp+KzxcywXVXMr50+X0Q/Lsb43OQHYWRCY2AiWywWQ= +github.com/klauspost/cpuid/v2 v2.3.0 h1:S4CRMLnYUhGeDFDqkGriYKdfoFlDnMtqTiI/sFzhA9Y= +github.com/klauspost/cpuid/v2 v2.3.0/go.mod h1:hqwkgyIinND0mEev00jJYCxPNVRVXFQeu1XKlok6oO0= +github.com/letsencrypt/challtestsrv v1.4.2 h1:0ON3ldMhZyWlfVNYYpFuWRTmZNnyfiL9Hh5YzC3JVwU= +github.com/letsencrypt/challtestsrv v1.4.2/go.mod h1:GhqMqcSoeGpYd5zX5TgwA6er/1MbWzx/o7yuuVya+Wk= +github.com/letsencrypt/pebble/v2 v2.10.0 h1:Wq6gYXlsY6ubqI3hhxsTzdyotvfdjFBxuwYqCLCnj/U= +github.com/letsencrypt/pebble/v2 v2.10.0/go.mod h1:Sk8cmUIPcIdv2nINo+9PB4L+ZBhzY+F9A1a/h/xmWiQ= +github.com/libdns/acmedns v0.5.0 h1:5pRtmUj4Lb/QkNJSl1xgOGBUJTWW7RjpNaIhjpDXjPE= +github.com/libdns/acmedns v0.5.0/go.mod h1:X7UAFP1Ep9NpTwWpVlrZzJLR7epynAy0wrIxSPFgKjQ= +github.com/libdns/alidns v1.0.6 h1:/Ii428ty6WHFJmE24rZxq2taq++gh7rf9jhgLfp8PmM= +github.com/libdns/alidns v1.0.6/go.mod h1:RECwyQ88e9VqQVtSrvX76o1ux3gQUKGzMgxICi+u7Ec= +github.com/libdns/cloudflare v0.2.2 h1:XWHv+C1dDcApqazlh08Q6pjytYLgR2a+Y3xrXFu0vsI= +github.com/libdns/cloudflare v0.2.2/go.mod h1:w9uTmRCDlAoafAsTPnn2nJ0XHK/eaUMh86DUk8BWi60= +github.com/libdns/libdns v1.1.1 h1:wPrHrXILoSHKWJKGd0EiAVmiJbFShguILTg9leS/P/U= +github.com/libdns/libdns v1.1.1/go.mod h1:4Bj9+5CQiNMVGf87wjX4CY3HQJypUHRuLvlsfsZqLWQ= github.com/logrusorgru/aurora v2.0.3+incompatible h1:tOpm7WcpBTn4fjmVfgpQq0EfczGlG91VSDkswnjF5A8= github.com/logrusorgru/aurora v2.0.3+incompatible/go.mod h1:7rIyQOR62GCctdiQpZ/zOJlFyk6y+94wXzv6RNZgaR4= -github.com/mdlayher/netlink v1.7.3-0.20250113171957-fbb4dce95f42 h1:A1Cq6Ysb0GM0tpKMbdCXCIfBclan4oHk1Jb+Hrejirg= -github.com/mdlayher/netlink v1.7.3-0.20250113171957-fbb4dce95f42/go.mod h1:BB4YCPDOzfy7FniQ/lxuYQ3dgmM2cZumHbK8RpTjN2o= +github.com/mdlayher/netlink v1.9.0 h1:G8+GLq2x3v4D4MVIqDdNUhTUC7TKiCy/6MDkmItfKco= +github.com/mdlayher/netlink v1.9.0/go.mod h1:YBnl5BXsCoRuwBjKKlZ+aYmEoq0r12FDA/3JC+94KDg= github.com/mdlayher/socket v0.5.1 h1:VZaqt6RkGkt2OE9l3GcC6nZkqD3xKeQLyfleW/uBcos= github.com/mdlayher/socket v0.5.1/go.mod h1:TjPLHI1UgwEv5J1B5q0zTZq12A/6H7nKmtTanQE37IQ= -github.com/metacubex/tfo-go v0.0.0-20250921095601-b102db4216c0 h1:Ui+/2s5Qz0lSnDUBmEL12M5Oi/PzvFxGTNohm8ZcsmE= -github.com/metacubex/tfo-go v0.0.0-20250921095601-b102db4216c0/go.mod h1:l9oLnLoEXyGZ5RVLsh7QCC5XsouTUyKk4F2nLm2DHLw= github.com/metacubex/utls v1.8.4 h1:HmL9nUApDdWSkgUyodfwF6hSjtiwCGGdyhaSpEejKpg= github.com/metacubex/utls v1.8.4/go.mod h1:kncGGVhFaoGn5M3pFe3SXhZCzsbCJayNOH4UEqTKTko= -github.com/mholt/acmez/v3 v3.1.2 h1:auob8J/0FhmdClQicvJvuDavgd5ezwLBfKuYmynhYzc= -github.com/mholt/acmez/v3 v3.1.2/go.mod h1:L1wOU06KKvq7tswuMDwKdcHeKpFFgkppZy/y0DFxagQ= -github.com/miekg/dns v1.1.67 h1:kg0EHj0G4bfT5/oOys6HhZw4vmMlnoZ+gDu8tJ/AlI0= -github.com/miekg/dns v1.1.67/go.mod h1:fujopn7TB3Pu3JM69XaawiU0wqjpL9/8xGop5UrTPps= +github.com/mholt/acmez/v3 v3.1.6 h1:eGVQNObP0pBN4sxqrXeg7MYqTOWyoiYpQqITVWlrevk= +github.com/mholt/acmez/v3 v3.1.6/go.mod h1:5nTPosTGosLxF3+LU4ygbgMRFDhbAVpqMI4+a4aHLBY= +github.com/miekg/dns v1.1.72 h1:vhmr+TF2A3tuoGNkLDFK9zi36F2LS+hKTRW0Uf8kbzI= +github.com/miekg/dns v1.1.72/go.mod h1:+EuEPhdHOsfk6Wk5TT2CzssZdqkmFhf8r+aVyDEToIs= github.com/oschwald/maxminddb-golang v1.13.1 h1:G3wwjdN9JmIK2o/ermkHM+98oX5fS+k5MbwsmL4MRQE= github.com/oschwald/maxminddb-golang v1.13.1/go.mod h1:K4pgV9N/GcK694KSTmVSDTODk4IsCNThNdTmnaBZ/F8= +github.com/pierrec/lz4/v4 v4.1.21 h1:yOVMLb6qSIDP67pl/5F7RepeKYu/VmTyEXvuMI5d9mQ= +github.com/pierrec/lz4/v4 v4.1.21/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/quic-go/qpack v0.5.1 h1:giqksBPnT/HDtZ6VhtFKgoLOWmlyo9Ei6u9PqzIMbhI= -github.com/quic-go/qpack v0.5.1/go.mod h1:+PC4XFrEskIVkcLzpEkbLqq1uCoxPhQuvK5rH1ZgaEg= +github.com/quic-go/qpack v0.6.0 h1:g7W+BMYynC1LbYLSqRt8PBg5Tgwxn214ZZR34VIOjz8= +github.com/quic-go/qpack v0.6.0/go.mod h1:lUpLKChi8njB4ty2bFLX2x4gzDqXwUpaO1DP9qMDZII= github.com/sagernet/bbolt v0.0.0-20231014093535-ea5cb2fe9f0a h1:+NkI2670SQpQWvkkD2QgdTuzQG263YZ+2emfpeyGqW0= github.com/sagernet/bbolt v0.0.0-20231014093535-ea5cb2fe9f0a/go.mod h1:63s7jpZqcDAIpj8oI/1v4Izok+npJOHACFCU6+huCkM= github.com/sagernet/cors v1.2.1 h1:Cv5Z8y9YSD6Gm+qSpNrL3LO4lD3eQVvbFYJSG7JCMHQ= github.com/sagernet/cors v1.2.1/go.mod h1:O64VyOjjhrkLmQIjF4KGRrJO/5dVXFdpEmCW/eISRAI= -github.com/sagernet/fswatch v0.1.1 h1:YqID+93B7VRfqIH3PArW/XpJv5H4OLEVWDfProGoRQs= -github.com/sagernet/fswatch v0.1.1/go.mod h1:nz85laH0mkQqJfaOrqPpkwtU1znMFNVTpT/5oRsVz/o= -github.com/sagernet/gvisor v0.0.0-20250325023245-7a9c0f5725fb h1:pprQtDqNgqXkRsXn+0E8ikKOemzmum8bODjSfDene38= -github.com/sagernet/gvisor v0.0.0-20250325023245-7a9c0f5725fb/go.mod h1:QkkPEJLw59/tfxgapHta14UL5qMUah5NXhO0Kw2Kan4= +github.com/sagernet/fswatch v0.1.2 h1:/TT7k4mkce1qFPxamLO842WjqBgbTBiXP2mlUjp9PFk= +github.com/sagernet/fswatch v0.1.2/go.mod h1:5BpGmpUQVd3Mc5r313HRpvADHRg3/rKn5QbwFteB880= +github.com/sagernet/gvisor v0.0.0-20250811.0-sing-box-mod.1 h1:AzCE2RhBjLJ4WIWc/GejpNh+z30d5H1hwaB0nD9eY3o= +github.com/sagernet/gvisor v0.0.0-20250811.0-sing-box-mod.1/go.mod h1:NJKBtm9nVEK3iyOYWsUlrDQuoGh4zJ4KOPhSYVidvQ4= github.com/sagernet/netlink v0.0.0-20240612041022-b9a21c07ac6a h1:ObwtHN2VpqE0ZNjr6sGeT00J8uU7JF4cNUdb44/Duis= github.com/sagernet/netlink v0.0.0-20240612041022-b9a21c07ac6a/go.mod h1:xLnfdiJbSp8rNqYEdIW/6eDO4mVoogml14Bh2hSiFpM= -github.com/sagernet/nftables v0.3.0-beta.4 h1:kbULlAwAC3jvdGAC1P5Fa3GSxVwQJibNenDW2zaXr8I= -github.com/sagernet/nftables v0.3.0-beta.4/go.mod h1:OQXAjvjNGGFxaTgVCSTRIhYB5/llyVDeapVoENYBDS8= -github.com/sagernet/quic-go v0.52.0-sing-box-mod.3 h1:ySqffGm82rPqI1TUPqmtHIYd12pfEGScygnOxjTL56w= -github.com/sagernet/quic-go v0.52.0-sing-box-mod.3/go.mod h1:OV+V5kEBb8kJS7k29MzDu6oj9GyMc7HA07sE1tedxz4= -github.com/sagernet/sing v0.7.18 h1:iZHkaru1/MoHugx3G+9S3WG4owMewKO/KvieE2Pzk4E= -github.com/sagernet/sing v0.7.18/go.mod h1:ARkL0gM13/Iv5VCZmci/NuoOlePoIsW0m7BWfln/Hak= -github.com/sagernet/sing-mux v0.3.4 h1:ZQplKl8MNXutjzbMVtWvWG31fohhgOfCuUZR4dVQ8+s= -github.com/sagernet/sing-mux v0.3.4/go.mod h1:QvlKMyNBNrQoyX4x+gq028uPbLM2XeRpWtDsWBJbFSk= -github.com/sagernet/sing-quic v0.5.2 h1:I3vlfRImhr0uLwRS3b3ib70RMG9FcXtOKKUDz3eKRWc= -github.com/sagernet/sing-quic v0.5.2/go.mod h1:evP1e++ZG8TJHVV5HudXV4vWeYzGfCdF4HwSJZcdqkI= +github.com/sagernet/nftables v0.3.0-mod.2 h1:ck2KMU02OxL1eDFgGaWYglMDpoOZ7OHzxje+vW5Q0OQ= +github.com/sagernet/nftables v0.3.0-mod.2/go.mod h1:8kslHG4VvYNihcco+i6uxIX7qbT8A56T0y5q7U44ZaQ= +github.com/sagernet/quic-go v0.59.0-sing-box-mod.4 h1:6qvrUW79S+CrPwWz6cMePXohgjHoKxLo3c+MDhNwc3o= +github.com/sagernet/quic-go v0.59.0-sing-box-mod.4/go.mod h1:OqILvS182CyOol5zNNo6bguvOGgXzV459+chpRaUC+4= +github.com/sagernet/sing v0.8.12 h1:v77YM0gB0uCQ74f1RmiTDtkV8eNT6Qtniobxh012a5I= +github.com/sagernet/sing v0.8.12/go.mod h1:olXxWQNqRW/l2Q6JI3b2Qmz8iQnIFlOeeH8bx6JhgUA= +github.com/sagernet/sing-mux v0.3.5 h1:RHnhVEc+SFqkrK4xMygYjDwwLhzp2Bj3lztSukONfhI= +github.com/sagernet/sing-mux v0.3.5/go.mod h1:QvlKMyNBNrQoyX4x+gq028uPbLM2XeRpWtDsWBJbFSk= +github.com/sagernet/sing-quic v0.6.4-0.20260803041914-d83826c306d7 h1:D46kmyvKMNVFvL3KXdq3T4vy8r29xCMmSqNuQHJBybE= +github.com/sagernet/sing-quic v0.6.4-0.20260803041914-d83826c306d7/go.mod h1:K5bWvITOm4vE10fwLfrWpw27bCoVJ+tfQ79tOWg+Ko8= github.com/sagernet/sing-shadowsocks v0.2.8 h1:PURj5PRoAkqeHh2ZW205RWzN9E9RtKCVCzByXruQWfE= github.com/sagernet/sing-shadowsocks v0.2.8/go.mod h1:lo7TWEMDcN5/h5B8S0ew+r78ZODn6SwVaFhvB6H+PTI= github.com/sagernet/sing-shadowsocks2 v0.2.1 h1:dWV9OXCeFPuYGHb6IRqlSptVnSzOelnqqs2gQ2/Qioo= github.com/sagernet/sing-shadowsocks2 v0.2.1/go.mod h1:RnXS0lExcDAovvDeniJ4IKa2IuChrdipolPYWBv9hWQ= -github.com/sagernet/sing-shadowtls v0.2.1-0.20250503051639-fcd445d33c11 h1:tK+75l64tm9WvEFrYRE1t0YxoFdWQqw/h7Uhzj0vJ+w= -github.com/sagernet/sing-shadowtls v0.2.1-0.20250503051639-fcd445d33c11/go.mod h1:sWqKnGlMipCHaGsw1sTTlimyUpgzP4WP3pjhCsYt9oA= -github.com/sagernet/sing-tun v0.7.10 h1:lLBaS9uL0mK/FCGDe3N4oKQxjMGfmv3u2/6jKtmq4Pw= -github.com/sagernet/sing-tun v0.7.10/go.mod h1:pUEjh9YHQ2gJT6Lk0TYDklh3WJy7lz+848vleGM3JPM= -github.com/sagernet/sing-vmess v0.2.7 h1:2ee+9kO0xW5P4mfe6TYVWf9VtY8k1JhNysBqsiYj0sk= -github.com/sagernet/sing-vmess v0.2.7/go.mod h1:5aYoOtYksAyS0NXDm0qKeTYW1yoE1bJVcv+XLcVoyJs= +github.com/sagernet/sing-shadowtls v0.2.1 h1:ZiHZdnEnP+YS73NMsxiZmIFCwNd0M4k7PkGCKNXhbaM= +github.com/sagernet/sing-shadowtls v0.2.1/go.mod h1:sWqKnGlMipCHaGsw1sTTlimyUpgzP4WP3pjhCsYt9oA= +github.com/sagernet/sing-tun v0.8.12-0.20260727151122-3a09076491df h1:IVG68QmUeO9xlvrBMB/0u/prBot+jIiEjCsNterk7qs= +github.com/sagernet/sing-tun v0.8.12-0.20260727151122-3a09076491df/go.mod h1:QvarqUtHfj1ULaRR+6kZOS/OoCE+pYGq67A5tyIy+dQ= +github.com/sagernet/sing-vmess v0.2.8-0.20250909125414-3aed155119a1 h1:aSwUNYUkVyVvdmBSufR8/nRFonwJeKSIROxHcm5br9o= +github.com/sagernet/sing-vmess v0.2.8-0.20250909125414-3aed155119a1/go.mod h1:P11scgTxMxVVQ8dlM27yNm3Cro40mD0+gHbnqrNGDuY= github.com/sagernet/smux v1.5.50-sing-box-mod.1 h1:XkJcivBC9V4wBjiGXIXZ229aZCU1hzcbp6kSkkyQ478= github.com/sagernet/smux v1.5.50-sing-box-mod.1/go.mod h1:NjhsCEWedJm7eFLyhuBgIEzwfhRmytrUoiLluxs5Sk8= -github.com/sagernet/wireguard-go v0.0.1-beta.7 h1:ltgBwYHfr+9Wz1eG59NiWnHrYEkDKHG7otNZvu85DXI= -github.com/sagernet/wireguard-go v0.0.1-beta.7/go.mod h1:jGXij2Gn2wbrWuYNUmmNhf1dwcZtvyAvQoe8Xd8MbUo= +github.com/sagernet/wireguard-go v0.0.4 h1:w/vHtk7AzMG37+D/uQROBL72Gj/Gj+FHMY5kg4q0CQ4= +github.com/sagernet/wireguard-go v0.0.4/go.mod h1:hEqi4y5czEg6LYtX2Bpjg+lV0b/J1n+5rA885Z66Mx0= github.com/sagernet/ws v0.0.0-20231204124109-acfe8907c854 h1:6uUiZcDRnZSAegryaUGwPC/Fj13JSHwiTftrXhMmYOc= github.com/sagernet/ws v0.0.0-20231204124109-acfe8907c854/go.mod h1:LtfoSK3+NG57tvnVEHgcuBW9ujgE8enPSgzgwStwCAA= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= -github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= +github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= +github.com/u-root/uio v0.0.0-20240224005618-d2acac8f3701 h1:pyC9PaHYZFgEKFdlp3G8RaCKgVpHZnecvArXvPXcFkM= +github.com/u-root/uio v0.0.0-20240224005618-d2acac8f3701/go.mod h1:P3a5rG4X7tI17Nn3aOIAYr5HbIMukwXG0urG0WuL8OA= github.com/ulikunitz/xz v0.5.15 h1:9DNdB5s+SgV3bQ2ApL10xRc35ck0DuIX/isZvIk+ubY= github.com/ulikunitz/xz v0.5.15/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14= github.com/vishvananda/netns v0.0.5 h1:DfiHV+j8bA32MFM7bfEunvT8IAqQ/NzSJHtcmW5zdEY= @@ -123,69 +146,69 @@ github.com/zeebo/blake3 v0.2.4 h1:KYQPkhpRtcqh0ssGYcKLG1JYvddkEA8QwCM/yBqhaZI= github.com/zeebo/blake3 v0.2.4/go.mod h1:7eeQ6d2iXWRGF6npfaxl2CU+xy2Fjo2gxeyZGCRUjcE= github.com/zeebo/pcg v1.0.1 h1:lyqfGeWiv4ahac6ttHs+I5hwtH/+1mrhlCtVNQM2kHo= github.com/zeebo/pcg v1.0.1/go.mod h1:09F0S9iiKrwn9rlI5yjLkmrug154/YRW6KnnXVDM/l4= -go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA= -go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A= -go.opentelemetry.io/otel v1.35.0 h1:xKWKPxrxB6OtMCbmMY021CqC45J+3Onta9MqjhnusiQ= -go.opentelemetry.io/otel v1.35.0/go.mod h1:UEqy8Zp11hpkUrL73gSlELM0DupHoiq72dR+Zqel/+Y= -go.opentelemetry.io/otel/metric v1.35.0 h1:0znxYu2SNyuMSQT4Y9WDWej0VpcsxkuklLa4/siN90M= -go.opentelemetry.io/otel/metric v1.35.0/go.mod h1:nKVFgxBZ2fReX6IlyW28MgZojkoAkJGaE8CpgeAU3oE= -go.opentelemetry.io/otel/sdk v1.35.0 h1:iPctf8iprVySXSKJffSS79eOjl9pvxV9ZqOWT0QejKY= -go.opentelemetry.io/otel/sdk v1.35.0/go.mod h1:+ga1bZliga3DxJ3CQGg3updiaAJoNECOgJREo9KHGQg= -go.opentelemetry.io/otel/sdk/metric v1.35.0 h1:1RriWBmCKgkeHEhM7a2uMjMUfP7MsOF5JpUCaEqEI9o= -go.opentelemetry.io/otel/sdk/metric v1.35.0/go.mod h1:is6XYCUMpcKi+ZsOvfluY5YstFnhW0BidkR+gL+qN+w= -go.opentelemetry.io/otel/trace v1.35.0 h1:dPpEfJu1sDIqruz7BHFG3c7528f6ddfSWfFDVt/xgMs= -go.opentelemetry.io/otel/trace v1.35.0/go.mod h1:WUk7DtFp1Aw2MkvqGdwiXYDZZNvA/1J8o6xRXLrIkyc= +go.opentelemetry.io/auto/sdk v1.2.1 h1:jXsnJ4Lmnqd11kwkBV2LgLoFMZKizbCi5fNZ/ipaZ64= +go.opentelemetry.io/auto/sdk v1.2.1/go.mod h1:KRTj+aOaElaLi+wW1kO/DZRXwkF4C5xPbEe3ZiIhN7Y= +go.opentelemetry.io/otel v1.39.0 h1:8yPrr/S0ND9QEfTfdP9V+SiwT4E0G7Y5MO7p85nis48= +go.opentelemetry.io/otel v1.39.0/go.mod h1:kLlFTywNWrFyEdH0oj2xK0bFYZtHRYUdv1NklR/tgc8= +go.opentelemetry.io/otel/metric v1.39.0 h1:d1UzonvEZriVfpNKEVmHXbdf909uGTOQjA0HF0Ls5Q0= +go.opentelemetry.io/otel/metric v1.39.0/go.mod h1:jrZSWL33sD7bBxg1xjrqyDjnuzTUB0x1nBERXd7Ftcs= +go.opentelemetry.io/otel/sdk v1.39.0 h1:nMLYcjVsvdui1B/4FRkwjzoRVsMK8uL/cj0OyhKzt18= +go.opentelemetry.io/otel/sdk v1.39.0/go.mod h1:vDojkC4/jsTJsE+kh+LXYQlbL8CgrEcwmt1ENZszdJE= +go.opentelemetry.io/otel/sdk/metric v1.39.0 h1:cXMVVFVgsIf2YL6QkRF4Urbr/aMInf+2WKg+sEJTtB8= +go.opentelemetry.io/otel/sdk/metric v1.39.0/go.mod h1:xq9HEVH7qeX69/JnwEfp6fVq5wosJsY1mt4lLfYdVew= +go.opentelemetry.io/otel/trace v1.39.0 h1:2d2vfpEDmCJ5zVYz7ijaJdOF59xLomrvj7bjt6/qCJI= +go.opentelemetry.io/otel/trace v1.39.0/go.mod h1:88w4/PnZSazkGzz/w84VHpQafiU4EtqqlVdxWy+rNOA= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= -go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8= -go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= +go.uber.org/zap v1.27.1 h1:08RqriUEv8+ArZRYSTXy1LeBScaMpVSTBhCeaZYfMYc= +go.uber.org/zap v1.27.1/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= go.uber.org/zap/exp v0.3.0 h1:6JYzdifzYkGmTdRR59oYH+Ng7k49H9qVpWwNSsGJj3U= go.uber.org/zap/exp v0.3.0/go.mod h1:5I384qq7XGxYyByIhHm6jg5CHkGY0nsTfbDLgDDlgJQ= go4.org/netipx v0.0.0-20231129151722-fdeea329fbba h1:0b9z3AuHCjxk0x/opv64kcgZLBseWJUpBw5I82+2U4M= go4.org/netipx v0.0.0-20231129151722-fdeea329fbba/go.mod h1:PLyyIXexvUFg3Owu6p/WfdlivPbZJsZdgWZlrGope/Y= golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8= -golang.org/x/crypto v0.41.0 h1:WKYxWedPGCTVVl5+WHSSrOBT0O8lx32+zxmHxijgXp4= -golang.org/x/crypto v0.41.0/go.mod h1:pO5AFd7FA68rFak7rOAGVuygIISepHftHnr8dr6+sUc= -golang.org/x/exp v0.0.0-20250506013437-ce4c2cf36ca6 h1:y5zboxd6LQAqYIhHnB48p0ByQ/GnQx2BE33L8BOHQkI= -golang.org/x/exp v0.0.0-20250506013437-ce4c2cf36ca6/go.mod h1:U6Lno4MTRCDY+Ba7aCcauB9T60gsv5s4ralQzP72ZoQ= -golang.org/x/mobile v0.0.0-20231108233038-35478a0c49da h1:gS9sVMAeHM+gVBmM9bTM6vUi/NHv58O3QzJ3vjjN84M= -golang.org/x/mobile v0.0.0-20231108233038-35478a0c49da/go.mod h1:IEceR0jfVklLJXrbUe90rfdAFAYDW0SQwKl4qvO1GBQ= -golang.org/x/mod v0.27.0 h1:kb+q2PyFnEADO2IEF935ehFUXlWiNjJWtRNgBLSfbxQ= -golang.org/x/mod v0.27.0/go.mod h1:rWI627Fq0DEoudcK+MBkNkCe0EetEaDSwJJkCcjpazc= +golang.org/x/crypto v0.48.0 h1:/VRzVqiRSggnhY7gNRxPauEQ5Drw9haKdM0jqfcCFts= +golang.org/x/crypto v0.48.0/go.mod h1:r0kV5h3qnFPlQnBSrULhlsRfryS2pmewsg+XfMgkVos= +golang.org/x/exp v0.0.0-20251219203646-944ab1f22d93 h1:fQsdNF2N+/YewlRZiricy4P1iimyPKZ/xwniHj8Q2a0= +golang.org/x/exp v0.0.0-20251219203646-944ab1f22d93/go.mod h1:EPRbTFwzwjXj9NpYyyrvenVh9Y+GFeEvMNh7Xuz7xgU= +golang.org/x/mod v0.33.0 h1:tHFzIWbBifEmbwtGz65eaWyGiGZatSrT9prnU8DbVL8= +golang.org/x/mod v0.33.0/go.mod h1:swjeQEj+6r7fODbD2cqrnje9PnziFuw4bmLbBZFrQ5w= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.43.0 h1:lat02VYK2j4aLzMzecihNvTlJNQUq316m2Mr9rnM6YE= -golang.org/x/net v0.43.0/go.mod h1:vhO1fvI4dGsIjh73sWfUVjj3N7CA9WkKJNQm2svM6Jg= -golang.org/x/sync v0.16.0 h1:ycBJEhp9p4vXvUZNszeOq0kGTPghopOL8q0fq3vstxw= -golang.org/x/sync v0.16.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= +golang.org/x/net v0.50.0 h1:ucWh9eiCGyDR3vtzso0WMQinm2Dnt8cFMuQa9K33J60= +golang.org/x/net v0.50.0/go.mod h1:UgoSli3F/pBgdJBHCTc+tp3gmrU4XswgGRgtnwWTfyM= +golang.org/x/sync v0.19.0 h1:vV+1eWNmZ5geRlYjzm2adRgW2/mcpevXNg50YZtPCE4= +golang.org/x/sync v0.19.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.35.0 h1:vz1N37gP5bs89s7He8XuIYXpyY0+QlsKmzipCbUtyxI= -golang.org/x/sys v0.35.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= +golang.org/x/sys v0.47.0 h1:o7XGOvZQCADBQQ4Y7VNq2dRWQR7JmOUW8Kxx4ZsNgWs= +golang.org/x/sys v0.47.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/term v0.34.0 h1:O/2T7POpk0ZZ7MAzMeWFSg6S5IpWd/RXDlM9hgM3DR4= -golang.org/x/term v0.34.0/go.mod h1:5jC53AEywhIVebHgPVeg0mj8OD3VO9OzclacVrqpaAw= +golang.org/x/term v0.40.0 h1:36e4zGLqU4yhjlmxEaagx2KuYbJq3EwY8K943ZsHcvg= +golang.org/x/term v0.40.0/go.mod h1:w2P8uVp06p2iyKKuvXIm7N/y0UCRt3UfJTfZ7oOpglM= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.28.0 h1:rhazDwis8INMIwQ4tpjLDzUhx6RlXqZNPEM0huQojng= -golang.org/x/text v0.28.0/go.mod h1:U8nCwOR8jO/marOQ0QbDiOngZVEBB7MAiitBuMjXiNU= -golang.org/x/time v0.9.0 h1:EsRrnYcQiGH+5FfbgvV4AP7qEZstoyrHB0DzarOQ4ZY= -golang.org/x/time v0.9.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= +golang.org/x/text v0.34.0 h1:oL/Qq0Kdaqxa1KbNeMKwQq0reLCCaFtqu2eNuSeNHbk= +golang.org/x/text v0.34.0/go.mod h1:homfLqTYRFyVYemLBFl5GgL/DWEiH5wcsQ5gSh1yziA= +golang.org/x/time v0.11.0 h1:/bpjEDfN9tkoN/ryeYHnv5hcMlc8ncjMcM4XBk5NWV0= +golang.org/x/time v0.11.0/go.mod h1:CDIdPxbZBQxdj6cxyCIdrNogrJKMJ7pr37NYpMcMDSg= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.36.0 h1:kWS0uv/zsvHEle1LbV5LE8QujrxB3wfQyxHfhOk0Qkg= -golang.org/x/tools v0.36.0/go.mod h1:WBDiHKJK8YgLHlcQPYQzNCkUxUypCaa5ZegCVutKm+s= +golang.org/x/tools v0.42.0 h1:uNgphsn75Tdz5Ji2q36v/nsFSfR/9BRFvqhGBaJGd5k= +golang.org/x/tools v0.42.0/go.mod h1:Ma6lCIwGZvHK6XtgbswSoWroEkhugApmsXyrUmBhfr0= golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2 h1:B82qJJgjvYKsXS9jeunTOisW56dUokqW/FOteYJJ/yg= golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2/go.mod h1:deeaetjYA+DHMHg+sMSMI58GrEteJUUzzw7en6TJQcI= -google.golang.org/genproto/googleapis/rpc v0.0.0-20250324211829-b45e905df463 h1:e0AIkUUhxyBKh6ssZNrAMeqhA7RKUj42346d1y02i2g= -google.golang.org/genproto/googleapis/rpc v0.0.0-20250324211829-b45e905df463/go.mod h1:qQ0YXyHHx3XkvlzUtpXDkS29lDSafHMZBAZDc03LQ3A= -google.golang.org/grpc v1.73.0 h1:VIWSmpI2MegBtTuFt5/JWy2oXxtjJ/e89Z70ImfD2ok= -google.golang.org/grpc v1.73.0/go.mod h1:50sbHOUqWoCQGI8V2HQLJM0B+LMlIUjNSZmow7EVBQc= -google.golang.org/protobuf v1.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY= -google.golang.org/protobuf v1.36.6/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY= +gonum.org/v1/gonum v0.16.0 h1:5+ul4Swaf3ESvrOnidPp4GZbzf0mxVQpDCYUQE7OJfk= +gonum.org/v1/gonum v0.16.0/go.mod h1:fef3am4MQ93R2HHpKnLk4/Tbh/s0+wqD5nfa6Pnwy4E= +google.golang.org/genproto/googleapis/rpc v0.0.0-20251202230838-ff82c1b0f217 h1:gRkg/vSppuSQoDjxyiGfN4Upv/h/DQmIR10ZU8dh4Ww= +google.golang.org/genproto/googleapis/rpc v0.0.0-20251202230838-ff82c1b0f217/go.mod h1:7i2o+ce6H/6BluujYR+kqX3GKH+dChPTQU19wjRPiGk= +google.golang.org/grpc v1.79.1 h1:zGhSi45ODB9/p3VAawt9a+O/MULLl9dpizzNNpq7flY= +google.golang.org/grpc v1.79.1/go.mod h1:KmT0Kjez+0dde/v2j9vzwoAScgEPx/Bw1CYChhHLrHQ= +google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE= +google.golang.org/protobuf v1.36.11/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= diff --git a/libcore/init.sh b/libcore/init.sh index 50bf4cfbd..5d0a0d53a 100755 --- a/libcore/init.sh +++ b/libcore/init.sh @@ -1,28 +1,37 @@ #!/bin/bash +set -e -chmod -R 777 .build 2>/dev/null +source ../buildScript/lib/core/get_source_env.sh + +if [ -d .build ]; then + chmod -R 777 .build +fi rm -rf .build 2>/dev/null if [ -z "$GOPATH" ]; then GOPATH=$(go env GOPATH) fi -# Install gomobile +# Keep the source checkout because go.mod replaces golang.org/x/mobile with it. +if [ ! -d gomobile ]; then + git clone --no-checkout "$REPOSITORY_GOMOBILE" gomobile +fi +pushd gomobile +git remote set-url origin "$REPOSITORY_GOMOBILE" +git fetch origin "$COMMIT_GOMOBILE" +git checkout "$COMMIT_GOMOBILE" + +# Install the matching gomobile tools once per GOPATH. if [ ! -f "$GOPATH/bin/gomobile-matsuri" ]; then - git clone https://github.com/MatsuriDayo/gomobile.git - pushd gomobile - git checkout origin/master2 - pushd cmd - pushd gomobile + pushd cmd/gomobile go install -v popd - pushd gobind + pushd cmd/gobind go install -v popd - popd - rm -rf gomobile mv "$GOPATH/bin/gomobile" "$GOPATH/bin/gomobile-matsuri" mv "$GOPATH/bin/gobind" "$GOPATH/bin/gobind-matsuri" fi +popd -GOBIND=gobind-matsuri gomobile-matsuri init +GOBIND="$GOPATH/bin/gobind-matsuri" "$GOPATH/bin/gomobile-matsuri" init diff --git a/libcore/interface_monitor.go b/libcore/interface_monitor.go index 0167666e7..0ac72360e 100644 --- a/libcore/interface_monitor.go +++ b/libcore/interface_monitor.go @@ -40,6 +40,6 @@ func (s *interfaceMonitorStub) UnregisterCallback(element *list.Element[tun.Defa func (s *interfaceMonitorStub) RegisterMyInterface(interfaceName string) { } -func (s *interfaceMonitorStub) MyInterface() string { - return "" +func (s *interfaceMonitorStub) MyInterfaces() []string { + return nil } diff --git a/libcore/platform_box.go b/libcore/platform_box.go index 316cbef58..9592b307c 100644 --- a/libcore/platform_box.go +++ b/libcore/platform_box.go @@ -1,7 +1,6 @@ package libcore import ( - "context" "encoding/json" "errors" "fmt" @@ -13,22 +12,24 @@ import ( "github.com/matsuridayo/libneko/neko_log" "github.com/sagernet/sing-box/adapter" - "github.com/sagernet/sing-box/common/process" - "github.com/sagernet/sing-box/experimental/libbox/platform" sblog "github.com/sagernet/sing-box/log" "github.com/sagernet/sing-box/option" tun "github.com/sagernet/sing-tun" E "github.com/sagernet/sing/common/exceptions" "github.com/sagernet/sing/common/logger" - N "github.com/sagernet/sing/common/network" ) -var boxPlatformInterfaceInstance platform.Interface = &boxPlatformInterfaceWrapper{} +var boxPlatformInterfaceInstance adapter.PlatformInterface = &boxPlatformInterfaceWrapper{} -type boxPlatformInterfaceWrapper struct{} +type boxPlatformInterfaceWrapper struct { + interfaceAddress []netip.Addr +} func (w *boxPlatformInterfaceWrapper) ReadWIFIState() adapter.WIFIState { - state := strings.Split(intfBox.WIFIState(), ",") + state := strings.SplitN(intfBox.WIFIState(), ",", 2) + if len(state) != 2 { + return adapter.WIFIState{} + } return adapter.WIFIState{ SSID: state[0], BSSID: state[1], @@ -53,7 +54,11 @@ func (w *boxPlatformInterfaceWrapper) AutoDetectInterfaceControl(fd int) error { return intfBox.AutoDetectInterfaceControl(int32(fd)) } -func (w *boxPlatformInterfaceWrapper) OpenTun(options *tun.Options, platformOptions option.TunPlatformOptions) (tun.Tun, error) { +func (w *boxPlatformInterfaceWrapper) UsePlatformInterface() bool { + return true +} + +func (w *boxPlatformInterfaceWrapper) OpenInterface(options *tun.Options, platformOptions option.TunPlatformOptions) (tun.Tun, error) { if len(options.IncludeUID) > 0 || len(options.ExcludeUID) > 0 { return nil, E.New("android: unsupported uid options") } @@ -73,9 +78,20 @@ func (w *boxPlatformInterfaceWrapper) OpenTun(options *tun.Options, platformOpti } // options.FileDescriptor = int(tunFd) + w.interfaceAddress = w.interfaceAddress[:0] + for _, prefix := range options.Inet4Address { + w.interfaceAddress = append(w.interfaceAddress, prefix.Addr()) + } + for _, prefix := range options.Inet6Address { + w.interfaceAddress = append(w.interfaceAddress, prefix.Addr()) + } return tun.New(*options) } +func (w *boxPlatformInterfaceWrapper) MyInterfaceAddress() []netip.Addr { + return append([]netip.Addr(nil), w.interfaceAddress...) +} + func (w *boxPlatformInterfaceWrapper) CloseTun() error { return nil } @@ -88,19 +104,31 @@ func (w *boxPlatformInterfaceWrapper) CreateDefaultInterfaceMonitor(l logger.Log return &interfaceMonitorStub{} } -func (w *boxPlatformInterfaceWrapper) UsePlatformInterfaceGetter() bool { +func (w *boxPlatformInterfaceWrapper) UsePlatformNetworkInterfaces() bool { return false } -func (w *boxPlatformInterfaceWrapper) Interfaces() ([]adapter.NetworkInterface, error) { - return nil, errors.New("wtf") +func (w *boxPlatformInterfaceWrapper) NetworkInterfaces() ([]adapter.NetworkInterface, error) { + return nil, errors.New("platform network interfaces are disabled") } -func (w *boxPlatformInterfaceWrapper) IncludeAllNetworks() bool { +func (w *boxPlatformInterfaceWrapper) NetworkExtensionIncludeAllNetworks() bool { return false } -func (w *boxPlatformInterfaceWrapper) SendNotification(notification *platform.Notification) error { +func (w *boxPlatformInterfaceWrapper) RequestPermissionForWIFIState() error { + return nil +} + +func (w *boxPlatformInterfaceWrapper) UsePlatformWIFIMonitor() bool { + return true +} + +func (w *boxPlatformInterfaceWrapper) UsePlatformNotification() bool { + return false +} + +func (w *boxPlatformInterfaceWrapper) SendNotification(notification *adapter.Notification) error { return nil } @@ -117,33 +145,57 @@ func (w *boxPlatformInterfaceWrapper) UnderNetworkExtension() bool { func (w *boxPlatformInterfaceWrapper) ClearDNSCache() { } -// process.Searcher +func (w *boxPlatformInterfaceWrapper) UsePlatformConnectionOwnerFinder() bool { + return true +} -func (w *boxPlatformInterfaceWrapper) FindProcessInfo(ctx context.Context, network string, source netip.AddrPort, destination netip.AddrPort) (*process.Info, error) { +func (w *boxPlatformInterfaceWrapper) FindConnectionOwner(request *adapter.FindConnectionOwnerRequest) (*adapter.ConnectionOwner, error) { var uid int32 if useProcfs { - uid = procfs.ResolveSocketByProcSearch(network, source, destination) + var network string + switch request.IpProtocol { + case int32(syscall.IPPROTO_TCP): + network = "tcp" + case int32(syscall.IPPROTO_UDP): + network = "udp" + default: + return nil, E.New("unknown protocol: ", request.IpProtocol) + } + sourceAddress, err := netip.ParseAddr(request.SourceAddress) + if err != nil { + return nil, err + } + destinationAddress, err := netip.ParseAddr(request.DestinationAddress) + if err != nil { + return nil, err + } + uid = procfs.ResolveSocketByProcSearch( + network, + netip.AddrPortFrom(sourceAddress, uint16(request.SourcePort)), + netip.AddrPortFrom(destinationAddress, uint16(request.DestinationPort)), + ) if uid == -1 { return nil, E.New("procfs: not found") } } else { - var ipProtocol int32 - switch N.NetworkName(network) { - case N.NetworkTCP: - ipProtocol = syscall.IPPROTO_TCP - case N.NetworkUDP: - ipProtocol = syscall.IPPROTO_UDP - default: - return nil, E.New("unknown network: ", network) - } var err error - uid, err = intfBox.FindConnectionOwner(ipProtocol, source.Addr().String(), int32(source.Port()), destination.Addr().String(), int32(destination.Port())) + uid, err = intfBox.FindConnectionOwner( + request.IpProtocol, + request.SourceAddress, + request.SourcePort, + request.DestinationAddress, + request.DestinationPort, + ) if err != nil { return nil, err } } packageName, _ := intfBox.PackageNameByUid(uid) - return &process.Info{UserId: uid, PackageName: packageName}, nil + var packageNames []string + if packageName != "" { + packageNames = []string{packageName} + } + return &adapter.ConnectionOwner{UserId: uid, AndroidPackageNames: packageNames}, nil } // io.Writer