diff --git a/.github/update.log b/.github/update.log index f9aa2b6eaa..62c61de644 100644 --- a/.github/update.log +++ b/.github/update.log @@ -1100,3 +1100,4 @@ Update On Thu Aug 21 20:41:11 CEST 2025 Update On Fri Aug 22 20:39:42 CEST 2025 Update On Sat Aug 23 20:35:18 CEST 2025 Update On Sun Aug 24 20:36:09 CEST 2025 +Update On Mon Aug 25 20:39:10 CEST 2025 diff --git a/clash-meta/component/dialer/bind_darwin.go b/clash-meta/component/dialer/bind_darwin.go index 159d3d270a..fdea24bfdc 100644 --- a/clash-meta/component/dialer/bind_darwin.go +++ b/clash-meta/component/dialer/bind_darwin.go @@ -21,10 +21,10 @@ func bindControl(ifaceIdx int) controlFn { var innerErr error err = c.Control(func(fd uintptr) { switch network { - case "tcp6", "udp6", "ip6": - innerErr = unix.SetsockoptInt(int(fd), unix.IPPROTO_IPV6, unix.IPV6_BOUND_IF, ifaceIdx) - default: + case "tcp4", "udp4": innerErr = unix.SetsockoptInt(int(fd), unix.IPPROTO_IP, unix.IP_BOUND_IF, ifaceIdx) + case "tcp6", "udp6": + innerErr = unix.SetsockoptInt(int(fd), unix.IPPROTO_IPV6, unix.IPV6_BOUND_IF, ifaceIdx) } }) diff --git a/clash-meta/component/dialer/dialer.go b/clash-meta/component/dialer/dialer.go index d490dca3de..4402f77459 100644 --- a/clash-meta/component/dialer/dialer.go +++ b/clash-meta/component/dialer/dialer.go @@ -9,7 +9,6 @@ import ( "os" "strings" "sync" - "syscall" "time" "github.com/metacubex/mihomo/component/keepalive" @@ -178,34 +177,6 @@ func dialContext(ctx context.Context, network string, destination netip.Addr, po return dialer.DialContext(ctx, network, address) } -func ICMPControl(destination netip.Addr) func(network, address string, conn syscall.RawConn) error { - return func(network, address string, conn syscall.RawConn) error { - if DefaultSocketHook != nil { - return DefaultSocketHook(network, address, conn) - } - dialer := &net.Dialer{} - interfaceName := DefaultInterface.Load() - if interfaceName == "" { - if finder := DefaultInterfaceFinder.Load(); finder != nil { - interfaceName = finder.FindInterfaceName(destination) - } - } - if interfaceName != "" { - if err := bindIfaceToDialer(interfaceName, dialer, network, destination); err != nil { - return err - } - } - routingMark := int(DefaultRoutingMark.Load()) - if routingMark != 0 { - bindMarkToDialer(routingMark, dialer, network, destination) - } - if dialer.ControlContext != nil { - return dialer.ControlContext(context.TODO(), network, address, conn) - } - return nil - } -} - func serialSingleStackDialContext(ctx context.Context, network string, ips []netip.Addr, port string, opt option) (net.Conn, error) { return serialDialContext(ctx, network, ips, port, opt) } diff --git a/clash-meta/go.mod b/clash-meta/go.mod index 0f5bbcb7b8..9d26656e33 100644 --- a/clash-meta/go.mod +++ b/clash-meta/go.mod @@ -24,13 +24,13 @@ require ( github.com/metacubex/quic-go v0.54.1-0.20250730114134-a1ae705fe295 github.com/metacubex/randv2 v0.2.0 github.com/metacubex/restls-client-go v0.1.7 - github.com/metacubex/sing v0.5.6-0.20250824161024-672b3e5150b5 + github.com/metacubex/sing v0.5.5 github.com/metacubex/sing-mux v0.3.3-0.20250813083925-d7c9aeaeeaac github.com/metacubex/sing-quic v0.0.0-20250718154553-1b193bec4cbb github.com/metacubex/sing-shadowsocks v0.2.12 github.com/metacubex/sing-shadowsocks2 v0.2.6 github.com/metacubex/sing-shadowtls v0.0.0-20250503063515-5d9f966d17a2 - github.com/metacubex/sing-tun v0.4.8-0.20250824174501-f44ca001b82b + github.com/metacubex/sing-tun v0.4.7 github.com/metacubex/sing-vmess v0.2.4-0.20250822020810-4856053566f0 github.com/metacubex/sing-wireguard v0.0.0-20250503063753-2dc62acc626f github.com/metacubex/smux v0.0.0-20250503055512-501391591dee @@ -89,7 +89,7 @@ require ( github.com/mailru/easyjson v0.7.7 // indirect github.com/mdlayher/socket v0.4.1 // indirect github.com/metacubex/ascon v0.1.0 // indirect - github.com/metacubex/gvisor v0.0.0-20250823135502-e52fca163229 // indirect + github.com/metacubex/gvisor v0.0.0-20250324165734-5857f47bd43b // indirect github.com/metacubex/nftables v0.0.0-20250503052935-30a69ab87793 // indirect github.com/oasisprotocol/deoxysii v0.0.0-20220228165953-2091330c22b7 // indirect github.com/onsi/ginkgo/v2 v2.9.5 // indirect diff --git a/clash-meta/go.sum b/clash-meta/go.sum index b51dcd6284..47b12b38d6 100644 --- a/clash-meta/go.sum +++ b/clash-meta/go.sum @@ -106,8 +106,8 @@ github.com/metacubex/fswatch v0.1.1 h1:jqU7C/v+g0qc2RUFgmAOPoVvfl2BXXUXEumn6oQux github.com/metacubex/fswatch v0.1.1/go.mod h1:czrTT7Zlbz7vWft8RQu9Qqh+JoX+Nnb+UabuyN1YsgI= github.com/metacubex/gopacket v1.1.20-0.20230608035415-7e2f98a3e759 h1:cjd4biTvOzK9ubNCCkQ+ldc4YSH/rILn53l/xGBFHHI= github.com/metacubex/gopacket v1.1.20-0.20230608035415-7e2f98a3e759/go.mod h1:UHOv2xu+RIgLwpXca7TLrXleEd4oR3sPatW6IF8wU88= -github.com/metacubex/gvisor v0.0.0-20250823135502-e52fca163229 h1:sXVGoj8TdkMYp/ZiZgZJ5lgNww2DJdA/Lywu63+Z2/w= -github.com/metacubex/gvisor v0.0.0-20250823135502-e52fca163229/go.mod h1:8LpS0IJW1VmWzUm3ylb0e2SK5QDm5lO/2qwWLZgRpBU= +github.com/metacubex/gvisor v0.0.0-20250324165734-5857f47bd43b h1:RUh4OdVPz/jDrM9MQ2ySuqu2aeBqcA8rtfWUYLZ8RtI= +github.com/metacubex/gvisor v0.0.0-20250324165734-5857f47bd43b/go.mod h1:8LpS0IJW1VmWzUm3ylb0e2SK5QDm5lO/2qwWLZgRpBU= github.com/metacubex/nftables v0.0.0-20250503052935-30a69ab87793 h1:1Qpuy+sU3DmyX9HwI+CrBT/oLNJngvBorR2RbajJcqo= github.com/metacubex/nftables v0.0.0-20250503052935-30a69ab87793/go.mod h1:RjRNb4G52yAgfR+Oe/kp9G4PJJ97Fnj89eY1BFO3YyA= github.com/metacubex/quic-go v0.54.1-0.20250730114134-a1ae705fe295 h1:8JVlYuE8uSJAvmyCd4TjvDxs57xjb0WxEoaWafK5+qs= @@ -117,8 +117,8 @@ github.com/metacubex/randv2 v0.2.0/go.mod h1:kFi2SzrQ5WuneuoLLCMkABtiBu6VRrMrWFq github.com/metacubex/restls-client-go v0.1.7 h1:eCwiXCTQb5WJu9IlgYvDBA1OgrINv58dEe7hcN5H15k= github.com/metacubex/restls-client-go v0.1.7/go.mod h1:BN/U52vPw7j8VTSh2vleD/MnmVKCov84mS5VcjVHH4g= github.com/metacubex/sing v0.5.2/go.mod h1:ypf0mjwlZm0sKdQSY+yQvmsbWa0hNPtkeqyRMGgoN+w= -github.com/metacubex/sing v0.5.6-0.20250824161024-672b3e5150b5 h1:SdDqZsb2RFGe8gDuCAvRgRARo0vdKrq8cYXcKU/3vkk= -github.com/metacubex/sing v0.5.6-0.20250824161024-672b3e5150b5/go.mod h1:ypf0mjwlZm0sKdQSY+yQvmsbWa0hNPtkeqyRMGgoN+w= +github.com/metacubex/sing v0.5.5 h1:m5U8iHvRAUxlme3FZlE/LPIGHjU8oMCUzXWGbQQAC1E= +github.com/metacubex/sing v0.5.5/go.mod h1:ypf0mjwlZm0sKdQSY+yQvmsbWa0hNPtkeqyRMGgoN+w= github.com/metacubex/sing-mux v0.3.3-0.20250813083925-d7c9aeaeeaac h1:wDH/Jh/yqWbzPktqJP+Y1cUG8hchcrzKzUxJiSpnaQs= github.com/metacubex/sing-mux v0.3.3-0.20250813083925-d7c9aeaeeaac/go.mod h1:3rt1soewn0O6j89GCLmwAQFsq257u0jf2zQSPhTL3Bw= github.com/metacubex/sing-quic v0.0.0-20250718154553-1b193bec4cbb h1:U/m3h8lp/j7i8zFgfvScLdZa1/Y8dd74oO7iZaQq80s= @@ -129,8 +129,8 @@ github.com/metacubex/sing-shadowsocks2 v0.2.6 h1:ZR1kYT0f0Vi64iQSS09OdhFfppiNkh7 github.com/metacubex/sing-shadowsocks2 v0.2.6/go.mod h1:vOEbfKC60txi0ca+yUlqEwOGc3Obl6cnSgx9Gf45KjE= github.com/metacubex/sing-shadowtls v0.0.0-20250503063515-5d9f966d17a2 h1:gXU+MYPm7Wme3/OAY2FFzVq9d9GxPHOqu5AQfg/ddhI= github.com/metacubex/sing-shadowtls v0.0.0-20250503063515-5d9f966d17a2/go.mod h1:mbfboaXauKJNIHJYxQRa+NJs4JU9NZfkA+I33dS2+9E= -github.com/metacubex/sing-tun v0.4.8-0.20250824174501-f44ca001b82b h1:QQm3Sq6HDkUpcUSnP8UfpGXtkwZVXINwAkHC78KpLzo= -github.com/metacubex/sing-tun v0.4.8-0.20250824174501-f44ca001b82b/go.mod h1:lY1AbDOLhkDNX/8cexsG82Fetg/O6vMA0eUW5SBMKhM= +github.com/metacubex/sing-tun v0.4.7 h1:ZDY/W+1c7PeWWKeKRyUo18fySF/TWjB0i5ui81Ar778= +github.com/metacubex/sing-tun v0.4.7/go.mod h1:xHecZRwBnKWe6zG9amAK9cXf91lF6blgjBqm+VvOrmU= github.com/metacubex/sing-vmess v0.2.4-0.20250822020810-4856053566f0 h1:WZepq4TOZa6WewB8tGAZrrL+bL2R2ivoBzuEgAeolWc= github.com/metacubex/sing-vmess v0.2.4-0.20250822020810-4856053566f0/go.mod h1:21R5R1u90uUvBQF0owoooEu96/SAYYD56nDrwm6nFaM= github.com/metacubex/sing-wireguard v0.0.0-20250503063753-2dc62acc626f h1:Sr/DYKYofKHKc4GF3qkRGNuj6XA6c0eqPgEDN+VAsYU= diff --git a/clash-meta/listener/sing_tun/prepare.go b/clash-meta/listener/sing_tun/prepare.go deleted file mode 100644 index 0ee3eb3729..0000000000 --- a/clash-meta/listener/sing_tun/prepare.go +++ /dev/null @@ -1,34 +0,0 @@ -package sing_tun - -import ( - "context" - "time" - - "github.com/metacubex/mihomo/component/dialer" - "github.com/metacubex/mihomo/component/resolver" - "github.com/metacubex/mihomo/log" - - tun "github.com/metacubex/sing-tun" - "github.com/metacubex/sing-tun/ping" - M "github.com/metacubex/sing/common/metadata" - N "github.com/metacubex/sing/common/network" -) - -func (h *ListenerHandler) PrepareConnection(network string, source M.Socksaddr, destination M.Socksaddr, routeContext tun.DirectRouteContext, timeout time.Duration) (tun.DirectRouteDestination, error) { - switch network { - case N.NetworkICMPv4, N.NetworkICMPv6: // our fork only send those type to PrepareConnection now - if resolver.IsFakeIP(destination.Addr) { // skip fakeip - log.Infoln("[ICMP] %s %s --> %s using fake ping echo", network, source, destination) - return nil, nil - } - log.Infoln("[ICMP] %s %s --> %s using DIRECT", network, source, destination) - directRouteDestination, err := ping.ConnectDestination(context.TODO(), log.SingLogger, dialer.ICMPControl(destination.Addr), destination.Addr, routeContext, timeout) - if err != nil { - log.Warnln("[ICMP] failed to connect to %s", destination) - return nil, err - } - log.Debugln("[ICMP] success connect to %s", destination) - return directRouteDestination, nil - } - return nil, nil -} diff --git a/clash-meta/listener/sing_tun/server.go b/clash-meta/listener/sing_tun/server.go index 6bee7ffc40..416cf30ced 100644 --- a/clash-meta/listener/sing_tun/server.go +++ b/clash-meta/listener/sing_tun/server.go @@ -11,7 +11,6 @@ import ( "strconv" "strings" "sync" - "time" "github.com/metacubex/mihomo/adapter/inbound" "github.com/metacubex/mihomo/component/dialer" @@ -175,11 +174,11 @@ func New(options LC.Tun, tunnel C.Tunnel, additions ...inbound.Addition) (l *Lis if tunMTU == 0 { tunMTU = 9000 } - var udpTimeout time.Duration + var udpTimeout int64 if options.UDPTimeout != 0 { - udpTimeout = time.Second * time.Duration(options.UDPTimeout) + udpTimeout = options.UDPTimeout } else { - udpTimeout = sing.UDPTimeout + udpTimeout = int64(sing.UDPTimeout.Seconds()) } tableIndex := options.IPRoute2TableIndex if tableIndex == 0 { diff --git a/clash-meta/transport/vless/encryption/client.go b/clash-meta/transport/vless/encryption/client.go index b504e153f4..465f16260f 100644 --- a/clash-meta/transport/vless/encryption/client.go +++ b/clash-meta/transport/vless/encryption/client.go @@ -160,7 +160,9 @@ func (i *ClientInstance) Handshake(conn net.Conn) (*CommonConn, error) { if err != nil { return nil, err } - pfsKey := append(mlkem768Key, x25519Key...) + pfsKey := make([]byte, 32+32) // no more capacity + copy(pfsKey, mlkem768Key) + copy(pfsKey[32:], x25519Key) c.UnitedKey = append(pfsKey, nfsKey...) c.GCM = NewGCM(pfsPublicKey, c.UnitedKey) c.PeerGCM = NewGCM(encryptedPfsPublicKey[:1088+32], c.UnitedKey) diff --git a/clash-meta/transport/vless/encryption/common.go b/clash-meta/transport/vless/encryption/common.go index 8e78d486eb..1b2aa18201 100644 --- a/clash-meta/transport/vless/encryption/common.go +++ b/clash-meta/transport/vless/encryption/common.go @@ -89,7 +89,7 @@ func (c *CommonConn) Read(b []byte) (int, error) { if err != nil { if c.Client != nil && strings.HasPrefix(err.Error(), "invalid header: ") { // client's 0-RTT c.Client.RWLock.Lock() - if bytes.Equal(c.UnitedKey[:32], c.Client.PfsKey) { + if bytes.HasPrefix(c.UnitedKey, c.Client.PfsKey) { c.Client.Expire = time.Now() // expired } c.Client.RWLock.Unlock() diff --git a/clash-meta/transport/vless/encryption/doc.go b/clash-meta/transport/vless/encryption/doc.go index d2eb27534c..177839c64a 100644 --- a/clash-meta/transport/vless/encryption/doc.go +++ b/clash-meta/transport/vless/encryption/doc.go @@ -19,4 +19,5 @@ // https://github.com/XTLS/Xray-core/commit/b33555cc0a52d0af3c23d2af8fca42f8a685d9af // https://github.com/XTLS/Xray-core/commit/ad7140641c44239c9dcdc3d7215ea639b1f0841c // https://github.com/XTLS/Xray-core/commit/0199dea39988a1a1b846d0bf8598631bade40902 +// https://github.com/XTLS/Xray-core/commit/fce1195b60f48ca18a953dbd5c7d991869de9a5e package encryption diff --git a/clash-meta/transport/vless/encryption/server.go b/clash-meta/transport/vless/encryption/server.go index 0bb5fa60bd..36ce399ab5 100644 --- a/clash-meta/transport/vless/encryption/server.go +++ b/clash-meta/transport/vless/encryption/server.go @@ -19,7 +19,7 @@ import ( type ServerSession struct { Expire time.Time PfsKey []byte - Replays sync.Map + NfsKeys sync.Map } type ServerInstance struct { @@ -177,7 +177,7 @@ func (i *ServerInstance) Handshake(conn net.Conn) (*CommonConn, error) { s := i.Sessions[[16]byte(ticket)] i.RWLock.RUnlock() if s == nil { - noises := make([]byte, randBetween(100, 1000)) + noises := make([]byte, randBetween(1268, 2268)) // matches 1-RTT's server hello length for "random", though it is not important, just for example var err error for err == nil { rand.Read(noises) @@ -186,21 +186,21 @@ func (i *ServerInstance) Handshake(conn net.Conn) (*CommonConn, error) { conn.Write(noises) // make client do new handshake return nil, errors.New("expired ticket") } - if _, replay := s.Replays.LoadOrStore([32]byte(nfsKey), true); replay { // prevents bad client also + if _, loaded := s.NfsKeys.LoadOrStore([32]byte(nfsKey), true); loaded { // prevents bad client also return nil, errors.New("replay detected") } - c.UnitedKey = append(s.PfsKey, nfsKey...) // the same nfsKey links the upload & download - c.PreWrite = make([]byte, 16) // always trust yourself, not the client - rand.Read(c.PreWrite) + c.UnitedKey = append(s.PfsKey, nfsKey...) // the same nfsKey links the upload & download (prevents server -> client's another request) + c.PreWrite = make([]byte, 16) + rand.Read(c.PreWrite) // always trust yourself, not the client (also prevents being parsed as TLS thus causing false interruption for "native" and "xorpub") c.GCM = NewGCM(c.PreWrite, c.UnitedKey) - c.PeerGCM = NewGCM(encryptedTicket, c.UnitedKey) // unchangeable ctx, and different ctx length for upload / download + c.PeerGCM = NewGCM(encryptedTicket, c.UnitedKey) // unchangeable ctx (prevents server -> server), and different ctx length for upload / download (prevents client -> client) if i.XorMode == 2 { c.Conn = NewXorConn(conn, NewCTR(c.UnitedKey, c.PreWrite), NewCTR(c.UnitedKey, iv), 16, 0) // it doesn't matter if the attacker sends client's iv back to the client } return c, nil } - if length < 1184+32+16 { // client may send more public keys + if length < 1184+32+16 { // client may send more public keys in the future's version return nil, errors.New("too short length") } encryptedPfsPublicKey := make([]byte, length) @@ -224,7 +224,9 @@ func (i *ServerInstance) Handshake(conn net.Conn) (*CommonConn, error) { if err != nil { return nil, err } - pfsKey := append(mlkem768Key, x25519Key...) + pfsKey := make([]byte, 32+32) // no more capacity + copy(pfsKey, mlkem768Key) + copy(pfsKey[32:], x25519Key) pfsPublicKey := append(encapsulatedPfsKey, x25519SKey.PublicKey().Bytes()...) c.UnitedKey = append(pfsKey, nfsKey...) c.GCM = NewGCM(pfsPublicKey, c.UnitedKey) diff --git a/clash-nyanpasu/frontend/interface/package.json b/clash-nyanpasu/frontend/interface/package.json index 64e150b177..7900e27a2e 100644 --- a/clash-nyanpasu/frontend/interface/package.json +++ b/clash-nyanpasu/frontend/interface/package.json @@ -11,7 +11,7 @@ "build": "tsc" }, "dependencies": { - "@tanstack/react-query": "5.84.2", + "@tanstack/react-query": "5.85.5", "@tauri-apps/api": "2.6.0", "ahooks": "3.9.4", "dayjs": "1.11.13", diff --git a/clash-nyanpasu/frontend/nyanpasu/package.json b/clash-nyanpasu/frontend/nyanpasu/package.json index 7e897268d7..6ae5ca474e 100644 --- a/clash-nyanpasu/frontend/nyanpasu/package.json +++ b/clash-nyanpasu/frontend/nyanpasu/package.json @@ -32,7 +32,7 @@ "country-emoji": "1.5.6", "dayjs": "1.11.13", "framer-motion": "12.23.12", - "i18next": "25.3.6", + "i18next": "25.4.2", "jotai": "2.13.1", "json-schema": "0.4.0", "material-react-table": "3.2.1", @@ -43,7 +43,7 @@ "react-error-boundary": "6.0.0", "react-fast-marquee": "1.6.5", "react-hook-form-mui": "7.6.2", - "react-i18next": "15.6.1", + "react-i18next": "15.7.2", "react-markdown": "10.1.0", "react-split-grid": "1.0.4", "react-use": "17.6.0", @@ -56,9 +56,9 @@ "@csstools/normalize.css": "12.1.1", "@emotion/babel-plugin": "11.13.5", "@emotion/react": "11.14.0", - "@iconify/json": "2.2.377", + "@iconify/json": "2.2.378", "@monaco-editor/react": "4.7.0", - "@tanstack/react-query": "5.84.2", + "@tanstack/react-query": "5.85.5", "@tanstack/react-router": "1.131.27", "@tanstack/react-router-devtools": "1.131.27", "@tanstack/router-plugin": "1.131.27", diff --git a/clash-nyanpasu/frontend/ui/package.json b/clash-nyanpasu/frontend/ui/package.json index d949fbf04f..b0df97f8d9 100644 --- a/clash-nyanpasu/frontend/ui/package.json +++ b/clash-nyanpasu/frontend/ui/package.json @@ -27,7 +27,7 @@ "react": "19.1.1", "react-dom": "19.1.1", "react-error-boundary": "6.0.0", - "react-i18next": "15.6.1", + "react-i18next": "15.7.2", "react-use": "17.6.0", "tailwindcss": "4.1.12", "vite": "7.1.3", diff --git a/clash-nyanpasu/manifest/version.json b/clash-nyanpasu/manifest/version.json index bc708fb5a1..28f2144301 100644 --- a/clash-nyanpasu/manifest/version.json +++ b/clash-nyanpasu/manifest/version.json @@ -2,10 +2,10 @@ "manifest_version": 1, "latest": { "mihomo": "v1.19.12", - "mihomo_alpha": "alpha-c2e2956", + "mihomo_alpha": "alpha-7dca644", "clash_rs": "v0.9.0", "clash_premium": "2023-09-05-gdcc8d87", - "clash_rs_alpha": "0.9.0-alpha+sha.51d55ef" + "clash_rs_alpha": "0.9.0-alpha+sha.56d36aa" }, "arch_template": { "mihomo": { @@ -69,5 +69,5 @@ "linux-armv7hf": "clash-armv7-unknown-linux-gnueabihf" } }, - "updated_at": "2025-08-23T22:20:47.994Z" + "updated_at": "2025-08-24T22:25:32.281Z" } diff --git a/clash-nyanpasu/package.json b/clash-nyanpasu/package.json index f886511fbf..8a2e7a5495 100644 --- a/clash-nyanpasu/package.json +++ b/clash-nyanpasu/package.json @@ -66,7 +66,7 @@ "@tauri-apps/cli": "2.6.2", "@types/fs-extra": "11.0.4", "@types/lodash-es": "4.17.12", - "@types/node": "22.17.2", + "@types/node": "22.18.0", "@typescript-eslint/eslint-plugin": "8.40.0", "@typescript-eslint/parser": "8.40.0", "autoprefixer": "10.4.21", diff --git a/clash-nyanpasu/pnpm-lock.yaml b/clash-nyanpasu/pnpm-lock.yaml index 2b1cb912c5..2ed3bbc021 100644 --- a/clash-nyanpasu/pnpm-lock.yaml +++ b/clash-nyanpasu/pnpm-lock.yaml @@ -24,7 +24,7 @@ importers: devDependencies: '@commitlint/cli': specifier: 19.8.1 - version: 19.8.1(@types/node@22.17.2)(typescript@5.9.2) + version: 19.8.1(@types/node@22.18.0)(typescript@5.9.2) '@commitlint/config-conventional': specifier: 19.8.1 version: 19.8.1 @@ -47,8 +47,8 @@ importers: specifier: 4.17.12 version: 4.17.12 '@types/node': - specifier: 22.17.2 - version: 22.17.2 + specifier: 22.18.0 + version: 22.18.0 '@typescript-eslint/eslint-plugin': specifier: 8.40.0 version: 8.40.0(@typescript-eslint/parser@8.40.0(eslint@9.34.0(jiti@2.5.1))(typescript@5.9.2))(eslint@9.34.0(jiti@2.5.1))(typescript@5.9.2) @@ -105,7 +105,7 @@ importers: version: 16.3.0 knip: specifier: 5.63.0 - version: 5.63.0(@types/node@22.17.2)(typescript@5.9.2) + version: 5.63.0(@types/node@22.18.0)(typescript@5.9.2) lint-staged: specifier: 16.1.5 version: 16.1.5 @@ -176,8 +176,8 @@ importers: frontend/interface: dependencies: '@tanstack/react-query': - specifier: 5.84.2 - version: 5.84.2(react@19.1.1) + specifier: 5.85.5 + version: 5.85.5(react@19.1.1) '@tauri-apps/api': specifier: 2.6.0 version: 2.6.0 @@ -276,8 +276,8 @@ importers: specifier: 12.23.12 version: 12.23.12(@emotion/is-prop-valid@1.3.0)(react-dom@19.1.1(react@19.1.1))(react@19.1.1) i18next: - specifier: 25.3.6 - version: 25.3.6(typescript@5.9.2) + specifier: 25.4.2 + version: 25.4.2(typescript@5.9.2) jotai: specifier: 2.13.1 version: 2.13.1(@babel/core@7.26.10)(@babel/template@7.27.2)(@types/react@19.1.11)(react@19.1.1) @@ -309,8 +309,8 @@ importers: specifier: 7.6.2 version: 7.6.2(9e88d804d29cfb33862d8a7cbbc03161) react-i18next: - specifier: 15.6.1 - version: 15.6.1(i18next@25.3.6(typescript@5.9.2))(react-dom@19.1.1(react@19.1.1))(react@19.1.1)(typescript@5.9.2) + specifier: 15.7.2 + version: 15.7.2(i18next@25.4.2(typescript@5.9.2))(react-dom@19.1.1(react@19.1.1))(react@19.1.1)(typescript@5.9.2) react-markdown: specifier: 10.1.0 version: 10.1.0(@types/react@19.1.11)(react@19.1.1) @@ -343,14 +343,14 @@ importers: specifier: 11.14.0 version: 11.14.0(@types/react@19.1.11)(react@19.1.1) '@iconify/json': - specifier: 2.2.377 - version: 2.2.377 + specifier: 2.2.378 + version: 2.2.378 '@monaco-editor/react': specifier: 4.7.0 version: 4.7.0(monaco-editor@0.52.2)(react-dom@19.1.1(react@19.1.1))(react@19.1.1) '@tanstack/react-query': - specifier: 5.84.2 - version: 5.84.2(react@19.1.1) + specifier: 5.85.5 + version: 5.85.5(react@19.1.1) '@tanstack/react-router': specifier: 1.131.27 version: 1.131.27(react-dom@19.1.1(react@19.1.1))(react@19.1.1) @@ -359,7 +359,7 @@ importers: version: 1.131.27(@tanstack/react-router@1.131.27(react-dom@19.1.1(react@19.1.1))(react@19.1.1))(@tanstack/router-core@1.131.27)(csstype@3.1.3)(react-dom@19.1.1(react@19.1.1))(react@19.1.1)(solid-js@1.9.5)(tiny-invariant@1.3.3) '@tanstack/router-plugin': specifier: 1.131.27 - version: 1.131.27(@tanstack/react-router@1.131.27(react-dom@19.1.1(react@19.1.1))(react@19.1.1))(vite@7.1.3(@types/node@22.17.2)(jiti@2.5.1)(less@4.2.0)(lightningcss@1.30.1)(sass-embedded@1.90.0)(sass@1.90.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.20.5)(yaml@2.8.1)) + version: 1.131.27(@tanstack/react-router@1.131.27(react-dom@19.1.1(react@19.1.1))(react@19.1.1))(vite@7.1.3(@types/node@22.18.0)(jiti@2.5.1)(less@4.2.0)(lightningcss@1.30.1)(sass-embedded@1.90.0)(sass@1.90.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.20.5)(yaml@2.8.1)) '@tauri-apps/plugin-clipboard-manager': specifier: 2.3.0 version: 2.3.0 @@ -395,13 +395,13 @@ importers: version: 13.15.2 '@vitejs/plugin-legacy': specifier: 7.2.1 - version: 7.2.1(terser@5.36.0)(vite@7.1.3(@types/node@22.17.2)(jiti@2.5.1)(less@4.2.0)(lightningcss@1.30.1)(sass-embedded@1.90.0)(sass@1.90.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.20.5)(yaml@2.8.1)) + version: 7.2.1(terser@5.36.0)(vite@7.1.3(@types/node@22.18.0)(jiti@2.5.1)(less@4.2.0)(lightningcss@1.30.1)(sass-embedded@1.90.0)(sass@1.90.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.20.5)(yaml@2.8.1)) '@vitejs/plugin-react': specifier: 5.0.1 - version: 5.0.1(vite@7.1.3(@types/node@22.17.2)(jiti@2.5.1)(less@4.2.0)(lightningcss@1.30.1)(sass-embedded@1.90.0)(sass@1.90.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.20.5)(yaml@2.8.1)) + version: 5.0.1(vite@7.1.3(@types/node@22.18.0)(jiti@2.5.1)(less@4.2.0)(lightningcss@1.30.1)(sass-embedded@1.90.0)(sass@1.90.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.20.5)(yaml@2.8.1)) '@vitejs/plugin-react-swc': specifier: 4.0.1 - version: 4.0.1(vite@7.1.3(@types/node@22.17.2)(jiti@2.5.1)(less@4.2.0)(lightningcss@1.30.1)(sass-embedded@1.90.0)(sass@1.90.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.20.5)(yaml@2.8.1)) + version: 4.0.1(vite@7.1.3(@types/node@22.18.0)(jiti@2.5.1)(less@4.2.0)(lightningcss@1.30.1)(sass-embedded@1.90.0)(sass@1.90.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.20.5)(yaml@2.8.1)) change-case: specifier: 5.4.4 version: 5.4.4 @@ -440,19 +440,19 @@ importers: version: 13.15.15 vite: specifier: 7.1.3 - version: 7.1.3(@types/node@22.17.2)(jiti@2.5.1)(less@4.2.0)(lightningcss@1.30.1)(sass-embedded@1.90.0)(sass@1.90.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.20.5)(yaml@2.8.1) + version: 7.1.3(@types/node@22.18.0)(jiti@2.5.1)(less@4.2.0)(lightningcss@1.30.1)(sass-embedded@1.90.0)(sass@1.90.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.20.5)(yaml@2.8.1) vite-plugin-html: specifier: 3.2.2 - version: 3.2.2(vite@7.1.3(@types/node@22.17.2)(jiti@2.5.1)(less@4.2.0)(lightningcss@1.30.1)(sass-embedded@1.90.0)(sass@1.90.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.20.5)(yaml@2.8.1)) + version: 3.2.2(vite@7.1.3(@types/node@22.18.0)(jiti@2.5.1)(less@4.2.0)(lightningcss@1.30.1)(sass-embedded@1.90.0)(sass@1.90.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.20.5)(yaml@2.8.1)) vite-plugin-sass-dts: specifier: 1.3.31 - version: 1.3.31(postcss@8.5.6)(prettier@3.6.2)(sass-embedded@1.90.0)(vite@7.1.3(@types/node@22.17.2)(jiti@2.5.1)(less@4.2.0)(lightningcss@1.30.1)(sass-embedded@1.90.0)(sass@1.90.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.20.5)(yaml@2.8.1)) + version: 1.3.31(postcss@8.5.6)(prettier@3.6.2)(sass-embedded@1.90.0)(vite@7.1.3(@types/node@22.18.0)(jiti@2.5.1)(less@4.2.0)(lightningcss@1.30.1)(sass-embedded@1.90.0)(sass@1.90.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.20.5)(yaml@2.8.1)) vite-plugin-svgr: specifier: 4.5.0 - version: 4.5.0(rollup@4.46.2)(typescript@5.9.2)(vite@7.1.3(@types/node@22.17.2)(jiti@2.5.1)(less@4.2.0)(lightningcss@1.30.1)(sass-embedded@1.90.0)(sass@1.90.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.20.5)(yaml@2.8.1)) + version: 4.5.0(rollup@4.46.2)(typescript@5.9.2)(vite@7.1.3(@types/node@22.18.0)(jiti@2.5.1)(less@4.2.0)(lightningcss@1.30.1)(sass-embedded@1.90.0)(sass@1.90.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.20.5)(yaml@2.8.1)) vite-tsconfig-paths: specifier: 5.1.4 - version: 5.1.4(typescript@5.9.2)(vite@7.1.3(@types/node@22.17.2)(jiti@2.5.1)(less@4.2.0)(lightningcss@1.30.1)(sass-embedded@1.90.0)(sass@1.90.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.20.5)(yaml@2.8.1)) + version: 5.1.4(typescript@5.9.2)(vite@7.1.3(@types/node@22.18.0)(jiti@2.5.1)(less@4.2.0)(lightningcss@1.30.1)(sass-embedded@1.90.0)(sass@1.90.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.20.5)(yaml@2.8.1)) zod: specifier: 4.0.17 version: 4.0.17 @@ -488,7 +488,7 @@ importers: version: 19.1.11 '@vitejs/plugin-react': specifier: 5.0.1 - version: 5.0.1(vite@7.1.3(@types/node@22.17.2)(jiti@2.5.1)(less@4.2.0)(lightningcss@1.30.1)(sass-embedded@1.90.0)(sass@1.90.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.20.5)(yaml@2.8.1)) + version: 5.0.1(vite@7.1.3(@types/node@22.18.0)(jiti@2.5.1)(less@4.2.0)(lightningcss@1.30.1)(sass-embedded@1.90.0)(sass@1.90.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.20.5)(yaml@2.8.1)) ahooks: specifier: 3.9.4 version: 3.9.4(react-dom@19.1.1(react@19.1.1))(react@19.1.1) @@ -508,8 +508,8 @@ importers: specifier: 6.0.0 version: 6.0.0(react@19.1.1) react-i18next: - specifier: 15.6.1 - version: 15.6.1(i18next@25.3.6(typescript@5.9.2))(react-dom@19.1.1(react@19.1.1))(react@19.1.1)(typescript@5.9.2) + specifier: 15.7.2 + version: 15.7.2(i18next@25.4.2(typescript@5.9.2))(react-dom@19.1.1(react@19.1.1))(react@19.1.1)(typescript@5.9.2) react-use: specifier: 17.6.0 version: 17.6.0(react-dom@19.1.1(react@19.1.1))(react@19.1.1) @@ -518,10 +518,10 @@ importers: version: 4.1.12 vite: specifier: 7.1.3 - version: 7.1.3(@types/node@22.17.2)(jiti@2.5.1)(less@4.2.0)(lightningcss@1.30.1)(sass-embedded@1.90.0)(sass@1.90.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.20.5)(yaml@2.8.1) + version: 7.1.3(@types/node@22.18.0)(jiti@2.5.1)(less@4.2.0)(lightningcss@1.30.1)(sass-embedded@1.90.0)(sass@1.90.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.20.5)(yaml@2.8.1) vite-tsconfig-paths: specifier: 5.1.4 - version: 5.1.4(typescript@5.9.2)(vite@7.1.3(@types/node@22.17.2)(jiti@2.5.1)(less@4.2.0)(lightningcss@1.30.1)(sass-embedded@1.90.0)(sass@1.90.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.20.5)(yaml@2.8.1)) + version: 5.1.4(typescript@5.9.2)(vite@7.1.3(@types/node@22.18.0)(jiti@2.5.1)(less@4.2.0)(lightningcss@1.30.1)(sass-embedded@1.90.0)(sass@1.90.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.20.5)(yaml@2.8.1)) devDependencies: '@emotion/react': specifier: 11.14.0 @@ -546,7 +546,7 @@ importers: version: 5.2.0(typescript@5.9.2) vite-plugin-dts: specifier: 4.5.4 - version: 4.5.4(@types/node@22.17.2)(rollup@4.46.2)(typescript@5.9.2)(vite@7.1.3(@types/node@22.17.2)(jiti@2.5.1)(less@4.2.0)(lightningcss@1.30.1)(sass-embedded@1.90.0)(sass@1.90.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.20.5)(yaml@2.8.1)) + version: 4.5.4(@types/node@22.18.0)(rollup@4.46.2)(typescript@5.9.2)(vite@7.1.3(@types/node@22.18.0)(jiti@2.5.1)(less@4.2.0)(lightningcss@1.30.1)(sass-embedded@1.90.0)(sass@1.90.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.20.5)(yaml@2.8.1)) scripts: dependencies: @@ -1799,8 +1799,8 @@ packages: prettier-plugin-ember-template-tag: optional: true - '@iconify/json@2.2.377': - resolution: {integrity: sha512-3BjwbsQPyt/Qceo0v3E0LktU3Ngc76KrZgLKX/2NfjqZxVl6NOZZ7D5crJZo9l3DJOx+6oe1pjF/+ezkRLG0Mg==} + '@iconify/json@2.2.378': + resolution: {integrity: sha512-mgz/rZVUIwq3btynvlHdUwrZbcb3KUSH97ehpOOq+t8hxTBsIwkkZf1ZgLaseNCSz1OrA+pcULsPDVl3h2odQg==} '@iconify/types@2.0.0': resolution: {integrity: sha512-+wluvCrRhXrhyOmRDJ3q8mux9JkKy5SJ/v8ol2tu4FVjyYvtEzkc/3pK15ET6RKg4b4w4BmTk1+gsCUhf21Ykg==} @@ -3013,11 +3013,11 @@ packages: resolution: {integrity: sha512-Wo1iKt2b9OT7d+YGhvEPD3DXvPv2etTusIMhMUoG7fbhmxcXCtIjJDEygy91Y2JFlwGyjqiBPRozme7UD8hoqg==} engines: {node: '>=12'} - '@tanstack/query-core@5.83.1': - resolution: {integrity: sha512-OG69LQgT7jSp+5pPuCfzltq/+7l2xoweggjme9vlbCPa/d7D7zaqv5vN/S82SzSYZ4EDLTxNO1PWrv49RAS64Q==} + '@tanstack/query-core@5.85.5': + resolution: {integrity: sha512-KO0WTob4JEApv69iYp1eGvfMSUkgw//IpMnq+//cORBzXf0smyRwPLrUvEe5qtAEGjwZTXrjxg+oJNP/C00t6w==} - '@tanstack/react-query@5.84.2': - resolution: {integrity: sha512-cZadySzROlD2+o8zIfbD978p0IphuQzRWiiH3I2ugnTmz4jbjc0+TdibpwqxlzynEen8OulgAg+rzdNF37s7XQ==} + '@tanstack/react-query@5.85.5': + resolution: {integrity: sha512-/X4EFNcnPiSs8wM2v+b6DqS5mmGeuJQvxBglmDxl6ZQb5V26ouD2SJYAcC3VjbNwqhY2zjxVD15rDA5nGbMn3A==} peerDependencies: react: ^18 || ^19 @@ -3417,8 +3417,8 @@ packages: '@types/node@16.18.108': resolution: {integrity: sha512-fj42LD82fSv6yN9C6Q4dzS+hujHj+pTv0IpRR3kI20fnYeS0ytBpjFO9OjmDowSPPt4lNKN46JLaKbCyP+BW2A==} - '@types/node@22.17.2': - resolution: {integrity: sha512-gL6z5N9Jm9mhY+U2KXZpteb+09zyffliRkZyZOHODGATyC5B1Jt/7TzuuiLkFsSUMLbS1OLmlj/E+/3KF4Q/4w==} + '@types/node@22.18.0': + resolution: {integrity: sha512-m5ObIqwsUp6BZzyiy4RdZpzWGub9bqLJMvZDD0QMXhxjqMHMENlj+SqF5QxoUwaQNFe+8kz8XM8ZQhqkQPTgMQ==} '@types/parse-json@4.0.2': resolution: {integrity: sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw==} @@ -5582,8 +5582,8 @@ packages: hyphenate-style-name@1.1.0: resolution: {integrity: sha512-WDC/ui2VVRrz3jOVi+XtjqkDjiVjTtFaAGiW37k6b+ohyQ5wYDOGkvCZa8+H0nx3gyvv0+BST9xuOgIyGQ00gw==} - i18next@25.3.6: - resolution: {integrity: sha512-dThZ0CTCM3sUG/qS0ZtQYZQcUI6DtBN8yBHK+SKEqihPcEYmjVWh/YJ4luic73Iq6Uxhp6q7LJJntRK5+1t7jQ==} + i18next@25.4.2: + resolution: {integrity: sha512-gD4T25a6ovNXsfXY1TwHXXXLnD/K2t99jyYMCSimSCBnBRJVQr5j+VAaU83RJCPzrTGhVQ6dqIga66xO2rtd5g==} peerDependencies: typescript: ^5 peerDependenciesMeta: @@ -7188,10 +7188,10 @@ packages: peerDependencies: react: ^16.8.0 || ^17 || ^18 || ^19 - react-i18next@15.6.1: - resolution: {integrity: sha512-uGrzSsOUUe2sDBG/+FJq2J1MM+Y4368/QW8OLEKSFvnDflHBbZhSd1u3UkW0Z06rMhZmnB/AQrhCpYfE5/5XNg==} + react-i18next@15.7.2: + resolution: {integrity: sha512-xJxq7ibnhUlMvd82lNC4te1GxGUMoM1A05KKyqoqsBXVZtEvZg/fz/fnVzdlY/hhQ3SpP/79qCocZOtICGhd3g==} peerDependencies: - i18next: '>= 23.2.3' + i18next: '>= 25.4.1' react: '>= 16.8.0' react-dom: '*' react-native: '*' @@ -9670,11 +9670,11 @@ snapshots: '@bufbuild/protobuf@2.5.2': {} - '@commitlint/cli@19.8.1(@types/node@22.17.2)(typescript@5.9.2)': + '@commitlint/cli@19.8.1(@types/node@22.18.0)(typescript@5.9.2)': dependencies: '@commitlint/format': 19.8.1 '@commitlint/lint': 19.8.1 - '@commitlint/load': 19.8.1(@types/node@22.17.2)(typescript@5.9.2) + '@commitlint/load': 19.8.1(@types/node@22.18.0)(typescript@5.9.2) '@commitlint/read': 19.8.1 '@commitlint/types': 19.8.1 tinyexec: 1.0.1 @@ -9721,7 +9721,7 @@ snapshots: '@commitlint/rules': 19.8.1 '@commitlint/types': 19.8.1 - '@commitlint/load@19.8.1(@types/node@22.17.2)(typescript@5.9.2)': + '@commitlint/load@19.8.1(@types/node@22.18.0)(typescript@5.9.2)': dependencies: '@commitlint/config-validator': 19.8.1 '@commitlint/execute-rule': 19.8.1 @@ -9729,7 +9729,7 @@ snapshots: '@commitlint/types': 19.8.1 chalk: 5.4.1 cosmiconfig: 9.0.0(typescript@5.9.2) - cosmiconfig-typescript-loader: 6.1.0(@types/node@22.17.2)(cosmiconfig@9.0.0(typescript@5.9.2))(typescript@5.9.2) + cosmiconfig-typescript-loader: 6.1.0(@types/node@22.18.0)(cosmiconfig@9.0.0(typescript@5.9.2))(typescript@5.9.2) lodash.isplainobject: 4.0.6 lodash.merge: 4.6.2 lodash.uniq: 4.5.0 @@ -10131,7 +10131,7 @@ snapshots: transitivePeerDependencies: - supports-color - '@iconify/json@2.2.377': + '@iconify/json@2.2.378': dependencies: '@iconify/types': 2.0.0 pathe: 1.1.2 @@ -10194,23 +10194,23 @@ snapshots: '@material/material-color-utilities@0.3.0': {} - '@microsoft/api-extractor-model@7.30.3(@types/node@22.17.2)': + '@microsoft/api-extractor-model@7.30.3(@types/node@22.18.0)': dependencies: '@microsoft/tsdoc': 0.15.1 '@microsoft/tsdoc-config': 0.17.1 - '@rushstack/node-core-library': 5.11.0(@types/node@22.17.2) + '@rushstack/node-core-library': 5.11.0(@types/node@22.18.0) transitivePeerDependencies: - '@types/node' - '@microsoft/api-extractor@7.51.0(@types/node@22.17.2)': + '@microsoft/api-extractor@7.51.0(@types/node@22.18.0)': dependencies: - '@microsoft/api-extractor-model': 7.30.3(@types/node@22.17.2) + '@microsoft/api-extractor-model': 7.30.3(@types/node@22.18.0) '@microsoft/tsdoc': 0.15.1 '@microsoft/tsdoc-config': 0.17.1 - '@rushstack/node-core-library': 5.11.0(@types/node@22.17.2) + '@rushstack/node-core-library': 5.11.0(@types/node@22.18.0) '@rushstack/rig-package': 0.5.3 - '@rushstack/terminal': 0.15.0(@types/node@22.17.2) - '@rushstack/ts-command-line': 4.23.5(@types/node@22.17.2) + '@rushstack/terminal': 0.15.0(@types/node@22.18.0) + '@rushstack/ts-command-line': 4.23.5(@types/node@22.18.0) lodash: 4.17.21 minimatch: 3.0.8 resolve: 1.22.8 @@ -10954,7 +10954,7 @@ snapshots: '@rtsao/scc@1.1.0': {} - '@rushstack/node-core-library@5.11.0(@types/node@22.17.2)': + '@rushstack/node-core-library@5.11.0(@types/node@22.18.0)': dependencies: ajv: 8.13.0 ajv-draft-04: 1.0.0(ajv@8.13.0) @@ -10965,23 +10965,23 @@ snapshots: resolve: 1.22.8 semver: 7.5.4 optionalDependencies: - '@types/node': 22.17.2 + '@types/node': 22.18.0 '@rushstack/rig-package@0.5.3': dependencies: resolve: 1.22.8 strip-json-comments: 3.1.1 - '@rushstack/terminal@0.15.0(@types/node@22.17.2)': + '@rushstack/terminal@0.15.0(@types/node@22.18.0)': dependencies: - '@rushstack/node-core-library': 5.11.0(@types/node@22.17.2) + '@rushstack/node-core-library': 5.11.0(@types/node@22.18.0) supports-color: 8.1.1 optionalDependencies: - '@types/node': 22.17.2 + '@types/node': 22.18.0 - '@rushstack/ts-command-line@4.23.5(@types/node@22.17.2)': + '@rushstack/ts-command-line@4.23.5(@types/node@22.18.0)': dependencies: - '@rushstack/terminal': 0.15.0(@types/node@22.17.2) + '@rushstack/terminal': 0.15.0(@types/node@22.18.0) '@types/argparse': 1.0.38 argparse: 1.0.10 string-argv: 0.3.2 @@ -11241,11 +11241,11 @@ snapshots: dependencies: remove-accents: 0.5.0 - '@tanstack/query-core@5.83.1': {} + '@tanstack/query-core@5.85.5': {} - '@tanstack/react-query@5.84.2(react@19.1.1)': + '@tanstack/react-query@5.85.5(react@19.1.1)': dependencies: - '@tanstack/query-core': 5.83.1 + '@tanstack/query-core': 5.85.5 react: 19.1.1 '@tanstack/react-router-devtools@1.131.27(@tanstack/react-router@1.131.27(react-dom@19.1.1(react@19.1.1))(react@19.1.1))(@tanstack/router-core@1.131.27)(csstype@3.1.3)(react-dom@19.1.1(react@19.1.1))(react@19.1.1)(solid-js@1.9.5)(tiny-invariant@1.3.3)': @@ -11323,7 +11323,7 @@ snapshots: transitivePeerDependencies: - supports-color - '@tanstack/router-plugin@1.131.27(@tanstack/react-router@1.131.27(react-dom@19.1.1(react@19.1.1))(react@19.1.1))(vite@7.1.3(@types/node@22.17.2)(jiti@2.5.1)(less@4.2.0)(lightningcss@1.30.1)(sass-embedded@1.90.0)(sass@1.90.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.20.5)(yaml@2.8.1))': + '@tanstack/router-plugin@1.131.27(@tanstack/react-router@1.131.27(react-dom@19.1.1(react@19.1.1))(react@19.1.1))(vite@7.1.3(@types/node@22.18.0)(jiti@2.5.1)(less@4.2.0)(lightningcss@1.30.1)(sass-embedded@1.90.0)(sass@1.90.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.20.5)(yaml@2.8.1))': dependencies: '@babel/core': 7.28.0 '@babel/plugin-syntax-jsx': 7.27.1(@babel/core@7.28.0) @@ -11341,7 +11341,7 @@ snapshots: zod: 3.25.76 optionalDependencies: '@tanstack/react-router': 1.131.27(react-dom@19.1.1(react@19.1.1))(react@19.1.1) - vite: 7.1.3(@types/node@22.17.2)(jiti@2.5.1)(less@4.2.0)(lightningcss@1.30.1)(sass-embedded@1.90.0)(sass@1.90.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.20.5)(yaml@2.8.1) + vite: 7.1.3(@types/node@22.18.0)(jiti@2.5.1)(less@4.2.0)(lightningcss@1.30.1)(sass-embedded@1.90.0)(sass@1.90.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.20.5)(yaml@2.8.1) transitivePeerDependencies: - supports-color @@ -11481,7 +11481,7 @@ snapshots: '@types/adm-zip@0.5.7': dependencies: - '@types/node': 22.17.2 + '@types/node': 22.18.0 '@types/argparse@1.0.38': {} @@ -11512,12 +11512,12 @@ snapshots: dependencies: '@types/http-cache-semantics': 4.0.4 '@types/keyv': 3.1.4 - '@types/node': 22.17.2 + '@types/node': 22.18.0 '@types/responselike': 1.0.3 '@types/conventional-commits-parser@5.0.0': dependencies: - '@types/node': 22.17.2 + '@types/node': 22.18.0 '@types/d3-array@3.2.1': {} @@ -11653,7 +11653,7 @@ snapshots: '@types/fs-extra@11.0.4': dependencies: '@types/jsonfile': 6.1.4 - '@types/node': 22.17.2 + '@types/node': 22.18.0 '@types/geojson@7946.0.14': {} @@ -11671,11 +11671,11 @@ snapshots: '@types/jsonfile@6.1.4': dependencies: - '@types/node': 22.17.2 + '@types/node': 22.18.0 '@types/keyv@3.1.4': dependencies: - '@types/node': 22.17.2 + '@types/node': 22.18.0 '@types/lodash-es@4.17.12': dependencies: @@ -11691,7 +11691,7 @@ snapshots: '@types/node@16.18.108': {} - '@types/node@22.17.2': + '@types/node@22.18.0': dependencies: undici-types: 6.21.0 @@ -11721,7 +11721,7 @@ snapshots: '@types/responselike@1.0.3': dependencies: - '@types/node': 22.17.2 + '@types/node': 22.18.0 '@types/retry@0.12.2': {} @@ -11741,7 +11741,7 @@ snapshots: '@types/yauzl@2.10.3': dependencies: - '@types/node': 22.17.2 + '@types/node': 22.18.0 optional: true '@typescript-eslint/eslint-plugin@8.40.0(@typescript-eslint/parser@8.40.0(eslint@9.34.0(jiti@2.5.1))(typescript@5.9.2))(eslint@9.34.0(jiti@2.5.1))(typescript@5.9.2)': @@ -11958,7 +11958,7 @@ snapshots: '@unrs/resolver-binding-win32-x64-msvc@1.10.1': optional: true - '@vitejs/plugin-legacy@7.2.1(terser@5.36.0)(vite@7.1.3(@types/node@22.17.2)(jiti@2.5.1)(less@4.2.0)(lightningcss@1.30.1)(sass-embedded@1.90.0)(sass@1.90.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.20.5)(yaml@2.8.1))': + '@vitejs/plugin-legacy@7.2.1(terser@5.36.0)(vite@7.1.3(@types/node@22.18.0)(jiti@2.5.1)(less@4.2.0)(lightningcss@1.30.1)(sass-embedded@1.90.0)(sass@1.90.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.20.5)(yaml@2.8.1))': dependencies: '@babel/core': 7.28.0 '@babel/plugin-transform-dynamic-import': 7.27.1(@babel/core@7.28.0) @@ -11973,19 +11973,19 @@ snapshots: regenerator-runtime: 0.14.1 systemjs: 6.15.1 terser: 5.36.0 - vite: 7.1.3(@types/node@22.17.2)(jiti@2.5.1)(less@4.2.0)(lightningcss@1.30.1)(sass-embedded@1.90.0)(sass@1.90.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.20.5)(yaml@2.8.1) + vite: 7.1.3(@types/node@22.18.0)(jiti@2.5.1)(less@4.2.0)(lightningcss@1.30.1)(sass-embedded@1.90.0)(sass@1.90.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.20.5)(yaml@2.8.1) transitivePeerDependencies: - supports-color - '@vitejs/plugin-react-swc@4.0.1(vite@7.1.3(@types/node@22.17.2)(jiti@2.5.1)(less@4.2.0)(lightningcss@1.30.1)(sass-embedded@1.90.0)(sass@1.90.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.20.5)(yaml@2.8.1))': + '@vitejs/plugin-react-swc@4.0.1(vite@7.1.3(@types/node@22.18.0)(jiti@2.5.1)(less@4.2.0)(lightningcss@1.30.1)(sass-embedded@1.90.0)(sass@1.90.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.20.5)(yaml@2.8.1))': dependencies: '@rolldown/pluginutils': 1.0.0-beta.32 '@swc/core': 1.13.3 - vite: 7.1.3(@types/node@22.17.2)(jiti@2.5.1)(less@4.2.0)(lightningcss@1.30.1)(sass-embedded@1.90.0)(sass@1.90.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.20.5)(yaml@2.8.1) + vite: 7.1.3(@types/node@22.18.0)(jiti@2.5.1)(less@4.2.0)(lightningcss@1.30.1)(sass-embedded@1.90.0)(sass@1.90.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.20.5)(yaml@2.8.1) transitivePeerDependencies: - '@swc/helpers' - '@vitejs/plugin-react@5.0.1(vite@7.1.3(@types/node@22.17.2)(jiti@2.5.1)(less@4.2.0)(lightningcss@1.30.1)(sass-embedded@1.90.0)(sass@1.90.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.20.5)(yaml@2.8.1))': + '@vitejs/plugin-react@5.0.1(vite@7.1.3(@types/node@22.18.0)(jiti@2.5.1)(less@4.2.0)(lightningcss@1.30.1)(sass-embedded@1.90.0)(sass@1.90.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.20.5)(yaml@2.8.1))': dependencies: '@babel/core': 7.28.3 '@babel/plugin-transform-react-jsx-self': 7.27.1(@babel/core@7.28.3) @@ -11993,7 +11993,7 @@ snapshots: '@rolldown/pluginutils': 1.0.0-beta.32 '@types/babel__core': 7.20.5 react-refresh: 0.17.0 - vite: 7.1.3(@types/node@22.17.2)(jiti@2.5.1)(less@4.2.0)(lightningcss@1.30.1)(sass-embedded@1.90.0)(sass@1.90.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.20.5)(yaml@2.8.1) + vite: 7.1.3(@types/node@22.18.0)(jiti@2.5.1)(less@4.2.0)(lightningcss@1.30.1)(sass-embedded@1.90.0)(sass@1.90.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.20.5)(yaml@2.8.1) transitivePeerDependencies: - supports-color @@ -12673,9 +12673,9 @@ snapshots: core-js@3.45.1: {} - cosmiconfig-typescript-loader@6.1.0(@types/node@22.17.2)(cosmiconfig@9.0.0(typescript@5.9.2))(typescript@5.9.2): + cosmiconfig-typescript-loader@6.1.0(@types/node@22.18.0)(cosmiconfig@9.0.0(typescript@5.9.2))(typescript@5.9.2): dependencies: - '@types/node': 22.17.2 + '@types/node': 22.18.0 cosmiconfig: 9.0.0(typescript@5.9.2) jiti: 2.5.1 typescript: 5.9.2 @@ -14312,7 +14312,7 @@ snapshots: hyphenate-style-name@1.1.0: {} - i18next@25.3.6(typescript@5.9.2): + i18next@25.4.2(typescript@5.9.2): dependencies: '@babel/runtime': 7.28.2 optionalDependencies: @@ -14768,10 +14768,10 @@ snapshots: kind-of@6.0.3: {} - knip@5.63.0(@types/node@22.17.2)(typescript@5.9.2): + knip@5.63.0(@types/node@22.18.0)(typescript@5.9.2): dependencies: '@nodelib/fs.walk': 1.2.8 - '@types/node': 22.17.2 + '@types/node': 22.18.0 fast-glob: 3.3.3 formatly: 0.3.0 jiti: 2.5.1 @@ -15953,11 +15953,11 @@ snapshots: dependencies: react: 19.1.1 - react-i18next@15.6.1(i18next@25.3.6(typescript@5.9.2))(react-dom@19.1.1(react@19.1.1))(react@19.1.1)(typescript@5.9.2): + react-i18next@15.7.2(i18next@25.4.2(typescript@5.9.2))(react-dom@19.1.1(react@19.1.1))(react@19.1.1)(typescript@5.9.2): dependencies: - '@babel/runtime': 7.27.6 + '@babel/runtime': 7.28.2 html-parse-stringify: 3.0.1 - i18next: 25.3.6(typescript@5.9.2) + i18next: 25.4.2(typescript@5.9.2) react: 19.1.1 optionalDependencies: react-dom: 19.1.1(react@19.1.1) @@ -17376,9 +17376,9 @@ snapshots: - rollup - supports-color - vite-plugin-dts@4.5.4(@types/node@22.17.2)(rollup@4.46.2)(typescript@5.9.2)(vite@7.1.3(@types/node@22.17.2)(jiti@2.5.1)(less@4.2.0)(lightningcss@1.30.1)(sass-embedded@1.90.0)(sass@1.90.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.20.5)(yaml@2.8.1)): + vite-plugin-dts@4.5.4(@types/node@22.18.0)(rollup@4.46.2)(typescript@5.9.2)(vite@7.1.3(@types/node@22.18.0)(jiti@2.5.1)(less@4.2.0)(lightningcss@1.30.1)(sass-embedded@1.90.0)(sass@1.90.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.20.5)(yaml@2.8.1)): dependencies: - '@microsoft/api-extractor': 7.51.0(@types/node@22.17.2) + '@microsoft/api-extractor': 7.51.0(@types/node@22.18.0) '@rollup/pluginutils': 5.1.4(rollup@4.46.2) '@volar/typescript': 2.4.11 '@vue/language-core': 2.2.0(typescript@5.9.2) @@ -17389,13 +17389,13 @@ snapshots: magic-string: 0.30.17 typescript: 5.9.2 optionalDependencies: - vite: 7.1.3(@types/node@22.17.2)(jiti@2.5.1)(less@4.2.0)(lightningcss@1.30.1)(sass-embedded@1.90.0)(sass@1.90.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.20.5)(yaml@2.8.1) + vite: 7.1.3(@types/node@22.18.0)(jiti@2.5.1)(less@4.2.0)(lightningcss@1.30.1)(sass-embedded@1.90.0)(sass@1.90.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.20.5)(yaml@2.8.1) transitivePeerDependencies: - '@types/node' - rollup - supports-color - vite-plugin-html@3.2.2(vite@7.1.3(@types/node@22.17.2)(jiti@2.5.1)(less@4.2.0)(lightningcss@1.30.1)(sass-embedded@1.90.0)(sass@1.90.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.20.5)(yaml@2.8.1)): + vite-plugin-html@3.2.2(vite@7.1.3(@types/node@22.18.0)(jiti@2.5.1)(less@4.2.0)(lightningcss@1.30.1)(sass-embedded@1.90.0)(sass@1.90.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.20.5)(yaml@2.8.1)): dependencies: '@rollup/pluginutils': 4.2.1 colorette: 2.0.20 @@ -17409,39 +17409,39 @@ snapshots: html-minifier-terser: 6.1.0 node-html-parser: 5.4.2 pathe: 0.2.0 - vite: 7.1.3(@types/node@22.17.2)(jiti@2.5.1)(less@4.2.0)(lightningcss@1.30.1)(sass-embedded@1.90.0)(sass@1.90.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.20.5)(yaml@2.8.1) + vite: 7.1.3(@types/node@22.18.0)(jiti@2.5.1)(less@4.2.0)(lightningcss@1.30.1)(sass-embedded@1.90.0)(sass@1.90.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.20.5)(yaml@2.8.1) - vite-plugin-sass-dts@1.3.31(postcss@8.5.6)(prettier@3.6.2)(sass-embedded@1.90.0)(vite@7.1.3(@types/node@22.17.2)(jiti@2.5.1)(less@4.2.0)(lightningcss@1.30.1)(sass-embedded@1.90.0)(sass@1.90.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.20.5)(yaml@2.8.1)): + vite-plugin-sass-dts@1.3.31(postcss@8.5.6)(prettier@3.6.2)(sass-embedded@1.90.0)(vite@7.1.3(@types/node@22.18.0)(jiti@2.5.1)(less@4.2.0)(lightningcss@1.30.1)(sass-embedded@1.90.0)(sass@1.90.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.20.5)(yaml@2.8.1)): dependencies: postcss: 8.5.6 postcss-js: 4.0.1(postcss@8.5.6) prettier: 3.6.2 sass-embedded: 1.90.0 - vite: 7.1.3(@types/node@22.17.2)(jiti@2.5.1)(less@4.2.0)(lightningcss@1.30.1)(sass-embedded@1.90.0)(sass@1.90.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.20.5)(yaml@2.8.1) + vite: 7.1.3(@types/node@22.18.0)(jiti@2.5.1)(less@4.2.0)(lightningcss@1.30.1)(sass-embedded@1.90.0)(sass@1.90.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.20.5)(yaml@2.8.1) - vite-plugin-svgr@4.5.0(rollup@4.46.2)(typescript@5.9.2)(vite@7.1.3(@types/node@22.17.2)(jiti@2.5.1)(less@4.2.0)(lightningcss@1.30.1)(sass-embedded@1.90.0)(sass@1.90.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.20.5)(yaml@2.8.1)): + vite-plugin-svgr@4.5.0(rollup@4.46.2)(typescript@5.9.2)(vite@7.1.3(@types/node@22.18.0)(jiti@2.5.1)(less@4.2.0)(lightningcss@1.30.1)(sass-embedded@1.90.0)(sass@1.90.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.20.5)(yaml@2.8.1)): dependencies: '@rollup/pluginutils': 5.2.0(rollup@4.46.2) '@svgr/core': 8.1.0(typescript@5.9.2) '@svgr/plugin-jsx': 8.1.0(@svgr/core@8.1.0(typescript@5.9.2)) - vite: 7.1.3(@types/node@22.17.2)(jiti@2.5.1)(less@4.2.0)(lightningcss@1.30.1)(sass-embedded@1.90.0)(sass@1.90.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.20.5)(yaml@2.8.1) + vite: 7.1.3(@types/node@22.18.0)(jiti@2.5.1)(less@4.2.0)(lightningcss@1.30.1)(sass-embedded@1.90.0)(sass@1.90.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.20.5)(yaml@2.8.1) transitivePeerDependencies: - rollup - supports-color - typescript - vite-tsconfig-paths@5.1.4(typescript@5.9.2)(vite@7.1.3(@types/node@22.17.2)(jiti@2.5.1)(less@4.2.0)(lightningcss@1.30.1)(sass-embedded@1.90.0)(sass@1.90.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.20.5)(yaml@2.8.1)): + vite-tsconfig-paths@5.1.4(typescript@5.9.2)(vite@7.1.3(@types/node@22.18.0)(jiti@2.5.1)(less@4.2.0)(lightningcss@1.30.1)(sass-embedded@1.90.0)(sass@1.90.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.20.5)(yaml@2.8.1)): dependencies: debug: 4.3.7 globrex: 0.1.2 tsconfck: 3.0.3(typescript@5.9.2) optionalDependencies: - vite: 7.1.3(@types/node@22.17.2)(jiti@2.5.1)(less@4.2.0)(lightningcss@1.30.1)(sass-embedded@1.90.0)(sass@1.90.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.20.5)(yaml@2.8.1) + vite: 7.1.3(@types/node@22.18.0)(jiti@2.5.1)(less@4.2.0)(lightningcss@1.30.1)(sass-embedded@1.90.0)(sass@1.90.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.20.5)(yaml@2.8.1) transitivePeerDependencies: - supports-color - typescript - vite@7.1.3(@types/node@22.17.2)(jiti@2.5.1)(less@4.2.0)(lightningcss@1.30.1)(sass-embedded@1.90.0)(sass@1.90.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.20.5)(yaml@2.8.1): + vite@7.1.3(@types/node@22.18.0)(jiti@2.5.1)(less@4.2.0)(lightningcss@1.30.1)(sass-embedded@1.90.0)(sass@1.90.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.20.5)(yaml@2.8.1): dependencies: esbuild: 0.25.0 fdir: 6.5.0(picomatch@4.0.3) @@ -17450,7 +17450,7 @@ snapshots: rollup: 4.46.2 tinyglobby: 0.2.14 optionalDependencies: - '@types/node': 22.17.2 + '@types/node': 22.18.0 fsevents: 2.3.3 jiti: 2.5.1 less: 4.2.0 diff --git a/lede/target/linux/qualcommax/patches-6.12/0170-clk-qcom-gcc-ipq8074-fix-broken-freq-table-for-nss_port6_tx_clk_src.patch b/lede/target/linux/qualcommax/patches-6.12/0170-clk-qcom-gcc-ipq8074-fix-broken-freq-table-for-nss_port6_tx_clk_src.patch deleted file mode 100644 index 1f4c0904e6..0000000000 --- a/lede/target/linux/qualcommax/patches-6.12/0170-clk-qcom-gcc-ipq8074-fix-broken-freq-table-for-nss_port6_tx_clk_src.patch +++ /dev/null @@ -1,143 +0,0 @@ -From patchwork Thu May 22 20:25:55 2025 -Content-Type: text/plain; charset="utf-8" -MIME-Version: 1.0 -Content-Transfer-Encoding: 7bit -X-Patchwork-Submitter: Christian Marangi -X-Patchwork-Id: 14097271 -Received: from mail-wr1-f50.google.com (mail-wr1-f50.google.com - [209.85.221.50]) - (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) - (No client certificate requested) - by smtp.subspace.kernel.org (Postfix) with ESMTPS id BE1BF2B9A9; - Thu, 22 May 2025 20:26:28 +0000 (UTC) -Authentication-Results: smtp.subspace.kernel.org; - arc=none smtp.client-ip=209.85.221.50 -ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; - t=1747945590; cv=none; - b=SJyQKJEIm31L7OgiCxpH5eSDCvy3pwWfc5Tm5ylnbA62aIfHLr9TAaJ3qgIEhatEmg1tASNg/kuDmfqVkvTcCgfN89i5AC/I6gvQRguLThtK4NHh5SuCKdUd49BWXk1X+Ma5cEIKEKY+Me0pO1q2XeLvwuWTFN3RHUkygO2Cias= -ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; - s=arc-20240116; t=1747945590; c=relaxed/simple; - bh=RcOtjmSun1IwEL5Wb3PSql0fo4oAT/kf0BO04Ne0FWo=; - h=From:To:Cc:Subject:Date:Message-ID:MIME-Version; - b=lOheyUFV/bVQ1HRRivMF7JOVhTelzBEnWB7rGJmANrNWl2gcgEf+xEHi3nWPULWal/ppIdrVL9LjC0v7KEKoHe6XJ/WmqmhJgrNKiUSUJQbnmUZgaser6iyO9XJUCjR3TlgdSnZ2A8dsLXVbiK2UPLe+GUdb0V5O5ZChOm6rVAM= -ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; - dmarc=pass (p=none dis=none) header.from=gmail.com; - spf=pass smtp.mailfrom=gmail.com; - dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com - header.b=U3Ibckvp; arc=none smtp.client-ip=209.85.221.50 -Authentication-Results: smtp.subspace.kernel.org; - dmarc=pass (p=none dis=none) header.from=gmail.com -Authentication-Results: smtp.subspace.kernel.org; - spf=pass smtp.mailfrom=gmail.com -Authentication-Results: smtp.subspace.kernel.org; - dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com - header.b="U3Ibckvp" -Received: by mail-wr1-f50.google.com with SMTP id - ffacd0b85a97d-3a367ec7840so3966539f8f.2; - Thu, 22 May 2025 13:26:28 -0700 (PDT) -DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; - d=gmail.com; s=20230601; t=1747945587; x=1748550387; - darn=vger.kernel.org; - h=content-transfer-encoding:mime-version:message-id:date:subject:cc - :to:from:from:to:cc:subject:date:message-id:reply-to; - bh=xgvKtt5DybnIrKc6mWPJ7EZTeS6I4nUMUzu2bm2zMtQ=; - b=U3IbckvpuScfyKSdVLd02B1axIbs/9630TXWceGPzDNFU/YHi8PIALyMXNVBZ5/DGb - fSlmQmam2bC0j5pk1bg2xqWs7I9sCteTah3Ygxo9X1vXhD9PnqbhJfgvQJp3KrNoLwC4 - JdRzdVi/vjJIEEuMlveXpcanmLLn+BjOEYYMs8x3EZ3yLYQr7KkHtJ+V6HTWPsE47qA8 - mOdp/ysLZ2jLPihravIjN6BlUSGMz5EkdYudIljy3wYNiga385aw4aQsa79gd/J7RxjD - o9GAIcFAtoRp4Co7G632DYC+zoYQw1G10ZfIzT7kOCPRZxoevlaGeRVxsgh9bCnsQ9LT - 3aog== -X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; - d=1e100.net; s=20230601; t=1747945587; x=1748550387; - h=content-transfer-encoding:mime-version:message-id:date:subject:cc - :to:from:x-gm-message-state:from:to:cc:subject:date:message-id - :reply-to; - bh=xgvKtt5DybnIrKc6mWPJ7EZTeS6I4nUMUzu2bm2zMtQ=; - b=Fdp0DTSGLe7u0fvh/rW+co2BBsFkL9sH5Y4cVO/uEyWrOuDZY4wEIY3k7tT9z/qusu - qsBqrFaiXgv99S3sOK6e4buTvnX+yvbk5hBq7kKb+WUSdLnvo7am0NzjlVz3/8ksSosU - g/6WFJbxG/UEf7eQS5ze9cOtfag1nj3qpj/wf1od2RAE8KLaGt1yT2RKXrxvWswjVtWc - TVKIc5mEANR4fTG4AwfOVG6QBU1JfLpTBS41O9THoy/vk3BI9id6by4w3zsD8BSc4Z6W - njvleK+s7I7draMy3YYcYM3etzGD2P5AiJj0NxoyEZ8hCSswjCDIcfQniPRhfblicRBT - Bi+Q== -X-Forwarded-Encrypted: i=1; - AJvYcCU//xD5uHyFhB4sHqPQHkUS/SeqLIOqpGrEMtx0zyh2/T2x39VopI/PnTpe2ESaMCDbmRl8MurqOBOJ@vger.kernel.org, - AJvYcCWlko+5ICQgXGZZ6qZxD3WWDXE1EmkOd7Tw+6qOZDni1suR0Um5tG1VcHHtIJIp034hXQ7Tj5WK3veOVQgD@vger.kernel.org, - AJvYcCXnJcB9/SJexBqJAU7vPtjnJ2eKMHLPx+eHgLCSNvPKpkH7r5TU+eAOzfjqSPvmxKNRZXM/L/CxkyxDzp+n@vger.kernel.org -X-Gm-Message-State: AOJu0Ywgx5kKVjnck8zcNF5jiJmr1aap8FGVVIFxqqFyLqAdMsRpJ5RM - YGVflzDLCHubLU2D5IwFoaoiTDyGi/eHphmIPndSUeFP8moWY/T6O3Pd -X-Gm-Gg: ASbGncunHQP8921RyvQsddVmY7ua8h+QTVvMvQHB4kaRgHeeD58OPdZJCqc3cNVNIP1 - X/LZAzqXAmd7j1ls65igxC/kCtPSyDnS4zh1hu6AFlttxuOfgdWgiXbFyqdozanfhYDRhD11FD6 - aAseq7i2gRb72LDgkGGmwREbBnHgtugTuSboaAJnCaoVVhU53SdpG0XfrAJBxVVHKFRv+WLtktr - o0itJiaG5BklL3SQ7I36EqdExH7yo3mPByvwYI5zarwBqgENcIqxoMbum72iweT8YSB7p6h0iMo - /dPKuoYps8Nt9k6kkL6oF2SkVLjTvYDQ4kna9JVBqwP0UdjBgTo+FMZBNy6UNnEnJC+4gKrLnE+ - I1asottOJwbm+C7Ke4/O9 -X-Google-Smtp-Source: - AGHT+IE/fBAh0wuvEHRV8Pp3re+RzxCwE85Zo4u5IxHZMcKKHBmdPi+/PvNmPZSoI/27B1urc+XZXg== -X-Received: by 2002:a05:6000:2281:b0:3a3:7be3:cba9 with SMTP id - ffacd0b85a97d-3a37be3cebdmr9761395f8f.18.1747945586791; - Thu, 22 May 2025 13:26:26 -0700 (PDT) -Received: from localhost.localdomain (93-34-88-225.ip49.fastwebnet.it. - [93.34.88.225]) - by smtp.googlemail.com with ESMTPSA id - ffacd0b85a97d-3a35ca5a03fsm23883073f8f.22.2025.05.22.13.26.25 - (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); - Thu, 22 May 2025 13:26:25 -0700 (PDT) -From: Christian Marangi -To: Bjorn Andersson , - Michael Turquette , - Stephen Boyd , - Christian Marangi , - linux-arm-msm@vger.kernel.org, - linux-clk@vger.kernel.org, - linux-kernel@vger.kernel.org -Cc: stable@vger.kernel.org -Subject: [PATCH] clk: qcom: gcc-ipq8074: fix broken freq table for - nss_port6_tx_clk_src -Date: Thu, 22 May 2025 22:25:55 +0200 -Message-ID: <20250522202600.4028-1-ansuelsmth@gmail.com> -X-Mailer: git-send-email 2.48.1 -Precedence: bulk -X-Mailing-List: linux-arm-msm@vger.kernel.org -List-Id: -List-Subscribe: -List-Unsubscribe: -MIME-Version: 1.0 - -With the conversion done by commit e88f03230dc0 ("clk: qcom: gcc-ipq8074: -rework nss_port5/6 clock to multiple conf") a Copy-Paste error was made -for the nss_port6_tx_clk_src frequency table. - -This was caused by the wrong setting of the parent in -ftbl_nss_port6_tx_clk_src that was wrongly set to P_UNIPHY1_RX instead -of P_UNIPHY2_TX. - -This cause the UNIPHY2 port to malfunction when it needs to be scaled to -higher clock. The malfunction was observed with the example scenario -with an Aquantia 10G PHY connected and a speed higher than 1G (example -2.5G) - -Fix the broken frequency table to restore original functionality. - -Cc: stable@vger.kernel.org -Fixes: e88f03230dc0 ("clk: qcom: gcc-ipq8074: rework nss_port5/6 clock to multiple conf") -Signed-off-by: Christian Marangi ---- - drivers/clk/qcom/gcc-ipq8074.c | 6 +++--- - 1 file changed, 3 insertions(+), 3 deletions(-) - ---- a/drivers/clk/qcom/gcc-ipq8074.c -+++ b/drivers/clk/qcom/gcc-ipq8074.c -@@ -1895,10 +1895,10 @@ static const struct freq_conf ftbl_nss_p - static const struct freq_multi_tbl ftbl_nss_port6_tx_clk_src[] = { - FMS(19200000, P_XO, 1, 0, 0), - FM(25000000, ftbl_nss_port6_tx_clk_src_25), -- FMS(78125000, P_UNIPHY1_RX, 4, 0, 0), -+ FMS(78125000, P_UNIPHY2_TX, 4, 0, 0), - FM(125000000, ftbl_nss_port6_tx_clk_src_125), -- FMS(156250000, P_UNIPHY1_RX, 2, 0, 0), -- FMS(312500000, P_UNIPHY1_RX, 1, 0, 0), -+ FMS(156250000, P_UNIPHY2_TX, 2, 0, 0), -+ FMS(312500000, P_UNIPHY2_TX, 1, 0, 0), - { } - }; - diff --git a/lede/target/linux/qualcommax/patches-6.12/0600-1-qca-nss-ecm-support-CORE.patch b/lede/target/linux/qualcommax/patches-6.12/0600-1-qca-nss-ecm-support-CORE.patch index 38358bb241..46889c36c8 100644 --- a/lede/target/linux/qualcommax/patches-6.12/0600-1-qca-nss-ecm-support-CORE.patch +++ b/lede/target/linux/qualcommax/patches-6.12/0600-1-qca-nss-ecm-support-CORE.patch @@ -76,9 +76,10 @@ + +} /* QCA NSS ECM support */ + - static inline struct net_device * - __vlan_find_dev_deep_rcu(struct net_device *real_dev, - __be16 vlan_proto, u16 vlan_id) + static inline bool is_vlan_dev(const struct net_device *dev) + { + return false; + } --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -2907,6 +2907,10 @@ enum netdev_cmd { diff --git a/mihomo/component/dialer/bind_darwin.go b/mihomo/component/dialer/bind_darwin.go index 159d3d270a..fdea24bfdc 100644 --- a/mihomo/component/dialer/bind_darwin.go +++ b/mihomo/component/dialer/bind_darwin.go @@ -21,10 +21,10 @@ func bindControl(ifaceIdx int) controlFn { var innerErr error err = c.Control(func(fd uintptr) { switch network { - case "tcp6", "udp6", "ip6": - innerErr = unix.SetsockoptInt(int(fd), unix.IPPROTO_IPV6, unix.IPV6_BOUND_IF, ifaceIdx) - default: + case "tcp4", "udp4": innerErr = unix.SetsockoptInt(int(fd), unix.IPPROTO_IP, unix.IP_BOUND_IF, ifaceIdx) + case "tcp6", "udp6": + innerErr = unix.SetsockoptInt(int(fd), unix.IPPROTO_IPV6, unix.IPV6_BOUND_IF, ifaceIdx) } }) diff --git a/mihomo/component/dialer/dialer.go b/mihomo/component/dialer/dialer.go index d490dca3de..4402f77459 100644 --- a/mihomo/component/dialer/dialer.go +++ b/mihomo/component/dialer/dialer.go @@ -9,7 +9,6 @@ import ( "os" "strings" "sync" - "syscall" "time" "github.com/metacubex/mihomo/component/keepalive" @@ -178,34 +177,6 @@ func dialContext(ctx context.Context, network string, destination netip.Addr, po return dialer.DialContext(ctx, network, address) } -func ICMPControl(destination netip.Addr) func(network, address string, conn syscall.RawConn) error { - return func(network, address string, conn syscall.RawConn) error { - if DefaultSocketHook != nil { - return DefaultSocketHook(network, address, conn) - } - dialer := &net.Dialer{} - interfaceName := DefaultInterface.Load() - if interfaceName == "" { - if finder := DefaultInterfaceFinder.Load(); finder != nil { - interfaceName = finder.FindInterfaceName(destination) - } - } - if interfaceName != "" { - if err := bindIfaceToDialer(interfaceName, dialer, network, destination); err != nil { - return err - } - } - routingMark := int(DefaultRoutingMark.Load()) - if routingMark != 0 { - bindMarkToDialer(routingMark, dialer, network, destination) - } - if dialer.ControlContext != nil { - return dialer.ControlContext(context.TODO(), network, address, conn) - } - return nil - } -} - func serialSingleStackDialContext(ctx context.Context, network string, ips []netip.Addr, port string, opt option) (net.Conn, error) { return serialDialContext(ctx, network, ips, port, opt) } diff --git a/mihomo/go.mod b/mihomo/go.mod index 0f5bbcb7b8..9d26656e33 100644 --- a/mihomo/go.mod +++ b/mihomo/go.mod @@ -24,13 +24,13 @@ require ( github.com/metacubex/quic-go v0.54.1-0.20250730114134-a1ae705fe295 github.com/metacubex/randv2 v0.2.0 github.com/metacubex/restls-client-go v0.1.7 - github.com/metacubex/sing v0.5.6-0.20250824161024-672b3e5150b5 + github.com/metacubex/sing v0.5.5 github.com/metacubex/sing-mux v0.3.3-0.20250813083925-d7c9aeaeeaac github.com/metacubex/sing-quic v0.0.0-20250718154553-1b193bec4cbb github.com/metacubex/sing-shadowsocks v0.2.12 github.com/metacubex/sing-shadowsocks2 v0.2.6 github.com/metacubex/sing-shadowtls v0.0.0-20250503063515-5d9f966d17a2 - github.com/metacubex/sing-tun v0.4.8-0.20250824174501-f44ca001b82b + github.com/metacubex/sing-tun v0.4.7 github.com/metacubex/sing-vmess v0.2.4-0.20250822020810-4856053566f0 github.com/metacubex/sing-wireguard v0.0.0-20250503063753-2dc62acc626f github.com/metacubex/smux v0.0.0-20250503055512-501391591dee @@ -89,7 +89,7 @@ require ( github.com/mailru/easyjson v0.7.7 // indirect github.com/mdlayher/socket v0.4.1 // indirect github.com/metacubex/ascon v0.1.0 // indirect - github.com/metacubex/gvisor v0.0.0-20250823135502-e52fca163229 // indirect + github.com/metacubex/gvisor v0.0.0-20250324165734-5857f47bd43b // indirect github.com/metacubex/nftables v0.0.0-20250503052935-30a69ab87793 // indirect github.com/oasisprotocol/deoxysii v0.0.0-20220228165953-2091330c22b7 // indirect github.com/onsi/ginkgo/v2 v2.9.5 // indirect diff --git a/mihomo/go.sum b/mihomo/go.sum index b51dcd6284..47b12b38d6 100644 --- a/mihomo/go.sum +++ b/mihomo/go.sum @@ -106,8 +106,8 @@ github.com/metacubex/fswatch v0.1.1 h1:jqU7C/v+g0qc2RUFgmAOPoVvfl2BXXUXEumn6oQux github.com/metacubex/fswatch v0.1.1/go.mod h1:czrTT7Zlbz7vWft8RQu9Qqh+JoX+Nnb+UabuyN1YsgI= github.com/metacubex/gopacket v1.1.20-0.20230608035415-7e2f98a3e759 h1:cjd4biTvOzK9ubNCCkQ+ldc4YSH/rILn53l/xGBFHHI= github.com/metacubex/gopacket v1.1.20-0.20230608035415-7e2f98a3e759/go.mod h1:UHOv2xu+RIgLwpXca7TLrXleEd4oR3sPatW6IF8wU88= -github.com/metacubex/gvisor v0.0.0-20250823135502-e52fca163229 h1:sXVGoj8TdkMYp/ZiZgZJ5lgNww2DJdA/Lywu63+Z2/w= -github.com/metacubex/gvisor v0.0.0-20250823135502-e52fca163229/go.mod h1:8LpS0IJW1VmWzUm3ylb0e2SK5QDm5lO/2qwWLZgRpBU= +github.com/metacubex/gvisor v0.0.0-20250324165734-5857f47bd43b h1:RUh4OdVPz/jDrM9MQ2ySuqu2aeBqcA8rtfWUYLZ8RtI= +github.com/metacubex/gvisor v0.0.0-20250324165734-5857f47bd43b/go.mod h1:8LpS0IJW1VmWzUm3ylb0e2SK5QDm5lO/2qwWLZgRpBU= github.com/metacubex/nftables v0.0.0-20250503052935-30a69ab87793 h1:1Qpuy+sU3DmyX9HwI+CrBT/oLNJngvBorR2RbajJcqo= github.com/metacubex/nftables v0.0.0-20250503052935-30a69ab87793/go.mod h1:RjRNb4G52yAgfR+Oe/kp9G4PJJ97Fnj89eY1BFO3YyA= github.com/metacubex/quic-go v0.54.1-0.20250730114134-a1ae705fe295 h1:8JVlYuE8uSJAvmyCd4TjvDxs57xjb0WxEoaWafK5+qs= @@ -117,8 +117,8 @@ github.com/metacubex/randv2 v0.2.0/go.mod h1:kFi2SzrQ5WuneuoLLCMkABtiBu6VRrMrWFq github.com/metacubex/restls-client-go v0.1.7 h1:eCwiXCTQb5WJu9IlgYvDBA1OgrINv58dEe7hcN5H15k= github.com/metacubex/restls-client-go v0.1.7/go.mod h1:BN/U52vPw7j8VTSh2vleD/MnmVKCov84mS5VcjVHH4g= github.com/metacubex/sing v0.5.2/go.mod h1:ypf0mjwlZm0sKdQSY+yQvmsbWa0hNPtkeqyRMGgoN+w= -github.com/metacubex/sing v0.5.6-0.20250824161024-672b3e5150b5 h1:SdDqZsb2RFGe8gDuCAvRgRARo0vdKrq8cYXcKU/3vkk= -github.com/metacubex/sing v0.5.6-0.20250824161024-672b3e5150b5/go.mod h1:ypf0mjwlZm0sKdQSY+yQvmsbWa0hNPtkeqyRMGgoN+w= +github.com/metacubex/sing v0.5.5 h1:m5U8iHvRAUxlme3FZlE/LPIGHjU8oMCUzXWGbQQAC1E= +github.com/metacubex/sing v0.5.5/go.mod h1:ypf0mjwlZm0sKdQSY+yQvmsbWa0hNPtkeqyRMGgoN+w= github.com/metacubex/sing-mux v0.3.3-0.20250813083925-d7c9aeaeeaac h1:wDH/Jh/yqWbzPktqJP+Y1cUG8hchcrzKzUxJiSpnaQs= github.com/metacubex/sing-mux v0.3.3-0.20250813083925-d7c9aeaeeaac/go.mod h1:3rt1soewn0O6j89GCLmwAQFsq257u0jf2zQSPhTL3Bw= github.com/metacubex/sing-quic v0.0.0-20250718154553-1b193bec4cbb h1:U/m3h8lp/j7i8zFgfvScLdZa1/Y8dd74oO7iZaQq80s= @@ -129,8 +129,8 @@ github.com/metacubex/sing-shadowsocks2 v0.2.6 h1:ZR1kYT0f0Vi64iQSS09OdhFfppiNkh7 github.com/metacubex/sing-shadowsocks2 v0.2.6/go.mod h1:vOEbfKC60txi0ca+yUlqEwOGc3Obl6cnSgx9Gf45KjE= github.com/metacubex/sing-shadowtls v0.0.0-20250503063515-5d9f966d17a2 h1:gXU+MYPm7Wme3/OAY2FFzVq9d9GxPHOqu5AQfg/ddhI= github.com/metacubex/sing-shadowtls v0.0.0-20250503063515-5d9f966d17a2/go.mod h1:mbfboaXauKJNIHJYxQRa+NJs4JU9NZfkA+I33dS2+9E= -github.com/metacubex/sing-tun v0.4.8-0.20250824174501-f44ca001b82b h1:QQm3Sq6HDkUpcUSnP8UfpGXtkwZVXINwAkHC78KpLzo= -github.com/metacubex/sing-tun v0.4.8-0.20250824174501-f44ca001b82b/go.mod h1:lY1AbDOLhkDNX/8cexsG82Fetg/O6vMA0eUW5SBMKhM= +github.com/metacubex/sing-tun v0.4.7 h1:ZDY/W+1c7PeWWKeKRyUo18fySF/TWjB0i5ui81Ar778= +github.com/metacubex/sing-tun v0.4.7/go.mod h1:xHecZRwBnKWe6zG9amAK9cXf91lF6blgjBqm+VvOrmU= github.com/metacubex/sing-vmess v0.2.4-0.20250822020810-4856053566f0 h1:WZepq4TOZa6WewB8tGAZrrL+bL2R2ivoBzuEgAeolWc= github.com/metacubex/sing-vmess v0.2.4-0.20250822020810-4856053566f0/go.mod h1:21R5R1u90uUvBQF0owoooEu96/SAYYD56nDrwm6nFaM= github.com/metacubex/sing-wireguard v0.0.0-20250503063753-2dc62acc626f h1:Sr/DYKYofKHKc4GF3qkRGNuj6XA6c0eqPgEDN+VAsYU= diff --git a/mihomo/listener/sing_tun/prepare.go b/mihomo/listener/sing_tun/prepare.go deleted file mode 100644 index 0ee3eb3729..0000000000 --- a/mihomo/listener/sing_tun/prepare.go +++ /dev/null @@ -1,34 +0,0 @@ -package sing_tun - -import ( - "context" - "time" - - "github.com/metacubex/mihomo/component/dialer" - "github.com/metacubex/mihomo/component/resolver" - "github.com/metacubex/mihomo/log" - - tun "github.com/metacubex/sing-tun" - "github.com/metacubex/sing-tun/ping" - M "github.com/metacubex/sing/common/metadata" - N "github.com/metacubex/sing/common/network" -) - -func (h *ListenerHandler) PrepareConnection(network string, source M.Socksaddr, destination M.Socksaddr, routeContext tun.DirectRouteContext, timeout time.Duration) (tun.DirectRouteDestination, error) { - switch network { - case N.NetworkICMPv4, N.NetworkICMPv6: // our fork only send those type to PrepareConnection now - if resolver.IsFakeIP(destination.Addr) { // skip fakeip - log.Infoln("[ICMP] %s %s --> %s using fake ping echo", network, source, destination) - return nil, nil - } - log.Infoln("[ICMP] %s %s --> %s using DIRECT", network, source, destination) - directRouteDestination, err := ping.ConnectDestination(context.TODO(), log.SingLogger, dialer.ICMPControl(destination.Addr), destination.Addr, routeContext, timeout) - if err != nil { - log.Warnln("[ICMP] failed to connect to %s", destination) - return nil, err - } - log.Debugln("[ICMP] success connect to %s", destination) - return directRouteDestination, nil - } - return nil, nil -} diff --git a/mihomo/listener/sing_tun/server.go b/mihomo/listener/sing_tun/server.go index 6bee7ffc40..416cf30ced 100644 --- a/mihomo/listener/sing_tun/server.go +++ b/mihomo/listener/sing_tun/server.go @@ -11,7 +11,6 @@ import ( "strconv" "strings" "sync" - "time" "github.com/metacubex/mihomo/adapter/inbound" "github.com/metacubex/mihomo/component/dialer" @@ -175,11 +174,11 @@ func New(options LC.Tun, tunnel C.Tunnel, additions ...inbound.Addition) (l *Lis if tunMTU == 0 { tunMTU = 9000 } - var udpTimeout time.Duration + var udpTimeout int64 if options.UDPTimeout != 0 { - udpTimeout = time.Second * time.Duration(options.UDPTimeout) + udpTimeout = options.UDPTimeout } else { - udpTimeout = sing.UDPTimeout + udpTimeout = int64(sing.UDPTimeout.Seconds()) } tableIndex := options.IPRoute2TableIndex if tableIndex == 0 { diff --git a/mihomo/transport/vless/encryption/client.go b/mihomo/transport/vless/encryption/client.go index b504e153f4..465f16260f 100644 --- a/mihomo/transport/vless/encryption/client.go +++ b/mihomo/transport/vless/encryption/client.go @@ -160,7 +160,9 @@ func (i *ClientInstance) Handshake(conn net.Conn) (*CommonConn, error) { if err != nil { return nil, err } - pfsKey := append(mlkem768Key, x25519Key...) + pfsKey := make([]byte, 32+32) // no more capacity + copy(pfsKey, mlkem768Key) + copy(pfsKey[32:], x25519Key) c.UnitedKey = append(pfsKey, nfsKey...) c.GCM = NewGCM(pfsPublicKey, c.UnitedKey) c.PeerGCM = NewGCM(encryptedPfsPublicKey[:1088+32], c.UnitedKey) diff --git a/mihomo/transport/vless/encryption/common.go b/mihomo/transport/vless/encryption/common.go index 8e78d486eb..1b2aa18201 100644 --- a/mihomo/transport/vless/encryption/common.go +++ b/mihomo/transport/vless/encryption/common.go @@ -89,7 +89,7 @@ func (c *CommonConn) Read(b []byte) (int, error) { if err != nil { if c.Client != nil && strings.HasPrefix(err.Error(), "invalid header: ") { // client's 0-RTT c.Client.RWLock.Lock() - if bytes.Equal(c.UnitedKey[:32], c.Client.PfsKey) { + if bytes.HasPrefix(c.UnitedKey, c.Client.PfsKey) { c.Client.Expire = time.Now() // expired } c.Client.RWLock.Unlock() diff --git a/mihomo/transport/vless/encryption/doc.go b/mihomo/transport/vless/encryption/doc.go index d2eb27534c..177839c64a 100644 --- a/mihomo/transport/vless/encryption/doc.go +++ b/mihomo/transport/vless/encryption/doc.go @@ -19,4 +19,5 @@ // https://github.com/XTLS/Xray-core/commit/b33555cc0a52d0af3c23d2af8fca42f8a685d9af // https://github.com/XTLS/Xray-core/commit/ad7140641c44239c9dcdc3d7215ea639b1f0841c // https://github.com/XTLS/Xray-core/commit/0199dea39988a1a1b846d0bf8598631bade40902 +// https://github.com/XTLS/Xray-core/commit/fce1195b60f48ca18a953dbd5c7d991869de9a5e package encryption diff --git a/mihomo/transport/vless/encryption/server.go b/mihomo/transport/vless/encryption/server.go index 0bb5fa60bd..36ce399ab5 100644 --- a/mihomo/transport/vless/encryption/server.go +++ b/mihomo/transport/vless/encryption/server.go @@ -19,7 +19,7 @@ import ( type ServerSession struct { Expire time.Time PfsKey []byte - Replays sync.Map + NfsKeys sync.Map } type ServerInstance struct { @@ -177,7 +177,7 @@ func (i *ServerInstance) Handshake(conn net.Conn) (*CommonConn, error) { s := i.Sessions[[16]byte(ticket)] i.RWLock.RUnlock() if s == nil { - noises := make([]byte, randBetween(100, 1000)) + noises := make([]byte, randBetween(1268, 2268)) // matches 1-RTT's server hello length for "random", though it is not important, just for example var err error for err == nil { rand.Read(noises) @@ -186,21 +186,21 @@ func (i *ServerInstance) Handshake(conn net.Conn) (*CommonConn, error) { conn.Write(noises) // make client do new handshake return nil, errors.New("expired ticket") } - if _, replay := s.Replays.LoadOrStore([32]byte(nfsKey), true); replay { // prevents bad client also + if _, loaded := s.NfsKeys.LoadOrStore([32]byte(nfsKey), true); loaded { // prevents bad client also return nil, errors.New("replay detected") } - c.UnitedKey = append(s.PfsKey, nfsKey...) // the same nfsKey links the upload & download - c.PreWrite = make([]byte, 16) // always trust yourself, not the client - rand.Read(c.PreWrite) + c.UnitedKey = append(s.PfsKey, nfsKey...) // the same nfsKey links the upload & download (prevents server -> client's another request) + c.PreWrite = make([]byte, 16) + rand.Read(c.PreWrite) // always trust yourself, not the client (also prevents being parsed as TLS thus causing false interruption for "native" and "xorpub") c.GCM = NewGCM(c.PreWrite, c.UnitedKey) - c.PeerGCM = NewGCM(encryptedTicket, c.UnitedKey) // unchangeable ctx, and different ctx length for upload / download + c.PeerGCM = NewGCM(encryptedTicket, c.UnitedKey) // unchangeable ctx (prevents server -> server), and different ctx length for upload / download (prevents client -> client) if i.XorMode == 2 { c.Conn = NewXorConn(conn, NewCTR(c.UnitedKey, c.PreWrite), NewCTR(c.UnitedKey, iv), 16, 0) // it doesn't matter if the attacker sends client's iv back to the client } return c, nil } - if length < 1184+32+16 { // client may send more public keys + if length < 1184+32+16 { // client may send more public keys in the future's version return nil, errors.New("too short length") } encryptedPfsPublicKey := make([]byte, length) @@ -224,7 +224,9 @@ func (i *ServerInstance) Handshake(conn net.Conn) (*CommonConn, error) { if err != nil { return nil, err } - pfsKey := append(mlkem768Key, x25519Key...) + pfsKey := make([]byte, 32+32) // no more capacity + copy(pfsKey, mlkem768Key) + copy(pfsKey[32:], x25519Key) pfsPublicKey := append(encapsulatedPfsKey, x25519SKey.PublicKey().Bytes()...) c.UnitedKey = append(pfsKey, nfsKey...) c.GCM = NewGCM(pfsPublicKey, c.UnitedKey) diff --git a/openwrt-passwall/luci-app-passwall/luasrc/passwall/util_xray.lua b/openwrt-passwall/luci-app-passwall/luasrc/passwall/util_xray.lua index 7152ad0afc..0ede4a92f7 100644 --- a/openwrt-passwall/luci-app-passwall/luasrc/passwall/util_xray.lua +++ b/openwrt-passwall/luci-app-passwall/luasrc/passwall/util_xray.lua @@ -779,6 +779,10 @@ function gen_config(var) table.insert(outbounds, outbound) fallback_node_tag = outbound.tag end + else + if gen_balancer(fallback_node) then + fallback_node_tag = fallback_node_id + end end end end diff --git a/openwrt-passwall2/luci-app-passwall2/Makefile b/openwrt-passwall2/luci-app-passwall2/Makefile index 7589c3973e..1a295a0647 100644 --- a/openwrt-passwall2/luci-app-passwall2/Makefile +++ b/openwrt-passwall2/luci-app-passwall2/Makefile @@ -5,7 +5,7 @@ include $(TOPDIR)/rules.mk PKG_NAME:=luci-app-passwall2 -PKG_VERSION:=25.8.22 +PKG_VERSION:=25.8.25 PKG_RELEASE:=1 PKG_CONFIG_DEPENDS:= \ diff --git a/openwrt-passwall2/luci-app-passwall2/luasrc/controller/passwall2.lua b/openwrt-passwall2/luci-app-passwall2/luasrc/controller/passwall2.lua index 5a6eba4b9d..3705051fef 100644 --- a/openwrt-passwall2/luci-app-passwall2/luasrc/controller/passwall2.lua +++ b/openwrt-passwall2/luci-app-passwall2/luasrc/controller/passwall2.lua @@ -376,6 +376,9 @@ function clear_all_nodes() end) uci:foreach(appname, "subscribe_list", function(t) uci:delete(appname, t[".name"], "md5") + uci:delete(appname, t[".name"], "chain_proxy") + uci:delete(appname, t[".name"], "preproxy_node") + uci:delete(appname, t[".name"], "to_node") end) api.uci_save(uci, appname, true, true) @@ -440,6 +443,16 @@ function delete_select_nodes() uci:delete(appname, t[".name"], "fallback_node") end end) + uci:foreach(appname, "subscribe_list", function(t) + if t["preproxy_node"] == w then + uci:delete(appname, t[".name"], "preproxy_node") + uci:delete(appname, t[".name"], "chain_proxy") + end + if t["to_node"] == w then + uci:delete(appname, t[".name"], "to_node") + uci:delete(appname, t[".name"], "chain_proxy") + end + end) if (uci:get(appname, w, "add_mode") or "0") == "2" then local add_from = uci:get(appname, w, "add_from") or "" if add_from ~= "" then @@ -531,20 +544,29 @@ function create_backup() end function restore_backup() + local result = { status = "error", message = "unknown error" } local ok, err = pcall(function() local filename = http.formvalue("filename") local chunk = http.formvalue("chunk") local chunk_index = tonumber(http.formvalue("chunk_index") or "-1") local total_chunks = tonumber(http.formvalue("total_chunks") or "-1") - if not filename or not chunk then - http_write_json({ status = "error", message = "Missing filename or chunk" }) + if not filename then + result = { status = "error", message = "Missing filename" } + return + end + if not chunk then + result = { status = "error", message = "Missing chunk data" } return end local file_path = "/tmp/" .. filename local decoded = nixio.bin.b64decode(chunk) + if not decoded then + result = { status = "error", message = "Base64 decode failed" } + return + end local fp = io.open(file_path, "a+") if not fp then - http_write_json({ status = "error", message = "Failed to open file for writing: " .. file_path }) + result = { status = "error", message = "Failed to open file: " .. file_path } return end fp:write(decoded) @@ -552,7 +574,7 @@ function restore_backup() if chunk_index + 1 == total_chunks then api.sys.call("echo '' > /tmp/log/passwall2.log") api.log(" * PassWall2 配置文件上传成功…") - local temp_dir = '/tmp/passwall_bak' + local temp_dir = '/tmp/passwall2_bak' api.sys.call("mkdir -p " .. temp_dir) if api.sys.call("tar -xzf " .. file_path .. " -C " .. temp_dir) == 0 then for _, backup_file in ipairs(backup_files) do @@ -563,21 +585,23 @@ function restore_backup() end api.log(" * PassWall2 配置还原成功…") api.log(" * 重启 PassWall2 服务中…\n") - api.sys.call('/etc/init.d/passwall2 restart > /dev/null 2>&1 &') - api.sys.call('/etc/init.d/passwall2_server restart > /dev/null 2>&1 &') + luci.sys.call('/etc/init.d/passwall2 restart > /dev/null 2>&1 &') + luci.sys.call('/etc/init.d/passwall2_server restart > /dev/null 2>&1 &') + result = { status = "success", message = "Upload completed", path = file_path } else api.log(" * PassWall2 配置文件解压失败,请重试!") + result = { status = "error", message = "Decompression failed" } end api.sys.call("rm -rf " .. temp_dir) fs.remove(file_path) - http_write_json({ status = "success", message = "Upload completed", path = file_path }) else - http_write_json({ status = "success", message = "Chunk received" }) + result = { status = "success", message = "Chunk received" } end end) if not ok then - http_write_json({ status = "error", message = tostring(err) }) + result = { status = "error", message = tostring(err) } end + http_write_json(result) end function geo_view() diff --git a/openwrt-passwall2/luci-app-passwall2/luasrc/model/cbi/passwall2/client/node_list.lua b/openwrt-passwall2/luci-app-passwall2/luasrc/model/cbi/passwall2/client/node_list.lua index c6ab4c3b55..b243f11187 100644 --- a/openwrt-passwall2/luci-app-passwall2/luasrc/model/cbi/passwall2/client/node_list.lua +++ b/openwrt-passwall2/luci-app-passwall2/luasrc/model/cbi/passwall2/client/node_list.lua @@ -84,6 +84,16 @@ function s.remove(e, t) m:del(s[".name"], "fallback_node") end end) + m.uci:foreach(appname, "subscribe_list", function(s) + if s["preproxy_node"] == t then + m:del(s[".name"], "preproxy_node") + m:del(s[".name"], "chain_proxy") + end + if s["to_node"] == t then + m:del(s[".name"], "to_node") + m:del(s[".name"], "chain_proxy") + end + end) if (m:get(t, "add_mode") or "0") == "2" then local add_from = m:get(t, "add_from") or "" if add_from ~= "" then @@ -157,6 +167,8 @@ o.cfgvalue = function(t, n) protocol = "HY2" elseif protocol == "anytls" then protocol = "AnyTLS" + elseif protocol == "ssh" then + protocol = "SSH" else protocol = protocol:gsub("^%l",string.upper) end diff --git a/openwrt-passwall2/luci-app-passwall2/luasrc/model/cbi/passwall2/client/node_subscribe_config.lua b/openwrt-passwall2/luci-app-passwall2/luasrc/model/cbi/passwall2/client/node_subscribe_config.lua index db0c137a40..df392e3b7d 100644 --- a/openwrt-passwall2/luci-app-passwall2/luasrc/model/cbi/passwall2/client/node_subscribe_config.lua +++ b/openwrt-passwall2/luci-app-passwall2/luasrc/model/cbi/passwall2/client/node_subscribe_config.lua @@ -51,6 +51,18 @@ if has_hysteria2 then local s = "hysteria2" table.insert(hysteria2_type, s) end +local nodes_table = {} +for k, e in ipairs(api.get_valid_nodes()) do + if e.node_type == "normal" then + nodes_table[#nodes_table + 1] = { + id = e[".name"], + remark = e["remark"], + type = e["type"], + add_mode = e["add_mode"], + chain_proxy = e["chain_proxy"] + } + end +end s = m:section(NamedSection, arg[1]) s.addremove = false @@ -205,4 +217,29 @@ o:value("Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, li o:value("Passwall2/OpenWrt", "PassWall2") o:value("v2rayN/9.99", "v2rayN") +o = s:option(ListValue, "chain_proxy", translate("Chain Proxy")) +o:value("", translate("Close(Not use)")) +o:value("1", translate("Preproxy Node")) +o:value("2", translate("Landing Node")) + +local descrStr = "Chained proxy works only with Xray or Sing-box nodes.
" +descrStr = descrStr .. "The chained node must be the same type as your subscription node (Xray with Xray, Sing-box with Sing-box).
" +descrStr = descrStr .. "You can only use manual or imported nodes as chained nodes." +descrStr = translate(descrStr) .. "
" .. translate("Only support a layer of proxy.") + +o = s:option(ListValue, "preproxy_node", translate("Preproxy Node")) +o:depends({ ["chain_proxy"] = "1" }) +o.description = descrStr + +o = s:option(ListValue, "to_node", translate("Landing Node")) +o:depends({ ["chain_proxy"] = "2" }) +o.description = descrStr + +for k, v in pairs(nodes_table) do + if (v.type == "Xray" or v.type == "sing-box") and (not v.chain_proxy or v.chain_proxy == "") and v.add_mode ~= "2" then + s.fields["preproxy_node"]:value(v.id, v.remark) + s.fields["to_node"]:value(v.id, v.remark) + end +end + return m diff --git a/openwrt-passwall2/luci-app-passwall2/luasrc/model/cbi/passwall2/client/type/sing-box.lua b/openwrt-passwall2/luci-app-passwall2/luasrc/model/cbi/passwall2/client/type/sing-box.lua index 13f2f7c1b5..c66028ad55 100644 --- a/openwrt-passwall2/luci-app-passwall2/luasrc/model/cbi/passwall2/client/type/sing-box.lua +++ b/openwrt-passwall2/luci-app-passwall2/luasrc/model/cbi/passwall2/client/type/sing-box.lua @@ -65,6 +65,7 @@ end if version_ge_1_12_0 then o:value("anytls", "AnyTLS") end +o:value("ssh", "SSH") o:value("_urltest", translate("URLTest")) o:value("_shunt", translate("Shunt")) o:value("_iface", translate("Custom Interface")) @@ -258,6 +259,7 @@ end o = s:option(Value, _n("username"), translate("Username")) o:depends({ [_n("protocol")] = "http" }) o:depends({ [_n("protocol")] = "socks" }) +o:depends({ [_n("protocol")] = "ssh" }) o = s:option(Value, _n("password"), translate("Password")) o.password = true @@ -268,6 +270,7 @@ o:depends({ [_n("protocol")] = "shadowsocksr" }) o:depends({ [_n("protocol")] = "trojan" }) o:depends({ [_n("protocol")] = "tuic" }) o:depends({ [_n("protocol")] = "anytls" }) +o:depends({ [_n("protocol")] = "ssh" }) o = s:option(ListValue, _n("security"), translate("Encrypt Method")) for a, t in ipairs(security_list) do o:value(t) end @@ -456,6 +459,24 @@ if singbox_tags:find("with_quic") then o:depends({ [_n("protocol")] = "hysteria2"}) end +-- [[ SSH config start ]] -- +o = s:option(Value, _n("ssh_priv_key"), translate("Private Key")) +o:depends({ [_n("protocol")] = "ssh" }) + +o = s:option(Value, _n("ssh_priv_key_pp"), translate("Private Key Passphrase")) +o.password = true +o:depends({ [_n("protocol")] = "ssh" }) + +o = s:option(DynamicList, _n("ssh_host_key"), translate("Host Key"), translate("Accept any if empty.")) +o:depends({ [_n("protocol")] = "ssh" }) + +o = s:option(DynamicList, _n("ssh_host_key_algo"), translate("Host Key Algorithms")) +o:depends({ [_n("protocol")] = "ssh" }) + +o = s:option(Value, _n("ssh_client_version"), translate("Client Version"), translate("Random version will be used if empty.")) +o:depends({ [_n("protocol")] = "ssh" }) +-- [[ SSH config end ]] -- + o = s:option(Flag, _n("tls"), translate("TLS")) o.default = 0 o:depends({ [_n("protocol")] = "vmess" }) diff --git a/openwrt-passwall2/luci-app-passwall2/luasrc/passwall2/api.lua b/openwrt-passwall2/luci-app-passwall2/luasrc/passwall2/api.lua index 58af0533f9..9b059df1f5 100644 --- a/openwrt-passwall2/luci-app-passwall2/luasrc/passwall2/api.lua +++ b/openwrt-passwall2/luci-app-passwall2/luasrc/passwall2/api.lua @@ -485,6 +485,8 @@ function get_valid_nodes() protocol = "HY2" elseif protocol == "anytls" then protocol = "AnyTLS" + elseif protocol == "ssh" then + protocol = "SSH" else protocol = protocol:gsub("^%l",string.upper) end @@ -530,6 +532,8 @@ function get_node_remarks(n) protocol = "HY2" elseif protocol == "anytls" then protocol = "AnyTLS" + elseif protocol == "ssh" then + protocol = "SSH" else protocol = protocol:gsub("^%l",string.upper) end diff --git a/openwrt-passwall2/luci-app-passwall2/luasrc/passwall2/util_sing-box.lua b/openwrt-passwall2/luci-app-passwall2/luasrc/passwall2/util_sing-box.lua index c4eee19ba4..79b83fbff9 100644 --- a/openwrt-passwall2/luci-app-passwall2/luasrc/passwall2/util_sing-box.lua +++ b/openwrt-passwall2/luci-app-passwall2/luasrc/passwall2/util_sing-box.lua @@ -439,6 +439,18 @@ function gen_outbound(flag, node, tag, proxy_table) } end + if node.protocol == "ssh" then + protocol_table = { + user = (node.username and node.username ~= "") and node.username or "root", + password = (node.password and node.password ~= "") and node.password or "", + private_key = node.ssh_priv_key, + private_key_passphrase = node.ssh_priv_key_pp, + host_key = node.ssh_host_key, + host_key_algorithms = node.ssh_host_key_algo, + client_version = node.ssh_client_version + } + end + if protocol_table then for key, value in pairs(protocol_table) do result[key] = value diff --git a/openwrt-passwall2/luci-app-passwall2/luasrc/passwall2/util_xray.lua b/openwrt-passwall2/luci-app-passwall2/luasrc/passwall2/util_xray.lua index 7fbd0b4e96..b819dc8f68 100644 --- a/openwrt-passwall2/luci-app-passwall2/luasrc/passwall2/util_xray.lua +++ b/openwrt-passwall2/luci-app-passwall2/luasrc/passwall2/util_xray.lua @@ -772,6 +772,10 @@ function gen_config(var) table.insert(outbounds, outbound) fallback_node_tag = outbound.tag end + else + if gen_balancer(fallback_node) then + fallback_node_tag = fallback_node_id + end end end end diff --git a/openwrt-passwall2/luci-app-passwall2/luasrc/view/passwall2/global/backup.htm b/openwrt-passwall2/luci-app-passwall2/luasrc/view/passwall2/global/backup.htm index 67aca2b92d..c96acda2c4 100644 --- a/openwrt-passwall2/luci-app-passwall2/luasrc/view/passwall2/global/backup.htm +++ b/openwrt-passwall2/luci-app-passwall2/luasrc/view/passwall2/global/backup.htm @@ -184,7 +184,6 @@ local api = require "luci.passwall2.api" const chunk = base64Data.substring(currentChunk * chunkSize, (currentChunk + 1) * chunkSize); const xhr = new XMLHttpRequest(); xhr.open("POST", '<%= api.url("restore_backup") %>', true); - xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded"); xhr.onreadystatechange = function () { if (xhr.readyState === 4) { if (xhr.status === 200) { @@ -203,12 +202,12 @@ local api = require "luci.passwall2.api" } } }; - xhr.send( - "filename=" + encodeURIComponent(file.name) + - "&chunk=" + encodeURIComponent(chunk) + - "&chunk_index=" + currentChunk + - "&total_chunks=" + totalChunks - ); + const formData = new FormData(); + formData.append("filename", file.name); + formData.append("chunk", chunk); + formData.append("chunk_index", currentChunk); + formData.append("total_chunks", totalChunks); + xhr.send(formData); } else { //alert("Upload completed."); document.getElementById("upload-btn").value = "<%:UL Restore%>"; diff --git a/openwrt-passwall2/luci-app-passwall2/po/zh-cn/passwall2.po b/openwrt-passwall2/luci-app-passwall2/po/zh-cn/passwall2.po index c3ac43cdce..819935b663 100644 --- a/openwrt-passwall2/luci-app-passwall2/po/zh-cn/passwall2.po +++ b/openwrt-passwall2/luci-app-passwall2/po/zh-cn/passwall2.po @@ -1645,6 +1645,15 @@ msgstr "落地节点" msgid "Only support a layer of proxy." msgstr "仅支持一层代理。" +msgid "" +"Chained proxy works only with Xray or Sing-box nodes.
" +"The chained node must be the same type as your subscription node (Xray with Xray, Sing-box with Sing-box).
" +"You can only use manual or imported nodes as chained nodes." +msgstr "" +"链式代理仅支持 Xray 与 Sing-box 节点。
" +"链式节点需与订阅节点类型一致(Xray 对应 Xray,Sing-box 对应 Sing-box)。
" +"仅支持手动添加或导入的节点用作链式节点。" + msgid "Set the default domain resolution strategy for the sing-box node." msgstr "为 sing-box 节点设置默认的域名解析策略。" @@ -1797,3 +1806,21 @@ msgstr "可以通过输入 GeoIP/Geosite,提取它们所包含的域名/IP。" msgid "Use the GeoIP/Geosite query function to verify if the entered Geo rules are correct." msgstr "利用 GeoIP/Geosite 查询功能,可以验证输入的 Geo 规则是否正确。" + +msgid "Private Key Passphrase" +msgstr "私钥指纹" + +msgid "Host Key" +msgstr "主机密钥" + +msgid "Accept any if empty." +msgstr "留空则不校验。" + +msgid "Host Key Algorithms" +msgstr "主机密钥算法" + +msgid "Client Version" +msgstr "客户端版本" + +msgid "Random version will be used if empty." +msgstr "如留空,则使用随机版本。" diff --git a/openwrt-passwall2/luci-app-passwall2/root/usr/share/passwall2/subscribe.lua b/openwrt-passwall2/luci-app-passwall2/root/usr/share/passwall2/subscribe.lua index 2d37277d79..b794d7e09e 100755 --- a/openwrt-passwall2/luci-app-passwall2/root/usr/share/passwall2/subscribe.lua +++ b/openwrt-passwall2/luci-app-passwall2/root/usr/share/passwall2/subscribe.lua @@ -35,6 +35,7 @@ local vless_type_default = uci:get(appname, "@global_subscribe[0]", "vless_type" local hysteria2_type_default = uci:get(appname, "@global_subscribe[0]", "hysteria2_type") or "hysteria2" local domain_strategy_default = uci:get(appname, "@global_subscribe[0]", "domain_strategy") or "" local domain_strategy_node = "" +local preproxy_node_group, to_node_group, chain_node_type = "", "", "" -- 判断是否过滤节点关键字 local filter_keyword_mode_default = uci:get(appname, "@global_subscribe[0]", "filter_keyword_mode") or "0" local filter_keyword_discard_list_default = uci:get(appname, "@global_subscribe[0]", "filter_discard_list") or {} @@ -1717,6 +1718,16 @@ local function update_node(manual) if kkk == "type" and vvv == "sing-box" then uci:set(appname, cfgid, "domain_strategy", domain_strategy_node) end + -- 订阅组链式代理 + if chain_node_type ~= "" and kkk == "type" and vvv == chain_node_type then + if preproxy_node_group ~="" then + uci:set(appname, cfgid, "chain_proxy", "1") + uci:set(appname, cfgid, "preproxy_node", preproxy_node_group) + elseif to_node_group ~= "" then + uci:set(appname, cfgid, "chain_proxy", "2") + uci:set(appname, cfgid, "to_node", to_node_group) + end + end end end end @@ -1919,6 +1930,22 @@ local execute = function() else domain_strategy_node = domain_strategy_default end + + -- 订阅组链式代理 + local function valid_chain_node(node) + if not node then return "" end + local cp = uci:get(appname, node, "chain_proxy") or "" + local am = uci:get(appname, node, "add_mode") or "0" + chain_node_type = (cp == "" and am ~= "2") and (uci:get(appname, node, "type") or "") or "" + if chain_node_type ~= "Xray" and chain_node_type ~= "sing-box" then + chain_node_type = "" + return "" + end + return node + end + preproxy_node_group = (value.chain_proxy == "1") and valid_chain_node(value.preproxy_node) or "" + to_node_group = (value.chain_proxy == "2") and valid_chain_node(value.to_node) or "" + local ua = value.user_agent local access_mode = value.access_mode local result = (not access_mode) and "自动" or (access_mode == "direct" and "直连访问" or (access_mode == "proxy" and "通过代理" or "自动")) diff --git a/sing-box/adapter/outbound.go b/sing-box/adapter/outbound.go index 67acb0618d..91fb9c6505 100644 --- a/sing-box/adapter/outbound.go +++ b/sing-box/adapter/outbound.go @@ -3,6 +3,7 @@ package adapter import ( "context" "net/netip" + "time" "github.com/sagernet/sing-box/log" "github.com/sagernet/sing-box/option" @@ -28,7 +29,7 @@ type OutboundWithPreferredRoutes interface { type DirectRouteOutbound interface { Outbound - NewDirectRouteConnection(metadata InboundContext, routeContext tun.DirectRouteContext) (tun.DirectRouteDestination, error) + NewDirectRouteConnection(metadata InboundContext, routeContext tun.DirectRouteContext, timeout time.Duration) (tun.DirectRouteDestination, error) } type OutboundRegistry interface { diff --git a/sing-box/adapter/router.go b/sing-box/adapter/router.go index eef4f50925..522a0d9d31 100644 --- a/sing-box/adapter/router.go +++ b/sing-box/adapter/router.go @@ -6,6 +6,7 @@ import ( "net" "net/http" "sync" + "time" C "github.com/sagernet/sing-box/constant" "github.com/sagernet/sing-tun" @@ -20,7 +21,7 @@ import ( type Router interface { Lifecycle ConnectionRouter - PreMatch(metadata InboundContext, context tun.DirectRouteContext) (tun.DirectRouteDestination, error) + PreMatch(metadata InboundContext, context tun.DirectRouteContext, timeout time.Duration) (tun.DirectRouteDestination, error) ConnectionRouterEx RuleSet(tag string) (RuleSet, bool) NeedWIFIState() bool diff --git a/sing-box/common/dialer/default.go b/sing-box/common/dialer/default.go index e4885ffe38..ae3908a6ee 100644 --- a/sing-box/common/dialer/default.go +++ b/sing-box/common/dialer/default.go @@ -15,7 +15,6 @@ import ( "github.com/sagernet/sing-box/experimental/libbox/platform" "github.com/sagernet/sing-box/option" "github.com/sagernet/sing/common" - "github.com/sagernet/sing/common/atomic" "github.com/sagernet/sing/common/control" E "github.com/sagernet/sing/common/exceptions" M "github.com/sagernet/sing/common/metadata" @@ -43,7 +42,7 @@ type DefaultDialer struct { networkType []C.InterfaceType fallbackNetworkType []C.InterfaceType networkFallbackDelay time.Duration - networkLastFallback atomic.TypedValue[time.Time] + networkLastFallback common.TypedValue[time.Time] } func NewDefault(ctx context.Context, options option.DialerOptions) (*DefaultDialer, error) { @@ -318,8 +317,8 @@ func (d *DefaultDialer) ListenPacket(ctx context.Context, destination M.Socksadd } } -func (d *DefaultDialer) DialerForICMPNetwork(network string) net.Dialer { - if network == N.NetworkICMPv6 { +func (d *DefaultDialer) DialerForICMPDestination(destination netip.Addr) net.Dialer { + if !destination.Is6() { return dialerFromTCPDialer(d.dialer6) } else { return dialerFromTCPDialer(d.dialer4) diff --git a/sing-box/common/dialer/tfo.go b/sing-box/common/dialer/tfo.go index cd1a2a2226..4832c12da7 100644 --- a/sing-box/common/dialer/tfo.go +++ b/sing-box/common/dialer/tfo.go @@ -8,10 +8,10 @@ import ( "net" "os" "sync" + "sync/atomic" "time" "github.com/sagernet/sing/common" - "github.com/sagernet/sing/common/atomic" "github.com/sagernet/sing/common/bufio" M "github.com/sagernet/sing/common/metadata" N "github.com/sagernet/sing/common/network" diff --git a/sing-box/dns/transport/local/local_resolved_linux.go b/sing-box/dns/transport/local/local_resolved_linux.go index 279f9c8eae..6fbd0a0e94 100644 --- a/sing-box/dns/transport/local/local_resolved_linux.go +++ b/sing-box/dns/transport/local/local_resolved_linux.go @@ -5,12 +5,12 @@ import ( "errors" "os" "sync" + "sync/atomic" "github.com/sagernet/sing-box/adapter" C "github.com/sagernet/sing-box/constant" "github.com/sagernet/sing-box/service/resolved" "github.com/sagernet/sing-tun" - "github.com/sagernet/sing/common/atomic" "github.com/sagernet/sing/common/control" E "github.com/sagernet/sing/common/exceptions" "github.com/sagernet/sing/common/logger" diff --git a/sing-box/experimental/clashapi/trafficontrol/manager.go b/sing-box/experimental/clashapi/trafficontrol/manager.go index 757ffdf917..7b69b93de1 100644 --- a/sing-box/experimental/clashapi/trafficontrol/manager.go +++ b/sing-box/experimental/clashapi/trafficontrol/manager.go @@ -3,12 +3,12 @@ package trafficontrol import ( "runtime" "sync" + "sync/atomic" "time" C "github.com/sagernet/sing-box/constant" "github.com/sagernet/sing-box/experimental/clashapi/compatible" "github.com/sagernet/sing/common" - "github.com/sagernet/sing/common/atomic" "github.com/sagernet/sing/common/json" "github.com/sagernet/sing/common/x/list" diff --git a/sing-box/experimental/clashapi/trafficontrol/tracker.go b/sing-box/experimental/clashapi/trafficontrol/tracker.go index e324be206e..48d54b2538 100644 --- a/sing-box/experimental/clashapi/trafficontrol/tracker.go +++ b/sing-box/experimental/clashapi/trafficontrol/tracker.go @@ -2,11 +2,11 @@ package trafficontrol import ( "net" + "sync/atomic" "time" "github.com/sagernet/sing-box/adapter" "github.com/sagernet/sing/common" - "github.com/sagernet/sing/common/atomic" "github.com/sagernet/sing/common/bufio" F "github.com/sagernet/sing/common/format" "github.com/sagernet/sing/common/json" diff --git a/sing-box/experimental/v2rayapi/stats.go b/sing-box/experimental/v2rayapi/stats.go index 16d441141a..c7b2b49f34 100644 --- a/sing-box/experimental/v2rayapi/stats.go +++ b/sing-box/experimental/v2rayapi/stats.go @@ -7,11 +7,11 @@ import ( "runtime" "strings" "sync" + "sync/atomic" "time" "github.com/sagernet/sing-box/adapter" "github.com/sagernet/sing-box/option" - "github.com/sagernet/sing/common/atomic" "github.com/sagernet/sing/common/bufio" E "github.com/sagernet/sing/common/exceptions" N "github.com/sagernet/sing/common/network" diff --git a/sing-box/go.mod b/sing-box/go.mod index 17beddc747..7d19c78a27 100644 --- a/sing-box/go.mod +++ b/sing-box/go.mod @@ -27,13 +27,13 @@ require ( github.com/sagernet/gomobile v0.1.8 github.com/sagernet/gvisor v0.0.0-20250822052253-5558536cf237 github.com/sagernet/quic-go v0.52.0-beta.1 - github.com/sagernet/sing v0.7.6-0.20250823024003-88f1880f43af + github.com/sagernet/sing v0.7.6-0.20250825141840-811aa328e57b github.com/sagernet/sing-mux v0.3.3 github.com/sagernet/sing-quic v0.5.0 github.com/sagernet/sing-shadowsocks v0.2.8 github.com/sagernet/sing-shadowsocks2 v0.2.1 github.com/sagernet/sing-shadowtls v0.2.1-0.20250503051639-fcd445d33c11 - github.com/sagernet/sing-tun v0.7.0-beta.1.0.20250824024715-dd18aa2b8633 + github.com/sagernet/sing-tun v0.7.0-beta.1.0.20250825142028-0386fcb66a72 github.com/sagernet/sing-vmess v0.2.7 github.com/sagernet/smux v1.5.34-mod.2 github.com/sagernet/tailscale v1.80.3-mod.6 diff --git a/sing-box/go.sum b/sing-box/go.sum index 77a502bfa3..7091db4775 100644 --- a/sing-box/go.sum +++ b/sing-box/go.sum @@ -167,8 +167,8 @@ github.com/sagernet/nftables v0.3.0-beta.4/go.mod h1:OQXAjvjNGGFxaTgVCSTRIhYB5/l github.com/sagernet/quic-go v0.52.0-beta.1 h1:hWkojLg64zjV+MJOvJU/kOeWndm3tiEfBLx5foisszs= github.com/sagernet/quic-go v0.52.0-beta.1/go.mod h1:OV+V5kEBb8kJS7k29MzDu6oj9GyMc7HA07sE1tedxz4= github.com/sagernet/sing v0.6.9/go.mod h1:ARkL0gM13/Iv5VCZmci/NuoOlePoIsW0m7BWfln/Hak= -github.com/sagernet/sing v0.7.6-0.20250823024003-88f1880f43af h1:/1H30c/+j7Q9BBPuJuX6eHyzKpbGWrr7S/4DcdtNIfw= -github.com/sagernet/sing v0.7.6-0.20250823024003-88f1880f43af/go.mod h1:ARkL0gM13/Iv5VCZmci/NuoOlePoIsW0m7BWfln/Hak= +github.com/sagernet/sing v0.7.6-0.20250825141840-811aa328e57b h1:RCfo1Q6VDAXfumNupRyqTomKzDODhASswkxVCqM8l2M= +github.com/sagernet/sing v0.7.6-0.20250825141840-811aa328e57b/go.mod h1:ARkL0gM13/Iv5VCZmci/NuoOlePoIsW0m7BWfln/Hak= github.com/sagernet/sing-mux v0.3.3 h1:YFgt9plMWzH994BMZLmyKL37PdIVaIilwP0Jg+EcLfw= github.com/sagernet/sing-mux v0.3.3/go.mod h1:pht8iFY4c9Xltj7rhVd208npkNaeCxzyXCgulDPLUDA= github.com/sagernet/sing-quic v0.5.0 h1:jNLIyVk24lFPvu8A4x+ZNEnZdI+Tg1rp7eCJ6v0Csak= @@ -179,8 +179,8 @@ github.com/sagernet/sing-shadowsocks2 v0.2.1 h1:dWV9OXCeFPuYGHb6IRqlSptVnSzOelnq 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.0-beta.1.0.20250824024715-dd18aa2b8633 h1:cqm3Gd253bpnQV5qQvvrFEcO0dzUrfsiOQRTtSFM8cs= -github.com/sagernet/sing-tun v0.7.0-beta.1.0.20250824024715-dd18aa2b8633/go.mod h1:z1lkiAE5ex5gHBzh5+G9TFsyM9grOaSsRx33mVfWfVI= +github.com/sagernet/sing-tun v0.7.0-beta.1.0.20250825142028-0386fcb66a72 h1:8UFMs1xVFIq+z+HVwe4NUjxqFfhbmomorH08SS1JjqE= +github.com/sagernet/sing-tun v0.7.0-beta.1.0.20250825142028-0386fcb66a72/go.mod h1:1fyZW3WhK6rg0REkeJ2LIuK/v+Q7X/gQU/FyQMza7LM= 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/smux v1.5.34-mod.2 h1:gkmBjIjlJ2zQKpLigOkFur5kBKdV6bNRoFu2WkltRQ4= diff --git a/sing-box/protocol/direct/outbound.go b/sing-box/protocol/direct/outbound.go index 30028a1421..cd93705355 100644 --- a/sing-box/protocol/direct/outbound.go +++ b/sing-box/protocol/direct/outbound.go @@ -62,7 +62,7 @@ func NewOutbound(ctx context.Context, router adapter.Router, logger log.ContextL return nil, err } outbound := &Outbound{ - Adapter: outbound.NewAdapterWithDialerOptions(C.TypeDirect, tag, []string{N.NetworkTCP, N.NetworkUDP, N.NetworkICMPv4, N.NetworkICMPv6}, options.DialerOptions), + Adapter: outbound.NewAdapterWithDialerOptions(C.TypeDirect, tag, []string{N.NetworkTCP, N.NetworkUDP, N.NetworkICMP}, options.DialerOptions), ctx: ctx, logger: logger, //nolint:staticcheck @@ -151,9 +151,9 @@ func (h *Outbound) ListenPacket(ctx context.Context, destination M.Socksaddr) (n return conn, nil } -func (h *Outbound) NewDirectRouteConnection(metadata adapter.InboundContext, routeContext tun.DirectRouteContext) (tun.DirectRouteDestination, error) { +func (h *Outbound) NewDirectRouteConnection(metadata adapter.InboundContext, routeContext tun.DirectRouteContext, timeout time.Duration) (tun.DirectRouteDestination, error) { ctx := log.ContextWithNewID(h.ctx) - destination, err := ping.ConnectDestination(ctx, h.logger, common.MustCast[*dialer.DefaultDialer](h.dialer).DialerForICMPNetwork(metadata.Network).Control, metadata.Destination.Addr, routeContext) + destination, err := ping.ConnectDestination(ctx, h.logger, common.MustCast[*dialer.DefaultDialer](h.dialer).DialerForICMPDestination(metadata.Destination.Addr).Control, metadata.Destination.Addr, routeContext, timeout) if err != nil { return nil, err } diff --git a/sing-box/protocol/group/selector.go b/sing-box/protocol/group/selector.go index 9806e03354..439283bd6c 100644 --- a/sing-box/protocol/group/selector.go +++ b/sing-box/protocol/group/selector.go @@ -10,7 +10,7 @@ import ( C "github.com/sagernet/sing-box/constant" "github.com/sagernet/sing-box/log" "github.com/sagernet/sing-box/option" - "github.com/sagernet/sing/common/atomic" + "github.com/sagernet/sing/common" E "github.com/sagernet/sing/common/exceptions" "github.com/sagernet/sing/common/logger" M "github.com/sagernet/sing/common/metadata" @@ -37,7 +37,7 @@ type Selector struct { tags []string defaultTag string outbounds map[string]adapter.Outbound - selected atomic.TypedValue[adapter.Outbound] + selected common.TypedValue[adapter.Outbound] interruptGroup *interrupt.Group interruptExternalConnections bool } diff --git a/sing-box/protocol/group/urltest.go b/sing-box/protocol/group/urltest.go index 719f4a2c6d..4bdef9fb40 100644 --- a/sing-box/protocol/group/urltest.go +++ b/sing-box/protocol/group/urltest.go @@ -4,6 +4,7 @@ import ( "context" "net" "sync" + "sync/atomic" "time" "github.com/sagernet/sing-box/adapter" @@ -14,7 +15,6 @@ import ( "github.com/sagernet/sing-box/log" "github.com/sagernet/sing-box/option" "github.com/sagernet/sing/common" - "github.com/sagernet/sing/common/atomic" "github.com/sagernet/sing/common/batch" E "github.com/sagernet/sing/common/exceptions" M "github.com/sagernet/sing/common/metadata" @@ -192,7 +192,7 @@ type URLTestGroup struct { ticker *time.Ticker close chan struct{} started bool - lastActive atomic.TypedValue[time.Time] + lastActive common.TypedValue[time.Time] } func NewURLTestGroup(ctx context.Context, outboundManager adapter.OutboundManager, logger log.Logger, outbounds []adapter.Outbound, link string, interval time.Duration, tolerance uint16, idleTimeout time.Duration, interruptExternalConnections bool) (*URLTestGroup, error) { diff --git a/sing-box/protocol/tailscale/endpoint.go b/sing-box/protocol/tailscale/endpoint.go index 743a793c39..09ec38cdde 100644 --- a/sing-box/protocol/tailscale/endpoint.go +++ b/sing-box/protocol/tailscale/endpoint.go @@ -13,6 +13,7 @@ import ( "reflect" "runtime" "strings" + "sync/atomic" "syscall" "time" @@ -30,10 +31,10 @@ import ( "github.com/sagernet/sing-box/experimental/libbox/platform" "github.com/sagernet/sing-box/log" "github.com/sagernet/sing-box/option" + "github.com/sagernet/sing-box/route/rule" "github.com/sagernet/sing-tun" "github.com/sagernet/sing-tun/ping" "github.com/sagernet/sing/common" - "github.com/sagernet/sing/common/atomic" "github.com/sagernet/sing/common/bufio" "github.com/sagernet/sing/common/control" E "github.com/sagernet/sing/common/exceptions" @@ -87,7 +88,7 @@ type Endpoint struct { cfg *wgcfg.Config dnsCfg *tsDNS.Config - routeDomains atomic.TypedValue[map[string]bool] + routeDomains common.TypedValue[map[string]bool] routePrefixes atomic.Pointer[netipx.IPSet] acceptRoutes bool @@ -181,7 +182,7 @@ func NewEndpoint(ctx context.Context, router adapter.Router, logger log.ContextL }, } return &Endpoint{ - Adapter: endpoint.NewAdapter(C.TypeTailscale, tag, []string{N.NetworkTCP, N.NetworkUDP, N.NetworkICMPv4, N.NetworkICMPv6}, nil), + Adapter: endpoint.NewAdapter(C.TypeTailscale, tag, []string{N.NetworkTCP, N.NetworkUDP, N.NetworkICMP}, nil), ctx: ctx, router: router, logger: logger, @@ -272,7 +273,7 @@ func (t *Endpoint) Start(stage adapter.StartStage) error { if err != nil { return E.Cause(err, "update prefs") } - t.filter = atomic.PointerForm(localBackend.ExportFilter()) + t.filter = localBackend.ExportFilter() go t.watchState() return nil } @@ -424,7 +425,7 @@ func (t *Endpoint) ListenPacket(ctx context.Context, destination M.Socksaddr) (n return udpConn, nil } -func (t *Endpoint) PrepareConnection(network string, source M.Socksaddr, destination M.Socksaddr, routeContext tun.DirectRouteContext) (tun.DirectRouteDestination, error) { +func (t *Endpoint) PrepareConnection(network string, source M.Socksaddr, destination M.Socksaddr, routeContext tun.DirectRouteContext, timeout time.Duration) (tun.DirectRouteDestination, error) { tsFilter := t.filter.Load() if tsFilter != nil { var ipProto ipproto.Proto @@ -433,6 +434,12 @@ func (t *Endpoint) PrepareConnection(network string, source M.Socksaddr, destina ipProto = ipproto.TCP case N.NetworkUDP: ipProto = ipproto.UDP + case N.NetworkICMP: + if !destination.IsIPv6() { + ipProto = ipproto.ICMPv4 + } else { + ipProto = ipproto.ICMPv6 + } } response := tsFilter.Check(source.Addr, destination.Addr, destination.Port, ipProto) switch response { @@ -442,13 +449,26 @@ func (t *Endpoint) PrepareConnection(network string, source M.Socksaddr, destina return nil, tun.ErrDrop } } - return t.router.PreMatch(adapter.InboundContext{ + var ipVersion uint8 + if !destination.IsIPv6() { + ipVersion = 4 + } else { + ipVersion = 6 + } + routeDestination, err := t.router.PreMatch(adapter.InboundContext{ Inbound: t.Tag(), InboundType: t.Type(), + IPVersion: ipVersion, Network: network, Source: source, Destination: destination, - }, routeContext) + }, routeContext, timeout) + if err != nil { + if !rule.IsRejected(err) { + t.logger.Warn(E.Cause(err, "link ", network, " connection from ", source.AddrString(), " to ", destination.AddrString())) + } + } + return routeDestination, err } func (t *Endpoint) NewConnectionEx(ctx context.Context, conn net.Conn, source M.Socksaddr, destination M.Socksaddr, onClose N.CloseHandlerFunc) { @@ -491,7 +511,7 @@ func (t *Endpoint) NewPacketConnectionEx(ctx context.Context, conn N.PacketConn, t.router.RoutePacketConnectionEx(ctx, conn, metadata, onClose) } -func (t *Endpoint) NewDirectRouteConnection(metadata adapter.InboundContext, routeContext tun.DirectRouteContext) (tun.DirectRouteDestination, error) { +func (t *Endpoint) NewDirectRouteConnection(metadata adapter.InboundContext, routeContext tun.DirectRouteContext, timeout time.Duration) (tun.DirectRouteDestination, error) { inet4Address, inet6Address := t.server.TailscaleIPs() if metadata.Destination.Addr.Is4() && !inet4Address.IsValid() || metadata.Destination.Addr.Is6() && !inet6Address.IsValid() { return nil, E.New("Tailscale is not ready yet") @@ -503,6 +523,7 @@ func (t *Endpoint) NewDirectRouteConnection(metadata adapter.InboundContext, rou routeContext, t.stack, inet4Address, inet6Address, + timeout, ) if err != nil { return nil, err diff --git a/sing-box/protocol/tun/inbound.go b/sing-box/protocol/tun/inbound.go index 4dd76243aa..3f013598a0 100644 --- a/sing-box/protocol/tun/inbound.go +++ b/sing-box/protocol/tun/inbound.go @@ -8,7 +8,6 @@ import ( "runtime" "strconv" "strings" - "syscall" "time" "github.com/sagernet/sing-box/adapter" @@ -19,6 +18,7 @@ import ( "github.com/sagernet/sing-box/experimental/libbox/platform" "github.com/sagernet/sing-box/log" "github.com/sagernet/sing-box/option" + "github.com/sagernet/sing-box/route/rule" "github.com/sagernet/sing-tun" "github.com/sagernet/sing/common" E "github.com/sagernet/sing/common/exceptions" @@ -455,18 +455,25 @@ func (t *Inbound) Close() error { ) } -func (t *Inbound) PrepareConnection(network string, source M.Socksaddr, destination M.Socksaddr, routeContext tun.DirectRouteContext) (tun.DirectRouteDestination, error) { +func (t *Inbound) PrepareConnection(network string, source M.Socksaddr, destination M.Socksaddr, routeContext tun.DirectRouteContext, timeout time.Duration) (tun.DirectRouteDestination, error) { + var ipVersion uint8 + if !destination.IsIPv6() { + ipVersion = 4 + } else { + ipVersion = 6 + } routeDestination, err := t.router.PreMatch(adapter.InboundContext{ Inbound: t.tag, InboundType: C.TypeTun, + IPVersion: ipVersion, Network: network, Source: source, Destination: destination, InboundOptions: t.inboundOptions, - }, routeContext) + }, routeContext, timeout) if err != nil { - if !E.IsMulti(err, tun.ErrDrop, syscall.ECONNREFUSED) { - t.logger.Warn(E.Cause(err, "link ", network, " connection from ", source, " to ", destination)) + if !rule.IsRejected(err) { + t.logger.Warn(E.Cause(err, "link ", network, " connection from ", source.AddrString(), " to ", destination.AddrString())) } } return routeDestination, err diff --git a/sing-box/protocol/wireguard/endpoint.go b/sing-box/protocol/wireguard/endpoint.go index dbf35602ba..811c6bb472 100644 --- a/sing-box/protocol/wireguard/endpoint.go +++ b/sing-box/protocol/wireguard/endpoint.go @@ -12,6 +12,7 @@ import ( C "github.com/sagernet/sing-box/constant" "github.com/sagernet/sing-box/log" "github.com/sagernet/sing-box/option" + "github.com/sagernet/sing-box/route/rule" "github.com/sagernet/sing-box/transport/wireguard" "github.com/sagernet/sing-tun" "github.com/sagernet/sing/common" @@ -41,7 +42,7 @@ type Endpoint struct { func NewEndpoint(ctx context.Context, router adapter.Router, logger log.ContextLogger, tag string, options option.WireGuardEndpointOptions) (adapter.Endpoint, error) { ep := &Endpoint{ - Adapter: endpoint.NewAdapterWithDialerOptions(C.TypeWireGuard, tag, []string{N.NetworkTCP, N.NetworkUDP, N.NetworkICMPv4, N.NetworkICMPv6}, options.DialerOptions), + Adapter: endpoint.NewAdapterWithDialerOptions(C.TypeWireGuard, tag, []string{N.NetworkTCP, N.NetworkUDP, N.NetworkICMP}, options.DialerOptions), ctx: ctx, router: router, dnsRouter: service.FromContext[adapter.DNSRouter](ctx), @@ -125,14 +126,27 @@ func (w *Endpoint) Close() error { return w.endpoint.Close() } -func (w *Endpoint) PrepareConnection(network string, source M.Socksaddr, destination M.Socksaddr, context tun.DirectRouteContext) (tun.DirectRouteDestination, error) { - return w.router.PreMatch(adapter.InboundContext{ +func (w *Endpoint) PrepareConnection(network string, source M.Socksaddr, destination M.Socksaddr, routeContext tun.DirectRouteContext, timeout time.Duration) (tun.DirectRouteDestination, error) { + var ipVersion uint8 + if !destination.IsIPv6() { + ipVersion = 4 + } else { + ipVersion = 6 + } + routeDestination, err := w.router.PreMatch(adapter.InboundContext{ Inbound: w.Tag(), InboundType: w.Type(), + IPVersion: ipVersion, Network: network, Source: source, Destination: destination, - }, context) + }, routeContext, timeout) + if err != nil { + if !rule.IsRejected(err) { + w.logger.Warn(E.Cause(err, "link ", network, " connection from ", source.AddrString(), " to ", destination.AddrString())) + } + } + return routeDestination, err } func (w *Endpoint) NewConnectionEx(ctx context.Context, conn net.Conn, source M.Socksaddr, destination M.Socksaddr, onClose N.CloseHandlerFunc) { @@ -222,11 +236,6 @@ func (w *Endpoint) PreferredAddress(address netip.Addr) bool { return w.endpoint.Lookup(address) != nil } -func (w *Endpoint) NewDirectRouteConnection(metadata adapter.InboundContext, routeContext tun.DirectRouteContext) (tun.DirectRouteDestination, error) { - destination, err := w.endpoint.NewDirectRouteConnection(metadata, routeContext) - if err != nil { - return nil, err - } - w.logger.Info("linked ", metadata.Network, " connection to ", metadata.Destination.AddrString()) - return destination, nil +func (w *Endpoint) NewDirectRouteConnection(metadata adapter.InboundContext, routeContext tun.DirectRouteContext, timeout time.Duration) (tun.DirectRouteDestination, error) { + return w.endpoint.NewDirectRouteConnection(metadata, routeContext, timeout) } diff --git a/sing-box/protocol/wireguard/outbound.go b/sing-box/protocol/wireguard/outbound.go index fa58d959f9..5b08c6a7a7 100644 --- a/sing-box/protocol/wireguard/outbound.go +++ b/sing-box/protocol/wireguard/outbound.go @@ -4,6 +4,7 @@ import ( "context" "net" "net/netip" + "time" "github.com/sagernet/sing-box/adapter" "github.com/sagernet/sing-box/adapter/outbound" @@ -13,6 +14,7 @@ import ( "github.com/sagernet/sing-box/log" "github.com/sagernet/sing-box/option" "github.com/sagernet/sing-box/transport/wireguard" + tun "github.com/sagernet/sing-tun" "github.com/sagernet/sing/common" E "github.com/sagernet/sing/common/exceptions" "github.com/sagernet/sing/common/logger" @@ -42,7 +44,7 @@ func NewOutbound(ctx context.Context, router adapter.Router, logger log.ContextL deprecated.Report(ctx, deprecated.OptionWireGuardGSO) } outbound := &Outbound{ - Adapter: outbound.NewAdapterWithDialerOptions(C.TypeWireGuard, tag, []string{N.NetworkTCP, N.NetworkUDP}, options.DialerOptions), + Adapter: outbound.NewAdapterWithDialerOptions(C.TypeWireGuard, tag, []string{N.NetworkTCP, N.NetworkUDP, N.NetworkICMP}, options.DialerOptions), ctx: ctx, dnsRouter: service.FromContext[adapter.DNSRouter](ctx), logger: logger, @@ -168,3 +170,7 @@ func (o *Outbound) PreferredDomain(domain string) bool { func (o *Outbound) PreferredAddress(address netip.Addr) bool { return o.endpoint.Lookup(address) != nil } + +func (o *Outbound) NewDirectRouteConnection(metadata adapter.InboundContext, routeContext tun.DirectRouteContext, timeout time.Duration) (tun.DirectRouteDestination, error) { + return o.endpoint.NewDirectRouteConnection(metadata, routeContext, timeout) +} diff --git a/sing-box/route/network.go b/sing-box/route/network.go index 6a45abc6a6..5009ec0b44 100644 --- a/sing-box/route/network.go +++ b/sing-box/route/network.go @@ -19,7 +19,6 @@ import ( "github.com/sagernet/sing-box/option" "github.com/sagernet/sing-tun" "github.com/sagernet/sing/common" - "github.com/sagernet/sing/common/atomic" "github.com/sagernet/sing/common/control" E "github.com/sagernet/sing/common/exceptions" F "github.com/sagernet/sing/common/format" @@ -37,7 +36,7 @@ var _ adapter.NetworkManager = (*NetworkManager)(nil) type NetworkManager struct { logger logger.ContextLogger interfaceFinder *control.DefaultInterfaceFinder - networkInterfaces atomic.TypedValue[[]adapter.NetworkInterface] + networkInterfaces common.TypedValue[[]adapter.NetworkInterface] autoDetectInterface bool defaultOptions adapter.NetworkOptions diff --git a/sing-box/route/route.go b/sing-box/route/route.go index 1a32b6dc60..c731362ebd 100644 --- a/sing-box/route/route.go +++ b/sing-box/route/route.go @@ -259,7 +259,7 @@ func (r *Router) routePacketConnection(ctx context.Context, conn N.PacketConn, m return nil } -func (r *Router) PreMatch(metadata adapter.InboundContext, routeContext tun.DirectRouteContext) (tun.DirectRouteDestination, error) { +func (r *Router) PreMatch(metadata adapter.InboundContext, routeContext tun.DirectRouteContext, timeout time.Duration) (tun.DirectRouteDestination, error) { selectedRule, _, _, _, err := r.matchRule(r.ctx, &metadata, true, nil, nil) if err != nil { return nil, err @@ -279,17 +279,17 @@ func (r *Router) PreMatch(metadata adapter.InboundContext, routeContext tun.Dire if !common.Contains(outbound.Network(), metadata.Network) { return nil, E.New(metadata.Network, " is not supported by outbound: ", action.Outbound) } - return outbound.(adapter.DirectRouteOutbound).NewDirectRouteConnection(metadata, routeContext) + return outbound.(adapter.DirectRouteOutbound).NewDirectRouteConnection(metadata, routeContext, timeout) } } - if metadata.Network != N.NetworkICMPv4 && metadata.Network != N.NetworkICMPv6 { + if selectedRule != nil || metadata.Network != N.NetworkICMP { return nil, nil } defaultOutbound := r.outbound.Default() if !common.Contains(defaultOutbound.Network(), metadata.Network) { return nil, E.New(metadata.Network, " is not supported by default outbound: ", defaultOutbound.Tag()) } - return defaultOutbound.(adapter.DirectRouteOutbound).NewDirectRouteConnection(metadata, routeContext) + return defaultOutbound.(adapter.DirectRouteOutbound).NewDirectRouteConnection(metadata, routeContext, timeout) } func (r *Router) matchRule( diff --git a/sing-box/route/rule/rule_set_local.go b/sing-box/route/rule/rule_set_local.go index 442302e2a8..597f81d499 100644 --- a/sing-box/route/rule/rule_set_local.go +++ b/sing-box/route/rule/rule_set_local.go @@ -6,6 +6,7 @@ import ( "path/filepath" "strings" "sync" + "sync/atomic" "github.com/sagernet/fswatch" "github.com/sagernet/sing-box/adapter" @@ -13,7 +14,6 @@ import ( C "github.com/sagernet/sing-box/constant" "github.com/sagernet/sing-box/option" "github.com/sagernet/sing/common" - "github.com/sagernet/sing/common/atomic" E "github.com/sagernet/sing/common/exceptions" F "github.com/sagernet/sing/common/format" "github.com/sagernet/sing/common/json" diff --git a/sing-box/route/rule/rule_set_remote.go b/sing-box/route/rule/rule_set_remote.go index f31ec1430d..d4c6288921 100644 --- a/sing-box/route/rule/rule_set_remote.go +++ b/sing-box/route/rule/rule_set_remote.go @@ -10,6 +10,7 @@ import ( "runtime" "strings" "sync" + "sync/atomic" "time" "github.com/sagernet/sing-box/adapter" @@ -17,7 +18,6 @@ import ( C "github.com/sagernet/sing-box/constant" "github.com/sagernet/sing-box/option" "github.com/sagernet/sing/common" - "github.com/sagernet/sing/common/atomic" E "github.com/sagernet/sing/common/exceptions" F "github.com/sagernet/sing/common/format" "github.com/sagernet/sing/common/json" diff --git a/sing-box/service/ssmapi/cache.go b/sing-box/service/ssmapi/cache.go index 4c82c9d008..03cc8c3f30 100644 --- a/sing-box/service/ssmapi/cache.go +++ b/sing-box/service/ssmapi/cache.go @@ -5,8 +5,8 @@ import ( "os" "path/filepath" "sort" + "sync/atomic" - "github.com/sagernet/sing/common/atomic" "github.com/sagernet/sing/common/json" "github.com/sagernet/sing/common/json/badjson" "github.com/sagernet/sing/service/filemanager" diff --git a/sing-box/service/ssmapi/traffic.go b/sing-box/service/ssmapi/traffic.go index f39d56d8f1..4a669adb40 100644 --- a/sing-box/service/ssmapi/traffic.go +++ b/sing-box/service/ssmapi/traffic.go @@ -3,9 +3,9 @@ package ssmapi import ( "net" "sync" + "sync/atomic" "github.com/sagernet/sing-box/adapter" - "github.com/sagernet/sing/common/atomic" "github.com/sagernet/sing/common/bufio" N "github.com/sagernet/sing/common/network" ) diff --git a/sing-box/transport/v2rayquic/client.go b/sing-box/transport/v2rayquic/client.go index 3d1d916e39..803d58c5d6 100644 --- a/sing-box/transport/v2rayquic/client.go +++ b/sing-box/transport/v2rayquic/client.go @@ -15,7 +15,6 @@ import ( "github.com/sagernet/sing-box/option" "github.com/sagernet/sing-quic" "github.com/sagernet/sing/common" - "github.com/sagernet/sing/common/atomic" "github.com/sagernet/sing/common/bufio" M "github.com/sagernet/sing/common/metadata" N "github.com/sagernet/sing/common/network" @@ -30,7 +29,7 @@ type Client struct { tlsConfig tls.Config quicConfig *quic.Config connAccess sync.Mutex - conn atomic.TypedValue[quic.Connection] + conn common.TypedValue[quic.Connection] rawConn net.Conn } diff --git a/sing-box/transport/wireguard/device.go b/sing-box/transport/wireguard/device.go index 0ef0407bfd..4dd615c585 100644 --- a/sing-box/transport/wireguard/device.go +++ b/sing-box/transport/wireguard/device.go @@ -47,5 +47,5 @@ func NewDevice(options DeviceOptions) (Device, error) { type NatDevice interface { Device - CreateDestination(metadata adapter.InboundContext, routeContext tun.DirectRouteContext) (tun.DirectRouteDestination, error) + CreateDestination(metadata adapter.InboundContext, routeContext tun.DirectRouteContext, timeout time.Duration) (tun.DirectRouteDestination, error) } diff --git a/sing-box/transport/wireguard/device_nat.go b/sing-box/transport/wireguard/device_nat.go index cff5c29d2a..e5a28c1b14 100644 --- a/sing-box/transport/wireguard/device_nat.go +++ b/sing-box/transport/wireguard/device_nat.go @@ -1,26 +1,36 @@ package wireguard import ( + "context" + "sync/atomic" + "time" + "github.com/sagernet/sing-box/adapter" + "github.com/sagernet/sing-box/log" "github.com/sagernet/sing-tun" "github.com/sagernet/sing-tun/ping" "github.com/sagernet/sing/common/buf" + "github.com/sagernet/sing/common/logger" ) var _ Device = (*natDeviceWrapper)(nil) type natDeviceWrapper struct { Device + ctx context.Context + logger logger.ContextLogger packetOutbound chan *buf.Buffer rewriter *ping.Rewriter buffer [][]byte } -func NewNATDevice(upstream Device) NatDevice { +func NewNATDevice(ctx context.Context, logger logger.ContextLogger, upstream Device) NatDevice { wrapper := &natDeviceWrapper{ Device: upstream, + ctx: ctx, + logger: logger, packetOutbound: make(chan *buf.Buffer, 256), - rewriter: ping.NewRewriter(upstream.Inet4Address(), upstream.Inet6Address()), + rewriter: ping.NewRewriter(ctx, logger, upstream.Inet4Address(), upstream.Inet6Address()), } return wrapper } @@ -57,13 +67,15 @@ func (d *natDeviceWrapper) Write(bufs [][]byte, offset int) (int, error) { return 0, nil } -func (d *natDeviceWrapper) CreateDestination(metadata adapter.InboundContext, routeContext tun.DirectRouteContext) (tun.DirectRouteDestination, error) { +func (d *natDeviceWrapper) CreateDestination(metadata adapter.InboundContext, routeContext tun.DirectRouteContext, timeout time.Duration) (tun.DirectRouteDestination, error) { + ctx := log.ContextWithNewID(d.ctx) session := tun.DirectRouteSession{ Source: metadata.Source.Addr, Destination: metadata.Destination.Addr, } d.rewriter.CreateSession(session, routeContext) - return &natDestination{d, session}, nil + d.logger.InfoContext(ctx, "linked ", metadata.Network, " connection from ", metadata.Source.AddrString(), " to ", metadata.Destination.AddrString()) + return &natDestination{device: d, session: session}, nil } var _ tun.DirectRouteDestination = (*natDestination)(nil) @@ -71,6 +83,7 @@ var _ tun.DirectRouteDestination = (*natDestination)(nil) type natDestination struct { device *natDeviceWrapper session tun.DirectRouteSession + closed atomic.Bool } func (d *natDestination) WritePacket(buffer *buf.Buffer) error { @@ -80,6 +93,11 @@ func (d *natDestination) WritePacket(buffer *buf.Buffer) error { } func (d *natDestination) Close() error { + d.closed.Store(true) d.device.rewriter.DeleteSession(d.session) return nil } + +func (d *natDestination) IsClosed() bool { + return d.closed.Load() +} diff --git a/sing-box/transport/wireguard/device_stack.go b/sing-box/transport/wireguard/device_stack.go index 94fa39f8d8..8b7c40cdef 100644 --- a/sing-box/transport/wireguard/device_stack.go +++ b/sing-box/transport/wireguard/device_stack.go @@ -7,6 +7,7 @@ import ( "net" "net/netip" "os" + "time" "github.com/sagernet/gvisor/pkg/buffer" "github.com/sagernet/gvisor/pkg/tcpip" @@ -251,7 +252,7 @@ func (w *stackDevice) BatchSize() int { return 1 } -func (w *stackDevice) CreateDestination(metadata adapter.InboundContext, routeContext tun.DirectRouteContext) (tun.DirectRouteDestination, error) { +func (w *stackDevice) CreateDestination(metadata adapter.InboundContext, routeContext tun.DirectRouteContext, timeout time.Duration) (tun.DirectRouteDestination, error) { ctx := log.ContextWithNewID(w.ctx) destination, err := ping.ConnectGVisor( ctx, w.logger, @@ -259,6 +260,7 @@ func (w *stackDevice) CreateDestination(metadata adapter.InboundContext, routeCo routeContext, w.stack, w.inet4Address, w.inet6Address, + timeout, ) if err != nil { return nil, err diff --git a/sing-box/transport/wireguard/device_system_stack.go b/sing-box/transport/wireguard/device_system_stack.go index 16f56ebd53..94fd6f4f97 100644 --- a/sing-box/transport/wireguard/device_system_stack.go +++ b/sing-box/transport/wireguard/device_system_stack.go @@ -5,6 +5,7 @@ package wireguard import ( "context" "net/netip" + "time" "github.com/sagernet/gvisor/pkg/buffer" "github.com/sagernet/gvisor/pkg/tcpip" @@ -159,7 +160,7 @@ func (w *systemStackDevice) writeStack(packet []byte) bool { return true } -func (w *systemStackDevice) CreateDestination(metadata adapter.InboundContext, routeContext tun.DirectRouteContext) (tun.DirectRouteDestination, error) { +func (w *systemStackDevice) CreateDestination(metadata adapter.InboundContext, routeContext tun.DirectRouteContext, timeout time.Duration) (tun.DirectRouteDestination, error) { ctx := log.ContextWithNewID(w.ctx) destination, err := ping.ConnectGVisor( ctx, w.logger, @@ -167,6 +168,7 @@ func (w *systemStackDevice) CreateDestination(metadata adapter.InboundContext, r routeContext, w.stack, w.inet4Address, w.inet6Address, + timeout, ) if err != nil { return nil, err diff --git a/sing-box/transport/wireguard/endpoint.go b/sing-box/transport/wireguard/endpoint.go index b2b419562f..12718b913c 100644 --- a/sing-box/transport/wireguard/endpoint.go +++ b/sing-box/transport/wireguard/endpoint.go @@ -10,6 +10,7 @@ import ( "os" "reflect" "strings" + "time" "unsafe" "github.com/sagernet/sing-box/adapter" @@ -119,7 +120,7 @@ func NewEndpoint(options EndpointOptions) (*Endpoint, error) { } natDevice, isNatDevice := tunDevice.(NatDevice) if !isNatDevice { - natDevice = NewNATDevice(tunDevice) + natDevice = NewNATDevice(options.Context, options.Logger, tunDevice) } return &Endpoint{ options: options, @@ -243,11 +244,11 @@ func (e *Endpoint) Lookup(address netip.Addr) *device.Peer { return e.allowedIPs.Lookup(address.AsSlice()) } -func (e *Endpoint) NewDirectRouteConnection(metadata adapter.InboundContext, routeContext tun.DirectRouteContext) (tun.DirectRouteDestination, error) { +func (e *Endpoint) NewDirectRouteConnection(metadata adapter.InboundContext, routeContext tun.DirectRouteContext, timeout time.Duration) (tun.DirectRouteDestination, error) { if e.natDevice == nil { return nil, os.ErrInvalid } - return e.natDevice.CreateDestination(metadata, routeContext) + return e.natDevice.CreateDestination(metadata, routeContext, timeout) } func (e *Endpoint) onPauseUpdated(event int) { diff --git a/small/luci-app-fchomo/htdocs/luci-static/resources/fchomo.js b/small/luci-app-fchomo/htdocs/luci-static/resources/fchomo.js index 16972f38ee..cfdc2e2562 100644 --- a/small/luci-app-fchomo/htdocs/luci-static/resources/fchomo.js +++ b/small/luci-app-fchomo/htdocs/luci-static/resources/fchomo.js @@ -390,7 +390,7 @@ const CBIListValue = form.ListValue.extend({ const CBIRichMultiValue = form.MultiValue.extend({ __name__: 'CBI.RichMultiValue', - value: (form.RichListValue || form.MultiValue).prototype.value // less_24_10 + value: (form.RichListValue || form.MultiValue).prototype.value // @less_24_10 }); const CBIStaticList = form.DynamicList.extend({ @@ -608,7 +608,7 @@ function bool2str(value) { return value ? '1' : '0'; } -// thanks to homeproxy +/* thanks to homeproxy */ function calcStringMD5(e) { /* Thanks to https://stackoverflow.com/a/41602636 */ let h = (a, b) => { @@ -683,7 +683,7 @@ function calcStringMD5(e) { return (p(a) + p(b) + p(c) + p(d)).toLowerCase(); } -// thanks to homeproxy +/* thanks to homeproxy */ function decodeBase64Str(str) { if (!str) return null; @@ -815,7 +815,7 @@ function getClashAPI(instance) { return L.resolveDefault(callGetClashAPI(instance), {}); } -// thanks to homeproxy +/* thanks to homeproxy */ function loadDefaultLabel(section_id) { const label = uci.get(this.config, section_id, 'label'); if (label) { @@ -826,7 +826,7 @@ function loadDefaultLabel(section_id) { } } -// thanks to homeproxy +/* thanks to homeproxy */ function loadModalTitle(title, addtitle, section_id) { const label = uci.get(this.config, section_id, 'label'); return label ? title + ' » ' + label : addtitle; @@ -1127,7 +1127,7 @@ function validateAuthPassword(section_id, value) { } function validateCommonPort(section_id, value) { - // thanks to homeproxy + /* thanks to homeproxy */ let stubValidator = { factory: validation, apply(type, value, args) { @@ -1348,7 +1348,7 @@ function removeFile(type, filename) { }); } -// thanks to homeproxy +/* thanks to homeproxy */ function uploadCertificate(type, filename, ev) { const callWriteCertificate = rpc.declare({ object: 'luci.fchomo', diff --git a/small/luci-app-fchomo/htdocs/luci-static/resources/view/fchomo/global.js b/small/luci-app-fchomo/htdocs/luci-static/resources/view/fchomo/global.js index 271edffdbd..f5737ac6d6 100644 --- a/small/luci-app-fchomo/htdocs/luci-static/resources/view/fchomo/global.js +++ b/small/luci-app-fchomo/htdocs/luci-static/resources/view/fchomo/global.js @@ -469,7 +469,7 @@ return view.extend({ so.placeholder = '7892'; so.rmempty = false; - // Not required for v1.19.2+ + // @Not required for v1.19.2+ so = ss.option(form.Value, 'tunnel_port', _('DNS port')); so.datatype = 'port'; so.placeholder = '7893'; @@ -491,7 +491,7 @@ return view.extend({ o = s.taboption('inbound', form.SectionValue, '_inbound', form.NamedSection, 'inbound', 'fchomo', _('Tun settings')); ss = o.subsection; - so = ss.option(form.RichListValue || form.ListValue, 'tun_stack', _('Stack'), // less_24_10 + so = ss.option(form.RichListValue || form.ListValue, 'tun_stack', _('Stack'), // @less_24_10 _('Tun stack.')); so.value('system', _('System'), _('Less compatibility and sometimes better performance.')); if (features.with_gvisor) { diff --git a/small/luci-app-fchomo/htdocs/luci-static/resources/view/fchomo/node.js b/small/luci-app-fchomo/htdocs/luci-static/resources/view/fchomo/node.js index dd23d94e44..6d5bcad7c2 100644 --- a/small/luci-app-fchomo/htdocs/luci-static/resources/view/fchomo/node.js +++ b/small/luci-app-fchomo/htdocs/luci-static/resources/view/fchomo/node.js @@ -268,7 +268,6 @@ return view.extend({ so = ss.taboption('field_general', form.ListValue, 'tuic_udp_relay_mode', _('UDP relay mode'), _('UDP packet relay mode.')); - so.value('', _('Default')); so.value('native', _('Native')); so.value('quic', _('QUIC')); so.depends({type: 'tuic', tuic_udp_over_stream: '0'}); diff --git a/small/luci-app-fchomo/htdocs/luci-static/resources/view/fchomo/server.js b/small/luci-app-fchomo/htdocs/luci-static/resources/view/fchomo/server.js index 71a8f91528..64bf6580e6 100644 --- a/small/luci-app-fchomo/htdocs/luci-static/resources/view/fchomo/server.js +++ b/small/luci-app-fchomo/htdocs/luci-static/resources/view/fchomo/server.js @@ -95,13 +95,13 @@ return view.extend({ o = s.taboption('field_general', form.Value, 'port', _('Listen port') + ' / ' + _('Ports pool')); o.datatype = 'or(port, portrange)'; - //o.placeholder = '1080,2079-2080,3080'; // Incompatible with firewall + //o.placeholder = '1080,2079-2080,3080'; // @fw4 does not support port lists with commas o.rmempty = false; - //o.validate = L.bind(hm.validateCommonPort, o); // Incompatible with firewall + //o.validate = L.bind(hm.validateCommonPort, o); // @fw4 does not support port lists with commas - // dev: Features under development - // rule - // proxy + // @dev: Features under development + // @rule + // @proxy /* HTTP / SOCKS fields */ /* hm.validateAuth */ diff --git a/small/luci-app-fchomo/po/zh_Hans/fchomo.po b/small/luci-app-fchomo/po/zh_Hans/fchomo.po index e141cb067b..eeee415ee1 100644 --- a/small/luci-app-fchomo/po/zh_Hans/fchomo.po +++ b/small/luci-app-fchomo/po/zh_Hans/fchomo.po @@ -1157,15 +1157,15 @@ msgstr "图标" #: htdocs/luci-static/resources/view/fchomo/node.js:339 msgid "Idle session check interval" -msgstr "空闲会话检查间隔" +msgstr "闲置会话检查间隔" #: htdocs/luci-static/resources/view/fchomo/node.js:346 msgid "Idle session timeout" -msgstr "空闲会话超时" +msgstr "闲置会话超时" #: htdocs/luci-static/resources/view/fchomo/server.js:200 msgid "Idle timeout" -msgstr "空闲超时" +msgstr "闲置超时" #: htdocs/luci-static/resources/fchomo.js:1150 msgid "If All ports is selected, uncheck others" @@ -1486,7 +1486,7 @@ msgstr "Mihomo 服务端" #: htdocs/luci-static/resources/view/fchomo/node.js:353 msgid "Min of idle sessions to keep" -msgstr "要保留的最少空闲会话数" +msgstr "要保留的最少闲置会话数" #: htdocs/luci-static/resources/view/fchomo/node.js:801 msgid "" diff --git a/small/luci-app-fchomo/po/zh_Hant/fchomo.po b/small/luci-app-fchomo/po/zh_Hant/fchomo.po index 4e19bac0c1..43c8745bc4 100644 --- a/small/luci-app-fchomo/po/zh_Hant/fchomo.po +++ b/small/luci-app-fchomo/po/zh_Hant/fchomo.po @@ -1157,15 +1157,15 @@ msgstr "圖標" #: htdocs/luci-static/resources/view/fchomo/node.js:339 msgid "Idle session check interval" -msgstr "空閒會話檢查間隔" +msgstr "閒置會話檢查間隔" #: htdocs/luci-static/resources/view/fchomo/node.js:346 msgid "Idle session timeout" -msgstr "空閒會話逾時" +msgstr "閒置會話逾時" #: htdocs/luci-static/resources/view/fchomo/server.js:200 msgid "Idle timeout" -msgstr "空閒逾時" +msgstr "閒置逾時" #: htdocs/luci-static/resources/fchomo.js:1150 msgid "If All ports is selected, uncheck others" @@ -1486,7 +1486,7 @@ msgstr "Mihomo 服務端" #: htdocs/luci-static/resources/view/fchomo/node.js:353 msgid "Min of idle sessions to keep" -msgstr "要保留的最少空閒會話數" +msgstr "要保留的最少閒置會話數" #: htdocs/luci-static/resources/view/fchomo/node.js:801 msgid "" diff --git a/small/luci-app-fchomo/root/etc/init.d/fchomo b/small/luci-app-fchomo/root/etc/init.d/fchomo index c5ac306e62..c32cb11409 100755 --- a/small/luci-app-fchomo/root/etc/init.d/fchomo +++ b/small/luci-app-fchomo/root/etc/init.d/fchomo @@ -164,7 +164,7 @@ start_service() { config_get_bool dns_ipv6 "dns" "ipv6" "1" local dns_port tunnel_port config_get dns_port "dns" "dns_port" "7853" - config_get tunnel_port "inbound" "tunnel_port" "7893" # Not required for v1.19.2+ + config_get tunnel_port "inbound" "tunnel_port" "7893" # @Not required for v1.19.2+ local routing_mode routing_domain config_get routing_mode "routing" "routing_mode" "" config_get_bool routing_domain "routing" "routing_domain" "0" diff --git a/small/luci-app-fchomo/root/usr/share/fchomo/firewall_post.ut b/small/luci-app-fchomo/root/usr/share/fchomo/firewall_post.ut index b6a43bf5ee..0753edaa25 100644 --- a/small/luci-app-fchomo/root/usr/share/fchomo/firewall_post.ut +++ b/small/luci-app-fchomo/root/usr/share/fchomo/firewall_post.ut @@ -74,7 +74,7 @@ const redir_port = uci.get(cfgname, 'inbound', 'redir_port') || '7891', tproxy_port = uci.get(cfgname, 'inbound', 'tproxy_port') || '7892', - tunnel_port = uci.get(cfgname, 'inbound', 'tunnel_port') || '7893', // Not required for v1.19.2+ + tunnel_port = uci.get(cfgname, 'inbound', 'tunnel_port') || '7893', // @Not required for v1.19.2+ proxy_mode = uci.get(cfgname, 'inbound', 'proxy_mode') || 'redir_tproxy'; const global_ipv6 = uci.get(cfgname, 'global', 'ipv6') || '1', diff --git a/small/luci-app-fchomo/root/usr/share/fchomo/generate_client.uc b/small/luci-app-fchomo/root/usr/share/fchomo/generate_client.uc index 1f3023e2ac..1a18a04e43 100644 --- a/small/luci-app-fchomo/root/usr/share/fchomo/generate_client.uc +++ b/small/luci-app-fchomo/root/usr/share/fchomo/generate_client.uc @@ -313,7 +313,7 @@ uci.foreach(uciconf, ucisniff, (cfg) => { return null; config.sniffer.sniff[cfg.protocol] = { - ports: map(cfg.ports, ports => strToInt(ports) || null), // DEBUG ERROR data type *utils.IntRanges[uint16] + ports: map(cfg.ports, ports => strToInt(ports) || null), // @DEBUG ERROR data type *utils.IntRanges[uint16] "override-destination": (cfg.override_destination === '0') ? false : true }; }); @@ -352,7 +352,7 @@ push(config.listeners, { listen: '::', network: ['tcp', 'udp'], target: '1.1.1.1:53' -}); // Not required for v1.19.2+ +}); // @Not required for v1.19.2+ /* Tun settings */ if (match(proxy_mode, /tun/)) push(config.listeners, { @@ -765,7 +765,7 @@ uci.foreach(uciconf, ucirule, (cfg) => { /* Routing rules START */ /* Routing rules */ config.rules = [ - "IN-NAME,dns-in,dns-out", // Not required for v1.19.2+ + "IN-NAME,dns-in,dns-out", // @Not required for v1.19.2+ "DST-PORT,53,dns-out" ]; uci.foreach(uciconf, ucirout, (cfg) => { diff --git a/small/luci-app-fchomo/root/usr/share/rpcd/ucode/luci.fchomo b/small/luci-app-fchomo/root/usr/share/rpcd/ucode/luci.fchomo index 639cc71aee..a47bff36ed 100644 --- a/small/luci-app-fchomo/root/usr/share/rpcd/ucode/luci.fchomo +++ b/small/luci-app-fchomo/root/usr/share/rpcd/ucode/luci.fchomo @@ -313,7 +313,7 @@ const methods = { } }, - // thanks to homeproxy + /* thanks to homeproxy */ certificate_write: { args: { filename: 'filename' }, call: function(req) { diff --git a/small/luci-app-momo/htdocs/luci-static/resources/tools/momo.js b/small/luci-app-momo/htdocs/luci-static/resources/tools/momo.js index 9a272a3f33..c8c78d1db7 100644 --- a/small/luci-app-momo/htdocs/luci-static/resources/tools/momo.js +++ b/small/luci-app-momo/htdocs/luci-static/resources/tools/momo.js @@ -45,6 +45,13 @@ const callMomoUpdateSubscription = rpc.declare({ expect: { '': {} } }); +const callMomoAPI = rpc.declare({ + object: 'luci.momo', + method: 'api', + params: ['method', 'path', 'query', 'body'], + expect: { '': {} } +}); + const callMomoGetIdentifiers = rpc.declare({ object: 'luci.momo', method: 'get_identifiers', @@ -86,21 +93,8 @@ return baseclass.extend({ return callMomoUpdateSubscription(section_id); }, - api: async function (method, path, query, body) { - const profile = await callMomoProfile({ 'experimental': { 'clash_api': { 'external_controller': null, 'secret': null } } }); - const apiListen = profile?.['experimental']?.['clash_api']?.['external_controller']; - const apiSecret = profile?.['experimental']?.['clash_api']?.['secret'] ?? ''; - if (!apiListen) { - return Promise.reject('Clash API has not been configured'); - } - const apiPort = apiListen.substring(apiListen.lastIndexOf(':') + 1); - const url = `http://${window.location.hostname}:${apiPort}${path}`; - return request.request(url, { - method: method, - headers: { 'Authorization': `Bearer ${apiSecret}` }, - query: query, - content: body - }) + updateDashboard: function () { + return callMomoAPI('POST', '/upgrade/ui'); }, openDashboard: async function () { @@ -123,10 +117,6 @@ return baseclass.extend({ return Promise.resolve(); }, - updateDashboard: function () { - return this.api('POST', '/upgrade/ui'); - }, - getIdentifiers: function () { return callMomoGetIdentifiers(); }, diff --git a/small/luci-app-momo/root/usr/share/rpcd/ucode/luci.momo b/small/luci-app-momo/root/usr/share/rpcd/ucode/luci.momo index 597f31fe44..9dce3295e1 100644 --- a/small/luci-app-momo/root/usr/share/rpcd/ucode/luci.momo +++ b/small/luci-app-momo/root/usr/share/rpcd/ucode/luci.momo @@ -57,6 +57,36 @@ const methods = { return { success: success }; } }, + api: { + args: { method: 'method', path: 'path', query: 'query', body: 'body' }, + call: function(req) { + let result = {}; + + const method = req.args?.method; + const path = req.args?.path; + const query = req.args?.query; + const body = req.args?.body; + + const paths = get_paths(); + const profile = json(readfile(paths.run_profile_path)); + const api_listen = profile['experimental']['clash_api']['external_controller']; + const api_secret = profile['experimental']['clash_api']['secret']; + + if (!api_listen) { + return result; + } + + const url = api_listen + path; + + const process = popen(`curl --request '${method}' --oauth2-bearer '${api_secret}' --url-query '${query}' --data '${body}' '${url}'`); + if (process) { + result = json(process); + process.close(); + } + + return result; + } + }, get_identifiers: { call: function() { const users = filter(get_users(), (x) => x != ''); diff --git a/small/luci-app-nikki/htdocs/luci-static/resources/tools/nikki.js b/small/luci-app-nikki/htdocs/luci-static/resources/tools/nikki.js index 9e5ea4d655..926ce2eaf5 100644 --- a/small/luci-app-nikki/htdocs/luci-static/resources/tools/nikki.js +++ b/small/luci-app-nikki/htdocs/luci-static/resources/tools/nikki.js @@ -39,6 +39,13 @@ const callNikkiUpdateSubscription = rpc.declare({ expect: { '': {} } }); +const callNikkiAPI = rpc.declare({ + object: 'luci.nikki', + method: 'api', + params: ['method', 'path', 'query', 'body'], + expect: { '': {} } +}); + const callNikkiGetIdentifiers = rpc.declare({ object: 'luci.nikki', method: 'get_identifiers', @@ -103,21 +110,8 @@ return baseclass.extend({ return callNikkiUpdateSubscription(section_id); }, - api: async function (method, path, query, body) { - const profile = await callNikkiProfile({ 'external-controller': null, 'secret': null }); - const apiListen = profile['external-controller']; - const apiSecret = profile['secret'] ?? ''; - if (!apiListen) { - return Promise.reject('API has not been configured'); - } - const apiPort = apiListen.substring(apiListen.lastIndexOf(':') + 1); - const url = `http://${window.location.hostname}:${apiPort}${path}`; - return request.request(url, { - method: method, - headers: { 'Authorization': `Bearer ${apiSecret}` }, - query: query, - content: body - }); + updateDashboard: function () { + return callNikkiAPI('POST', '/upgrade/ui'); }, openDashboard: async function () { @@ -146,10 +140,6 @@ return baseclass.extend({ return Promise.resolve(); }, - updateDashboard: function () { - return this.api('POST', '/upgrade/ui'); - }, - getIdentifiers: function () { return callNikkiGetIdentifiers(); }, diff --git a/small/luci-app-nikki/root/usr/share/rpcd/ucode/luci.nikki b/small/luci-app-nikki/root/usr/share/rpcd/ucode/luci.nikki index 7c9013ff41..9bd3069e99 100644 --- a/small/luci-app-nikki/root/usr/share/rpcd/ucode/luci.nikki +++ b/small/luci-app-nikki/root/usr/share/rpcd/ucode/luci.nikki @@ -3,7 +3,7 @@ 'use strict'; import { access, popen, writefile } from 'fs'; -import { get_users, get_groups, get_cgroups } from '/etc/nikki/ucode/include.uc'; +import { load_profile, get_users, get_groups, get_cgroups } from '/etc/nikki/ucode/include.uc'; const methods = { version: { @@ -62,6 +62,35 @@ const methods = { return { success: success }; } }, + api: { + args: { method: 'method', path: 'path', query: 'query', body: 'body' }, + call: function(req) { + let result = {}; + + const method = req.args?.method; + const path = req.args?.path; + const query = req.args?.query; + const body = req.args?.body; + + const profile = load_profile(); + const api_listen = profile['external-controller']; + const api_secret = profile['secret']; + + if (!api_listen) { + return result; + } + + const url = api_listen + path; + + const process = popen(`curl --request '${method}' --oauth2-bearer '${api_secret}' --url-query '${query}' --data '${body}' '${url}'`); + if (process) { + result = json(process); + process.close(); + } + + return result; + } + }, get_identifiers: { call: function() { const users = filter(get_users(), (x) => x != ''); diff --git a/small/luci-app-passwall/luasrc/passwall/util_xray.lua b/small/luci-app-passwall/luasrc/passwall/util_xray.lua index 7152ad0afc..0ede4a92f7 100644 --- a/small/luci-app-passwall/luasrc/passwall/util_xray.lua +++ b/small/luci-app-passwall/luasrc/passwall/util_xray.lua @@ -779,6 +779,10 @@ function gen_config(var) table.insert(outbounds, outbound) fallback_node_tag = outbound.tag end + else + if gen_balancer(fallback_node) then + fallback_node_tag = fallback_node_id + end end end end diff --git a/small/luci-app-passwall2/Makefile b/small/luci-app-passwall2/Makefile index 7589c3973e..1a295a0647 100644 --- a/small/luci-app-passwall2/Makefile +++ b/small/luci-app-passwall2/Makefile @@ -5,7 +5,7 @@ include $(TOPDIR)/rules.mk PKG_NAME:=luci-app-passwall2 -PKG_VERSION:=25.8.22 +PKG_VERSION:=25.8.25 PKG_RELEASE:=1 PKG_CONFIG_DEPENDS:= \ diff --git a/small/luci-app-passwall2/luasrc/controller/passwall2.lua b/small/luci-app-passwall2/luasrc/controller/passwall2.lua index 5a6eba4b9d..3705051fef 100644 --- a/small/luci-app-passwall2/luasrc/controller/passwall2.lua +++ b/small/luci-app-passwall2/luasrc/controller/passwall2.lua @@ -376,6 +376,9 @@ function clear_all_nodes() end) uci:foreach(appname, "subscribe_list", function(t) uci:delete(appname, t[".name"], "md5") + uci:delete(appname, t[".name"], "chain_proxy") + uci:delete(appname, t[".name"], "preproxy_node") + uci:delete(appname, t[".name"], "to_node") end) api.uci_save(uci, appname, true, true) @@ -440,6 +443,16 @@ function delete_select_nodes() uci:delete(appname, t[".name"], "fallback_node") end end) + uci:foreach(appname, "subscribe_list", function(t) + if t["preproxy_node"] == w then + uci:delete(appname, t[".name"], "preproxy_node") + uci:delete(appname, t[".name"], "chain_proxy") + end + if t["to_node"] == w then + uci:delete(appname, t[".name"], "to_node") + uci:delete(appname, t[".name"], "chain_proxy") + end + end) if (uci:get(appname, w, "add_mode") or "0") == "2" then local add_from = uci:get(appname, w, "add_from") or "" if add_from ~= "" then @@ -531,20 +544,29 @@ function create_backup() end function restore_backup() + local result = { status = "error", message = "unknown error" } local ok, err = pcall(function() local filename = http.formvalue("filename") local chunk = http.formvalue("chunk") local chunk_index = tonumber(http.formvalue("chunk_index") or "-1") local total_chunks = tonumber(http.formvalue("total_chunks") or "-1") - if not filename or not chunk then - http_write_json({ status = "error", message = "Missing filename or chunk" }) + if not filename then + result = { status = "error", message = "Missing filename" } + return + end + if not chunk then + result = { status = "error", message = "Missing chunk data" } return end local file_path = "/tmp/" .. filename local decoded = nixio.bin.b64decode(chunk) + if not decoded then + result = { status = "error", message = "Base64 decode failed" } + return + end local fp = io.open(file_path, "a+") if not fp then - http_write_json({ status = "error", message = "Failed to open file for writing: " .. file_path }) + result = { status = "error", message = "Failed to open file: " .. file_path } return end fp:write(decoded) @@ -552,7 +574,7 @@ function restore_backup() if chunk_index + 1 == total_chunks then api.sys.call("echo '' > /tmp/log/passwall2.log") api.log(" * PassWall2 配置文件上传成功…") - local temp_dir = '/tmp/passwall_bak' + local temp_dir = '/tmp/passwall2_bak' api.sys.call("mkdir -p " .. temp_dir) if api.sys.call("tar -xzf " .. file_path .. " -C " .. temp_dir) == 0 then for _, backup_file in ipairs(backup_files) do @@ -563,21 +585,23 @@ function restore_backup() end api.log(" * PassWall2 配置还原成功…") api.log(" * 重启 PassWall2 服务中…\n") - api.sys.call('/etc/init.d/passwall2 restart > /dev/null 2>&1 &') - api.sys.call('/etc/init.d/passwall2_server restart > /dev/null 2>&1 &') + luci.sys.call('/etc/init.d/passwall2 restart > /dev/null 2>&1 &') + luci.sys.call('/etc/init.d/passwall2_server restart > /dev/null 2>&1 &') + result = { status = "success", message = "Upload completed", path = file_path } else api.log(" * PassWall2 配置文件解压失败,请重试!") + result = { status = "error", message = "Decompression failed" } end api.sys.call("rm -rf " .. temp_dir) fs.remove(file_path) - http_write_json({ status = "success", message = "Upload completed", path = file_path }) else - http_write_json({ status = "success", message = "Chunk received" }) + result = { status = "success", message = "Chunk received" } end end) if not ok then - http_write_json({ status = "error", message = tostring(err) }) + result = { status = "error", message = tostring(err) } end + http_write_json(result) end function geo_view() diff --git a/small/luci-app-passwall2/luasrc/model/cbi/passwall2/client/node_list.lua b/small/luci-app-passwall2/luasrc/model/cbi/passwall2/client/node_list.lua index c6ab4c3b55..b243f11187 100644 --- a/small/luci-app-passwall2/luasrc/model/cbi/passwall2/client/node_list.lua +++ b/small/luci-app-passwall2/luasrc/model/cbi/passwall2/client/node_list.lua @@ -84,6 +84,16 @@ function s.remove(e, t) m:del(s[".name"], "fallback_node") end end) + m.uci:foreach(appname, "subscribe_list", function(s) + if s["preproxy_node"] == t then + m:del(s[".name"], "preproxy_node") + m:del(s[".name"], "chain_proxy") + end + if s["to_node"] == t then + m:del(s[".name"], "to_node") + m:del(s[".name"], "chain_proxy") + end + end) if (m:get(t, "add_mode") or "0") == "2" then local add_from = m:get(t, "add_from") or "" if add_from ~= "" then @@ -157,6 +167,8 @@ o.cfgvalue = function(t, n) protocol = "HY2" elseif protocol == "anytls" then protocol = "AnyTLS" + elseif protocol == "ssh" then + protocol = "SSH" else protocol = protocol:gsub("^%l",string.upper) end diff --git a/small/luci-app-passwall2/luasrc/model/cbi/passwall2/client/node_subscribe_config.lua b/small/luci-app-passwall2/luasrc/model/cbi/passwall2/client/node_subscribe_config.lua index db0c137a40..df392e3b7d 100644 --- a/small/luci-app-passwall2/luasrc/model/cbi/passwall2/client/node_subscribe_config.lua +++ b/small/luci-app-passwall2/luasrc/model/cbi/passwall2/client/node_subscribe_config.lua @@ -51,6 +51,18 @@ if has_hysteria2 then local s = "hysteria2" table.insert(hysteria2_type, s) end +local nodes_table = {} +for k, e in ipairs(api.get_valid_nodes()) do + if e.node_type == "normal" then + nodes_table[#nodes_table + 1] = { + id = e[".name"], + remark = e["remark"], + type = e["type"], + add_mode = e["add_mode"], + chain_proxy = e["chain_proxy"] + } + end +end s = m:section(NamedSection, arg[1]) s.addremove = false @@ -205,4 +217,29 @@ o:value("Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, li o:value("Passwall2/OpenWrt", "PassWall2") o:value("v2rayN/9.99", "v2rayN") +o = s:option(ListValue, "chain_proxy", translate("Chain Proxy")) +o:value("", translate("Close(Not use)")) +o:value("1", translate("Preproxy Node")) +o:value("2", translate("Landing Node")) + +local descrStr = "Chained proxy works only with Xray or Sing-box nodes.
" +descrStr = descrStr .. "The chained node must be the same type as your subscription node (Xray with Xray, Sing-box with Sing-box).
" +descrStr = descrStr .. "You can only use manual or imported nodes as chained nodes." +descrStr = translate(descrStr) .. "
" .. translate("Only support a layer of proxy.") + +o = s:option(ListValue, "preproxy_node", translate("Preproxy Node")) +o:depends({ ["chain_proxy"] = "1" }) +o.description = descrStr + +o = s:option(ListValue, "to_node", translate("Landing Node")) +o:depends({ ["chain_proxy"] = "2" }) +o.description = descrStr + +for k, v in pairs(nodes_table) do + if (v.type == "Xray" or v.type == "sing-box") and (not v.chain_proxy or v.chain_proxy == "") and v.add_mode ~= "2" then + s.fields["preproxy_node"]:value(v.id, v.remark) + s.fields["to_node"]:value(v.id, v.remark) + end +end + return m diff --git a/small/luci-app-passwall2/luasrc/model/cbi/passwall2/client/type/sing-box.lua b/small/luci-app-passwall2/luasrc/model/cbi/passwall2/client/type/sing-box.lua index 13f2f7c1b5..c66028ad55 100644 --- a/small/luci-app-passwall2/luasrc/model/cbi/passwall2/client/type/sing-box.lua +++ b/small/luci-app-passwall2/luasrc/model/cbi/passwall2/client/type/sing-box.lua @@ -65,6 +65,7 @@ end if version_ge_1_12_0 then o:value("anytls", "AnyTLS") end +o:value("ssh", "SSH") o:value("_urltest", translate("URLTest")) o:value("_shunt", translate("Shunt")) o:value("_iface", translate("Custom Interface")) @@ -258,6 +259,7 @@ end o = s:option(Value, _n("username"), translate("Username")) o:depends({ [_n("protocol")] = "http" }) o:depends({ [_n("protocol")] = "socks" }) +o:depends({ [_n("protocol")] = "ssh" }) o = s:option(Value, _n("password"), translate("Password")) o.password = true @@ -268,6 +270,7 @@ o:depends({ [_n("protocol")] = "shadowsocksr" }) o:depends({ [_n("protocol")] = "trojan" }) o:depends({ [_n("protocol")] = "tuic" }) o:depends({ [_n("protocol")] = "anytls" }) +o:depends({ [_n("protocol")] = "ssh" }) o = s:option(ListValue, _n("security"), translate("Encrypt Method")) for a, t in ipairs(security_list) do o:value(t) end @@ -456,6 +459,24 @@ if singbox_tags:find("with_quic") then o:depends({ [_n("protocol")] = "hysteria2"}) end +-- [[ SSH config start ]] -- +o = s:option(Value, _n("ssh_priv_key"), translate("Private Key")) +o:depends({ [_n("protocol")] = "ssh" }) + +o = s:option(Value, _n("ssh_priv_key_pp"), translate("Private Key Passphrase")) +o.password = true +o:depends({ [_n("protocol")] = "ssh" }) + +o = s:option(DynamicList, _n("ssh_host_key"), translate("Host Key"), translate("Accept any if empty.")) +o:depends({ [_n("protocol")] = "ssh" }) + +o = s:option(DynamicList, _n("ssh_host_key_algo"), translate("Host Key Algorithms")) +o:depends({ [_n("protocol")] = "ssh" }) + +o = s:option(Value, _n("ssh_client_version"), translate("Client Version"), translate("Random version will be used if empty.")) +o:depends({ [_n("protocol")] = "ssh" }) +-- [[ SSH config end ]] -- + o = s:option(Flag, _n("tls"), translate("TLS")) o.default = 0 o:depends({ [_n("protocol")] = "vmess" }) diff --git a/small/luci-app-passwall2/luasrc/passwall2/api.lua b/small/luci-app-passwall2/luasrc/passwall2/api.lua index 58af0533f9..9b059df1f5 100644 --- a/small/luci-app-passwall2/luasrc/passwall2/api.lua +++ b/small/luci-app-passwall2/luasrc/passwall2/api.lua @@ -485,6 +485,8 @@ function get_valid_nodes() protocol = "HY2" elseif protocol == "anytls" then protocol = "AnyTLS" + elseif protocol == "ssh" then + protocol = "SSH" else protocol = protocol:gsub("^%l",string.upper) end @@ -530,6 +532,8 @@ function get_node_remarks(n) protocol = "HY2" elseif protocol == "anytls" then protocol = "AnyTLS" + elseif protocol == "ssh" then + protocol = "SSH" else protocol = protocol:gsub("^%l",string.upper) end diff --git a/small/luci-app-passwall2/luasrc/passwall2/util_sing-box.lua b/small/luci-app-passwall2/luasrc/passwall2/util_sing-box.lua index c4eee19ba4..79b83fbff9 100644 --- a/small/luci-app-passwall2/luasrc/passwall2/util_sing-box.lua +++ b/small/luci-app-passwall2/luasrc/passwall2/util_sing-box.lua @@ -439,6 +439,18 @@ function gen_outbound(flag, node, tag, proxy_table) } end + if node.protocol == "ssh" then + protocol_table = { + user = (node.username and node.username ~= "") and node.username or "root", + password = (node.password and node.password ~= "") and node.password or "", + private_key = node.ssh_priv_key, + private_key_passphrase = node.ssh_priv_key_pp, + host_key = node.ssh_host_key, + host_key_algorithms = node.ssh_host_key_algo, + client_version = node.ssh_client_version + } + end + if protocol_table then for key, value in pairs(protocol_table) do result[key] = value diff --git a/small/luci-app-passwall2/luasrc/passwall2/util_xray.lua b/small/luci-app-passwall2/luasrc/passwall2/util_xray.lua index 7fbd0b4e96..b819dc8f68 100644 --- a/small/luci-app-passwall2/luasrc/passwall2/util_xray.lua +++ b/small/luci-app-passwall2/luasrc/passwall2/util_xray.lua @@ -772,6 +772,10 @@ function gen_config(var) table.insert(outbounds, outbound) fallback_node_tag = outbound.tag end + else + if gen_balancer(fallback_node) then + fallback_node_tag = fallback_node_id + end end end end diff --git a/small/luci-app-passwall2/luasrc/view/passwall2/global/backup.htm b/small/luci-app-passwall2/luasrc/view/passwall2/global/backup.htm index 67aca2b92d..c96acda2c4 100644 --- a/small/luci-app-passwall2/luasrc/view/passwall2/global/backup.htm +++ b/small/luci-app-passwall2/luasrc/view/passwall2/global/backup.htm @@ -184,7 +184,6 @@ local api = require "luci.passwall2.api" const chunk = base64Data.substring(currentChunk * chunkSize, (currentChunk + 1) * chunkSize); const xhr = new XMLHttpRequest(); xhr.open("POST", '<%= api.url("restore_backup") %>', true); - xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded"); xhr.onreadystatechange = function () { if (xhr.readyState === 4) { if (xhr.status === 200) { @@ -203,12 +202,12 @@ local api = require "luci.passwall2.api" } } }; - xhr.send( - "filename=" + encodeURIComponent(file.name) + - "&chunk=" + encodeURIComponent(chunk) + - "&chunk_index=" + currentChunk + - "&total_chunks=" + totalChunks - ); + const formData = new FormData(); + formData.append("filename", file.name); + formData.append("chunk", chunk); + formData.append("chunk_index", currentChunk); + formData.append("total_chunks", totalChunks); + xhr.send(formData); } else { //alert("Upload completed."); document.getElementById("upload-btn").value = "<%:UL Restore%>"; diff --git a/small/luci-app-passwall2/po/zh-cn/passwall2.po b/small/luci-app-passwall2/po/zh-cn/passwall2.po index c3ac43cdce..819935b663 100644 --- a/small/luci-app-passwall2/po/zh-cn/passwall2.po +++ b/small/luci-app-passwall2/po/zh-cn/passwall2.po @@ -1645,6 +1645,15 @@ msgstr "落地节点" msgid "Only support a layer of proxy." msgstr "仅支持一层代理。" +msgid "" +"Chained proxy works only with Xray or Sing-box nodes.
" +"The chained node must be the same type as your subscription node (Xray with Xray, Sing-box with Sing-box).
" +"You can only use manual or imported nodes as chained nodes." +msgstr "" +"链式代理仅支持 Xray 与 Sing-box 节点。
" +"链式节点需与订阅节点类型一致(Xray 对应 Xray,Sing-box 对应 Sing-box)。
" +"仅支持手动添加或导入的节点用作链式节点。" + msgid "Set the default domain resolution strategy for the sing-box node." msgstr "为 sing-box 节点设置默认的域名解析策略。" @@ -1797,3 +1806,21 @@ msgstr "可以通过输入 GeoIP/Geosite,提取它们所包含的域名/IP。" msgid "Use the GeoIP/Geosite query function to verify if the entered Geo rules are correct." msgstr "利用 GeoIP/Geosite 查询功能,可以验证输入的 Geo 规则是否正确。" + +msgid "Private Key Passphrase" +msgstr "私钥指纹" + +msgid "Host Key" +msgstr "主机密钥" + +msgid "Accept any if empty." +msgstr "留空则不校验。" + +msgid "Host Key Algorithms" +msgstr "主机密钥算法" + +msgid "Client Version" +msgstr "客户端版本" + +msgid "Random version will be used if empty." +msgstr "如留空,则使用随机版本。" diff --git a/small/luci-app-passwall2/root/usr/share/passwall2/subscribe.lua b/small/luci-app-passwall2/root/usr/share/passwall2/subscribe.lua index 2d37277d79..b794d7e09e 100755 --- a/small/luci-app-passwall2/root/usr/share/passwall2/subscribe.lua +++ b/small/luci-app-passwall2/root/usr/share/passwall2/subscribe.lua @@ -35,6 +35,7 @@ local vless_type_default = uci:get(appname, "@global_subscribe[0]", "vless_type" local hysteria2_type_default = uci:get(appname, "@global_subscribe[0]", "hysteria2_type") or "hysteria2" local domain_strategy_default = uci:get(appname, "@global_subscribe[0]", "domain_strategy") or "" local domain_strategy_node = "" +local preproxy_node_group, to_node_group, chain_node_type = "", "", "" -- 判断是否过滤节点关键字 local filter_keyword_mode_default = uci:get(appname, "@global_subscribe[0]", "filter_keyword_mode") or "0" local filter_keyword_discard_list_default = uci:get(appname, "@global_subscribe[0]", "filter_discard_list") or {} @@ -1717,6 +1718,16 @@ local function update_node(manual) if kkk == "type" and vvv == "sing-box" then uci:set(appname, cfgid, "domain_strategy", domain_strategy_node) end + -- 订阅组链式代理 + if chain_node_type ~= "" and kkk == "type" and vvv == chain_node_type then + if preproxy_node_group ~="" then + uci:set(appname, cfgid, "chain_proxy", "1") + uci:set(appname, cfgid, "preproxy_node", preproxy_node_group) + elseif to_node_group ~= "" then + uci:set(appname, cfgid, "chain_proxy", "2") + uci:set(appname, cfgid, "to_node", to_node_group) + end + end end end end @@ -1919,6 +1930,22 @@ local execute = function() else domain_strategy_node = domain_strategy_default end + + -- 订阅组链式代理 + local function valid_chain_node(node) + if not node then return "" end + local cp = uci:get(appname, node, "chain_proxy") or "" + local am = uci:get(appname, node, "add_mode") or "0" + chain_node_type = (cp == "" and am ~= "2") and (uci:get(appname, node, "type") or "") or "" + if chain_node_type ~= "Xray" and chain_node_type ~= "sing-box" then + chain_node_type = "" + return "" + end + return node + end + preproxy_node_group = (value.chain_proxy == "1") and valid_chain_node(value.preproxy_node) or "" + to_node_group = (value.chain_proxy == "2") and valid_chain_node(value.to_node) or "" + local ua = value.user_agent local access_mode = value.access_mode local result = (not access_mode) and "自动" or (access_mode == "direct" and "直连访问" or (access_mode == "proxy" and "通过代理" or "自动")) diff --git a/small/v2ray-geodata/Makefile b/small/v2ray-geodata/Makefile index 18577fa5fd..1a397bca75 100644 --- a/small/v2ray-geodata/Makefile +++ b/small/v2ray-geodata/Makefile @@ -21,16 +21,16 @@ define Download/geoip HASH:=54761d8691a5756fdb08d2cd4d0a9c889dbaab786e1cf758592e09fb00377f53 endef -GEOSITE_VER:=20250821174337 +GEOSITE_VER:=20250825084009 GEOSITE_FILE:=dlc.dat.$(GEOSITE_VER) define Download/geosite URL:=https://github.com/v2fly/domain-list-community/releases/download/$(GEOSITE_VER)/ URL_FILE:=dlc.dat FILE:=$(GEOSITE_FILE) - HASH:=751dc96e9becf21e4fb49817c6f8d5fbd62f178868e3421bf40328185caed166 + HASH:=48c53d519c19d145e409d70ebfc14367bdbd7d7175dfa09441eab44483a7d7c4 endef -GEOSITE_IRAN_VER:=202508180044 +GEOSITE_IRAN_VER:=202508250041 GEOSITE_IRAN_FILE:=iran.dat.$(GEOSITE_IRAN_VER) define Download/geosite-ir URL:=https://github.com/bootmortis/iran-hosted-domains/releases/download/$(GEOSITE_IRAN_VER)/ diff --git a/v2rayn/v2rayN/ServiceLib/Enums/ECoreType.cs b/v2rayn/v2rayN/ServiceLib/Enums/ECoreType.cs index e164a2abd2..9310a0a92b 100644 --- a/v2rayn/v2rayN/ServiceLib/Enums/ECoreType.cs +++ b/v2rayn/v2rayN/ServiceLib/Enums/ECoreType.cs @@ -15,5 +15,6 @@ public enum ECoreType brook = 27, overtls = 28, shadowquic = 29, + mieru = 30, v2rayN = 99 } diff --git a/v2rayn/v2rayN/ServiceLib/Global.cs b/v2rayn/v2rayN/ServiceLib/Global.cs index 733c569d44..a7c74c083e 100644 --- a/v2rayn/v2rayN/ServiceLib/Global.cs +++ b/v2rayn/v2rayN/ServiceLib/Global.cs @@ -560,6 +560,7 @@ public class Global { ECoreType.brook, "txthinking/brook" }, { ECoreType.overtls, "ShadowsocksR-Live/overtls" }, { ECoreType.shadowquic, "spongebob888/shadowquic" }, + { ECoreType.mieru, "enfein/mieru" }, { ECoreType.v2rayN, "2dust/v2rayN" }, }; diff --git a/v2rayn/v2rayN/ServiceLib/Manager/CoreInfoManager.cs b/v2rayn/v2rayN/ServiceLib/Manager/CoreInfoManager.cs index 12345499fb..790e883902 100644 --- a/v2rayn/v2rayN/ServiceLib/Manager/CoreInfoManager.cs +++ b/v2rayn/v2rayN/ServiceLib/Manager/CoreInfoManager.cs @@ -80,6 +80,10 @@ public sealed class CoreInfoManager Url = GetCoreUrl(ECoreType.v2fly), Match = "V2Ray", VersionArg = "-version", + Environment = new Dictionary() + { + { Global.V2RayLocalAsset, Utils.GetBinPath("") }, + }, }, new CoreInfo @@ -90,6 +94,10 @@ public sealed class CoreInfoManager Url = GetCoreUrl(ECoreType.v2fly_v5), Match = "V2Ray", VersionArg = "version", + Environment = new Dictionary() + { + { Global.V2RayLocalAsset, Utils.GetBinPath("") }, + }, }, new CoreInfo @@ -107,6 +115,11 @@ public sealed class CoreInfoManager DownloadUrlOSXArm64 = urlXray + "/download/{0}/Xray-macos-arm64-v8a.zip", Match = "Xray", VersionArg = "-version", + Environment = new Dictionary() + { + { Global.XrayLocalAsset, Utils.GetBinPath("") }, + { Global.XrayLocalCert, Utils.GetBinPath("") }, + }, }, new CoreInfo @@ -205,12 +218,24 @@ public sealed class CoreInfoManager new CoreInfo { CoreType = ECoreType.shadowquic, - CoreExes = [ "shadowquic", "shadowquic"], + CoreExes = [ "shadowquic" ], Arguments = "-c {0}", Url = GetCoreUrl(ECoreType.shadowquic), AbsolutePath = false, - } + }, + new CoreInfo + { + CoreType = ECoreType.mieru, + CoreExes = [ "mieru" ], + Arguments = "run", + Url = GetCoreUrl(ECoreType.mieru), + AbsolutePath = false, + Environment = new Dictionary() + { + { "MIERU_CONFIG_JSON_FILE", "{0}" }, + }, + }, ]; } diff --git a/v2rayn/v2rayN/ServiceLib/Manager/CoreManager.cs b/v2rayn/v2rayN/ServiceLib/Manager/CoreManager.cs index d0fcc0fa03..74cdaf917a 100644 --- a/v2rayn/v2rayN/ServiceLib/Manager/CoreManager.cs +++ b/v2rayn/v2rayN/ServiceLib/Manager/CoreManager.cs @@ -22,10 +22,6 @@ public class CoreManager _config = config; _updateFunc = updateFunc; - Environment.SetEnvironmentVariable(Global.V2RayLocalAsset, Utils.GetBinPath(""), EnvironmentVariableTarget.Process); - Environment.SetEnvironmentVariable(Global.XrayLocalAsset, Utils.GetBinPath(""), EnvironmentVariableTarget.Process); - Environment.SetEnvironmentVariable(Global.XrayLocalCert, Utils.GetBinPath(""), EnvironmentVariableTarget.Process); - //Copy the bin folder to the storage location (for init) if (Environment.GetEnvironmentVariable(Global.LocalAppData) == "1") { @@ -277,6 +273,10 @@ public class CoreManager StandardErrorEncoding = displayLog ? Encoding.UTF8 : null, } }; + foreach (var kv in coreInfo.Environment) + { + proc.StartInfo.Environment[kv.Key] = string.Format(kv.Value, coreInfo.AbsolutePath ? Utils.GetBinConfigPath(configPath).AppendQuotes() : configPath); + } if (displayLog) { diff --git a/v2rayn/v2rayN/ServiceLib/Models/CoreInfo.cs b/v2rayn/v2rayN/ServiceLib/Models/CoreInfo.cs index faf899a934..eb4404cb7e 100644 --- a/v2rayn/v2rayN/ServiceLib/Models/CoreInfo.cs +++ b/v2rayn/v2rayN/ServiceLib/Models/CoreInfo.cs @@ -17,4 +17,5 @@ public class CoreInfo public string? Match { get; set; } public string? VersionArg { get; set; } public bool AbsolutePath { get; set; } + public IDictionary Environment { get; set; } = new Dictionary(); } diff --git a/v2rayng/V2rayNG/app/src/main/java/com/v2ray/ang/ui/PerAppProxyActivity.kt b/v2rayng/V2rayNG/app/src/main/java/com/v2ray/ang/ui/PerAppProxyActivity.kt index b0df22e522..3835cff9db 100644 --- a/v2rayng/V2rayNG/app/src/main/java/com/v2ray/ang/ui/PerAppProxyActivity.kt +++ b/v2rayng/V2rayNG/app/src/main/java/com/v2ray/ang/ui/PerAppProxyActivity.kt @@ -56,8 +56,14 @@ class PerAppProxyActivity : BaseActivity() { appsList.sortedWith { p1, p2 -> when { p1.isSelected > p2.isSelected -> -1 - p1.isSelected == p2.isSelected -> 0 - else -> 1 + p1.isSelected < p2.isSelected -> 1 + p1.isSystemApp > p2.isSystemApp -> 1 + p1.isSystemApp < p2.isSystemApp -> -1 + p1.appName.lowercase() > p2.appName.lowercase() -> 1 + p1.appName.lowercase() < p2.appName.lowercase() -> -1 + p1.packageName > p2.packageName -> 1 + p1.packageName < p2.packageName -> -1 + else -> 0 } } } else { diff --git a/v2rayng/V2rayNG/gradle/libs.versions.toml b/v2rayng/V2rayNG/gradle/libs.versions.toml index aec0224b59..6ffe5c2163 100644 --- a/v2rayng/V2rayNG/gradle/libs.versions.toml +++ b/v2rayng/V2rayNG/gradle/libs.versions.toml @@ -1,12 +1,12 @@ [versions] -agp = "8.12.0" +agp = "8.12.1" desugarJdkLibs = "2.1.5" gradleLicensePlugin = "0.9.8" -kotlin = "2.2.0" +kotlin = "2.2.10" coreKtx = "1.16.0" junit = "4.13.2" -junitVersion = "1.2.1" -espressoCore = "3.6.1" +junitVersion = "1.3.0" +espressoCore = "3.7.0" appcompat = "1.7.1" material = "1.12.0" activity = "1.10.1" @@ -20,7 +20,7 @@ swiperefreshlayout = "1.1.0" toasty = "1.5.2" editorkit = "2.9.0" core = "3.5.3" -workRuntimeKtx = "2.10.2" +workRuntimeKtx = "2.10.3" lifecycleViewmodelKtx = "2.9.2" multidex = "2.0.1" mockitoMockitoInline = "5.2.0" diff --git a/xray-core/go.mod b/xray-core/go.mod index e983e336a4..c5e8d2e2a8 100644 --- a/xray-core/go.mod +++ b/xray-core/go.mod @@ -16,7 +16,7 @@ require ( github.com/sagernet/sing v0.5.1 github.com/sagernet/sing-shadowsocks v0.2.7 github.com/seiflotfy/cuckoofilter v0.0.0-20240715131351-a2f2c23f1771 - github.com/stretchr/testify v1.10.0 + github.com/stretchr/testify v1.11.0 github.com/v2fly/ss-bloomring v0.0.0-20210312155135-28617310f63e github.com/vishvananda/netlink v1.3.1 github.com/xtls/reality v0.0.0-20250725142056-5b52a03d4fb7 diff --git a/xray-core/go.sum b/xray-core/go.sum index 1b4675278c..f6c95e350e 100644 --- a/xray-core/go.sum +++ b/xray-core/go.sum @@ -67,8 +67,8 @@ github.com/seiflotfy/cuckoofilter v0.0.0-20240715131351-a2f2c23f1771 h1:emzAzMZ1 github.com/seiflotfy/cuckoofilter v0.0.0-20240715131351-a2f2c23f1771/go.mod h1:bR6DqgcAl1zTcOX8/pE2Qkj9XO00eCNqmKb7lXP8EAg= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.6.1/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.0 h1:ib4sjIrwZKxE5u/Japgo/7SJV3PvgjGiRNAvTVGqQl8= +github.com/stretchr/testify v1.11.0/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= github.com/v2fly/ss-bloomring v0.0.0-20210312155135-28617310f63e h1:5QefA066A1tF8gHIiADmOVOV5LS43gt3ONnlEl3xkwI= github.com/v2fly/ss-bloomring v0.0.0-20210312155135-28617310f63e/go.mod h1:5t19P9LBIrNamL6AcMQOncg/r10y3Pc01AbHeMhwlpU= github.com/vishvananda/netlink v1.3.1 h1:3AEMt62VKqz90r0tmNhog0r/PpWKmrEShJU0wJW6bV0=