From c6a142ac6548eaf5a33e12c41d74440dc616958a Mon Sep 17 00:00:00 2001 From: "github-action[bot]" Date: Fri, 22 Aug 2025 20:39:51 +0200 Subject: [PATCH] Update On Fri Aug 22 20:39:51 CEST 2025 --- .github/update.log | 1 + brook/protocol/user.md | 4 + clash-meta/common/buf/sing.go | 1 + clash-meta/common/net/sing.go | 4 + clash-meta/go.mod | 2 +- clash-meta/go.sum | 4 +- clash-meta/listener/inbound/common_test.go | 4 +- .../transport/vless/encryption/client.go | 38 +- .../transport/vless/encryption/common.go | 11 +- clash-meta/transport/vless/encryption/doc.go | 2 + .../transport/vless/encryption/server.go | 88 ++-- clash-meta/transport/vless/encryption/xor.go | 2 +- clash-meta/transport/vless/vision/conn.go | 72 ++- clash-meta/transport/vless/vision/padding.go | 40 +- clash-nyanpasu/backend/Cargo.lock | 64 +-- clash-nyanpasu/frontend/nyanpasu/package.json | 2 +- clash-nyanpasu/manifest/version.json | 4 +- clash-nyanpasu/pnpm-lock.yaml | 10 +- filebrowser/tools/go.mod | 2 +- filebrowser/tools/go.sum | 4 +- .../base-files/files/etc/rc.button/reset | 2 +- lede/package/base-files/files/sbin/firstboot | 2 +- lede/package/system/fstools/Makefile | 11 +- .../system/fstools/patches/0001-EroFS.patch | 139 ------ .../fstools/patches/0100-automount.patch | 20 - mieru/.github/ISSUE_TEMPLATE/bug_report.yaml | 2 - .../.github/ISSUE_TEMPLATE/bug_report_zh.yaml | 2 - mieru/test/deploy/packetdrop/client_tcp.json | 3 +- mieru/test/deploy/packetdrop/client_udp.json | 3 +- mihomo/common/buf/sing.go | 1 + mihomo/common/net/sing.go | 4 + mihomo/go.mod | 2 +- mihomo/go.sum | 4 +- mihomo/listener/inbound/common_test.go | 4 +- mihomo/transport/vless/encryption/client.go | 38 +- mihomo/transport/vless/encryption/common.go | 11 +- mihomo/transport/vless/encryption/doc.go | 2 + mihomo/transport/vless/encryption/server.go | 88 ++-- mihomo/transport/vless/encryption/xor.go | 2 +- mihomo/transport/vless/vision/conn.go | 72 ++- mihomo/transport/vless/vision/padding.go | 40 +- .../luasrc/controller/passwall.lua | 23 +- .../luasrc/view/passwall/global/backup.htm | 13 +- openwrt-passwall2/luci-app-passwall2/Makefile | 2 +- .../cbi/passwall2/client/type/hysteria2.lua | 8 +- .../model/cbi/passwall2/client/type/ray.lua | 13 +- .../cbi/passwall2/client/type/sing-box.lua | 40 +- .../luasrc/passwall2/util_sing-box.lua | 12 +- .../luasrc/passwall2/util_xray.lua | 5 +- .../passwall2/node_list/link_share_man.htm | 24 +- .../luci-app-passwall2/po/zh-cn/passwall2.po | 6 + .../root/usr/share/passwall2/app.sh | 18 +- .../root/usr/share/passwall2/iptables.sh | 12 +- .../root/usr/share/passwall2/nftables.sh | 12 +- .../root/usr/share/passwall2/subscribe.lua | 7 +- shadowsocks-rust/Cargo.lock | 8 +- sing-box/adapter/outbound.go | 7 + sing-box/adapter/router.go | 3 +- sing-box/common/dialer/default.go | 8 + sing-box/go.mod | 4 +- sing-box/go.sum | 8 +- sing-box/protocol/direct/outbound.go | 11 +- sing-box/protocol/tailscale/endpoint.go | 15 +- sing-box/protocol/tun/inbound.go | 13 +- sing-box/protocol/wireguard/endpoint.go | 16 +- sing-box/route/route.go | 35 +- sing-box/transport/wireguard/device.go | 8 + sing-box/transport/wireguard/device_nat.go | 85 ++++ .../transport/wireguard/device_nat_gvisor.go | 48 ++ .../wireguard/device_nat_non_gvisor.go | 20 + sing-box/transport/wireguard/device_stack.go | 233 ++++++++- sing-box/transport/wireguard/device_system.go | 28 ++ sing-box/transport/wireguard/endpoint.go | 23 +- small/luci-app-fchomo/root/etc/init.d/fchomo | 9 +- .../usr/share/rpcd/acl.d/luci-app-nikki.json | 4 - .../luasrc/controller/passwall.lua | 23 +- .../luasrc/view/passwall/global/backup.htm | 13 +- small/luci-app-passwall2/Makefile | 2 +- .../cbi/passwall2/client/type/hysteria2.lua | 8 +- .../model/cbi/passwall2/client/type/ray.lua | 13 +- .../cbi/passwall2/client/type/sing-box.lua | 40 +- .../luasrc/passwall2/util_sing-box.lua | 12 +- .../luasrc/passwall2/util_xray.lua | 5 +- .../passwall2/node_list/link_share_man.htm | 24 +- .../luci-app-passwall2/po/zh-cn/passwall2.po | 6 + .../root/usr/share/passwall2/app.sh | 18 +- .../root/usr/share/passwall2/iptables.sh | 12 +- .../root/usr/share/passwall2/nftables.sh | 12 +- .../root/usr/share/passwall2/subscribe.lua | 7 +- .../model/cbi/shadowsocksr/client-config.lua | 16 +- .../luasrc/view/shadowsocksr/ssrurl.htm | 16 +- .../po/templates/ssr-plus.pot | 455 +++++++++--------- .../luci-app-ssr-plus/po/zh_Hans/ssr-plus.po | 455 +++++++++--------- .../usr/share/shadowsocksr/gen_config.lua | 28 +- small/nikki/files/nikki.upgrade | 2 - small/nikki/files/ucode/hijack.ut | 4 +- small/v2ray-geodata/Makefile | 4 +- yt-dlp/yt_dlp/cookies.py | 17 +- yt-dlp/yt_dlp/extractor/mediaklikk.py | 131 ++--- 99 files changed, 1633 insertions(+), 1282 deletions(-) delete mode 100644 lede/package/system/fstools/patches/0001-EroFS.patch delete mode 100644 lede/package/system/fstools/patches/0100-automount.patch create mode 100644 sing-box/transport/wireguard/device_nat.go create mode 100644 sing-box/transport/wireguard/device_nat_gvisor.go create mode 100644 sing-box/transport/wireguard/device_nat_non_gvisor.go diff --git a/.github/update.log b/.github/update.log index d072464c43..85a20acd71 100644 --- a/.github/update.log +++ b/.github/update.log @@ -1097,3 +1097,4 @@ Update On Mon Aug 18 20:42:30 CEST 2025 Update On Tue Aug 19 20:36:45 CEST 2025 Update On Wed Aug 20 20:53:01 CEST 2025 Update On Thu Aug 21 20:41:11 CEST 2025 +Update On Fri Aug 22 20:39:42 CEST 2025 diff --git a/brook/protocol/user.md b/brook/protocol/user.md index 1ebb7e5097..e4e3cda47c 100644 --- a/brook/protocol/user.md +++ b/brook/protocol/user.md @@ -80,3 +80,7 @@ brook link --server 1.2.3.4:9999 --password hello --token xxx ## A sample implementation https://github.com/TxThinkingInc/brook-store + +## Read more + +[Brook Business: Powering Your Own Branded Client](https://www.txthinking.com/talks/articles/brook-business-en.article) diff --git a/clash-meta/common/buf/sing.go b/clash-meta/common/buf/sing.go index 59c650adeb..73f65f150d 100644 --- a/clash-meta/common/buf/sing.go +++ b/clash-meta/common/buf/sing.go @@ -14,6 +14,7 @@ var NewPacket = buf.NewPacket var NewSize = buf.NewSize var With = buf.With var As = buf.As +var ReleaseMulti = buf.ReleaseMulti var ( Must = common.Must diff --git a/clash-meta/common/net/sing.go b/clash-meta/common/net/sing.go index 2cd1d726af..5cf9759427 100644 --- a/clash-meta/common/net/sing.go +++ b/clash-meta/common/net/sing.go @@ -22,6 +22,10 @@ type ExtendedReader = network.ExtendedReader var WriteBuffer = bufio.WriteBuffer +type ReadWaitOptions = network.ReadWaitOptions + +var NewReadWaitOptions = network.NewReadWaitOptions + func NewDeadlineConn(conn net.Conn) ExtendedConn { if deadline.IsPipe(conn) || deadline.IsPipe(network.UnwrapReader(conn)) { return NewExtendedConn(conn) // pipe always have correctly deadline implement diff --git a/clash-meta/go.mod b/clash-meta/go.mod index 57c10000ba..eb949cd582 100644 --- a/clash-meta/go.mod +++ b/clash-meta/go.mod @@ -31,7 +31,7 @@ require ( 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.7 - github.com/metacubex/sing-vmess v0.2.4-0.20250821024956-97839f31a65d + 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 github.com/metacubex/tfo-go v0.0.0-20250516165257-e29c16ae41d4 diff --git a/clash-meta/go.sum b/clash-meta/go.sum index d8bfd9a592..ca829a3f21 100644 --- a/clash-meta/go.sum +++ b/clash-meta/go.sum @@ -131,8 +131,8 @@ github.com/metacubex/sing-shadowtls v0.0.0-20250503063515-5d9f966d17a2 h1:gXU+MY github.com/metacubex/sing-shadowtls v0.0.0-20250503063515-5d9f966d17a2/go.mod h1:mbfboaXauKJNIHJYxQRa+NJs4JU9NZfkA+I33dS2+9E= 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.20250821024956-97839f31a65d h1:jchYEho5+kTmok4aTMflqJyTRnqVPTOVeC1RFXxuw9A= -github.com/metacubex/sing-vmess v0.2.4-0.20250821024956-97839f31a65d/go.mod h1:21R5R1u90uUvBQF0owoooEu96/SAYYD56nDrwm6nFaM= +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= github.com/metacubex/sing-wireguard v0.0.0-20250503063753-2dc62acc626f/go.mod h1:jpAkVLPnCpGSfNyVmj6Cq4YbuZsFepm/Dc+9BAOcR80= github.com/metacubex/smux v0.0.0-20250503055512-501391591dee h1:lp6hJ+4wCLZu113awp7P6odM2okB5s60HUyF0FMqKmo= diff --git a/clash-meta/listener/inbound/common_test.go b/clash-meta/listener/inbound/common_test.go index 75b98e0bc4..79e382fa81 100644 --- a/clash-meta/listener/inbound/common_test.go +++ b/clash-meta/listener/inbound/common_test.go @@ -1,6 +1,7 @@ package inbound_test import ( + "bytes" "context" "crypto/rand" "crypto/tls" @@ -142,6 +143,7 @@ func NewHttpTestTunnel() *TestTunnel { render.PlainText(w, r, err.Error()) return } + io.Copy(io.Discard, r.Body) render.Data(w, r, httpData[:size]) }) h2Server := &http2.Server{} @@ -149,7 +151,7 @@ func NewHttpTestTunnel() *TestTunnel { _ = http2.ConfigureServer(&server, h2Server) go server.Serve(ln) testFn := func(t *testing.T, proxy C.ProxyAdapter, proto string, size int) { - req, err := http.NewRequest(http.MethodGet, fmt.Sprintf("%s://%s%s?size=%d", proto, remoteAddr, httpPath, size), nil) + req, err := http.NewRequest(http.MethodGet, fmt.Sprintf("%s://%s%s?size=%d", proto, remoteAddr, httpPath, size), bytes.NewReader(httpData[:size])) if !assert.NoError(t, err) { return } diff --git a/clash-meta/transport/vless/encryption/client.go b/clash-meta/transport/vless/encryption/client.go index dfa4fa63b7..cd94758750 100644 --- a/clash-meta/transport/vless/encryption/client.go +++ b/clash-meta/transport/vless/encryption/client.go @@ -57,7 +57,7 @@ type ClientConn struct { random []byte aead cipher.AEAD nonce []byte - peerAead cipher.AEAD + peerAEAD cipher.AEAD peerNonce []byte input bytes.Reader // peerCache } @@ -70,13 +70,13 @@ func (i *ClientInstance) Init(nfsEKeyBytes, xorPKeyBytes []byte, xorMode, minute if i.nfsEKey, err = mlkem.NewEncapsulationKey768(nfsEKeyBytes); err != nil { return } - hash32 := sha3.Sum256(nfsEKeyBytes) - copy(i.hash11[:], hash32[:]) if xorMode > 0 { i.xorMode = xorMode if i.xorPKey, err = ecdh.X25519().NewPublicKey(xorPKeyBytes); err != nil { return } + hash32 := sha3.Sum256(nfsEKeyBytes) + copy(i.hash11[:], hash32[:]) } i.minutes = time.Duration(minutes) * time.Minute return @@ -108,23 +108,25 @@ func (i *ClientInstance) Handshake(conn net.Conn) (*ClientConn, error) { pfsDKey, _ := mlkem.NewDecapsulationKey768(pfsDKeySeed) pfsEKeyBytes := pfsDKey.EncapsulationKey().Bytes() nfsKey, encapsulatedNfsKey := i.nfsEKey.Encapsulate() - paddingLen := randBetween(100, 1000) + nfsAEAD := NewAEAD(ClientCipher, nfsKey, pfsEKeyBytes, encapsulatedNfsKey) - clientHello := make([]byte, 5+11+1+1184+1088+5+paddingLen) + clientHello := make([]byte, 5+11+1+1184+1088+randBetween(100, 1000)) EncodeHeader(clientHello, 1, 11+1+1184+1088) copy(clientHello[5:], i.hash11[:]) clientHello[5+11] = ClientCipher copy(clientHello[5+11+1:], pfsEKeyBytes) copy(clientHello[5+11+1+1184:], encapsulatedNfsKey) - EncodeHeader(clientHello[5+11+1+1184+1088:], 23, int(paddingLen)) - rand.Read(clientHello[5+11+1+1184+1088+5:]) + padding := clientHello[5+11+1+1184+1088:] + rand.Read(padding) // important + EncodeHeader(padding, 23, len(padding)-5) + nfsAEAD.Seal(padding[:5], clientHello[5:5+11+1], padding[5:len(padding)-16], padding[:5]) if _, err := c.Conn.Write(clientHello); err != nil { return nil, err } - // client can send more paddings / NFS AEAD messages if needed + // client can send more NFS AEAD paddings / messages if needed - _, t, l, err := ReadAndDiscardPaddings(c.Conn) // allow paddings before server hello + _, t, l, err := ReadAndDiscardPaddings(c.Conn, nil, nil) // allow paddings before server hello if err != nil { return nil, err } @@ -206,10 +208,10 @@ func (c *ClientConn) Read(b []byte) (int, error) { if len(b) == 0 { return 0, nil } - if c.peerAead == nil { - _, t, l, err := ReadAndDiscardPaddings(c.Conn) // allow paddings before random hello + if c.peerAEAD == nil { + _, t, l, err := ReadAndDiscardPaddings(c.Conn, nil, nil) // allow paddings before random hello if err != nil { - if c.instance != nil && strings.HasPrefix(err.Error(), "invalid header: ") { // 0-RTT's 0-RTT + if c.instance != nil && strings.HasPrefix(err.Error(), "invalid header: ") { // 0-RTT c.instance.Lock() if bytes.Equal(c.ticket, c.instance.ticket) { c.instance.expire = time.Now() // expired @@ -232,7 +234,7 @@ func (c *ClientConn) Read(b []byte) (int, error) { if c.random == nil { return 0, errors.New("empty c.random") } - c.peerAead = NewAEAD(ClientCipher, c.baseKey, peerRandomHello, c.random) + c.peerAEAD = NewAEAD(ClientCipher, c.baseKey, peerRandomHello, c.random) c.peerNonce = make([]byte, 12) } if c.input.Len() > 0 { @@ -253,13 +255,13 @@ func (c *ClientConn) Read(b []byte) (int, error) { if len(dst) <= len(b) { dst = b[:len(dst)] // avoids another copy() } - var peerAead cipher.AEAD + var peerAEAD cipher.AEAD if bytes.Equal(c.peerNonce, MaxNonce) { - peerAead = NewAEAD(ClientCipher, c.baseKey, peerData, h) + peerAEAD = NewAEAD(ClientCipher, c.baseKey, peerData, h) } - _, err = c.peerAead.Open(dst[:0], c.peerNonce, peerData, h) - if peerAead != nil { - c.peerAead = peerAead + _, err = c.peerAEAD.Open(dst[:0], c.peerNonce, peerData, h) + if peerAEAD != nil { + c.peerAEAD = peerAEAD } IncreaseNonce(c.peerNonce) if err != nil { diff --git a/clash-meta/transport/vless/encryption/common.go b/clash-meta/transport/vless/encryption/common.go index d383d22e98..84784cb2e1 100644 --- a/clash-meta/transport/vless/encryption/common.go +++ b/clash-meta/transport/vless/encryption/common.go @@ -62,14 +62,21 @@ func ReadAndDecodeHeader(conn net.Conn) (h []byte, t byte, l int, err error) { return } -func ReadAndDiscardPaddings(conn net.Conn) (h []byte, t byte, l int, err error) { +func ReadAndDiscardPaddings(conn net.Conn, aead cipher.AEAD, nonce []byte) (h []byte, t byte, l int, err error) { for { if h, t, l, err = ReadAndDecodeHeader(conn); err != nil || t != 23 { return } - if _, err = io.ReadFull(conn, make([]byte, l)); err != nil { + padding := make([]byte, l) + if _, err = io.ReadFull(conn, padding); err != nil { return } + if aead != nil { + if _, err := aead.Open(nil, nonce, padding, h); err != nil { + return h, t, l, err + } + IncreaseNonce(nonce) + } } } diff --git a/clash-meta/transport/vless/encryption/doc.go b/clash-meta/transport/vless/encryption/doc.go index 10cd320b2b..8e3ff8a9ea 100644 --- a/clash-meta/transport/vless/encryption/doc.go +++ b/clash-meta/transport/vless/encryption/doc.go @@ -15,4 +15,6 @@ // https://github.com/XTLS/Xray-core/commit/49580705f6029648399304b816a2737f991582a8 // https://github.com/XTLS/Xray-core/commit/84835bec7d0d8555d0dd30953ed26a272de814c4 // https://github.com/XTLS/Xray-core/commit/373558ed7abdbac3de41745cf30ec04c9adde604 +// https://github.com/XTLS/Xray-core/commit/38cc306c955c362f044e074049a5e67b6b9fb389 +// https://github.com/XTLS/Xray-core/commit/b33555cc0a52d0af3c23d2af8fca42f8a685d9af package encryption diff --git a/clash-meta/transport/vless/encryption/server.go b/clash-meta/transport/vless/encryption/server.go index baa8432cd0..6df2729baa 100644 --- a/clash-meta/transport/vless/encryption/server.go +++ b/clash-meta/transport/vless/encryption/server.go @@ -40,7 +40,7 @@ type ServerConn struct { baseKey []byte ticket []byte peerRandom []byte - peerAead cipher.AEAD + peerAEAD cipher.AEAD peerNonce []byte input bytes.Reader // peerCache aead cipher.AEAD @@ -55,13 +55,13 @@ func (i *ServerInstance) Init(nfsDKeySeed, xorSKeyBytes []byte, xorMode, minutes if i.nfsDKey, err = mlkem.NewDecapsulationKey768(nfsDKeySeed); err != nil { return } - hash32 := sha3.Sum256(i.nfsDKey.EncapsulationKey().Bytes()) - copy(i.hash11[:], hash32[:]) if xorMode > 0 { i.xorMode = xorMode if i.xorSKey, err = ecdh.X25519().NewPrivateKey(xorSKeyBytes); err != nil { return } + hash32 := sha3.Sum256(i.nfsDKey.EncapsulationKey().Bytes()) + copy(i.hash11[:], hash32[:]) } if minutes > 0 { i.minutes = time.Duration(minutes) * time.Minute @@ -106,7 +106,7 @@ func (i *ServerInstance) Handshake(conn net.Conn) (*ServerConn, error) { } c := &ServerConn{Conn: conn} - _, t, l, err := ReadAndDiscardPaddings(c.Conn) // allow paddings before client/ticket hello + _, t, l, err := ReadAndDiscardPaddings(c.Conn, nil, nil) // allow paddings before client/ticket hello if err != nil { return nil, err } @@ -170,32 +170,57 @@ func (i *ServerInstance) Handshake(conn net.Conn) (*ServerConn, error) { if err != nil { return nil, err } + nfsAEAD := NewAEAD(c.cipher, nfsKey, pfsEKeyBytes, encapsulatedNfsKey) + nfsNonce := append([]byte{}, peerClientHello[:11+1]...) pfsKey, encapsulatedPfsKey := pfsEKey.Encapsulate() c.baseKey = append(pfsKey, nfsKey...) + pfsAEAD := NewAEAD(c.cipher, c.baseKey, encapsulatedPfsKey, encapsulatedNfsKey) + pfsNonce := append([]byte{}, peerClientHello[:11+1]...) + c.ticket = append(i.hash11[:], pfsAEAD.Seal(nil, pfsNonce, []byte("VLESS"), pfsEKeyBytes)...) + IncreaseNonce(pfsNonce) - c.ticket = append(i.hash11[:], NewAEAD(c.cipher, c.baseKey, encapsulatedPfsKey, encapsulatedNfsKey).Seal(nil, peerClientHello[:12], []byte("VLESS"), pfsEKeyBytes)...) - - paddingLen := randBetween(100, 1000) - - serverHello := make([]byte, 5+1088+21+5+paddingLen) + serverHello := make([]byte, 5+1088+21+randBetween(100, 1000)) EncodeHeader(serverHello, 1, 1088+21) copy(serverHello[5:], encapsulatedPfsKey) copy(serverHello[5+1088:], c.ticket[11:]) - EncodeHeader(serverHello[5+1088+21:], 23, int(paddingLen)) - rand.Read(serverHello[5+1088+21+5:]) + padding := serverHello[5+1088+21:] + rand.Read(padding) // important + EncodeHeader(padding, 23, len(padding)-5) + pfsAEAD.Seal(padding[:5], pfsNonce, padding[5:len(padding)-16], padding[:5]) if _, err := c.Conn.Write(serverHello); err != nil { return nil, err } - // server can send more paddings / PFS AEAD messages if needed + // server can send more PFS AEAD paddings / messages if needed + + _, t, l, err = ReadAndDiscardPaddings(c.Conn, nfsAEAD, nfsNonce) // allow paddings before ticket hello + if err != nil { + return nil, err + } + if t != 0 { + return nil, fmt.Errorf("unexpected type %v, expect ticket hello", t) + } + peerTicketHello := make([]byte, 32+32) + if l != len(peerTicketHello) { + return nil, fmt.Errorf("unexpected length %v for ticket hello", l) + } + if _, err := io.ReadFull(c.Conn, peerTicketHello); err != nil { + return nil, err + } + if !bytes.Equal(peerTicketHello[:32], c.ticket) { + return nil, errors.New("naughty boy") + } + c.peerRandom = peerTicketHello[32:] if i.minutes > 0 { i.Lock() - i.sessions[[32]byte(c.ticket)] = &ServerSession{ + s := &ServerSession{ expire: time.Now().Add(i.minutes), cipher: c.cipher, baseKey: c.baseKey, } + s.randoms.Store([32]byte(c.peerRandom), true) + i.sessions[[32]byte(c.ticket)] = s i.Unlock() } @@ -206,28 +231,8 @@ func (c *ServerConn) Read(b []byte) (int, error) { if len(b) == 0 { return 0, nil } - if c.peerAead == nil { - if c.peerRandom == nil { // 1-RTT's 0-RTT - _, t, l, err := ReadAndDiscardPaddings(c.Conn) // allow paddings before ticket hello - if err != nil { - return 0, err - } - if t != 0 { - return 0, fmt.Errorf("unexpected type %v, expect ticket hello", t) - } - peerTicketHello := make([]byte, 32+32) - if l != len(peerTicketHello) { - return 0, fmt.Errorf("unexpected length %v for ticket hello", l) - } - if _, err := io.ReadFull(c.Conn, peerTicketHello); err != nil { - return 0, err - } - if !bytes.Equal(peerTicketHello[:32], c.ticket) { - return 0, errors.New("naughty boy") - } - c.peerRandom = peerTicketHello[32:] - } - c.peerAead = NewAEAD(c.cipher, c.baseKey, c.peerRandom, c.ticket) + if c.peerAEAD == nil { + c.peerAEAD = NewAEAD(c.cipher, c.baseKey, c.peerRandom, c.ticket) c.peerNonce = make([]byte, 12) } if c.input.Len() > 0 { @@ -248,13 +253,13 @@ func (c *ServerConn) Read(b []byte) (int, error) { if len(dst) <= len(b) { dst = b[:len(dst)] // avoids another copy() } - var peerAead cipher.AEAD + var peerAEAD cipher.AEAD if bytes.Equal(c.peerNonce, MaxNonce) { - peerAead = NewAEAD(c.cipher, c.baseKey, peerData, h) + peerAEAD = NewAEAD(c.cipher, c.baseKey, peerData, h) } - _, err = c.peerAead.Open(dst[:0], c.peerNonce, peerData, h) - if peerAead != nil { - c.peerAead = peerAead + _, err = c.peerAEAD.Open(dst[:0], c.peerNonce, peerData, h) + if peerAEAD != nil { + c.peerAEAD = peerAEAD } IncreaseNonce(c.peerNonce) if err != nil { @@ -279,9 +284,6 @@ func (c *ServerConn) Write(b []byte) (int, error) { } n += len(b) if c.aead == nil { - if c.peerRandom == nil { - return 0, errors.New("empty c.peerRandom") - } data = make([]byte, 5+32+5+len(b)+16) EncodeHeader(data, 0, 32) rand.Read(data[5 : 5+32]) diff --git a/clash-meta/transport/vless/encryption/xor.go b/clash-meta/transport/vless/encryption/xor.go index 88bd76982e..a97bb8718d 100644 --- a/clash-meta/transport/vless/encryption/xor.go +++ b/clash-meta/transport/vless/encryption/xor.go @@ -57,7 +57,7 @@ func NewXorConn(conn net.Conn, mode uint32, pKey *ecdh.PublicKey, sKey *ecdh.Pri if pKey != nil { c.head = make([]byte, 16+32) rand.Read(c.head) - eSKey, _ := ecdh.X25519().GenerateKey(rand.Reader) + eSKey, _ := ecdh.X25519().NewPrivateKey(c.head[16:]) NewCTR(pKey.Bytes(), c.head[:16], false).XORKeyStream(c.head[16:], eSKey.PublicKey().Bytes()) // make X25519 public key distinguishable from random bytes c.key, _ = eSKey.ECDH(pKey) c.ctr = NewCTR(c.key, c.head[:16], false) diff --git a/clash-meta/transport/vless/vision/conn.go b/clash-meta/transport/vless/vision/conn.go index b8367fb9e4..0c300e05d1 100644 --- a/clash-meta/transport/vless/vision/conn.go +++ b/clash-meta/transport/vless/vision/conn.go @@ -170,7 +170,7 @@ func (vc *Conn) WriteBuffer(buffer *buf.Buffer) (err error) { if vc.needHandshake { vc.needHandshake = false if buffer.IsEmpty() { - ApplyPadding(buffer, commandPaddingContinue, vc.userUUID, false) + ApplyPadding(buffer, commandPaddingContinue, vc.userUUID, true) // we do a long padding to hide vless header } else { vc.FilterTLS(buffer.Bytes()) ApplyPadding(buffer, commandPaddingContinue, vc.userUUID, vc.isTLS) @@ -190,55 +190,37 @@ func (vc *Conn) WriteBuffer(buffer *buf.Buffer) (err error) { } if vc.writeFilterApplicationData { - buffer2 := ReshapeBuffer(buffer) - defer buffer2.Release() vc.FilterTLS(buffer.Bytes()) - command := commandPaddingContinue - if !vc.isTLS { - command = commandPaddingEnd - - // disable XTLS - //vc.readProcess = false - vc.writeFilterApplicationData = false - vc.packetsToFilter = 0 - } else if buffer.Len() > 6 && bytes.Equal(buffer.To(3), tlsApplicationDataStart) || vc.packetsToFilter <= 0 { - command = commandPaddingEnd - if vc.enableXTLS { - command = commandPaddingDirect - vc.writeDirect = true - } - vc.writeFilterApplicationData = false - } - ApplyPadding(buffer, command, nil, vc.isTLS) - err = vc.ExtendedWriter.WriteBuffer(buffer) - if err != nil { - return err - } - if vc.writeDirect { - vc.ExtendedWriter = N.NewExtendedWriter(vc.netConn) - log.Debugln("XTLS Vision direct write start") - //time.Sleep(5 * time.Millisecond) - } - if buffer2 != nil { - if vc.writeDirect || !vc.isTLS { - return vc.ExtendedWriter.WriteBuffer(buffer2) - } - vc.FilterTLS(buffer2.Bytes()) - command = commandPaddingContinue - if buffer2.Len() > 6 && bytes.Equal(buffer2.To(3), tlsApplicationDataStart) || vc.packetsToFilter <= 0 { - command = commandPaddingEnd - if vc.enableXTLS { - command = commandPaddingDirect - vc.writeDirect = true + buffers := vc.ReshapeBuffer(buffer) + applyPadding := true + for i, buffer := range buffers { + command := commandPaddingContinue + if applyPadding { + if vc.isTLS && buffer.Len() > 6 && bytes.Equal(buffer.To(3), tlsApplicationDataStart) { + command = commandPaddingEnd + if vc.enableXTLS { + command = commandPaddingDirect + vc.writeDirect = true + } + vc.writeFilterApplicationData = false + applyPadding = false + } else if !vc.isTLS12orAbove && vc.packetsToFilter <= 1 { + command = commandPaddingEnd + vc.writeFilterApplicationData = false + applyPadding = false } - vc.writeFilterApplicationData = false + ApplyPadding(buffer, command, nil, vc.isTLS) } - ApplyPadding(buffer2, command, nil, vc.isTLS) - err = vc.ExtendedWriter.WriteBuffer(buffer2) - if vc.writeDirect { + + err = vc.ExtendedWriter.WriteBuffer(buffer) + if err != nil { + buf.ReleaseMulti(buffers[i:]) // release unwritten buffers + return + } + if command == commandPaddingDirect { vc.ExtendedWriter = N.NewExtendedWriter(vc.netConn) log.Debugln("XTLS Vision direct write start") - //time.Sleep(10 * time.Millisecond) + //time.Sleep(5 * time.Millisecond) } } return err diff --git a/clash-meta/transport/vless/vision/padding.go b/clash-meta/transport/vless/vision/padding.go index dd9cb261a3..710f64c217 100644 --- a/clash-meta/transport/vless/vision/padding.go +++ b/clash-meta/transport/vless/vision/padding.go @@ -6,6 +6,7 @@ import ( "github.com/metacubex/mihomo/common/buf" "github.com/metacubex/mihomo/log" + N "github.com/metacubex/sing/common/network" "github.com/gofrs/uuid/v5" "github.com/metacubex/randv2" @@ -19,30 +20,6 @@ const ( commandPaddingDirect byte = 0x02 ) -func WriteWithPadding(buffer *buf.Buffer, p []byte, command byte, userUUID *uuid.UUID, paddingTLS bool) { - contentLen := int32(len(p)) - var paddingLen int32 - if contentLen < 900 { - if paddingTLS { - //log.Debugln("long padding") - paddingLen = randv2.Int32N(500) + 900 - contentLen - } else { - paddingLen = randv2.Int32N(256) - } - } - if userUUID != nil { - buffer.Write(userUUID.Bytes()) - } - - buffer.WriteByte(command) - binary.BigEndian.PutUint16(buffer.Extend(2), uint16(contentLen)) - binary.BigEndian.PutUint16(buffer.Extend(2), uint16(paddingLen)) - buffer.Write(p) - - buffer.Extend(int(paddingLen)) - log.Debugln("XTLS Vision write padding1: command=%v, payloadLen=%v, paddingLen=%v", command, contentLen, paddingLen) -} - func ApplyPadding(buffer *buf.Buffer, command byte, userUUID *uuid.UUID, paddingTLS bool) { contentLen := int32(buffer.Len()) var paddingLen int32 @@ -63,19 +40,20 @@ func ApplyPadding(buffer *buf.Buffer, command byte, userUUID *uuid.UUID, padding } buffer.Extend(int(paddingLen)) - log.Debugln("XTLS Vision write padding2: command=%d, payloadLen=%d, paddingLen=%d", command, contentLen, paddingLen) + log.Debugln("XTLS Vision write padding: command=%d, payloadLen=%d, paddingLen=%d", command, contentLen, paddingLen) } -func ReshapeBuffer(buffer *buf.Buffer) *buf.Buffer { - if buffer.Len() <= buf.BufferSize-PaddingHeaderLen { - return nil +func (vc *Conn) ReshapeBuffer(buffer *buf.Buffer) []*buf.Buffer { + const xrayBufSize = 8192 + if buffer.Len() <= xrayBufSize-PaddingHeaderLen { + return []*buf.Buffer{buffer} } cutAt := bytes.LastIndex(buffer.Bytes(), tlsApplicationDataStart) if cutAt == -1 { - cutAt = buf.BufferSize / 2 + cutAt = xrayBufSize / 2 } - buffer2 := buf.New() + buffer2 := N.NewReadWaitOptions(nil, vc).NewBuffer() // ensure the new buffer can send used in vc.WriteBuffer buffer2.Write(buffer.From(cutAt)) buffer.Truncate(cutAt) - return buffer2 + return []*buf.Buffer{buffer, buffer2} } diff --git a/clash-nyanpasu/backend/Cargo.lock b/clash-nyanpasu/backend/Cargo.lock index b7e9ed5b0f..e4f616ba26 100644 --- a/clash-nyanpasu/backend/Cargo.lock +++ b/clash-nyanpasu/backend/Cargo.lock @@ -3099,9 +3099,9 @@ checksum = "aa9a19cbb55df58761df49b23516a86d432839add4af60fc256da840f66ed35b" [[package]] name = "form_urlencoded" -version = "1.2.1" +version = "1.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" +checksum = "cb4cb245038516f5f85277875cdaa4f7d2c9a0fa0468de06ed190163b1581fcf" dependencies = [ "percent-encoding", ] @@ -4376,9 +4376,9 @@ checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" [[package]] name = "idna" -version = "1.0.3" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "686f825264d630750a544639377bae737628043f20d38bbc029e8f29ea968a7e" +checksum = "3b0875f23caa03898994f6ddc501886a45c7d3d62d04d2d90788d47be1b1e4de" dependencies = [ "idna_adapter", "smallvec", @@ -6552,9 +6552,9 @@ dependencies = [ [[package]] name = "oxc_allocator" -version = "0.82.2" +version = "0.82.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01443e3e95c7916a6a260335ebd4dee8775ad5e2f285adcf49bd35ddff49cf4d" +checksum = "e887a8496b18a4bce4a760ae2dbd50e5137fa2a27ee99087797d7b8e860a7b5c" dependencies = [ "allocator-api2", "bumpalo", @@ -6565,9 +6565,9 @@ dependencies = [ [[package]] name = "oxc_ast" -version = "0.82.2" +version = "0.82.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ee82b1e75533bd63802583d42cff22173e799bff19681fbd300a254585cf6b8" +checksum = "931e1fae25d9669204681577381f6e90d2c9fe502d306c862f46ff72bcef8cf7" dependencies = [ "bitflags 2.9.2", "oxc_allocator", @@ -6581,9 +6581,9 @@ dependencies = [ [[package]] name = "oxc_ast_macros" -version = "0.82.2" +version = "0.82.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a119414d0ea2d4ead85d7d9095f59a248fa1eb8e0832687016180655fc2b622" +checksum = "5958a8ac69a955048dabcfcbf8af791dbb7f598bbea5bae33243240f3846457c" dependencies = [ "phf 0.12.1", "proc-macro2", @@ -6593,9 +6593,9 @@ dependencies = [ [[package]] name = "oxc_ast_visit" -version = "0.82.2" +version = "0.82.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f393c0ed3f2750ed971d1da803c6816f9c2e1881d0261d3a7220d67c27fedbf0" +checksum = "95d2ce2cb5be550d7a94fc3b927d4247d69aea57943baafbf6547362831e69a5" dependencies = [ "oxc_allocator", "oxc_ast", @@ -6605,15 +6605,15 @@ dependencies = [ [[package]] name = "oxc_data_structures" -version = "0.82.2" +version = "0.82.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd798dc264a18b4c472246ca60f4bc9d723e679e57f8b1daa3af65bacccb2987" +checksum = "67b3258dc882e0348934e2a9973cd0d9e3c465642b729842320d23abf835175a" [[package]] name = "oxc_diagnostics" -version = "0.82.2" +version = "0.82.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5a103b0344d5b9bc38db54b2214ae2f45aebf6bc5473ed0a204ae458be8b0a6" +checksum = "5dc24fdf0407c9ecb202efb99fa9870f3623994ae8daae56e696a511894d67ba" dependencies = [ "cow-utils", "oxc-miette", @@ -6622,9 +6622,9 @@ dependencies = [ [[package]] name = "oxc_ecmascript" -version = "0.82.2" +version = "0.82.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c128f12fc96dc9e9694ea97e49869f1f181f9afc3e90bc94f677d8cb85ecee2" +checksum = "61cfc9801af5b0068e11061ff8100fb38c2ca0875c696aa405b5505d212b5e2f" dependencies = [ "cow-utils", "num-bigint", @@ -6637,9 +6637,9 @@ dependencies = [ [[package]] name = "oxc_estree" -version = "0.82.2" +version = "0.82.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25b152c37513a595c4013f1da6c32a5652da2bbeea8dee2c94231be9e29f9511" +checksum = "2bac265e2cd8c77ac8d4230f1538e8ff9f6f5d9e41b9107af58f8d3c4626b028" [[package]] name = "oxc_index" @@ -6649,9 +6649,9 @@ checksum = "2fa07b0cfa997730afed43705766ef27792873fdf5215b1391949fec678d2392" [[package]] name = "oxc_parser" -version = "0.82.2" +version = "0.82.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78d36a87565a624893fff4c2ed46eafe9dd447a0dd82cbcfaf9b2a52e35a84ba" +checksum = "8b4427e7c4d4507bb4561c113e25bbbb737d03355f311d3fb606f0029fdcb3f6" dependencies = [ "bitflags 2.9.2", "cow-utils", @@ -6672,9 +6672,9 @@ dependencies = [ [[package]] name = "oxc_regular_expression" -version = "0.82.2" +version = "0.82.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81876a23eb6e3d951c8d23066d9377cf2b5dd66035b00f38ffdd21b29c2694a1" +checksum = "17ec07cb1081ed5798e2ef7d3e10154784cd1bf47c5170ff3d519d44bc97ad07" dependencies = [ "bitflags 2.9.2", "oxc_allocator", @@ -6688,9 +6688,9 @@ dependencies = [ [[package]] name = "oxc_span" -version = "0.82.2" +version = "0.82.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8352ac817efc16314a8da4a8f3c73275b0e1d364a2fb4903092e1ac971806229" +checksum = "008d14e804d79adac31c5cb5b27fbfde52055a0cf86276c9b822cfa40b24d75c" dependencies = [ "compact_str", "oxc-miette", @@ -6701,9 +6701,9 @@ dependencies = [ [[package]] name = "oxc_syntax" -version = "0.82.2" +version = "0.82.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9dcec4c2eea751e2823f814ba0e543a1ce64288154b0d784e883d46c216da92f" +checksum = "675313926fe94e71b9cdf6ed0338e0bfb40e827e2b5fd0c65a059aff002e7fa2" dependencies = [ "bitflags 2.9.2", "cow-utils", @@ -6811,9 +6811,9 @@ dependencies = [ [[package]] name = "percent-encoding" -version = "2.3.1" +version = "2.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" +checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" [[package]] name = "pest" @@ -10598,9 +10598,9 @@ dependencies = [ [[package]] name = "url" -version = "2.5.4" +version = "2.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32f8b686cadd1473f4bd0117a5d28d36b1ade384ea9b5069a1c40aefed7fda60" +checksum = "137a3c834eaf7139b73688502f3f1141a0337c5d8e4d9b536f9b8c796e26a7c4" dependencies = [ "form_urlencoded", "idna", diff --git a/clash-nyanpasu/frontend/nyanpasu/package.json b/clash-nyanpasu/frontend/nyanpasu/package.json index 5e2bd7f52a..e140efd209 100644 --- a/clash-nyanpasu/frontend/nyanpasu/package.json +++ b/clash-nyanpasu/frontend/nyanpasu/package.json @@ -56,7 +56,7 @@ "@csstools/normalize.css": "12.1.1", "@emotion/babel-plugin": "11.13.5", "@emotion/react": "11.14.0", - "@iconify/json": "2.2.376", + "@iconify/json": "2.2.377", "@monaco-editor/react": "4.7.0", "@tanstack/react-query": "5.84.2", "@tanstack/react-router": "1.131.27", diff --git a/clash-nyanpasu/manifest/version.json b/clash-nyanpasu/manifest/version.json index 8f6621fcca..ded1a97519 100644 --- a/clash-nyanpasu/manifest/version.json +++ b/clash-nyanpasu/manifest/version.json @@ -2,7 +2,7 @@ "manifest_version": 1, "latest": { "mihomo": "v1.19.12", - "mihomo_alpha": "alpha-5f09db2", + "mihomo_alpha": "alpha-b0d461f", "clash_rs": "v0.9.0", "clash_premium": "2023-09-05-gdcc8d87", "clash_rs_alpha": "0.9.0-alpha+sha.51d55ef" @@ -69,5 +69,5 @@ "linux-armv7hf": "clash-armv7-unknown-linux-gnueabihf" } }, - "updated_at": "2025-08-20T22:21:19.472Z" + "updated_at": "2025-08-21T22:21:18.011Z" } diff --git a/clash-nyanpasu/pnpm-lock.yaml b/clash-nyanpasu/pnpm-lock.yaml index f3ecfaef6e..5672cafa6e 100644 --- a/clash-nyanpasu/pnpm-lock.yaml +++ b/clash-nyanpasu/pnpm-lock.yaml @@ -343,8 +343,8 @@ importers: specifier: 11.14.0 version: 11.14.0(@types/react@19.1.10)(react@19.1.1) '@iconify/json': - specifier: 2.2.376 - version: 2.2.376 + specifier: 2.2.377 + version: 2.2.377 '@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) @@ -1790,8 +1790,8 @@ packages: prettier-plugin-ember-template-tag: optional: true - '@iconify/json@2.2.376': - resolution: {integrity: sha512-2jQ+5zPV7Lva9iuFOvMkcq5XQyRx7xvLuodpDI+yjAxOnB2gpWa4caFz53tyPgCWU50Zd9/JSNZaCNYSTniSrg==} + '@iconify/json@2.2.377': + resolution: {integrity: sha512-3BjwbsQPyt/Qceo0v3E0LktU3Ngc76KrZgLKX/2NfjqZxVl6NOZZ7D5crJZo9l3DJOx+6oe1pjF/+ezkRLG0Mg==} '@iconify/types@2.0.0': resolution: {integrity: sha512-+wluvCrRhXrhyOmRDJ3q8mux9JkKy5SJ/v8ol2tu4FVjyYvtEzkc/3pK15ET6RKg4b4w4BmTk1+gsCUhf21Ykg==} @@ -10074,7 +10074,7 @@ snapshots: transitivePeerDependencies: - supports-color - '@iconify/json@2.2.376': + '@iconify/json@2.2.377': dependencies: '@iconify/types': 2.0.0 pathe: 1.1.2 diff --git a/filebrowser/tools/go.mod b/filebrowser/tools/go.mod index 4bea35a1f6..fb417176d3 100644 --- a/filebrowser/tools/go.mod +++ b/filebrowser/tools/go.mod @@ -69,7 +69,7 @@ require ( github.com/go-toolsmith/astp v1.1.0 // indirect github.com/go-toolsmith/strparse v1.1.0 // indirect github.com/go-toolsmith/typep v1.1.0 // indirect - github.com/go-viper/mapstructure/v2 v2.3.0 // indirect + github.com/go-viper/mapstructure/v2 v2.4.0 // indirect github.com/go-xmlfmt/xmlfmt v1.1.3 // indirect github.com/gobwas/glob v0.2.3 // indirect github.com/gofrs/flock v0.12.1 // indirect diff --git a/filebrowser/tools/go.sum b/filebrowser/tools/go.sum index 40279fb5ab..ae8c484aff 100644 --- a/filebrowser/tools/go.sum +++ b/filebrowser/tools/go.sum @@ -207,8 +207,8 @@ github.com/go-toolsmith/strparse v1.1.0 h1:GAioeZUK9TGxnLS+qfdqNbA4z0SSm5zVNtCQi github.com/go-toolsmith/strparse v1.1.0/go.mod h1:7ksGy58fsaQkGQlY8WVoBFNyEPMGuJin1rfoPS4lBSQ= github.com/go-toolsmith/typep v1.1.0 h1:fIRYDyF+JywLfqzyhdiHzRop/GQDxxNhLGQ6gFUNHus= github.com/go-toolsmith/typep v1.1.0/go.mod h1:fVIw+7zjdsMxDA3ITWnH1yOiw1rnTQKCsF/sk2H/qig= -github.com/go-viper/mapstructure/v2 v2.3.0 h1:27XbWsHIqhbdR5TIC911OfYvgSaW93HM+dX7970Q7jk= -github.com/go-viper/mapstructure/v2 v2.3.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM= +github.com/go-viper/mapstructure/v2 v2.4.0 h1:EBsztssimR/CONLSZZ04E8qAkxNYq4Qp9LvH92wZUgs= +github.com/go-viper/mapstructure/v2 v2.4.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM= github.com/go-xmlfmt/xmlfmt v1.1.3 h1:t8Ey3Uy7jDSEisW2K3somuMKIpzktkWptA0iFCnRUWY= github.com/go-xmlfmt/xmlfmt v1.1.3/go.mod h1:aUCEOzzezBEjDBbFBoSiya/gduyIiWYRP6CnSFIV8AM= github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y= diff --git a/lede/package/base-files/files/etc/rc.button/reset b/lede/package/base-files/files/etc/rc.button/reset index 2403122ad2..8465133471 100755 --- a/lede/package/base-files/files/etc/rc.button/reset +++ b/lede/package/base-files/files/etc/rc.button/reset @@ -23,7 +23,7 @@ released) elif [ "$SEEN" -ge 5 -a -n "$OVERLAY" ] then echo "FACTORY RESET" > /dev/console - jffs2reset -y && reboot & + factoryreset -y && reboot & fi ;; esac diff --git a/lede/package/base-files/files/sbin/firstboot b/lede/package/base-files/files/sbin/firstboot index d9af57d596..3dd6f1e7d2 100755 --- a/lede/package/base-files/files/sbin/firstboot +++ b/lede/package/base-files/files/sbin/firstboot @@ -1,3 +1,3 @@ #!/bin/sh -/sbin/jffs2reset $@ +/sbin/factoryreset $@ diff --git a/lede/package/system/fstools/Makefile b/lede/package/system/fstools/Makefile index d54d5f872b..d1249a643b 100644 --- a/lede/package/system/fstools/Makefile +++ b/lede/package/system/fstools/Makefile @@ -12,9 +12,9 @@ PKG_RELEASE:=1 PKG_SOURCE_PROTO:=git PKG_SOURCE_URL=$(PROJECT_GIT)/project/fstools.git -PKG_MIRROR_HASH:=32e39891455b602e9deb367c9ce2d099dc72353fad0bf0433307416925f7b393 -PKG_SOURCE_DATE:=2024-01-22 -PKG_SOURCE_VERSION:=08cd7083cac4bddf88459efa0881ee52858e7d0a +PKG_MIRROR_HASH:=b579796bd410765df8a5c0957f89e01256e96bdcfd5cdcae61c71949a273ce03 +PKG_SOURCE_DATE:=2025-07-05 +PKG_SOURCE_VERSION:=e8cd820cdbb8fba990fd79efda90c5dc10d8e45c CMAKE_INSTALL:=1 PKG_LICENSE:=GPL-2.0 @@ -96,9 +96,10 @@ endef define Package/fstools/install $(INSTALL_DIR) $(1)/sbin $(1)/lib - $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/sbin/{mount_root,jffs2reset} $(1)/sbin/ + $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/sbin/{mount_root,factoryreset} $(1)/sbin/ $(INSTALL_DATA) $(PKG_INSTALL_DIR)/usr/lib/libfstools.so $(1)/lib/ - $(LN) jffs2reset $(1)/sbin/jffs2mark + $(LN) factoryreset $(1)/sbin/jffs2mark + $(LN) factoryreset $(1)/sbin/jffs2reset endef define Package/snapshot-tool/install diff --git a/lede/package/system/fstools/patches/0001-EroFS.patch b/lede/package/system/fstools/patches/0001-EroFS.patch deleted file mode 100644 index 31800a6b1e..0000000000 --- a/lede/package/system/fstools/patches/0001-EroFS.patch +++ /dev/null @@ -1,139 +0,0 @@ -From e8cd820cdbb8fba990fd79efda90c5dc10d8e45c Mon Sep 17 00:00:00 2001 -From: Gao Xiang -Subject: [PATCH] libfstools: add support for EroFS based images - -Add support to libfstools to parse and support EroFS based images to -permit correct mounting of OverlayFS with it. (in addition to SquashFS -support) - -While at it rework the code to better handle the 2 different filesystem -introducing a similar pattern. - -Signed-off-by: Gao Xiang -Signed-off-by: Christian Marangi ---- - libfstools/rootdisk.c | 83 +++++++++++++++++++++++++++++++++++++++---- - 1 file changed, 77 insertions(+), 6 deletions(-) - ---- a/libfstools/rootdisk.c -+++ b/libfstools/rootdisk.c -@@ -15,6 +15,8 @@ - - #include - -+#define SQUASHFS_MAGIC "hsqs" -+#define EROFS_MAGIC 0xE0F5E1E2 - #define ROOTDEV_OVERLAY_ALIGN (64ULL * 1024ULL) - #define F2FS_MINSIZE (100ULL * 1024ULL * 1024ULL) - -@@ -24,6 +26,14 @@ struct squashfs_super_block { - uint64_t bytes_used; - }; - -+struct erofs_super_block { -+ uint32_t s_magic; -+ uint32_t pad0[2]; -+ uint8_t blkszbits; -+ uint8_t pad1[23]; -+ uint32_t blocks; -+}; -+ - struct rootdev_volume { - struct volume v; - uint64_t offset; -@@ -93,10 +103,66 @@ static int get_squashfs(struct squashfs_ - return 0; - } - --static struct volume *rootdisk_volume_find(char *name) -+static int check_squashfs(uint64_t *offset) - { -+ const char *s_magic = SQUASHFS_MAGIC; - struct squashfs_super_block sb; -+ int ret; -+ -+ ret = get_squashfs(&sb); -+ if (ret) -+ return ret; -+ -+ if (memcmp(&sb.s_magic, s_magic, sizeof(sb.s_magic))) -+ return -1; -+ -+ *offset = le64_to_cpu(sb.bytes_used); -+ return 0; -+} -+ -+static int get_erofs(struct erofs_super_block *sb) -+{ -+ FILE *f; -+ int len; -+ -+ f = fopen(rootdev, "r"); -+ if (!f) -+ return -1; -+ -+ if (fseek(f, 1024, SEEK_SET)) -+ return -1; -+ -+ len = fread(sb, sizeof(*sb), 1, f); -+ fclose(f); -+ -+ if (len != 1) -+ return -1; -+ -+ return 0; -+} -+ -+static int check_erofs(uint64_t *offset) -+{ -+ uint32_t s_magic = cpu_to_le32(EROFS_MAGIC); -+ struct erofs_super_block sb; -+ int ret; -+ -+ ret = get_erofs(&sb); -+ if (ret) -+ return ret; -+ -+ if (memcmp(&sb.s_magic, &s_magic, sizeof(sb.s_magic))) -+ return -1; -+ -+ *offset = (uint64_t)le32_to_cpu(sb.blocks) << sb.blkszbits; -+ return 0; -+} -+ -+static struct volume *rootdisk_volume_find(char *name) -+{ - struct rootdev_volume *p; -+ uint64_t offset; -+ int ret; - - if (strcmp(name, "rootfs_data") != 0) - return NULL; -@@ -108,17 +174,22 @@ static struct volume *rootdisk_volume_fi - if (!rootdev) - return NULL; - -- if (get_squashfs(&sb)) -- return NULL; -- -- if (memcmp(&sb.s_magic, "hsqs", sizeof(sb.s_magic)) != 0) -+ /* -+ * We support both SquashFS and EroFS. -+ * First check for SquashFS and then check -+ * for EroFS on new images. -+ */ -+ ret = check_squashfs(&offset); -+ if (ret < 0 || !offset) -+ ret = check_erofs(&offset); -+ if (ret < 0 || !offset) - return NULL; - - p = calloc(1, sizeof(*p)); - p->v.drv = &rootdisk_driver; - p->v.name = "rootfs_data"; - -- p->offset = le64_to_cpu(sb.bytes_used); -+ p->offset = offset; - p->offset = ((p->offset + (ROOTDEV_OVERLAY_ALIGN - 1)) & - ~(ROOTDEV_OVERLAY_ALIGN - 1)); - diff --git a/lede/package/system/fstools/patches/0100-automount.patch b/lede/package/system/fstools/patches/0100-automount.patch deleted file mode 100644 index 6a68444e0e..0000000000 --- a/lede/package/system/fstools/patches/0100-automount.patch +++ /dev/null @@ -1,20 +0,0 @@ ---- a/block.c -+++ b/block.c -@@ -729,7 +729,7 @@ static int print_block_uci(struct probe_ - printf("\toption\tuuid\t'%s'\n", pr->uuid); - else - printf("\toption\tdevice\t'%s'\n", pr->dev); -- printf("\toption\tenabled\t'0'\n\n"); -+ printf("\toption\tenabled\t'1'\n\n"); - - return 0; - } -@@ -1794,7 +1794,7 @@ static int main_detect(int argc, char ** - cache_load(0); - printf("config 'global'\n"); - printf("\toption\tanon_swap\t'0'\n"); -- printf("\toption\tanon_mount\t'0'\n"); -+ printf("\toption\tanon_mount\t'1'\n"); - printf("\toption\tauto_swap\t'1'\n"); - printf("\toption\tauto_mount\t'1'\n"); - printf("\toption\tdelay_root\t'5'\n"); diff --git a/mieru/.github/ISSUE_TEMPLATE/bug_report.yaml b/mieru/.github/ISSUE_TEMPLATE/bug_report.yaml index a2db277f68..a50946eeb0 100644 --- a/mieru/.github/ISSUE_TEMPLATE/bug_report.yaml +++ b/mieru/.github/ISSUE_TEMPLATE/bug_report.yaml @@ -50,8 +50,6 @@ body: attributes: label: Reproduction description: Steps to reproduce the error, including the configuration files. - validations: - required: true - type: textarea attributes: label: Logs diff --git a/mieru/.github/ISSUE_TEMPLATE/bug_report_zh.yaml b/mieru/.github/ISSUE_TEMPLATE/bug_report_zh.yaml index e35d6ae50f..86038bf8a9 100644 --- a/mieru/.github/ISSUE_TEMPLATE/bug_report_zh.yaml +++ b/mieru/.github/ISSUE_TEMPLATE/bug_report_zh.yaml @@ -50,8 +50,6 @@ body: attributes: label: 重现方式 description: 请提供重现错误的步骤,包括重现错误的配置文件。 - validations: - required: true - type: textarea attributes: label: 日志 diff --git a/mieru/test/deploy/packetdrop/client_tcp.json b/mieru/test/deploy/packetdrop/client_tcp.json index 0eac774c99..ac47f52b56 100644 --- a/mieru/test/deploy/packetdrop/client_tcp.json +++ b/mieru/test/deploy/packetdrop/client_tcp.json @@ -16,7 +16,8 @@ } ] } - ] + ], + "handshakeMode": "HANDSHAKE_NO_WAIT" } ], "activeProfile": "default", diff --git a/mieru/test/deploy/packetdrop/client_udp.json b/mieru/test/deploy/packetdrop/client_udp.json index bb83e26816..f74983365d 100644 --- a/mieru/test/deploy/packetdrop/client_udp.json +++ b/mieru/test/deploy/packetdrop/client_udp.json @@ -17,7 +17,8 @@ ] } ], - "mtu": 1400 + "mtu": 1400, + "handshakeMode": "HANDSHAKE_NO_WAIT" } ], "activeProfile": "default", diff --git a/mihomo/common/buf/sing.go b/mihomo/common/buf/sing.go index 59c650adeb..73f65f150d 100644 --- a/mihomo/common/buf/sing.go +++ b/mihomo/common/buf/sing.go @@ -14,6 +14,7 @@ var NewPacket = buf.NewPacket var NewSize = buf.NewSize var With = buf.With var As = buf.As +var ReleaseMulti = buf.ReleaseMulti var ( Must = common.Must diff --git a/mihomo/common/net/sing.go b/mihomo/common/net/sing.go index 2cd1d726af..5cf9759427 100644 --- a/mihomo/common/net/sing.go +++ b/mihomo/common/net/sing.go @@ -22,6 +22,10 @@ type ExtendedReader = network.ExtendedReader var WriteBuffer = bufio.WriteBuffer +type ReadWaitOptions = network.ReadWaitOptions + +var NewReadWaitOptions = network.NewReadWaitOptions + func NewDeadlineConn(conn net.Conn) ExtendedConn { if deadline.IsPipe(conn) || deadline.IsPipe(network.UnwrapReader(conn)) { return NewExtendedConn(conn) // pipe always have correctly deadline implement diff --git a/mihomo/go.mod b/mihomo/go.mod index 57c10000ba..eb949cd582 100644 --- a/mihomo/go.mod +++ b/mihomo/go.mod @@ -31,7 +31,7 @@ require ( 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.7 - github.com/metacubex/sing-vmess v0.2.4-0.20250821024956-97839f31a65d + 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 github.com/metacubex/tfo-go v0.0.0-20250516165257-e29c16ae41d4 diff --git a/mihomo/go.sum b/mihomo/go.sum index d8bfd9a592..ca829a3f21 100644 --- a/mihomo/go.sum +++ b/mihomo/go.sum @@ -131,8 +131,8 @@ github.com/metacubex/sing-shadowtls v0.0.0-20250503063515-5d9f966d17a2 h1:gXU+MY github.com/metacubex/sing-shadowtls v0.0.0-20250503063515-5d9f966d17a2/go.mod h1:mbfboaXauKJNIHJYxQRa+NJs4JU9NZfkA+I33dS2+9E= 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.20250821024956-97839f31a65d h1:jchYEho5+kTmok4aTMflqJyTRnqVPTOVeC1RFXxuw9A= -github.com/metacubex/sing-vmess v0.2.4-0.20250821024956-97839f31a65d/go.mod h1:21R5R1u90uUvBQF0owoooEu96/SAYYD56nDrwm6nFaM= +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= github.com/metacubex/sing-wireguard v0.0.0-20250503063753-2dc62acc626f/go.mod h1:jpAkVLPnCpGSfNyVmj6Cq4YbuZsFepm/Dc+9BAOcR80= github.com/metacubex/smux v0.0.0-20250503055512-501391591dee h1:lp6hJ+4wCLZu113awp7P6odM2okB5s60HUyF0FMqKmo= diff --git a/mihomo/listener/inbound/common_test.go b/mihomo/listener/inbound/common_test.go index 75b98e0bc4..79e382fa81 100644 --- a/mihomo/listener/inbound/common_test.go +++ b/mihomo/listener/inbound/common_test.go @@ -1,6 +1,7 @@ package inbound_test import ( + "bytes" "context" "crypto/rand" "crypto/tls" @@ -142,6 +143,7 @@ func NewHttpTestTunnel() *TestTunnel { render.PlainText(w, r, err.Error()) return } + io.Copy(io.Discard, r.Body) render.Data(w, r, httpData[:size]) }) h2Server := &http2.Server{} @@ -149,7 +151,7 @@ func NewHttpTestTunnel() *TestTunnel { _ = http2.ConfigureServer(&server, h2Server) go server.Serve(ln) testFn := func(t *testing.T, proxy C.ProxyAdapter, proto string, size int) { - req, err := http.NewRequest(http.MethodGet, fmt.Sprintf("%s://%s%s?size=%d", proto, remoteAddr, httpPath, size), nil) + req, err := http.NewRequest(http.MethodGet, fmt.Sprintf("%s://%s%s?size=%d", proto, remoteAddr, httpPath, size), bytes.NewReader(httpData[:size])) if !assert.NoError(t, err) { return } diff --git a/mihomo/transport/vless/encryption/client.go b/mihomo/transport/vless/encryption/client.go index dfa4fa63b7..cd94758750 100644 --- a/mihomo/transport/vless/encryption/client.go +++ b/mihomo/transport/vless/encryption/client.go @@ -57,7 +57,7 @@ type ClientConn struct { random []byte aead cipher.AEAD nonce []byte - peerAead cipher.AEAD + peerAEAD cipher.AEAD peerNonce []byte input bytes.Reader // peerCache } @@ -70,13 +70,13 @@ func (i *ClientInstance) Init(nfsEKeyBytes, xorPKeyBytes []byte, xorMode, minute if i.nfsEKey, err = mlkem.NewEncapsulationKey768(nfsEKeyBytes); err != nil { return } - hash32 := sha3.Sum256(nfsEKeyBytes) - copy(i.hash11[:], hash32[:]) if xorMode > 0 { i.xorMode = xorMode if i.xorPKey, err = ecdh.X25519().NewPublicKey(xorPKeyBytes); err != nil { return } + hash32 := sha3.Sum256(nfsEKeyBytes) + copy(i.hash11[:], hash32[:]) } i.minutes = time.Duration(minutes) * time.Minute return @@ -108,23 +108,25 @@ func (i *ClientInstance) Handshake(conn net.Conn) (*ClientConn, error) { pfsDKey, _ := mlkem.NewDecapsulationKey768(pfsDKeySeed) pfsEKeyBytes := pfsDKey.EncapsulationKey().Bytes() nfsKey, encapsulatedNfsKey := i.nfsEKey.Encapsulate() - paddingLen := randBetween(100, 1000) + nfsAEAD := NewAEAD(ClientCipher, nfsKey, pfsEKeyBytes, encapsulatedNfsKey) - clientHello := make([]byte, 5+11+1+1184+1088+5+paddingLen) + clientHello := make([]byte, 5+11+1+1184+1088+randBetween(100, 1000)) EncodeHeader(clientHello, 1, 11+1+1184+1088) copy(clientHello[5:], i.hash11[:]) clientHello[5+11] = ClientCipher copy(clientHello[5+11+1:], pfsEKeyBytes) copy(clientHello[5+11+1+1184:], encapsulatedNfsKey) - EncodeHeader(clientHello[5+11+1+1184+1088:], 23, int(paddingLen)) - rand.Read(clientHello[5+11+1+1184+1088+5:]) + padding := clientHello[5+11+1+1184+1088:] + rand.Read(padding) // important + EncodeHeader(padding, 23, len(padding)-5) + nfsAEAD.Seal(padding[:5], clientHello[5:5+11+1], padding[5:len(padding)-16], padding[:5]) if _, err := c.Conn.Write(clientHello); err != nil { return nil, err } - // client can send more paddings / NFS AEAD messages if needed + // client can send more NFS AEAD paddings / messages if needed - _, t, l, err := ReadAndDiscardPaddings(c.Conn) // allow paddings before server hello + _, t, l, err := ReadAndDiscardPaddings(c.Conn, nil, nil) // allow paddings before server hello if err != nil { return nil, err } @@ -206,10 +208,10 @@ func (c *ClientConn) Read(b []byte) (int, error) { if len(b) == 0 { return 0, nil } - if c.peerAead == nil { - _, t, l, err := ReadAndDiscardPaddings(c.Conn) // allow paddings before random hello + if c.peerAEAD == nil { + _, t, l, err := ReadAndDiscardPaddings(c.Conn, nil, nil) // allow paddings before random hello if err != nil { - if c.instance != nil && strings.HasPrefix(err.Error(), "invalid header: ") { // 0-RTT's 0-RTT + if c.instance != nil && strings.HasPrefix(err.Error(), "invalid header: ") { // 0-RTT c.instance.Lock() if bytes.Equal(c.ticket, c.instance.ticket) { c.instance.expire = time.Now() // expired @@ -232,7 +234,7 @@ func (c *ClientConn) Read(b []byte) (int, error) { if c.random == nil { return 0, errors.New("empty c.random") } - c.peerAead = NewAEAD(ClientCipher, c.baseKey, peerRandomHello, c.random) + c.peerAEAD = NewAEAD(ClientCipher, c.baseKey, peerRandomHello, c.random) c.peerNonce = make([]byte, 12) } if c.input.Len() > 0 { @@ -253,13 +255,13 @@ func (c *ClientConn) Read(b []byte) (int, error) { if len(dst) <= len(b) { dst = b[:len(dst)] // avoids another copy() } - var peerAead cipher.AEAD + var peerAEAD cipher.AEAD if bytes.Equal(c.peerNonce, MaxNonce) { - peerAead = NewAEAD(ClientCipher, c.baseKey, peerData, h) + peerAEAD = NewAEAD(ClientCipher, c.baseKey, peerData, h) } - _, err = c.peerAead.Open(dst[:0], c.peerNonce, peerData, h) - if peerAead != nil { - c.peerAead = peerAead + _, err = c.peerAEAD.Open(dst[:0], c.peerNonce, peerData, h) + if peerAEAD != nil { + c.peerAEAD = peerAEAD } IncreaseNonce(c.peerNonce) if err != nil { diff --git a/mihomo/transport/vless/encryption/common.go b/mihomo/transport/vless/encryption/common.go index d383d22e98..84784cb2e1 100644 --- a/mihomo/transport/vless/encryption/common.go +++ b/mihomo/transport/vless/encryption/common.go @@ -62,14 +62,21 @@ func ReadAndDecodeHeader(conn net.Conn) (h []byte, t byte, l int, err error) { return } -func ReadAndDiscardPaddings(conn net.Conn) (h []byte, t byte, l int, err error) { +func ReadAndDiscardPaddings(conn net.Conn, aead cipher.AEAD, nonce []byte) (h []byte, t byte, l int, err error) { for { if h, t, l, err = ReadAndDecodeHeader(conn); err != nil || t != 23 { return } - if _, err = io.ReadFull(conn, make([]byte, l)); err != nil { + padding := make([]byte, l) + if _, err = io.ReadFull(conn, padding); err != nil { return } + if aead != nil { + if _, err := aead.Open(nil, nonce, padding, h); err != nil { + return h, t, l, err + } + IncreaseNonce(nonce) + } } } diff --git a/mihomo/transport/vless/encryption/doc.go b/mihomo/transport/vless/encryption/doc.go index 10cd320b2b..8e3ff8a9ea 100644 --- a/mihomo/transport/vless/encryption/doc.go +++ b/mihomo/transport/vless/encryption/doc.go @@ -15,4 +15,6 @@ // https://github.com/XTLS/Xray-core/commit/49580705f6029648399304b816a2737f991582a8 // https://github.com/XTLS/Xray-core/commit/84835bec7d0d8555d0dd30953ed26a272de814c4 // https://github.com/XTLS/Xray-core/commit/373558ed7abdbac3de41745cf30ec04c9adde604 +// https://github.com/XTLS/Xray-core/commit/38cc306c955c362f044e074049a5e67b6b9fb389 +// https://github.com/XTLS/Xray-core/commit/b33555cc0a52d0af3c23d2af8fca42f8a685d9af package encryption diff --git a/mihomo/transport/vless/encryption/server.go b/mihomo/transport/vless/encryption/server.go index baa8432cd0..6df2729baa 100644 --- a/mihomo/transport/vless/encryption/server.go +++ b/mihomo/transport/vless/encryption/server.go @@ -40,7 +40,7 @@ type ServerConn struct { baseKey []byte ticket []byte peerRandom []byte - peerAead cipher.AEAD + peerAEAD cipher.AEAD peerNonce []byte input bytes.Reader // peerCache aead cipher.AEAD @@ -55,13 +55,13 @@ func (i *ServerInstance) Init(nfsDKeySeed, xorSKeyBytes []byte, xorMode, minutes if i.nfsDKey, err = mlkem.NewDecapsulationKey768(nfsDKeySeed); err != nil { return } - hash32 := sha3.Sum256(i.nfsDKey.EncapsulationKey().Bytes()) - copy(i.hash11[:], hash32[:]) if xorMode > 0 { i.xorMode = xorMode if i.xorSKey, err = ecdh.X25519().NewPrivateKey(xorSKeyBytes); err != nil { return } + hash32 := sha3.Sum256(i.nfsDKey.EncapsulationKey().Bytes()) + copy(i.hash11[:], hash32[:]) } if minutes > 0 { i.minutes = time.Duration(minutes) * time.Minute @@ -106,7 +106,7 @@ func (i *ServerInstance) Handshake(conn net.Conn) (*ServerConn, error) { } c := &ServerConn{Conn: conn} - _, t, l, err := ReadAndDiscardPaddings(c.Conn) // allow paddings before client/ticket hello + _, t, l, err := ReadAndDiscardPaddings(c.Conn, nil, nil) // allow paddings before client/ticket hello if err != nil { return nil, err } @@ -170,32 +170,57 @@ func (i *ServerInstance) Handshake(conn net.Conn) (*ServerConn, error) { if err != nil { return nil, err } + nfsAEAD := NewAEAD(c.cipher, nfsKey, pfsEKeyBytes, encapsulatedNfsKey) + nfsNonce := append([]byte{}, peerClientHello[:11+1]...) pfsKey, encapsulatedPfsKey := pfsEKey.Encapsulate() c.baseKey = append(pfsKey, nfsKey...) + pfsAEAD := NewAEAD(c.cipher, c.baseKey, encapsulatedPfsKey, encapsulatedNfsKey) + pfsNonce := append([]byte{}, peerClientHello[:11+1]...) + c.ticket = append(i.hash11[:], pfsAEAD.Seal(nil, pfsNonce, []byte("VLESS"), pfsEKeyBytes)...) + IncreaseNonce(pfsNonce) - c.ticket = append(i.hash11[:], NewAEAD(c.cipher, c.baseKey, encapsulatedPfsKey, encapsulatedNfsKey).Seal(nil, peerClientHello[:12], []byte("VLESS"), pfsEKeyBytes)...) - - paddingLen := randBetween(100, 1000) - - serverHello := make([]byte, 5+1088+21+5+paddingLen) + serverHello := make([]byte, 5+1088+21+randBetween(100, 1000)) EncodeHeader(serverHello, 1, 1088+21) copy(serverHello[5:], encapsulatedPfsKey) copy(serverHello[5+1088:], c.ticket[11:]) - EncodeHeader(serverHello[5+1088+21:], 23, int(paddingLen)) - rand.Read(serverHello[5+1088+21+5:]) + padding := serverHello[5+1088+21:] + rand.Read(padding) // important + EncodeHeader(padding, 23, len(padding)-5) + pfsAEAD.Seal(padding[:5], pfsNonce, padding[5:len(padding)-16], padding[:5]) if _, err := c.Conn.Write(serverHello); err != nil { return nil, err } - // server can send more paddings / PFS AEAD messages if needed + // server can send more PFS AEAD paddings / messages if needed + + _, t, l, err = ReadAndDiscardPaddings(c.Conn, nfsAEAD, nfsNonce) // allow paddings before ticket hello + if err != nil { + return nil, err + } + if t != 0 { + return nil, fmt.Errorf("unexpected type %v, expect ticket hello", t) + } + peerTicketHello := make([]byte, 32+32) + if l != len(peerTicketHello) { + return nil, fmt.Errorf("unexpected length %v for ticket hello", l) + } + if _, err := io.ReadFull(c.Conn, peerTicketHello); err != nil { + return nil, err + } + if !bytes.Equal(peerTicketHello[:32], c.ticket) { + return nil, errors.New("naughty boy") + } + c.peerRandom = peerTicketHello[32:] if i.minutes > 0 { i.Lock() - i.sessions[[32]byte(c.ticket)] = &ServerSession{ + s := &ServerSession{ expire: time.Now().Add(i.minutes), cipher: c.cipher, baseKey: c.baseKey, } + s.randoms.Store([32]byte(c.peerRandom), true) + i.sessions[[32]byte(c.ticket)] = s i.Unlock() } @@ -206,28 +231,8 @@ func (c *ServerConn) Read(b []byte) (int, error) { if len(b) == 0 { return 0, nil } - if c.peerAead == nil { - if c.peerRandom == nil { // 1-RTT's 0-RTT - _, t, l, err := ReadAndDiscardPaddings(c.Conn) // allow paddings before ticket hello - if err != nil { - return 0, err - } - if t != 0 { - return 0, fmt.Errorf("unexpected type %v, expect ticket hello", t) - } - peerTicketHello := make([]byte, 32+32) - if l != len(peerTicketHello) { - return 0, fmt.Errorf("unexpected length %v for ticket hello", l) - } - if _, err := io.ReadFull(c.Conn, peerTicketHello); err != nil { - return 0, err - } - if !bytes.Equal(peerTicketHello[:32], c.ticket) { - return 0, errors.New("naughty boy") - } - c.peerRandom = peerTicketHello[32:] - } - c.peerAead = NewAEAD(c.cipher, c.baseKey, c.peerRandom, c.ticket) + if c.peerAEAD == nil { + c.peerAEAD = NewAEAD(c.cipher, c.baseKey, c.peerRandom, c.ticket) c.peerNonce = make([]byte, 12) } if c.input.Len() > 0 { @@ -248,13 +253,13 @@ func (c *ServerConn) Read(b []byte) (int, error) { if len(dst) <= len(b) { dst = b[:len(dst)] // avoids another copy() } - var peerAead cipher.AEAD + var peerAEAD cipher.AEAD if bytes.Equal(c.peerNonce, MaxNonce) { - peerAead = NewAEAD(c.cipher, c.baseKey, peerData, h) + peerAEAD = NewAEAD(c.cipher, c.baseKey, peerData, h) } - _, err = c.peerAead.Open(dst[:0], c.peerNonce, peerData, h) - if peerAead != nil { - c.peerAead = peerAead + _, err = c.peerAEAD.Open(dst[:0], c.peerNonce, peerData, h) + if peerAEAD != nil { + c.peerAEAD = peerAEAD } IncreaseNonce(c.peerNonce) if err != nil { @@ -279,9 +284,6 @@ func (c *ServerConn) Write(b []byte) (int, error) { } n += len(b) if c.aead == nil { - if c.peerRandom == nil { - return 0, errors.New("empty c.peerRandom") - } data = make([]byte, 5+32+5+len(b)+16) EncodeHeader(data, 0, 32) rand.Read(data[5 : 5+32]) diff --git a/mihomo/transport/vless/encryption/xor.go b/mihomo/transport/vless/encryption/xor.go index 88bd76982e..a97bb8718d 100644 --- a/mihomo/transport/vless/encryption/xor.go +++ b/mihomo/transport/vless/encryption/xor.go @@ -57,7 +57,7 @@ func NewXorConn(conn net.Conn, mode uint32, pKey *ecdh.PublicKey, sKey *ecdh.Pri if pKey != nil { c.head = make([]byte, 16+32) rand.Read(c.head) - eSKey, _ := ecdh.X25519().GenerateKey(rand.Reader) + eSKey, _ := ecdh.X25519().NewPrivateKey(c.head[16:]) NewCTR(pKey.Bytes(), c.head[:16], false).XORKeyStream(c.head[16:], eSKey.PublicKey().Bytes()) // make X25519 public key distinguishable from random bytes c.key, _ = eSKey.ECDH(pKey) c.ctr = NewCTR(c.key, c.head[:16], false) diff --git a/mihomo/transport/vless/vision/conn.go b/mihomo/transport/vless/vision/conn.go index b8367fb9e4..0c300e05d1 100644 --- a/mihomo/transport/vless/vision/conn.go +++ b/mihomo/transport/vless/vision/conn.go @@ -170,7 +170,7 @@ func (vc *Conn) WriteBuffer(buffer *buf.Buffer) (err error) { if vc.needHandshake { vc.needHandshake = false if buffer.IsEmpty() { - ApplyPadding(buffer, commandPaddingContinue, vc.userUUID, false) + ApplyPadding(buffer, commandPaddingContinue, vc.userUUID, true) // we do a long padding to hide vless header } else { vc.FilterTLS(buffer.Bytes()) ApplyPadding(buffer, commandPaddingContinue, vc.userUUID, vc.isTLS) @@ -190,55 +190,37 @@ func (vc *Conn) WriteBuffer(buffer *buf.Buffer) (err error) { } if vc.writeFilterApplicationData { - buffer2 := ReshapeBuffer(buffer) - defer buffer2.Release() vc.FilterTLS(buffer.Bytes()) - command := commandPaddingContinue - if !vc.isTLS { - command = commandPaddingEnd - - // disable XTLS - //vc.readProcess = false - vc.writeFilterApplicationData = false - vc.packetsToFilter = 0 - } else if buffer.Len() > 6 && bytes.Equal(buffer.To(3), tlsApplicationDataStart) || vc.packetsToFilter <= 0 { - command = commandPaddingEnd - if vc.enableXTLS { - command = commandPaddingDirect - vc.writeDirect = true - } - vc.writeFilterApplicationData = false - } - ApplyPadding(buffer, command, nil, vc.isTLS) - err = vc.ExtendedWriter.WriteBuffer(buffer) - if err != nil { - return err - } - if vc.writeDirect { - vc.ExtendedWriter = N.NewExtendedWriter(vc.netConn) - log.Debugln("XTLS Vision direct write start") - //time.Sleep(5 * time.Millisecond) - } - if buffer2 != nil { - if vc.writeDirect || !vc.isTLS { - return vc.ExtendedWriter.WriteBuffer(buffer2) - } - vc.FilterTLS(buffer2.Bytes()) - command = commandPaddingContinue - if buffer2.Len() > 6 && bytes.Equal(buffer2.To(3), tlsApplicationDataStart) || vc.packetsToFilter <= 0 { - command = commandPaddingEnd - if vc.enableXTLS { - command = commandPaddingDirect - vc.writeDirect = true + buffers := vc.ReshapeBuffer(buffer) + applyPadding := true + for i, buffer := range buffers { + command := commandPaddingContinue + if applyPadding { + if vc.isTLS && buffer.Len() > 6 && bytes.Equal(buffer.To(3), tlsApplicationDataStart) { + command = commandPaddingEnd + if vc.enableXTLS { + command = commandPaddingDirect + vc.writeDirect = true + } + vc.writeFilterApplicationData = false + applyPadding = false + } else if !vc.isTLS12orAbove && vc.packetsToFilter <= 1 { + command = commandPaddingEnd + vc.writeFilterApplicationData = false + applyPadding = false } - vc.writeFilterApplicationData = false + ApplyPadding(buffer, command, nil, vc.isTLS) } - ApplyPadding(buffer2, command, nil, vc.isTLS) - err = vc.ExtendedWriter.WriteBuffer(buffer2) - if vc.writeDirect { + + err = vc.ExtendedWriter.WriteBuffer(buffer) + if err != nil { + buf.ReleaseMulti(buffers[i:]) // release unwritten buffers + return + } + if command == commandPaddingDirect { vc.ExtendedWriter = N.NewExtendedWriter(vc.netConn) log.Debugln("XTLS Vision direct write start") - //time.Sleep(10 * time.Millisecond) + //time.Sleep(5 * time.Millisecond) } } return err diff --git a/mihomo/transport/vless/vision/padding.go b/mihomo/transport/vless/vision/padding.go index dd9cb261a3..710f64c217 100644 --- a/mihomo/transport/vless/vision/padding.go +++ b/mihomo/transport/vless/vision/padding.go @@ -6,6 +6,7 @@ import ( "github.com/metacubex/mihomo/common/buf" "github.com/metacubex/mihomo/log" + N "github.com/metacubex/sing/common/network" "github.com/gofrs/uuid/v5" "github.com/metacubex/randv2" @@ -19,30 +20,6 @@ const ( commandPaddingDirect byte = 0x02 ) -func WriteWithPadding(buffer *buf.Buffer, p []byte, command byte, userUUID *uuid.UUID, paddingTLS bool) { - contentLen := int32(len(p)) - var paddingLen int32 - if contentLen < 900 { - if paddingTLS { - //log.Debugln("long padding") - paddingLen = randv2.Int32N(500) + 900 - contentLen - } else { - paddingLen = randv2.Int32N(256) - } - } - if userUUID != nil { - buffer.Write(userUUID.Bytes()) - } - - buffer.WriteByte(command) - binary.BigEndian.PutUint16(buffer.Extend(2), uint16(contentLen)) - binary.BigEndian.PutUint16(buffer.Extend(2), uint16(paddingLen)) - buffer.Write(p) - - buffer.Extend(int(paddingLen)) - log.Debugln("XTLS Vision write padding1: command=%v, payloadLen=%v, paddingLen=%v", command, contentLen, paddingLen) -} - func ApplyPadding(buffer *buf.Buffer, command byte, userUUID *uuid.UUID, paddingTLS bool) { contentLen := int32(buffer.Len()) var paddingLen int32 @@ -63,19 +40,20 @@ func ApplyPadding(buffer *buf.Buffer, command byte, userUUID *uuid.UUID, padding } buffer.Extend(int(paddingLen)) - log.Debugln("XTLS Vision write padding2: command=%d, payloadLen=%d, paddingLen=%d", command, contentLen, paddingLen) + log.Debugln("XTLS Vision write padding: command=%d, payloadLen=%d, paddingLen=%d", command, contentLen, paddingLen) } -func ReshapeBuffer(buffer *buf.Buffer) *buf.Buffer { - if buffer.Len() <= buf.BufferSize-PaddingHeaderLen { - return nil +func (vc *Conn) ReshapeBuffer(buffer *buf.Buffer) []*buf.Buffer { + const xrayBufSize = 8192 + if buffer.Len() <= xrayBufSize-PaddingHeaderLen { + return []*buf.Buffer{buffer} } cutAt := bytes.LastIndex(buffer.Bytes(), tlsApplicationDataStart) if cutAt == -1 { - cutAt = buf.BufferSize / 2 + cutAt = xrayBufSize / 2 } - buffer2 := buf.New() + buffer2 := N.NewReadWaitOptions(nil, vc).NewBuffer() // ensure the new buffer can send used in vc.WriteBuffer buffer2.Write(buffer.From(cutAt)) buffer.Truncate(cutAt) - return buffer2 + return []*buf.Buffer{buffer, buffer2} } diff --git a/openwrt-passwall/luci-app-passwall/luasrc/controller/passwall.lua b/openwrt-passwall/luci-app-passwall/luasrc/controller/passwall.lua index 2d62b8dcbb..d90b49b47d 100644 --- a/openwrt-passwall/luci-app-passwall/luasrc/controller/passwall.lua +++ b/openwrt-passwall/luci-app-passwall/luasrc/controller/passwall.lua @@ -633,20 +633,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) @@ -667,19 +676,21 @@ function restore_backup() api.log(" * 重启 PassWall 服务中…\n") luci.sys.call('/etc/init.d/passwall restart > /dev/null 2>&1 &') luci.sys.call('/etc/init.d/passwall_server restart > /dev/null 2>&1 &') + result = { status = "success", message = "Upload completed", path = file_path } else api.log(" * PassWall 配置文件解压失败,请重试!") + result = { status = "error", message = "Decompression failed" } end luci.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-passwall/luci-app-passwall/luasrc/view/passwall/global/backup.htm b/openwrt-passwall/luci-app-passwall/luasrc/view/passwall/global/backup.htm index c0d2e76f1e..918417cf3f 100644 --- a/openwrt-passwall/luci-app-passwall/luasrc/view/passwall/global/backup.htm +++ b/openwrt-passwall/luci-app-passwall/luasrc/view/passwall/global/backup.htm @@ -184,7 +184,6 @@ local api = require "luci.passwall.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.passwall.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/Makefile b/openwrt-passwall2/luci-app-passwall2/Makefile index 721c9aeace..7589c3973e 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.9 +PKG_VERSION:=25.8.22 PKG_RELEASE:=1 PKG_CONFIG_DEPENDS:= \ diff --git a/openwrt-passwall2/luci-app-passwall2/luasrc/model/cbi/passwall2/client/type/hysteria2.lua b/openwrt-passwall2/luci-app-passwall2/luasrc/model/cbi/passwall2/client/type/hysteria2.lua index 7b6bd7d1ff..e8d54732c1 100644 --- a/openwrt-passwall2/luci-app-passwall2/luasrc/model/cbi/passwall2/client/type/hysteria2.lua +++ b/openwrt-passwall2/luci-app-passwall2/luasrc/model/cbi/passwall2/client/type/hysteria2.lua @@ -30,6 +30,11 @@ o = s:option(Value, _n("hop"), translate("Port hopping range")) o.description = translate("Format as 1000:2000 or 1000-2000 Multiple groups are separated by commas (,).") o.rewrite_option = o.option +o = s:option(Value, _n("hop_interval"), translate("Hop Interval"), translate("Example:") .. "30s (≥5s)") +o.placeholder = "30s" +o.default = "30s" +o.rewrite_option = o.option + o = s:option(Value, _n("obfs"), translate("Obfs Password")) o.rewrite_option = o.option @@ -54,9 +59,6 @@ o.rewrite_option = o.option o = s:option(Value, _n("down_mbps"), translate("Max download Mbps")) o.rewrite_option = o.option -o = s:option(Value, _n("hop_interval"), translate("Hop Interval"), translate("Example:") .. "30s (≥5s)") -o.rewrite_option = o.option - o = s:option(Value, _n("recv_window"), translate("QUIC stream receive window")) o.rewrite_option = o.option diff --git a/openwrt-passwall2/luci-app-passwall2/luasrc/model/cbi/passwall2/client/type/ray.lua b/openwrt-passwall2/luci-app-passwall2/luasrc/model/cbi/passwall2/client/type/ray.lua index 73f25b30ec..125dac4ac3 100644 --- a/openwrt-passwall2/luci-app-passwall2/luasrc/model/cbi/passwall2/client/type/ray.lua +++ b/openwrt-passwall2/luci-app-passwall2/luasrc/model/cbi/passwall2/client/type/ray.lua @@ -61,7 +61,8 @@ for k, e in ipairs(api.get_valid_nodes()) do nodes_table[#nodes_table + 1] = { id = e[".name"], remark = e["remark"], - type = e["type"] + type = e["type"], + chain_proxy = e["chain_proxy"] } end if e.protocol == "_balancing" then @@ -337,6 +338,7 @@ o.default = "" o:value("", translate("Disable")) o:value("xtls-rprx-vision") o:depends({ [_n("protocol")] = "vless", [_n("tls")] = true, [_n("transport")] = "raw" }) +o:depends({ [_n("protocol")] = "trojan", [_n("tls")] = true, [_n("transport")] = "raw" }) o = s:option(Flag, _n("tls"), translate("TLS")) o.default = 0 @@ -392,6 +394,13 @@ o.validate = function(self, value) return api.trim(value:gsub("[\r\n]", "")) end +o = s:option(ListValue, _n("ech_ForceQuery"), translate("ECH Query Policy"), translate("Controls the policy used when performing DNS queries for ECH configuration.")) +o.default = "none" +o:value("none") +o:value("half") +o:value("full") +o:depends({ [_n("ech")] = true }) + -- [[ REALITY部分 ]] -- o = s:option(Value, _n("reality_publicKey"), translate("Public Key")) o:depends({ [_n("tls")] = true, [_n("reality")] = true }) @@ -696,7 +705,7 @@ o = s:option(ListValue, _n("to_node"), translate("Landing Node"), translate("Onl o:depends({ [_n("chain_proxy")] = "2" }) for k, v in pairs(nodes_table) do - if v.type == "Xray" and v.id ~= arg[1] then + if v.type == "Xray" and v.id ~= arg[1] and (not v.chain_proxy or v.chain_proxy == "") then s.fields[_n("preproxy_node")]:value(v.id, v.remark) s.fields[_n("to_node")]:value(v.id, v.remark) end 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 998e689c72..13f2f7c1b5 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 @@ -81,7 +81,8 @@ for k, e in ipairs(api.get_valid_nodes()) do nodes_table[#nodes_table + 1] = { id = e[".name"], remark = e["remark"], - type = e["type"] + type = e["type"], + chain_proxy = e["chain_proxy"] } end if e.protocol == "_iface" then @@ -339,12 +340,18 @@ o.default = "" o:value("", translate("Disable")) o:value("xtls-rprx-vision") o:depends({ [_n("protocol")] = "vless", [_n("tls")] = true }) +o:depends({ [_n("protocol")] = "trojan", [_n("tls")] = true }) if singbox_tags:find("with_quic") then o = s:option(Value, _n("hysteria_hop"), translate("Port hopping range")) o.description = translate("Format as 1000:2000 or 1000-2000 Multiple groups are separated by commas (,).") o:depends({ [_n("protocol")] = "hysteria" }) + o = s:option(Value, _n("hysteria_hop_interval"), translate("Hop Interval"), translate("Example:") .. "30s (≥5s)") + o.placeholder = "30s" + o.default = "30s" + o:depends({ [_n("protocol")] = "hysteria" }) + o = s:option(Value, _n("hysteria_obfs"), translate("Obfs Password")) o:depends({ [_n("protocol")] = "hysteria" }) @@ -425,6 +432,11 @@ if singbox_tags:find("with_quic") then o.description = translate("Format as 1000:2000 or 1000-2000 Multiple groups are separated by commas (,).") o:depends({ [_n("protocol")] = "hysteria2" }) + o = s:option(Value, _n("hysteria2_hop_interval"), translate("Hop Interval"), translate("Example:") .. "30s (≥5s)") + o.placeholder = "30s" + o.default = "30s" + o:depends({ [_n("protocol")] = "hysteria2" }) + o = s:option(Value, _n("hysteria2_up_mbps"), translate("Max upload Mbps")) o:depends({ [_n("protocol")] = "hysteria2" }) @@ -526,30 +538,30 @@ if singbox_tags:find("with_utls") then o:value("firefox") o:value("edge") o:value("safari") - -- o:value("360") + o:value("360") o:value("qq") o:value("ios") - -- o:value("android") + o:value("android") o:value("random") - -- o:value("randomized") + o:value("randomized") o.default = "chrome" - o:depends({ [_n("tls")] = true, [_n("utls")] = true }) + o:depends({ [_n("utls")] = true }) -- [[ REALITY部分 ]] -- o = s:option(Flag, _n("reality"), translate("REALITY")) o.default = 0 - o:depends({ [_n("protocol")] = "vless", [_n("utls")] = true }) - o:depends({ [_n("protocol")] = "vmess", [_n("utls")] = true }) - o:depends({ [_n("protocol")] = "shadowsocks", [_n("utls")] = true }) - o:depends({ [_n("protocol")] = "socks", [_n("utls")] = true }) - o:depends({ [_n("protocol")] = "trojan", [_n("utls")] = true }) - o:depends({ [_n("protocol")] = "anytls", [_n("utls")] = true }) + o:depends({ [_n("protocol")] = "vless", [_n("tls")] = true }) + o:depends({ [_n("protocol")] = "vmess", [_n("tls")] = true }) + o:depends({ [_n("protocol")] = "shadowsocks", [_n("tls")] = true }) + o:depends({ [_n("protocol")] = "socks", [_n("tls")] = true }) + o:depends({ [_n("protocol")] = "trojan", [_n("tls")] = true }) + o:depends({ [_n("protocol")] = "anytls", [_n("tls")] = true }) o = s:option(Value, _n("reality_publicKey"), translate("Public Key")) - o:depends({ [_n("utls")] = true, [_n("reality")] = true }) + o:depends({ [_n("reality")] = true }) o = s:option(Value, _n("reality_shortId"), translate("Short Id")) - o:depends({ [_n("utls")] = true, [_n("reality")] = true }) + o:depends({ [_n("reality")] = true }) end o = s:option(ListValue, _n("transport"), translate("Transport")) @@ -801,7 +813,7 @@ o = s:option(ListValue, _n("to_node"), translate("Landing Node"), translate("Onl o:depends({ [_n("chain_proxy")] = "2" }) for k, v in pairs(nodes_table) do - if v.type == "sing-box" and v.id ~= arg[1] then + if v.type == "sing-box" and v.id ~= arg[1] and (not v.chain_proxy or v.chain_proxy == "") then s.fields[_n("preproxy_node")]:value(v.id, v.remark) s.fields[_n("to_node")]:value(v.id, v.remark) 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 dd71579480..c4eee19ba4 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 @@ -321,7 +321,11 @@ function gen_outbound(flag, node, tag, proxy_table) end protocol_table = { server_ports = next(server_ports) and server_ports or nil, - hop_interval = next(server_ports) and "30s" or nil, + hop_interval = (function() + if not next(server_ports) then return nil end + local v = tonumber((node.hysteria_hop_interval or "30s"):match("^%d+")) + return (v and v >= 5) and (v .. "s") or "30s" + end)(), up_mbps = tonumber(node.hysteria_up_mbps), down_mbps = tonumber(node.hysteria_down_mbps), obfs = node.hysteria_obfs, @@ -397,7 +401,11 @@ function gen_outbound(flag, node, tag, proxy_table) end protocol_table = { server_ports = next(server_ports) and server_ports or nil, - hop_interval = next(server_ports) and "30s" or nil, + hop_interval = (function() + if not next(server_ports) then return nil end + local v = tonumber((node.hysteria2_hop_interval or "30s"):match("^%d+")) + return (v and v >= 5) and (v .. "s") or "30s" + end)(), up_mbps = (node.hysteria2_up_mbps and tonumber(node.hysteria2_up_mbps)) and tonumber(node.hysteria2_up_mbps) or nil, down_mbps = (node.hysteria2_down_mbps and tonumber(node.hysteria2_down_mbps)) and tonumber(node.hysteria2_down_mbps) or nil, obfs = { 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 058de37890..7fbd0b4e96 100644 --- a/openwrt-passwall2/luci-app-passwall2/luasrc/passwall2/util_xray.lua +++ b/openwrt-passwall2/luci-app-passwall2/luasrc/passwall2/util_xray.lua @@ -155,7 +155,8 @@ function gen_outbound(flag, node, tag, proxy_table) serverName = node.tls_serverName, allowInsecure = (node.tls_allowInsecure == "1") and true or false, fingerprint = (node.type == "Xray" and node.utls == "1" and node.fingerprint and node.fingerprint ~= "") and node.fingerprint or nil, - echConfigList = (node.ech == "1") and node.ech_config or nil + echConfigList = (node.ech == "1") and node.ech_config or nil, + echForceQuery = (node.ech == "1") and (node.ech_ForceQuery or "none") or nil } or nil, realitySettings = (node.stream_security == "reality") and { serverName = node.tls_serverName, @@ -1060,6 +1061,7 @@ function gen_config(var) domains = {} string.gsub(e.domain_list, '[^' .. "\r\n" .. ']+', function(w) if w:find("#") == 1 then return end + if w:find("rule-set:", 1, true) == 1 or w:find("rs:") == 1 then return end table.insert(domains, w) table.insert(domain_table.domain, w) end) @@ -1073,6 +1075,7 @@ function gen_config(var) ip = {} string.gsub(e.ip_list, '[^' .. "\r\n" .. ']+', function(w) if w:find("#") == 1 then return end + if w:find("rule-set:", 1, true) == 1 or w:find("rs:") == 1 then return end table.insert(ip, w) end) if #ip == 0 then ip = nil end diff --git a/openwrt-passwall2/luci-app-passwall2/luasrc/view/passwall2/node_list/link_share_man.htm b/openwrt-passwall2/luci-app-passwall2/luasrc/view/passwall2/node_list/link_share_man.htm index 57985d3876..1ecd231601 100644 --- a/openwrt-passwall2/luci-app-passwall2/luasrc/view/passwall2/node_list/link_share_man.htm +++ b/openwrt-passwall2/luci-app-passwall2/luasrc/view/passwall2/node_list/link_share_man.htm @@ -284,10 +284,6 @@ local hysteria2_type = map:get("@global_subscribe[0]", "hysteria2_type") or "sin params += opt.query("spx", dom_prefix + "reality_spiderX"); params += opt.query("pqv", dom_prefix + "reality_mldsa65Verify"); } - if (opt.get(dom_prefix + "flow") && opt.get(dom_prefix + "flow").value) { - let v_flow = opt.get(dom_prefix + "flow").value; - params += "&flow=" + v_flow; - } params += "&security=" + v_security; params += opt.query("alpn", dom_prefix + "alpn"); params += opt.query("sni", dom_prefix + "tls_serverName"); @@ -960,11 +956,10 @@ local hysteria2_type = map:get("@global_subscribe[0]", "hysteria2_type") or "sin if (queryParam.security == "tls") { opt.set(dom_prefix + 'tls', true); opt.set(dom_prefix + 'reality', false); - opt.set(dom_prefix + 'flow', queryParam.flow || ''); opt.set(dom_prefix + 'alpn', queryParam.alpn || 'default'); opt.set(dom_prefix + 'tls_serverName', queryParam.sni || ''); opt.set(dom_prefix + 'tls_allowInsecure', true); - if (queryParam.allowinsecure === '0' || queryParam.insecure === '0') { + if ((queryParam.allowinsecure ?? '0') === '0' && (queryParam.insecure ?? '0') === '0') { opt.set(dom_prefix + 'tls_allowInsecure', false); } if (queryParam.fp && queryParam.fp.trim() != "") { @@ -978,7 +973,6 @@ local hysteria2_type = map:get("@global_subscribe[0]", "hysteria2_type") or "sin if (queryParam.security == "reality") { opt.set(dom_prefix + 'tls', true); opt.set(dom_prefix + 'reality', true); - opt.set(dom_prefix + 'flow', queryParam.flow || ''); opt.set(dom_prefix + 'alpn', queryParam.alpn || 'default'); opt.set(dom_prefix + 'tls_serverName', queryParam.sni || ''); if (queryParam.fp && queryParam.fp.trim() != "") { @@ -1205,9 +1199,11 @@ local hysteria2_type = map:get("@global_subscribe[0]", "hysteria2_type") or "sin } tls_serverName = tls_serverName || ""; opt.set(dom_prefix + 'tls_serverName', tls_serverName); + opt.set(dom_prefix + 'flow', (queryParam.flow || '').replace('-udp443', '')); + opt.set(dom_prefix + 'alpn', queryParam.alpn || 'default'); } opt.set(dom_prefix + 'tls_allowInsecure', true); - if (queryParam.allowinsecure === '0' || queryParam.insecure === '0') { + if ((queryParam.allowinsecure ?? '0') === '0' && (queryParam.insecure ?? '0') === '0') { opt.set(dom_prefix + 'tls_allowInsecure', false); } @@ -1342,11 +1338,11 @@ local hysteria2_type = map:get("@global_subscribe[0]", "hysteria2_type") or "sin if (queryParam.security == "tls") { opt.set(dom_prefix + 'tls', true); opt.set(dom_prefix + 'reality', false); - opt.set(dom_prefix + 'flow', queryParam.flow || ''); + opt.set(dom_prefix + 'flow', (queryParam.flow || '').replace('-udp443', '')); opt.set(dom_prefix + 'alpn', queryParam.alpn || 'default'); opt.set(dom_prefix + 'tls_serverName', queryParam.sni || ''); opt.set(dom_prefix + 'tls_allowInsecure', true); - if (queryParam.allowinsecure === '0' || queryParam.insecure === '0') { + if ((queryParam.allowinsecure ?? '0') === '0' && (queryParam.insecure ?? '0') === '0') { opt.set(dom_prefix + 'tls_allowInsecure', false); } if (queryParam.fp && queryParam.fp.trim() != "") { @@ -1360,7 +1356,7 @@ local hysteria2_type = map:get("@global_subscribe[0]", "hysteria2_type") or "sin if (queryParam.security == "reality") { opt.set(dom_prefix + 'tls', true); opt.set(dom_prefix + 'reality', true); - opt.set(dom_prefix + 'flow', queryParam.flow || ''); + opt.set(dom_prefix + 'flow', (queryParam.flow || '').replace('-udp443', '')); opt.set(dom_prefix + 'alpn', queryParam.alpn || 'default'); opt.set(dom_prefix + 'tls_serverName', queryParam.sni || ''); if (queryParam.fp && queryParam.fp.trim() != "") { @@ -1539,7 +1535,7 @@ local hysteria2_type = map:get("@global_subscribe[0]", "hysteria2_type") or "sin opt.set(dom_prefix + 'tuic_alpn', queryParam.alpn || 'default'); opt.set(dom_prefix + 'tls_serverName', queryParam.sni || ''); opt.set(dom_prefix + 'tls_allowInsecure', true); - if (queryParam.allowinsecure === '0' || queryParam.insecure === '0') { + if ((queryParam.allowinsecure ?? '0') === '0' && (queryParam.insecure ?? '0') === '0') { opt.set(dom_prefix + 'tls_allowInsecure', false); } if (hash) { @@ -1579,11 +1575,10 @@ local hysteria2_type = map:get("@global_subscribe[0]", "hysteria2_type") or "sin if (queryParam.security == "tls") { opt.set(dom_prefix + 'tls', true); opt.set(dom_prefix + 'reality', false); - opt.set(dom_prefix + 'flow', queryParam.flow || ''); opt.set(dom_prefix + 'alpn', queryParam.alpn || 'default'); opt.set(dom_prefix + 'tls_serverName', queryParam.sni || ''); opt.set(dom_prefix + 'tls_allowInsecure', true); - if (queryParam.allowinsecure === '0' || queryParam.insecure === '0') { + if ((queryParam.allowinsecure ?? '0') === '0' && (queryParam.insecure ?? '0') === '0') { opt.set(dom_prefix + 'tls_allowInsecure', false); } if (queryParam.fp && queryParam.fp.trim() != "") { @@ -1594,7 +1589,6 @@ local hysteria2_type = map:get("@global_subscribe[0]", "hysteria2_type") or "sin if (queryParam.security == "reality") { opt.set(dom_prefix + 'tls', true); opt.set(dom_prefix + 'reality', true); - opt.set(dom_prefix + 'flow', queryParam.flow || ''); opt.set(dom_prefix + 'alpn', queryParam.alpn || 'default'); opt.set(dom_prefix + 'tls_serverName', queryParam.sni || ''); if (queryParam.fp && queryParam.fp.trim() != "") { 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 4db28139df..c3ac43cdce 100644 --- a/openwrt-passwall2/luci-app-passwall2/po/zh-cn/passwall2.po +++ b/openwrt-passwall2/luci-app-passwall2/po/zh-cn/passwall2.po @@ -1576,6 +1576,12 @@ msgstr "后量子对等证书签名方案" msgid "Disable adaptive sizing of TLS records" msgstr "禁用 TLS 记录的自适应大小调整" +msgid "ECH Query Policy" +msgstr "ECH 查询策略" + +msgid "Controls the policy used when performing DNS queries for ECH configuration." +msgstr "控制使用 DNS 查询 ECH 配置时的策略。" + msgid "Enable Multipath TCP, need to be enabled in both server and client configuration." msgstr "启用 Multipath TCP,需在服务端和客户端配置中同时启用。" diff --git a/openwrt-passwall2/luci-app-passwall2/root/usr/share/passwall2/app.sh b/openwrt-passwall2/luci-app-passwall2/root/usr/share/passwall2/app.sh index 89b4efbeea..814fa08004 100755 --- a/openwrt-passwall2/luci-app-passwall2/root/usr/share/passwall2/app.sh +++ b/openwrt-passwall2/luci-app-passwall2/root/usr/share/passwall2/app.sh @@ -336,6 +336,15 @@ eval_cache_var() { [ -s "$TMP_PATH/var" ] && eval $(cat "$TMP_PATH/var") } +has_1_65535() { + local val="$1" + val=${val//:/-} + case ",$val," in + *,1-65535,*) return 0 ;; + *) return 1 ;; + esac +} + run_xray() { local flag node redir_port tcp_proxy_way socks_address socks_port socks_username socks_password http_address http_port http_username http_password local dns_listen_port direct_dns_query_strategy remote_dns_protocol remote_dns_udp_server remote_dns_tcp_server remote_dns_doh remote_dns_client_ip remote_dns_detour remote_fakedns remote_dns_query_strategy dns_cache write_ipset_direct @@ -1146,11 +1155,10 @@ acl_app() { index=$(expr $index + 1) local enabled sid remarks sources interface tcp_no_redir_ports udp_no_redir_ports node direct_dns_query_strategy write_ipset_direct remote_dns_protocol remote_dns remote_dns_doh remote_dns_client_ip remote_dns_detour remote_fakedns remote_dns_query_strategy local _ip _mac _iprange _ipset _ip_or_mac source_list config_file - sid=$(uci -q show "${CONFIG}.${item}" | grep "=acl_rule" | awk -F '=' '{print $1}' | awk -F '.' '{print $2}') + local sid=$(uci -q show "${CONFIG}.${item}" | grep "=acl_rule" | awk -F '=' '{print $1}' | awk -F '.' '{print $2}') + [ "$(config_n_get $sid enabled)" = "1" ] || continue eval $(uci -q show "${CONFIG}.${item}" | cut -d'.' -sf 3-) - [ "$enabled" = "1" ] || continue - if [ -n "${sources}" ]; then for s in $sources; do local s2 @@ -1183,7 +1191,9 @@ acl_app() { udp_no_redir_ports=${udp_no_redir_ports:-default} [ "$tcp_no_redir_ports" = "default" ] && tcp_no_redir_ports=$TCP_NO_REDIR_PORTS [ "$udp_no_redir_ports" = "default" ] && udp_no_redir_ports=$UDP_NO_REDIR_PORTS - [ "$tcp_no_redir_ports" == "1:65535" ] && [ "$udp_no_redir_ports" == "1:65535" ] && unset node + if has_1_65535 "$tcp_no_redir_ports" && has_1_65535 "$udp_no_redir_ports"; then + unset node + fi [ -n "$node" ] && { tcp_proxy_mode="global" diff --git a/openwrt-passwall2/luci-app-passwall2/root/usr/share/passwall2/iptables.sh b/openwrt-passwall2/luci-app-passwall2/root/usr/share/passwall2/iptables.sh index c1e0759684..44cc493460 100755 --- a/openwrt-passwall2/luci-app-passwall2/root/usr/share/passwall2/iptables.sh +++ b/openwrt-passwall2/luci-app-passwall2/root/usr/share/passwall2/iptables.sh @@ -418,7 +418,7 @@ load_acl() { [ -n "${is_tproxy}" ] && ipt_tmp=$ipt_m [ "$tcp_no_redir_ports" != "disable" ] && { - if [ "$tcp_no_redir_ports" != "1:65535" ]; then + if ! has_1_65535 "$tcp_no_redir_ports"; then [ "$_ipv4" != "1" ] && add_port_rules "$ip6t_m -A PSW2 $(comment "$remarks") ${_ipt_source} -p tcp" $tcp_no_redir_ports "-j RETURN" 2>/dev/null add_port_rules "$ipt_tmp -A PSW2 $(comment "$remarks") ${_ipt_source} -p tcp" $tcp_no_redir_ports "-j RETURN" echolog " - ${msg}不代理 TCP 端口[${tcp_no_redir_ports}]" @@ -430,7 +430,7 @@ load_acl() { } [ "$udp_no_redir_ports" != "disable" ] && { - if [ "$udp_no_redir_ports" != "1:65535" ]; then + if ! has_1_65535 "$udp_no_redir_ports"; then [ "$_ipv4" != "1" ] && add_port_rules "$ip6t_m -A PSW2 $(comment "$remarks") ${_ipt_source} -p udp" $udp_no_redir_ports "-j RETURN" 2>/dev/null add_port_rules "$ipt_m -A PSW2 $(comment "$remarks") ${_ipt_source} -p udp" $udp_no_redir_ports "-j RETURN" echolog " - ${msg}不代理 UDP 端口[${udp_no_redir_ports}]" @@ -526,7 +526,7 @@ load_acl() { [ "$TCP_NO_REDIR_PORTS" != "disable" ] && { add_port_rules "$ip6t_m -A PSW2 $(comment "默认") -p tcp" $TCP_NO_REDIR_PORTS "-j RETURN" add_port_rules "$ipt_tmp -A PSW2 $(comment "默认") -p tcp" $TCP_NO_REDIR_PORTS "-j RETURN" - if [ "$TCP_NO_REDIR_PORTS" != "1:65535" ]; then + if ! has_1_65535 "$TCP_NO_REDIR_PORTS"; then echolog " - ${msg}不代理 TCP 端口[${TCP_NO_REDIR_PORTS}]" else TCP_PROXY_MODE="disable" @@ -537,7 +537,7 @@ load_acl() { [ "$UDP_NO_REDIR_PORTS" != "disable" ] && { add_port_rules "$ip6t_m -A PSW2 $(comment "默认") -p udp" $UDP_NO_REDIR_PORTS "-j RETURN" add_port_rules "$ipt_tmp -A PSW2 $(comment "默认") -p udp" $UDP_NO_REDIR_PORTS "-j RETURN" - if [ "$UDP_NO_REDIR_PORTS" != "1:65535" ]; then + if ! has_1_65535 "$UDP_NO_REDIR_PORTS"; then echolog " - ${msg}不代理 UDP 端口[${UDP_NO_REDIR_PORTS}]" else UDP_PROXY_MODE="disable" @@ -871,7 +871,7 @@ add_firewall_rule() { [ "$TCP_NO_REDIR_PORTS" != "disable" ] && { add_port_rules "$ipt_tmp -A PSW2_OUTPUT -p tcp" $TCP_NO_REDIR_PORTS "-j RETURN" add_port_rules "$ip6t_m -A PSW2_OUTPUT -p tcp" $TCP_NO_REDIR_PORTS "-j RETURN" - if [ "$TCP_NO_REDIR_PORTS" != "1:65535" ]; then + if ! has_1_65535 "$TCP_NO_REDIR_PORTS"; then echolog " - ${msg}不代理 TCP 端口[${TCP_NO_REDIR_PORTS}]" else unset TCP_LOCALHOST_PROXY @@ -882,7 +882,7 @@ add_firewall_rule() { [ "$UDP_NO_REDIR_PORTS" != "disable" ] && { add_port_rules "$ipt_m -A PSW2_OUTPUT -p udp" $UDP_NO_REDIR_PORTS "-j RETURN" add_port_rules "$ip6t_m -A PSW2_OUTPUT -p udp" $UDP_NO_REDIR_PORTS "-j RETURN" - if [ "$UDP_NO_REDIR_PORTS" != "1:65535" ]; then + if ! has_1_65535 "$UDP_NO_REDIR_PORTS"; then echolog " - ${msg}不代理 UDP 端口[${UDP_NO_REDIR_PORTS}]" else unset UDP_LOCALHOST_PROXY diff --git a/openwrt-passwall2/luci-app-passwall2/root/usr/share/passwall2/nftables.sh b/openwrt-passwall2/luci-app-passwall2/root/usr/share/passwall2/nftables.sh index 0ae46b3993..4d6b946d1b 100755 --- a/openwrt-passwall2/luci-app-passwall2/root/usr/share/passwall2/nftables.sh +++ b/openwrt-passwall2/luci-app-passwall2/root/usr/share/passwall2/nftables.sh @@ -432,7 +432,7 @@ load_acl() { msg="【$remarks】,${msg}" [ "$tcp_no_redir_ports" != "disable" ] && { - if [ "$tcp_no_redir_ports" != "1:65535" ]; then + if ! has_1_65535 "$tcp_no_redir_ports"; then nft "add rule $NFTABLE_NAME $nft_prerouting_chain ${_ipt_source} ip protocol tcp $(factor $tcp_no_redir_ports "tcp dport") counter return comment \"$remarks\"" [ "$_ipv4" != "1" ] && nft "add rule $NFTABLE_NAME PSW2_MANGLE_V6 ${_ipt_source} meta l4proto tcp $(factor $tcp_no_redir_ports "tcp dport") counter return comment \"$remarks\"" echolog " - ${msg}不代理 TCP 端口[${tcp_no_redir_ports}]" @@ -444,7 +444,7 @@ load_acl() { } [ "$udp_no_redir_ports" != "disable" ] && { - if [ "$udp_no_redir_ports" != "1:65535" ]; then + if ! has_1_65535 "$udp_no_redir_ports"; then nft "add rule $NFTABLE_NAME PSW2_MANGLE ip protocol udp ${_ipt_source} $(factor $udp_no_redir_ports "udp dport") counter return comment \"$remarks\"" [ "$_ipv4" != "1" ] && nft "add rule $NFTABLE_NAME PSW2_MANGLE_V6 meta l4proto udp ${_ipt_source} $(factor $udp_no_redir_ports "udp dport") counter return comment \"$remarks\"" 2>/dev/null echolog " - ${msg}不代理 UDP 端口[${udp_no_redir_ports}]" @@ -544,7 +544,7 @@ load_acl() { [ "$TCP_NO_REDIR_PORTS" != "disable" ] && { nft "add rule $NFTABLE_NAME $nft_prerouting_chain ip protocol tcp $(factor $TCP_NO_REDIR_PORTS "tcp dport") counter return comment \"默认\"" nft "add rule $NFTABLE_NAME PSW2_MANGLE_V6 meta l4proto tcp $(factor $TCP_NO_REDIR_PORTS "tcp dport") counter return comment \"默认\"" - if [ "$TCP_NO_REDIR_PORTS" != "1:65535" ]; then + if ! has_1_65535 "$TCP_NO_REDIR_PORTS"; then echolog " - ${msg}不代理 TCP 端口[${TCP_NO_REDIR_PORTS}]" else TCP_PROXY_MODE="disable" @@ -555,7 +555,7 @@ load_acl() { [ "$UDP_NO_REDIR_PORTS" != "disable" ] && { nft "add $NFTABLE_NAME PSW2_MANGLE ip protocol udp $(factor $UDP_NO_REDIR_PORTS "udp dport") counter return comment \"默认\"" nft "add $NFTABLE_NAME PSW2_MANGLE_V6 counter meta l4proto udp $(factor $UDP_NO_REDIR_PORTS "udp dport") counter return comment \"默认\"" - if [ "$UDP_NO_REDIR_PORTS" != "1:65535" ]; then + if ! has_1_65535 "$UDP_NO_REDIR_PORTS"; then echolog " - ${msg}不代理 UDP 端口[${UDP_NO_REDIR_PORTS}]" else UDP_PROXY_MODE="disable" @@ -893,7 +893,7 @@ add_firewall_rule() { [ "$TCP_NO_REDIR_PORTS" != "disable" ] && { nft "add rule $NFTABLE_NAME $nft_output_chain ip protocol tcp $(factor $TCP_NO_REDIR_PORTS "tcp dport") counter return" nft "add rule $NFTABLE_NAME PSW2_OUTPUT_MANGLE_V6 meta l4proto tcp $(factor $TCP_NO_REDIR_PORTS "tcp dport") counter return" - if [ "$TCP_NO_REDIR_PORTS" != "1:65535" ]; then + if ! has_1_65535 "$TCP_NO_REDIR_PORTS"; then echolog " - ${msg}不代理 TCP 端口[${TCP_NO_REDIR_PORTS}]" else unset TCP_LOCALHOST_PROXY @@ -904,7 +904,7 @@ add_firewall_rule() { [ "$UDP_NO_REDIR_PORTS" != "disable" ] && { nft "add rule $NFTABLE_NAME PSW2_OUTPUT_MANGLE ip protocol udp $(factor $UDP_NO_REDIR_PORTS "udp dport") counter return" nft "add rule $NFTABLE_NAME PSW2_OUTPUT_MANGLE_V6 meta l4proto udp $(factor $UDP_NO_REDIR_PORTS "udp dport") counter return" - if [ "$UDP_NO_REDIR_PORTS" != "1:65535" ]; then + if ! has_1_65535 "$UDP_NO_REDIR_PORTS"; then echolog " - ${msg}不代理 UDP 端口[${UDP_NO_REDIR_PORTS}]" else unset UDP_LOCALHOST_PROXY 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 25754a664b..2d37277d79 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 @@ -1042,8 +1042,8 @@ local function processData(szType, content, add_mode, add_from) end result.encryption = params.encryption or "none" - - result.flow = params.flow or nil + result.flow = params.flow and params.flow:gsub("-udp443", "") or nil + result.alpn = params.alpn if result.type == "sing-box" and (result.transport == "mkcp" or result.transport == "xhttp" or result.transport == "splithttp") then log("跳过节点:" .. result.remarks ..",因Sing-Box不支持" .. szType .. "协议的" .. result.transport .. "传输方式,需更换Xray。") @@ -1194,7 +1194,7 @@ local function processData(szType, content, add_mode, add_from) result.encryption = params.encryption or "none" - result.flow = params.flow or nil + result.flow = params.flow and params.flow:gsub("-udp443", "") or nil result.tls = "0" if params.security == "tls" or params.security == "reality" then @@ -1272,7 +1272,6 @@ local function processData(szType, content, add_mode, add_from) else result.address = host_port end - result.protocol = params.protocol result.hysteria_obfs = params.obfsParam result.hysteria_auth_type = "string" result.hysteria_auth_password = params.auth diff --git a/shadowsocks-rust/Cargo.lock b/shadowsocks-rust/Cargo.lock index 350d474067..0f46cc4dd0 100644 --- a/shadowsocks-rust/Cargo.lock +++ b/shadowsocks-rust/Cargo.lock @@ -1703,9 +1703,9 @@ dependencies = [ [[package]] name = "idna" -version = "1.0.3" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "686f825264d630750a544639377bae737628043f20d38bbc029e8f29ea968a7e" +checksum = "3b0875f23caa03898994f6ddc501886a45c7d3d62d04d2d90788d47be1b1e4de" dependencies = [ "idna_adapter", "smallvec", @@ -2440,9 +2440,9 @@ dependencies = [ [[package]] name = "percent-encoding" -version = "2.3.1" +version = "2.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" +checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" [[package]] name = "pest" diff --git a/sing-box/adapter/outbound.go b/sing-box/adapter/outbound.go index 517aa0feca..67acb0618d 100644 --- a/sing-box/adapter/outbound.go +++ b/sing-box/adapter/outbound.go @@ -6,6 +6,7 @@ import ( "github.com/sagernet/sing-box/log" "github.com/sagernet/sing-box/option" + "github.com/sagernet/sing-tun" N "github.com/sagernet/sing/common/network" ) @@ -20,10 +21,16 @@ type Outbound interface { } type OutboundWithPreferredRoutes interface { + Outbound PreferredDomain(domain string) bool PreferredAddress(address netip.Addr) bool } +type DirectRouteOutbound interface { + Outbound + NewDirectRouteConnection(metadata InboundContext, routeContext tun.DirectRouteContext) (tun.DirectRouteDestination, error) +} + type OutboundRegistry interface { option.OutboundOptionsRegistry CreateOutbound(ctx context.Context, router Router, logger log.ContextLogger, tag string, outboundType string, options any) (Outbound, error) diff --git a/sing-box/adapter/router.go b/sing-box/adapter/router.go index 0b7c8f4f74..eef4f50925 100644 --- a/sing-box/adapter/router.go +++ b/sing-box/adapter/router.go @@ -8,6 +8,7 @@ import ( "sync" C "github.com/sagernet/sing-box/constant" + "github.com/sagernet/sing-tun" M "github.com/sagernet/sing/common/metadata" N "github.com/sagernet/sing/common/network" "github.com/sagernet/sing/common/ntp" @@ -19,7 +20,7 @@ import ( type Router interface { Lifecycle ConnectionRouter - PreMatch(metadata InboundContext) error + PreMatch(metadata InboundContext, context tun.DirectRouteContext) (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 4afa00911e..e4885ffe38 100644 --- a/sing-box/common/dialer/default.go +++ b/sing-box/common/dialer/default.go @@ -318,6 +318,14 @@ func (d *DefaultDialer) ListenPacket(ctx context.Context, destination M.Socksadd } } +func (d *DefaultDialer) DialerForICMPNetwork(network string) net.Dialer { + if network == N.NetworkICMPv6 { + return dialerFromTCPDialer(d.dialer6) + } else { + return dialerFromTCPDialer(d.dialer4) + } +} + func (d *DefaultDialer) ListenSerialInterfacePacket(ctx context.Context, destination M.Socksaddr, strategy *C.NetworkStrategy, interfaceType []C.InterfaceType, fallbackInterfaceType []C.InterfaceType, fallbackDelay time.Duration) (net.PacketConn, error) { if strategy == nil { strategy = d.networkStrategy diff --git a/sing-box/go.mod b/sing-box/go.mod index 452694c678..282153670e 100644 --- a/sing-box/go.mod +++ b/sing-box/go.mod @@ -25,7 +25,7 @@ require ( github.com/sagernet/cors v1.2.1 github.com/sagernet/fswatch v0.1.1 github.com/sagernet/gomobile v0.1.8 - github.com/sagernet/gvisor v0.0.0-20250325023245-7a9c0f5725fb + 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.20250815070458-d33ece7a184f github.com/sagernet/sing-mux v0.3.3 @@ -33,7 +33,7 @@ require ( 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 + github.com/sagernet/sing-tun v0.7.0-beta.1.0.20250822062121-036d61a0aace 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.5 diff --git a/sing-box/go.sum b/sing-box/go.sum index d0f21c8cc2..4f4572283f 100644 --- a/sing-box/go.sum +++ b/sing-box/go.sum @@ -158,8 +158,8 @@ github.com/sagernet/fswatch v0.1.1 h1:YqID+93B7VRfqIH3PArW/XpJv5H4OLEVWDfProGoRQ github.com/sagernet/fswatch v0.1.1/go.mod h1:nz85laH0mkQqJfaOrqPpkwtU1znMFNVTpT/5oRsVz/o= github.com/sagernet/gomobile v0.1.8 h1:vXgoN0pjsMONAaYCTdsKBX2T1kxuS7sbT/mZ7PElGoo= github.com/sagernet/gomobile v0.1.8/go.mod h1:A8l3FlHi2D/+mfcd4HHvk5DGFPW/ShFb9jHP5VmSiDY= -github.com/sagernet/gvisor v0.0.0-20250325023245-7a9c0f5725fb h1:pprQtDqNgqXkRsXn+0E8ikKOemzmum8bODjSfDene38= -github.com/sagernet/gvisor v0.0.0-20250325023245-7a9c0f5725fb/go.mod h1:QkkPEJLw59/tfxgapHta14UL5qMUah5NXhO0Kw2Kan4= +github.com/sagernet/gvisor v0.0.0-20250822052253-5558536cf237 h1:SUPFNB+vSP4RBPrSEgNII+HkfqC8hKMpYLodom4o4EU= +github.com/sagernet/gvisor v0.0.0-20250822052253-5558536cf237/go.mod h1:QkkPEJLw59/tfxgapHta14UL5qMUah5NXhO0Kw2Kan4= github.com/sagernet/netlink v0.0.0-20240612041022-b9a21c07ac6a h1:ObwtHN2VpqE0ZNjr6sGeT00J8uU7JF4cNUdb44/Duis= github.com/sagernet/netlink v0.0.0-20240612041022-b9a21c07ac6a/go.mod h1:xLnfdiJbSp8rNqYEdIW/6eDO4mVoogml14Bh2hSiFpM= github.com/sagernet/nftables v0.3.0-beta.4 h1:kbULlAwAC3jvdGAC1P5Fa3GSxVwQJibNenDW2zaXr8I= @@ -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 h1:mBIFXYAnGO5ey/HcCYanqnBx61E7yF8zTFGRZonGYmY= -github.com/sagernet/sing-tun v0.7.0-beta.1/go.mod h1:AHJuRrLbNRJuivuFZ2VhXwDj4ViYp14szG5EkkKAqRQ= +github.com/sagernet/sing-tun v0.7.0-beta.1.0.20250822062121-036d61a0aace h1:whFyDOTkuDqjNwGMUbVCMiIqpV2iwXwBCZ1E/X9ZgJI= +github.com/sagernet/sing-tun v0.7.0-beta.1.0.20250822062121-036d61a0aace/go.mod h1:kEYEIq6pYBnKfQ1s4rEuiM+HWNYz96waFccPHbdCM9A= 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 84838bc0a6..22ab98c43e 100644 --- a/sing-box/protocol/direct/outbound.go +++ b/sing-box/protocol/direct/outbound.go @@ -13,6 +13,7 @@ import ( C "github.com/sagernet/sing-box/constant" "github.com/sagernet/sing-box/log" "github.com/sagernet/sing-box/option" + tun "github.com/sagernet/sing-tun" "github.com/sagernet/sing/common" "github.com/sagernet/sing/common/bufio" E "github.com/sagernet/sing/common/exceptions" @@ -29,10 +30,12 @@ var ( _ N.ParallelDialer = (*Outbound)(nil) _ dialer.ParallelNetworkDialer = (*Outbound)(nil) _ dialer.DirectDialer = (*Outbound)(nil) + _ adapter.DirectRouteOutbound = (*Outbound)(nil) ) type Outbound struct { outbound.Adapter + ctx context.Context logger logger.ContextLogger dialer dialer.ParallelInterfaceDialer domainStrategy C.DomainStrategy @@ -58,7 +61,8 @@ 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}, options.DialerOptions), + Adapter: outbound.NewAdapterWithDialerOptions(C.TypeDirect, tag, []string{N.NetworkTCP, N.NetworkUDP, N.NetworkICMPv4, N.NetworkICMPv6}, options.DialerOptions), + ctx: ctx, logger: logger, //nolint:staticcheck domainStrategy: C.DomainStrategy(options.DomainStrategy), @@ -146,6 +150,11 @@ 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) { + h.logger.Info("linked ", metadata.Network, " connection to ", metadata.Destination.AddrString()) + return tun.NewICMPDestination(h.ctx, h.logger, common.MustCast[*dialer.DefaultDialer](h.dialer).DialerForICMPNetwork(metadata.Network), metadata.Network, metadata.Destination.Addr, routeContext) +} + func (h *Outbound) DialParallel(ctx context.Context, network string, destination M.Socksaddr, destinationAddresses []netip.Addr) (net.Conn, error) { ctx, metadata := adapter.ExtendContext(ctx) metadata.Outbound = h.Tag() diff --git a/sing-box/protocol/tailscale/endpoint.go b/sing-box/protocol/tailscale/endpoint.go index 44c882de3a..b6a1b7419f 100644 --- a/sing-box/protocol/tailscale/endpoint.go +++ b/sing-box/protocol/tailscale/endpoint.go @@ -20,6 +20,7 @@ import ( "github.com/sagernet/gvisor/pkg/tcpip/adapters/gonet" "github.com/sagernet/gvisor/pkg/tcpip/header" "github.com/sagernet/gvisor/pkg/tcpip/stack" + "github.com/sagernet/gvisor/pkg/tcpip/transport/icmp" "github.com/sagernet/gvisor/pkg/tcpip/transport/tcp" "github.com/sagernet/gvisor/pkg/tcpip/transport/udp" "github.com/sagernet/sing-box/adapter" @@ -240,8 +241,10 @@ func (t *Endpoint) Start(stage adapter.StartStage) error { return gonet.TranslateNetstackError(gErr) } ipStack.SetTransportProtocolHandler(tcp.ProtocolNumber, tun.NewTCPForwarder(t.ctx, ipStack, t).HandlePacket) - udpForwarder := tun.NewUDPForwarder(t.ctx, ipStack, t, t.udpTimeout) - ipStack.SetTransportProtocolHandler(udp.ProtocolNumber, udpForwarder.HandlePacket) + ipStack.SetTransportProtocolHandler(udp.ProtocolNumber, tun.NewUDPForwarder(t.ctx, ipStack, t, t.udpTimeout).HandlePacket) + icmpForwarder := tun.NewICMPForwarder(t.ctx, ipStack, t, t.udpTimeout) + ipStack.SetTransportProtocolHandler(icmp.ProtocolNumber4, icmpForwarder.HandlePacket) + ipStack.SetTransportProtocolHandler(icmp.ProtocolNumber6, icmpForwarder.HandlePacket) t.stack = ipStack localBackend := t.server.ExportLocalBackend() @@ -415,7 +418,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) error { +func (t *Endpoint) PrepareConnection(network string, source M.Socksaddr, destination M.Socksaddr, routeContext tun.DirectRouteContext) (tun.DirectRouteDestination, error) { tsFilter := t.filter.Load() if tsFilter != nil { var ipProto ipproto.Proto @@ -428,9 +431,9 @@ func (t *Endpoint) PrepareConnection(network string, source M.Socksaddr, destina response := tsFilter.Check(source.Addr, destination.Addr, destination.Port, ipProto) switch response { case filter.Drop: - return syscall.ECONNRESET + return nil, syscall.ECONNREFUSED case filter.DropSilently: - return tun.ErrDrop + return nil, tun.ErrDrop } } return t.router.PreMatch(adapter.InboundContext{ @@ -439,7 +442,7 @@ func (t *Endpoint) PrepareConnection(network string, source M.Socksaddr, destina Network: network, Source: source, Destination: destination, - }) + }, routeContext) } func (t *Endpoint) NewConnectionEx(ctx context.Context, conn net.Conn, source M.Socksaddr, destination M.Socksaddr, onClose N.CloseHandlerFunc) { diff --git a/sing-box/protocol/tun/inbound.go b/sing-box/protocol/tun/inbound.go index fc69309c02..a3af1efabc 100644 --- a/sing-box/protocol/tun/inbound.go +++ b/sing-box/protocol/tun/inbound.go @@ -8,6 +8,7 @@ import ( "runtime" "strconv" "strings" + "syscall" "time" "github.com/sagernet/sing-box/adapter" @@ -454,15 +455,21 @@ func (t *Inbound) Close() error { ) } -func (t *Inbound) PrepareConnection(network string, source M.Socksaddr, destination M.Socksaddr) error { - return t.router.PreMatch(adapter.InboundContext{ +func (t *Inbound) PrepareConnection(network string, source M.Socksaddr, destination M.Socksaddr, routeContext tun.DirectRouteContext) (tun.DirectRouteDestination, error) { + routeDestination, err := t.router.PreMatch(adapter.InboundContext{ Inbound: t.tag, InboundType: C.TypeTun, Network: network, Source: source, Destination: destination, InboundOptions: t.inboundOptions, - }) + }, routeContext) + if err != nil { + if !E.IsMulti(err, tun.ErrDrop, syscall.ECONNREFUSED) { + t.logger.Warn(err) + } + } + return routeDestination, err } func (t *Inbound) NewConnectionEx(ctx context.Context, conn net.Conn, source M.Socksaddr, destination M.Socksaddr, onClose N.CloseHandlerFunc) { diff --git a/sing-box/protocol/wireguard/endpoint.go b/sing-box/protocol/wireguard/endpoint.go index 207670c202..dbf35602ba 100644 --- a/sing-box/protocol/wireguard/endpoint.go +++ b/sing-box/protocol/wireguard/endpoint.go @@ -13,6 +13,7 @@ import ( "github.com/sagernet/sing-box/log" "github.com/sagernet/sing-box/option" "github.com/sagernet/sing-box/transport/wireguard" + "github.com/sagernet/sing-tun" "github.com/sagernet/sing/common" "github.com/sagernet/sing/common/bufio" E "github.com/sagernet/sing/common/exceptions" @@ -40,7 +41,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}, options.DialerOptions), + Adapter: endpoint.NewAdapterWithDialerOptions(C.TypeWireGuard, tag, []string{N.NetworkTCP, N.NetworkUDP, N.NetworkICMPv4, N.NetworkICMPv6}, options.DialerOptions), ctx: ctx, router: router, dnsRouter: service.FromContext[adapter.DNSRouter](ctx), @@ -124,14 +125,14 @@ func (w *Endpoint) Close() error { return w.endpoint.Close() } -func (w *Endpoint) PrepareConnection(network string, source M.Socksaddr, destination M.Socksaddr) error { +func (w *Endpoint) PrepareConnection(network string, source M.Socksaddr, destination M.Socksaddr, context tun.DirectRouteContext) (tun.DirectRouteDestination, error) { return w.router.PreMatch(adapter.InboundContext{ Inbound: w.Tag(), InboundType: w.Type(), Network: network, Source: source, Destination: destination, - }) + }, context) } func (w *Endpoint) NewConnectionEx(ctx context.Context, conn net.Conn, source M.Socksaddr, destination M.Socksaddr, onClose N.CloseHandlerFunc) { @@ -220,3 +221,12 @@ func (w *Endpoint) PreferredDomain(domain string) bool { 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 +} diff --git a/sing-box/route/route.go b/sing-box/route/route.go index 20fbf4ec7d..1a32b6dc60 100644 --- a/sing-box/route/route.go +++ b/sing-box/route/route.go @@ -17,6 +17,7 @@ import ( "github.com/sagernet/sing-box/option" R "github.com/sagernet/sing-box/route/rule" "github.com/sagernet/sing-mux" + "github.com/sagernet/sing-tun" "github.com/sagernet/sing-vmess" "github.com/sagernet/sing/common" "github.com/sagernet/sing/common/buf" @@ -258,19 +259,37 @@ func (r *Router) routePacketConnection(ctx context.Context, conn N.PacketConn, m return nil } -func (r *Router) PreMatch(metadata adapter.InboundContext) error { +func (r *Router) PreMatch(metadata adapter.InboundContext, routeContext tun.DirectRouteContext) (tun.DirectRouteDestination, error) { selectedRule, _, _, _, err := r.matchRule(r.ctx, &metadata, true, nil, nil) if err != nil { - return err + return nil, err } - if selectedRule == nil { - return nil + if selectedRule != nil { + switch action := selectedRule.Action().(type) { + case *R.RuleActionReject: + return nil, action.Error(context.Background()) + case *R.RuleActionRoute: + if routeContext == nil { + return nil, nil + } + outbound, loaded := r.outbound.Outbound(action.Outbound) + if !loaded { + return nil, E.New("outbound not found: ", action.Outbound) + } + 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) + } } - rejectAction, isReject := selectedRule.Action().(*R.RuleActionReject) - if !isReject { - return nil + if metadata.Network != N.NetworkICMPv4 && metadata.Network != N.NetworkICMPv6 { + return nil, nil } - return rejectAction.Error(context.Background()) + 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) } func (r *Router) matchRule( diff --git a/sing-box/transport/wireguard/device.go b/sing-box/transport/wireguard/device.go index 7a17b8f35c..4e2d6a249c 100644 --- a/sing-box/transport/wireguard/device.go +++ b/sing-box/transport/wireguard/device.go @@ -5,6 +5,7 @@ import ( "net/netip" "time" + "github.com/sagernet/sing-box/adapter" "github.com/sagernet/sing-tun" "github.com/sagernet/sing/common/logger" N "github.com/sagernet/sing/common/network" @@ -17,6 +18,8 @@ type Device interface { N.Dialer Start() error SetDevice(device *device.Device) + Inet4Address() netip.Addr + Inet6Address() netip.Addr } type DeviceOptions struct { @@ -41,3 +44,8 @@ func NewDevice(options DeviceOptions) (Device, error) { return newSystemStackDevice(options) } } + +type NatDevice interface { + Device + CreateDestination(metadata adapter.InboundContext, routeContext tun.DirectRouteContext) (tun.DirectRouteDestination, error) +} diff --git a/sing-box/transport/wireguard/device_nat.go b/sing-box/transport/wireguard/device_nat.go new file mode 100644 index 0000000000..2c482d30f4 --- /dev/null +++ b/sing-box/transport/wireguard/device_nat.go @@ -0,0 +1,85 @@ +package wireguard + +import ( + "github.com/sagernet/sing-box/adapter" + "github.com/sagernet/sing-tun" + "github.com/sagernet/sing/common/buf" +) + +var _ Device = (*natDeviceWrapper)(nil) + +type natDeviceWrapper struct { + Device + gVisorOutbound + packetOutbound chan *buf.Buffer + mapping *tun.NatMapping + writer *tun.NatWriter + buffer [][]byte +} + +func NewNATDevice(upstream Device, ipRewrite bool) NatDevice { + wrapper := &natDeviceWrapper{ + Device: upstream, + gVisorOutbound: newGVisorOutbound(), + packetOutbound: make(chan *buf.Buffer, 256), + mapping: tun.NewNatMapping(ipRewrite), + } + if ipRewrite { + wrapper.writer = tun.NewNatWriter(upstream.Inet4Address(), upstream.Inet6Address()) + } + return wrapper +} + +func (d *natDeviceWrapper) Write(bufs [][]byte, offset int) (int, error) { + for _, buffer := range bufs { + handled, err := d.mapping.WritePacket(buffer[offset:]) + if handled { + if err != nil { + return 0, err + } + } else { + d.buffer = append(d.buffer, buffer) + } + } + if len(d.buffer) > 0 { + _, err := d.Device.Write(d.buffer, offset) + if err != nil { + return 0, err + } + d.buffer = d.buffer[:0] + } + return 0, nil +} + +func (d *natDeviceWrapper) CreateDestination(metadata adapter.InboundContext, routeContext tun.DirectRouteContext) (tun.DirectRouteDestination, error) { + session := tun.DirectRouteSession{ + Source: metadata.Source.Addr, + Destination: metadata.Destination.Addr, + } + d.mapping.CreateSession(session, routeContext) + return &natDestinationWrapper{d, session}, nil +} + +var _ tun.DirectRouteDestination = (*natDestinationWrapper)(nil) + +type natDestinationWrapper struct { + device *natDeviceWrapper + session tun.DirectRouteSession +} + +func (d *natDestinationWrapper) WritePacket(buffer *buf.Buffer) error { + if d.device.writer != nil { + d.device.writer.RewritePacket(buffer.Bytes()) + } + d.device.packetOutbound <- buffer + return nil +} + +func (d *natDestinationWrapper) Close() error { + d.device.mapping.DeleteSession(d.session) + return nil +} + +func (d *natDestinationWrapper) Timeout() bool { + return false +} diff --git a/sing-box/transport/wireguard/device_nat_gvisor.go b/sing-box/transport/wireguard/device_nat_gvisor.go new file mode 100644 index 0000000000..edecba3491 --- /dev/null +++ b/sing-box/transport/wireguard/device_nat_gvisor.go @@ -0,0 +1,48 @@ +//go:build with_gvisor + +package wireguard + +import ( + "github.com/sagernet/gvisor/pkg/tcpip/stack" +) + +type gVisorOutbound struct { + outbound chan *stack.PacketBuffer +} + +func newGVisorOutbound() gVisorOutbound { + return gVisorOutbound{ + outbound: make(chan *stack.PacketBuffer, 256), + } +} + +func (d *natDeviceWrapper) Read(bufs [][]byte, sizes []int, offset int) (n int, err error) { + select { + case packet := <-d.outbound: + defer packet.DecRef() + var copyN int + /*rangeIterate(packet.Data().AsRange(), func(view *buffer.View) { + copyN += copy(bufs[0][offset+copyN:], view.AsSlice()) + })*/ + for _, view := range packet.AsSlices() { + copyN += copy(bufs[0][offset+copyN:], view) + } + sizes[0] = copyN + return 1, nil + case packet := <-d.packetOutbound: + defer packet.Release() + sizes[0] = copy(bufs[0][offset:], packet.Bytes()) + return 1, nil + default: + } + return d.Device.Read(bufs, sizes, offset) +} + +func (d *natDestinationWrapper) WritePacketBuffer(packetBuffer *stack.PacketBuffer) error { + println("read from wg") + if d.device.writer != nil { + d.device.writer.RewritePacketBuffer(packetBuffer) + } + d.device.outbound <- packetBuffer + return nil +} diff --git a/sing-box/transport/wireguard/device_nat_non_gvisor.go b/sing-box/transport/wireguard/device_nat_non_gvisor.go new file mode 100644 index 0000000000..e81e1e3187 --- /dev/null +++ b/sing-box/transport/wireguard/device_nat_non_gvisor.go @@ -0,0 +1,20 @@ +//go:build !with_gvisor + +package wireguard + +type gVisorOutbound struct{} + +func newGVisorOutbound() gVisorOutbound { + return gVisorOutbound{} +} + +func (d *natDeviceWrapper) Read(bufs [][]byte, sizes []int, offset int) (n int, err error) { + select { + case packet := <-d.packetOutbound: + defer packet.Release() + sizes[0] = copy(bufs[0][offset:], packet.Bytes()) + return 1, nil + default: + } + return d.Device.Read(bufs, sizes, offset) +} diff --git a/sing-box/transport/wireguard/device_stack.go b/sing-box/transport/wireguard/device_stack.go index f9440f02fa..eb759a2bf0 100644 --- a/sing-box/transport/wireguard/device_stack.go +++ b/sing-box/transport/wireguard/device_stack.go @@ -5,6 +5,7 @@ package wireguard import ( "context" "net" + "net/netip" "os" "github.com/sagernet/gvisor/pkg/buffer" @@ -14,9 +15,12 @@ import ( "github.com/sagernet/gvisor/pkg/tcpip/network/ipv4" "github.com/sagernet/gvisor/pkg/tcpip/network/ipv6" "github.com/sagernet/gvisor/pkg/tcpip/stack" + "github.com/sagernet/gvisor/pkg/tcpip/transport/icmp" "github.com/sagernet/gvisor/pkg/tcpip/transport/tcp" "github.com/sagernet/gvisor/pkg/tcpip/transport/udp" + "github.com/sagernet/sing-box/adapter" "github.com/sagernet/sing-tun" + "github.com/sagernet/sing/common/buf" E "github.com/sagernet/sing/common/exceptions" M "github.com/sagernet/sing/common/metadata" N "github.com/sagernet/sing/common/network" @@ -24,25 +28,30 @@ import ( wgTun "github.com/sagernet/wireguard-go/tun" ) -var _ Device = (*stackDevice)(nil) +var _ NatDevice = (*stackDevice)(nil) type stackDevice struct { - stack *stack.Stack - mtu uint32 - events chan wgTun.Event - outbound chan *stack.PacketBuffer - done chan struct{} - dispatcher stack.NetworkDispatcher - addr4 tcpip.Address - addr6 tcpip.Address + stack *stack.Stack + mtu uint32 + events chan wgTun.Event + outbound chan *stack.PacketBuffer + packetOutbound chan *buf.Buffer + done chan struct{} + dispatcher stack.NetworkDispatcher + addr4 tcpip.Address + addr6 tcpip.Address + mapping *tun.NatMapping + writer *tun.NatWriter } func newStackDevice(options DeviceOptions) (*stackDevice, error) { tunDevice := &stackDevice{ - mtu: options.MTU, - events: make(chan wgTun.Event, 1), - outbound: make(chan *stack.PacketBuffer, 256), - done: make(chan struct{}), + mtu: options.MTU, + events: make(chan wgTun.Event, 1), + outbound: make(chan *stack.PacketBuffer, 256), + packetOutbound: make(chan *buf.Buffer, 256), + done: make(chan struct{}), + mapping: tun.NewNatMapping(true), } ipStack, err := tun.NewGVisorStack((*wireEndpoint)(tunDevice)) if err != nil { @@ -68,10 +77,14 @@ func newStackDevice(options DeviceOptions) (*stackDevice, error) { return nil, E.New("parse local address ", protoAddr.AddressWithPrefix, ": ", gErr.String()) } } + tunDevice.writer = tun.NewNatWriter(tunDevice.Inet4Address(), tunDevice.Inet6Address()) tunDevice.stack = ipStack if options.Handler != nil { ipStack.SetTransportProtocolHandler(tcp.ProtocolNumber, tun.NewTCPForwarder(options.Context, ipStack, options.Handler).HandlePacket) ipStack.SetTransportProtocolHandler(udp.ProtocolNumber, tun.NewUDPForwarder(options.Context, ipStack, options.Handler, options.UDPTimeout).HandlePacket) + icmpForwarder := tun.NewICMPForwarder(options.Context, ipStack, options.Handler, options.UDPTimeout) + ipStack.SetTransportProtocolHandler(icmp.ProtocolNumber4, icmpForwarder.HandlePacket) + ipStack.SetTransportProtocolHandler(icmp.ProtocolNumber6, icmpForwarder.HandlePacket) } return tunDevice, nil } @@ -130,6 +143,14 @@ func (w *stackDevice) ListenPacket(ctx context.Context, destination M.Socksaddr) return udpConn, nil } +func (w *stackDevice) Inet4Address() netip.Addr { + return netip.AddrFrom4(w.addr4.As4()) +} + +func (w *stackDevice) Inet6Address() netip.Addr { + return netip.AddrFrom16(w.addr6.As16()) +} + func (w *stackDevice) SetDevice(device *device.Device) { } @@ -144,20 +165,24 @@ func (w *stackDevice) File() *os.File { func (w *stackDevice) Read(bufs [][]byte, sizes []int, offset int) (count int, err error) { select { - case packetBuffer, ok := <-w.outbound: + case packet, ok := <-w.outbound: if !ok { return 0, os.ErrClosed } - defer packetBuffer.DecRef() - p := bufs[0] - p = p[offset:] - n := 0 - for _, slice := range packetBuffer.AsSlices() { - n += copy(p[n:], slice) + defer packet.DecRef() + var copyN int + /*rangeIterate(packet.Data().AsRange(), func(view *buffer.View) { + copyN += copy(bufs[0][offset+copyN:], view.AsSlice()) + })*/ + for _, view := range packet.AsSlices() { + copyN += copy(bufs[0][offset+copyN:], view) } - sizes[0] = n - count = 1 - return + sizes[0] = copyN + return 1, nil + case packet := <-w.packetOutbound: + defer packet.Release() + sizes[0] = copy(bufs[0][offset:], packet.Bytes()) + return 1, nil case <-w.done: return 0, os.ErrClosed } @@ -169,6 +194,14 @@ func (w *stackDevice) Write(bufs [][]byte, offset int) (count int, err error) { if len(b) == 0 { continue } + handled, err := w.mapping.WritePacket(b) + if handled { + if err != nil { + return count, err + } + count++ + continue + } var networkProtocol tcpip.NetworkProtocolNumber switch header.IPVersion(b) { case header.IPv4Version: @@ -282,3 +315,157 @@ func (ep *wireEndpoint) Close() { func (ep *wireEndpoint) SetOnCloseAction(f func()) { } + +func (w *stackDevice) CreateDestination(metadata adapter.InboundContext, routeContext tun.DirectRouteContext) (tun.DirectRouteDestination, error) { + /* var wq waiter.Queue + ep, err := raw.NewEndpoint(w.stack, ipv4.ProtocolNumber, icmp.ProtocolNumber4, &wq) + if err != nil { + return nil, E.Cause(gonet.TranslateNetstackError(err), "create endpoint") + } + err = ep.Connect(tcpip.FullAddress{ + NIC: tun.DefaultNIC, + Port: metadata.Destination.Port, + Addr: tun.AddressFromAddr(metadata.Destination.Addr), + }) + if err != nil { + ep.Close() + return nil, E.Cause(gonet.TranslateNetstackError(err), "ICMP connect ", metadata.Destination) + } + fmt.Println("linked ", metadata.Network, " connection to ", metadata.Destination.AddrString()) + destination := &endpointNatDestination{ + ep: ep, + wq: &wq, + context: routeContext, + } + go destination.loopRead() + return destination, nil*/ + session := tun.DirectRouteSession{ + Source: metadata.Source.Addr, + Destination: metadata.Destination.Addr, + } + w.mapping.CreateSession(session, routeContext) + return &stackNatDestination{ + device: w, + session: session, + }, nil +} + +type stackNatDestination struct { + device *stackDevice + session tun.DirectRouteSession +} + +func (d *stackNatDestination) WritePacket(buffer *buf.Buffer) error { + if d.device.writer != nil { + d.device.writer.RewritePacket(buffer.Bytes()) + } + d.device.packetOutbound <- buffer + return nil +} + +func (d *stackNatDestination) WritePacketBuffer(buffer *stack.PacketBuffer) error { + if d.device.writer != nil { + d.device.writer.RewritePacketBuffer(buffer) + } + d.device.outbound <- buffer + return nil +} + +func (d *stackNatDestination) Close() error { + d.device.mapping.DeleteSession(d.session) + return nil +} + +func (d *stackNatDestination) Timeout() bool { + return false +} + +/*type endpointNatDestination struct { + ep tcpip.Endpoint + wq *waiter.Queue + networkProto tcpip.NetworkProtocolNumber + context tun.DirectRouteContext + done chan struct{} +} + +func (d *endpointNatDestination) loopRead() { + for { + println("start read") + buffer, err := commonRead(d.ep, d.wq, d.done) + if err != nil { + log.Error(err) + return + } + println("done read") + ipHdr := header.IPv4(buffer.Bytes()) + if ipHdr.TransportProtocol() != header.ICMPv4ProtocolNumber { + buffer.Release() + continue + } + icmpHdr := header.ICMPv4(ipHdr.Payload()) + if icmpHdr.Type() != header.ICMPv4EchoReply { + buffer.Release() + continue + } + fmt.Println("read echo reply") + _ = d.context.WritePacket(ipHdr) + buffer.Release() + } +} + +func commonRead(ep tcpip.Endpoint, wq *waiter.Queue, done chan struct{}) (*buf.Buffer, error) { + buffer := buf.NewPacket() + result, err := ep.Read(buffer, tcpip.ReadOptions{}) + if err != nil { + if _, ok := err.(*tcpip.ErrWouldBlock); ok { + waitEntry, notifyCh := waiter.NewChannelEntry(waiter.ReadableEvents) + wq.EventRegister(&waitEntry) + defer wq.EventUnregister(&waitEntry) + for { + result, err = ep.Read(buffer, tcpip.ReadOptions{}) + if _, ok := err.(*tcpip.ErrWouldBlock); !ok { + break + } + select { + case <-notifyCh: + case <-done: + buffer.Release() + return nil, context.DeadlineExceeded + } + } + } + return nil, gonet.TranslateNetstackError(err) + } + buffer.Truncate(result.Count) + return buffer, nil +} + +func (d *endpointNatDestination) WritePacket(buffer *buf.Buffer) error { + _, err := d.ep.Write(buffer, tcpip.WriteOptions{}) + if err != nil { + return gonet.TranslateNetstackError(err) + } + return nil +} + +func (d *endpointNatDestination) WritePacketBuffer(buffer *stack.PacketBuffer) error { + data := buffer.ToView().AsSlice() + println("write echo request buffer :" + fmt.Sprint(data)) + _, err := d.ep.Write(bytes.NewReader(data), tcpip.WriteOptions{}) + if err != nil { + log.Error(err) + return gonet.TranslateNetstackError(err) + } + return nil +} + +func (d *endpointNatDestination) Close() error { + d.ep.Abort() + close(d.done) + return nil +} + +func (d *endpointNatDestination) Timeout() bool { + return false +} +*/ diff --git a/sing-box/transport/wireguard/device_system.go b/sing-box/transport/wireguard/device_system.go index fa54f33293..90abee4b43 100644 --- a/sing-box/transport/wireguard/device_system.go +++ b/sing-box/transport/wireguard/device_system.go @@ -28,16 +28,36 @@ type systemDevice struct { batchDevice tun.LinuxTUN events chan wgTun.Event closeOnce sync.Once + addr4 netip.Addr + addr6 netip.Addr } func newSystemDevice(options DeviceOptions) (*systemDevice, error) { if options.Name == "" { options.Name = tun.CalculateInterfaceName("wg") } + var inet4Address netip.Addr + var inet6Address netip.Addr + if len(options.Address) > 0 { + if prefix := common.Find(options.Address, func(it netip.Prefix) bool { + return it.Addr().Is4() + }); prefix.IsValid() { + inet4Address = prefix.Addr() + } + } + if len(options.Address) > 0 { + if prefix := common.Find(options.Address, func(it netip.Prefix) bool { + return it.Addr().Is6() + }); prefix.IsValid() { + inet6Address = prefix.Addr() + } + } return &systemDevice{ options: options, dialer: options.CreateDialer(options.Name), events: make(chan wgTun.Event, 1), + addr4: inet4Address, + addr6: inet6Address, }, nil } @@ -49,6 +69,14 @@ func (w *systemDevice) ListenPacket(ctx context.Context, destination M.Socksaddr return w.dialer.ListenPacket(ctx, destination) } +func (w *systemDevice) Inet4Address() netip.Addr { + return w.addr4 +} + +func (w *systemDevice) Inet6Address() netip.Addr { + return w.addr6 +} + func (w *systemDevice) SetDevice(device *device.Device) { } diff --git a/sing-box/transport/wireguard/endpoint.go b/sing-box/transport/wireguard/endpoint.go index 2adf783213..fe3a5a5cf1 100644 --- a/sing-box/transport/wireguard/endpoint.go +++ b/sing-box/transport/wireguard/endpoint.go @@ -12,6 +12,8 @@ import ( "strings" "unsafe" + "github.com/sagernet/sing-box/adapter" + "github.com/sagernet/sing-tun" "github.com/sagernet/sing/common" E "github.com/sagernet/sing/common/exceptions" F "github.com/sagernet/sing/common/format" @@ -31,6 +33,7 @@ type Endpoint struct { ipcConf string allowedAddress []netip.Prefix tunDevice Device + natDevice NatDevice device *device.Device allowedIPs *device.AllowedIPs pause pause.Manager @@ -114,12 +117,17 @@ func NewEndpoint(options EndpointOptions) (*Endpoint, error) { if err != nil { return nil, E.Cause(err, "create WireGuard device") } + natDevice, isNatDevice := tunDevice.(NatDevice) + if !isNatDevice { + natDevice = NewNATDevice(tunDevice, true) + } return &Endpoint{ options: options, peers: peers, ipcConf: ipcConf, allowedAddress: allowedAddresses, tunDevice: tunDevice, + natDevice: natDevice, }, nil } @@ -179,7 +187,13 @@ func (e *Endpoint) Start(resolve bool) error { e.options.Logger.Error(fmt.Sprintf(strings.ToLower(format), args...)) }, } - wgDevice := device.NewDevice(e.options.Context, e.tunDevice, bind, logger, e.options.Workers) + var deviceInput Device + if e.natDevice != nil { + deviceInput = e.natDevice + } else { + deviceInput = e.tunDevice + } + wgDevice := device.NewDevice(e.options.Context, deviceInput, bind, logger, e.options.Workers) e.tunDevice.SetDevice(wgDevice) ipcConf := e.ipcConf for _, peer := range e.peers { @@ -229,6 +243,13 @@ 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) { + if e.natDevice == nil { + return nil, os.ErrInvalid + } + return e.natDevice.CreateDestination(metadata, routeContext) +} + func (e *Endpoint) onPauseUpdated(event int) { switch event { case pause.EventDevicePaused, pause.EventNetworkPause: diff --git a/small/luci-app-fchomo/root/etc/init.d/fchomo b/small/luci-app-fchomo/root/etc/init.d/fchomo index d9524bf5eb..c5ac306e62 100755 --- a/small/luci-app-fchomo/root/etc/init.d/fchomo +++ b/small/luci-app-fchomo/root/etc/init.d/fchomo @@ -219,8 +219,6 @@ start_service() { fi fi - /etc/init.d/dnsmasq reload >/dev/null 2>&1 - # Setup routing table local proxy_mode table_id rule_pref config_get proxy_mode "inbound" "proxy_mode" "redir_tproxy" @@ -386,7 +384,10 @@ start_service() { log "$(mihomo -v | awk 'NR==1{print $1,$3}') started." } -service_started() { procd_set_config_changed firewall; } +service_started() { + procd_set_config_changed dnsmasq + procd_set_config_changed firewall +} stop_service() { # Client @@ -429,7 +430,6 @@ stop_client() { # Remove DNSMasq servers rm -rf "$DNSMASQ_DIR/../dnsmasq-fchomo.conf" "$DNSMASQ_DIR" - /etc/init.d/dnsmasq reload >/dev/null 2>&1 # Remove Clash API Dashboard rm -rf "$RUN_DIR/ui" @@ -453,6 +453,7 @@ service_stopped() { [ -n "$(/etc/init.d/$CONF info | jsonfilter -q -e '@.'"$CONF"'.instances["mihomo-c"]')" ] || client_stopped # Server + procd_set_config_changed dnsmasq procd_set_config_changed firewall } diff --git a/small/luci-app-nikki/root/usr/share/rpcd/acl.d/luci-app-nikki.json b/small/luci-app-nikki/root/usr/share/rpcd/acl.d/luci-app-nikki.json index 580d08dd38..f551c22c90 100644 --- a/small/luci-app-nikki/root/usr/share/rpcd/acl.d/luci-app-nikki.json +++ b/small/luci-app-nikki/root/usr/share/rpcd/acl.d/luci-app-nikki.json @@ -16,8 +16,6 @@ "/etc/nikki/run/config.yaml": ["read"], "/etc/nikki/run/providers/rule/*": ["read"], "/etc/nikki/run/providers/proxy/*": ["read"], - "/etc/nikki/nftables/reserved_ip.nft": ["read"], - "/etc/nikki/nftables/reserved_ip6.nft": ["read"], "/var/log/nikki/*.log": ["read"] } }, @@ -32,8 +30,6 @@ "/etc/nikki/run/config.yaml": ["write"], "/etc/nikki/run/providers/rule/*": ["write"], "/etc/nikki/run/providers/proxy/*": ["write"], - "/etc/nikki/nftables/reserved_ip.nft": ["write"], - "/etc/nikki/nftables/reserved_ip6.nft": ["write"], "/var/log/nikki/*.log": ["write"] } } diff --git a/small/luci-app-passwall/luasrc/controller/passwall.lua b/small/luci-app-passwall/luasrc/controller/passwall.lua index 2d62b8dcbb..d90b49b47d 100644 --- a/small/luci-app-passwall/luasrc/controller/passwall.lua +++ b/small/luci-app-passwall/luasrc/controller/passwall.lua @@ -633,20 +633,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) @@ -667,19 +676,21 @@ function restore_backup() api.log(" * 重启 PassWall 服务中…\n") luci.sys.call('/etc/init.d/passwall restart > /dev/null 2>&1 &') luci.sys.call('/etc/init.d/passwall_server restart > /dev/null 2>&1 &') + result = { status = "success", message = "Upload completed", path = file_path } else api.log(" * PassWall 配置文件解压失败,请重试!") + result = { status = "error", message = "Decompression failed" } end luci.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-passwall/luasrc/view/passwall/global/backup.htm b/small/luci-app-passwall/luasrc/view/passwall/global/backup.htm index c0d2e76f1e..918417cf3f 100644 --- a/small/luci-app-passwall/luasrc/view/passwall/global/backup.htm +++ b/small/luci-app-passwall/luasrc/view/passwall/global/backup.htm @@ -184,7 +184,6 @@ local api = require "luci.passwall.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.passwall.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/Makefile b/small/luci-app-passwall2/Makefile index 721c9aeace..7589c3973e 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.9 +PKG_VERSION:=25.8.22 PKG_RELEASE:=1 PKG_CONFIG_DEPENDS:= \ diff --git a/small/luci-app-passwall2/luasrc/model/cbi/passwall2/client/type/hysteria2.lua b/small/luci-app-passwall2/luasrc/model/cbi/passwall2/client/type/hysteria2.lua index 7b6bd7d1ff..e8d54732c1 100644 --- a/small/luci-app-passwall2/luasrc/model/cbi/passwall2/client/type/hysteria2.lua +++ b/small/luci-app-passwall2/luasrc/model/cbi/passwall2/client/type/hysteria2.lua @@ -30,6 +30,11 @@ o = s:option(Value, _n("hop"), translate("Port hopping range")) o.description = translate("Format as 1000:2000 or 1000-2000 Multiple groups are separated by commas (,).") o.rewrite_option = o.option +o = s:option(Value, _n("hop_interval"), translate("Hop Interval"), translate("Example:") .. "30s (≥5s)") +o.placeholder = "30s" +o.default = "30s" +o.rewrite_option = o.option + o = s:option(Value, _n("obfs"), translate("Obfs Password")) o.rewrite_option = o.option @@ -54,9 +59,6 @@ o.rewrite_option = o.option o = s:option(Value, _n("down_mbps"), translate("Max download Mbps")) o.rewrite_option = o.option -o = s:option(Value, _n("hop_interval"), translate("Hop Interval"), translate("Example:") .. "30s (≥5s)") -o.rewrite_option = o.option - o = s:option(Value, _n("recv_window"), translate("QUIC stream receive window")) o.rewrite_option = o.option diff --git a/small/luci-app-passwall2/luasrc/model/cbi/passwall2/client/type/ray.lua b/small/luci-app-passwall2/luasrc/model/cbi/passwall2/client/type/ray.lua index 73f25b30ec..125dac4ac3 100644 --- a/small/luci-app-passwall2/luasrc/model/cbi/passwall2/client/type/ray.lua +++ b/small/luci-app-passwall2/luasrc/model/cbi/passwall2/client/type/ray.lua @@ -61,7 +61,8 @@ for k, e in ipairs(api.get_valid_nodes()) do nodes_table[#nodes_table + 1] = { id = e[".name"], remark = e["remark"], - type = e["type"] + type = e["type"], + chain_proxy = e["chain_proxy"] } end if e.protocol == "_balancing" then @@ -337,6 +338,7 @@ o.default = "" o:value("", translate("Disable")) o:value("xtls-rprx-vision") o:depends({ [_n("protocol")] = "vless", [_n("tls")] = true, [_n("transport")] = "raw" }) +o:depends({ [_n("protocol")] = "trojan", [_n("tls")] = true, [_n("transport")] = "raw" }) o = s:option(Flag, _n("tls"), translate("TLS")) o.default = 0 @@ -392,6 +394,13 @@ o.validate = function(self, value) return api.trim(value:gsub("[\r\n]", "")) end +o = s:option(ListValue, _n("ech_ForceQuery"), translate("ECH Query Policy"), translate("Controls the policy used when performing DNS queries for ECH configuration.")) +o.default = "none" +o:value("none") +o:value("half") +o:value("full") +o:depends({ [_n("ech")] = true }) + -- [[ REALITY部分 ]] -- o = s:option(Value, _n("reality_publicKey"), translate("Public Key")) o:depends({ [_n("tls")] = true, [_n("reality")] = true }) @@ -696,7 +705,7 @@ o = s:option(ListValue, _n("to_node"), translate("Landing Node"), translate("Onl o:depends({ [_n("chain_proxy")] = "2" }) for k, v in pairs(nodes_table) do - if v.type == "Xray" and v.id ~= arg[1] then + if v.type == "Xray" and v.id ~= arg[1] and (not v.chain_proxy or v.chain_proxy == "") then s.fields[_n("preproxy_node")]:value(v.id, v.remark) s.fields[_n("to_node")]:value(v.id, v.remark) end 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 998e689c72..13f2f7c1b5 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 @@ -81,7 +81,8 @@ for k, e in ipairs(api.get_valid_nodes()) do nodes_table[#nodes_table + 1] = { id = e[".name"], remark = e["remark"], - type = e["type"] + type = e["type"], + chain_proxy = e["chain_proxy"] } end if e.protocol == "_iface" then @@ -339,12 +340,18 @@ o.default = "" o:value("", translate("Disable")) o:value("xtls-rprx-vision") o:depends({ [_n("protocol")] = "vless", [_n("tls")] = true }) +o:depends({ [_n("protocol")] = "trojan", [_n("tls")] = true }) if singbox_tags:find("with_quic") then o = s:option(Value, _n("hysteria_hop"), translate("Port hopping range")) o.description = translate("Format as 1000:2000 or 1000-2000 Multiple groups are separated by commas (,).") o:depends({ [_n("protocol")] = "hysteria" }) + o = s:option(Value, _n("hysteria_hop_interval"), translate("Hop Interval"), translate("Example:") .. "30s (≥5s)") + o.placeholder = "30s" + o.default = "30s" + o:depends({ [_n("protocol")] = "hysteria" }) + o = s:option(Value, _n("hysteria_obfs"), translate("Obfs Password")) o:depends({ [_n("protocol")] = "hysteria" }) @@ -425,6 +432,11 @@ if singbox_tags:find("with_quic") then o.description = translate("Format as 1000:2000 or 1000-2000 Multiple groups are separated by commas (,).") o:depends({ [_n("protocol")] = "hysteria2" }) + o = s:option(Value, _n("hysteria2_hop_interval"), translate("Hop Interval"), translate("Example:") .. "30s (≥5s)") + o.placeholder = "30s" + o.default = "30s" + o:depends({ [_n("protocol")] = "hysteria2" }) + o = s:option(Value, _n("hysteria2_up_mbps"), translate("Max upload Mbps")) o:depends({ [_n("protocol")] = "hysteria2" }) @@ -526,30 +538,30 @@ if singbox_tags:find("with_utls") then o:value("firefox") o:value("edge") o:value("safari") - -- o:value("360") + o:value("360") o:value("qq") o:value("ios") - -- o:value("android") + o:value("android") o:value("random") - -- o:value("randomized") + o:value("randomized") o.default = "chrome" - o:depends({ [_n("tls")] = true, [_n("utls")] = true }) + o:depends({ [_n("utls")] = true }) -- [[ REALITY部分 ]] -- o = s:option(Flag, _n("reality"), translate("REALITY")) o.default = 0 - o:depends({ [_n("protocol")] = "vless", [_n("utls")] = true }) - o:depends({ [_n("protocol")] = "vmess", [_n("utls")] = true }) - o:depends({ [_n("protocol")] = "shadowsocks", [_n("utls")] = true }) - o:depends({ [_n("protocol")] = "socks", [_n("utls")] = true }) - o:depends({ [_n("protocol")] = "trojan", [_n("utls")] = true }) - o:depends({ [_n("protocol")] = "anytls", [_n("utls")] = true }) + o:depends({ [_n("protocol")] = "vless", [_n("tls")] = true }) + o:depends({ [_n("protocol")] = "vmess", [_n("tls")] = true }) + o:depends({ [_n("protocol")] = "shadowsocks", [_n("tls")] = true }) + o:depends({ [_n("protocol")] = "socks", [_n("tls")] = true }) + o:depends({ [_n("protocol")] = "trojan", [_n("tls")] = true }) + o:depends({ [_n("protocol")] = "anytls", [_n("tls")] = true }) o = s:option(Value, _n("reality_publicKey"), translate("Public Key")) - o:depends({ [_n("utls")] = true, [_n("reality")] = true }) + o:depends({ [_n("reality")] = true }) o = s:option(Value, _n("reality_shortId"), translate("Short Id")) - o:depends({ [_n("utls")] = true, [_n("reality")] = true }) + o:depends({ [_n("reality")] = true }) end o = s:option(ListValue, _n("transport"), translate("Transport")) @@ -801,7 +813,7 @@ o = s:option(ListValue, _n("to_node"), translate("Landing Node"), translate("Onl o:depends({ [_n("chain_proxy")] = "2" }) for k, v in pairs(nodes_table) do - if v.type == "sing-box" and v.id ~= arg[1] then + if v.type == "sing-box" and v.id ~= arg[1] and (not v.chain_proxy or v.chain_proxy == "") then s.fields[_n("preproxy_node")]:value(v.id, v.remark) s.fields[_n("to_node")]:value(v.id, v.remark) 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 dd71579480..c4eee19ba4 100644 --- a/small/luci-app-passwall2/luasrc/passwall2/util_sing-box.lua +++ b/small/luci-app-passwall2/luasrc/passwall2/util_sing-box.lua @@ -321,7 +321,11 @@ function gen_outbound(flag, node, tag, proxy_table) end protocol_table = { server_ports = next(server_ports) and server_ports or nil, - hop_interval = next(server_ports) and "30s" or nil, + hop_interval = (function() + if not next(server_ports) then return nil end + local v = tonumber((node.hysteria_hop_interval or "30s"):match("^%d+")) + return (v and v >= 5) and (v .. "s") or "30s" + end)(), up_mbps = tonumber(node.hysteria_up_mbps), down_mbps = tonumber(node.hysteria_down_mbps), obfs = node.hysteria_obfs, @@ -397,7 +401,11 @@ function gen_outbound(flag, node, tag, proxy_table) end protocol_table = { server_ports = next(server_ports) and server_ports or nil, - hop_interval = next(server_ports) and "30s" or nil, + hop_interval = (function() + if not next(server_ports) then return nil end + local v = tonumber((node.hysteria2_hop_interval or "30s"):match("^%d+")) + return (v and v >= 5) and (v .. "s") or "30s" + end)(), up_mbps = (node.hysteria2_up_mbps and tonumber(node.hysteria2_up_mbps)) and tonumber(node.hysteria2_up_mbps) or nil, down_mbps = (node.hysteria2_down_mbps and tonumber(node.hysteria2_down_mbps)) and tonumber(node.hysteria2_down_mbps) or nil, obfs = { diff --git a/small/luci-app-passwall2/luasrc/passwall2/util_xray.lua b/small/luci-app-passwall2/luasrc/passwall2/util_xray.lua index 058de37890..7fbd0b4e96 100644 --- a/small/luci-app-passwall2/luasrc/passwall2/util_xray.lua +++ b/small/luci-app-passwall2/luasrc/passwall2/util_xray.lua @@ -155,7 +155,8 @@ function gen_outbound(flag, node, tag, proxy_table) serverName = node.tls_serverName, allowInsecure = (node.tls_allowInsecure == "1") and true or false, fingerprint = (node.type == "Xray" and node.utls == "1" and node.fingerprint and node.fingerprint ~= "") and node.fingerprint or nil, - echConfigList = (node.ech == "1") and node.ech_config or nil + echConfigList = (node.ech == "1") and node.ech_config or nil, + echForceQuery = (node.ech == "1") and (node.ech_ForceQuery or "none") or nil } or nil, realitySettings = (node.stream_security == "reality") and { serverName = node.tls_serverName, @@ -1060,6 +1061,7 @@ function gen_config(var) domains = {} string.gsub(e.domain_list, '[^' .. "\r\n" .. ']+', function(w) if w:find("#") == 1 then return end + if w:find("rule-set:", 1, true) == 1 or w:find("rs:") == 1 then return end table.insert(domains, w) table.insert(domain_table.domain, w) end) @@ -1073,6 +1075,7 @@ function gen_config(var) ip = {} string.gsub(e.ip_list, '[^' .. "\r\n" .. ']+', function(w) if w:find("#") == 1 then return end + if w:find("rule-set:", 1, true) == 1 or w:find("rs:") == 1 then return end table.insert(ip, w) end) if #ip == 0 then ip = nil end diff --git a/small/luci-app-passwall2/luasrc/view/passwall2/node_list/link_share_man.htm b/small/luci-app-passwall2/luasrc/view/passwall2/node_list/link_share_man.htm index 57985d3876..1ecd231601 100644 --- a/small/luci-app-passwall2/luasrc/view/passwall2/node_list/link_share_man.htm +++ b/small/luci-app-passwall2/luasrc/view/passwall2/node_list/link_share_man.htm @@ -284,10 +284,6 @@ local hysteria2_type = map:get("@global_subscribe[0]", "hysteria2_type") or "sin params += opt.query("spx", dom_prefix + "reality_spiderX"); params += opt.query("pqv", dom_prefix + "reality_mldsa65Verify"); } - if (opt.get(dom_prefix + "flow") && opt.get(dom_prefix + "flow").value) { - let v_flow = opt.get(dom_prefix + "flow").value; - params += "&flow=" + v_flow; - } params += "&security=" + v_security; params += opt.query("alpn", dom_prefix + "alpn"); params += opt.query("sni", dom_prefix + "tls_serverName"); @@ -960,11 +956,10 @@ local hysteria2_type = map:get("@global_subscribe[0]", "hysteria2_type") or "sin if (queryParam.security == "tls") { opt.set(dom_prefix + 'tls', true); opt.set(dom_prefix + 'reality', false); - opt.set(dom_prefix + 'flow', queryParam.flow || ''); opt.set(dom_prefix + 'alpn', queryParam.alpn || 'default'); opt.set(dom_prefix + 'tls_serverName', queryParam.sni || ''); opt.set(dom_prefix + 'tls_allowInsecure', true); - if (queryParam.allowinsecure === '0' || queryParam.insecure === '0') { + if ((queryParam.allowinsecure ?? '0') === '0' && (queryParam.insecure ?? '0') === '0') { opt.set(dom_prefix + 'tls_allowInsecure', false); } if (queryParam.fp && queryParam.fp.trim() != "") { @@ -978,7 +973,6 @@ local hysteria2_type = map:get("@global_subscribe[0]", "hysteria2_type") or "sin if (queryParam.security == "reality") { opt.set(dom_prefix + 'tls', true); opt.set(dom_prefix + 'reality', true); - opt.set(dom_prefix + 'flow', queryParam.flow || ''); opt.set(dom_prefix + 'alpn', queryParam.alpn || 'default'); opt.set(dom_prefix + 'tls_serverName', queryParam.sni || ''); if (queryParam.fp && queryParam.fp.trim() != "") { @@ -1205,9 +1199,11 @@ local hysteria2_type = map:get("@global_subscribe[0]", "hysteria2_type") or "sin } tls_serverName = tls_serverName || ""; opt.set(dom_prefix + 'tls_serverName', tls_serverName); + opt.set(dom_prefix + 'flow', (queryParam.flow || '').replace('-udp443', '')); + opt.set(dom_prefix + 'alpn', queryParam.alpn || 'default'); } opt.set(dom_prefix + 'tls_allowInsecure', true); - if (queryParam.allowinsecure === '0' || queryParam.insecure === '0') { + if ((queryParam.allowinsecure ?? '0') === '0' && (queryParam.insecure ?? '0') === '0') { opt.set(dom_prefix + 'tls_allowInsecure', false); } @@ -1342,11 +1338,11 @@ local hysteria2_type = map:get("@global_subscribe[0]", "hysteria2_type") or "sin if (queryParam.security == "tls") { opt.set(dom_prefix + 'tls', true); opt.set(dom_prefix + 'reality', false); - opt.set(dom_prefix + 'flow', queryParam.flow || ''); + opt.set(dom_prefix + 'flow', (queryParam.flow || '').replace('-udp443', '')); opt.set(dom_prefix + 'alpn', queryParam.alpn || 'default'); opt.set(dom_prefix + 'tls_serverName', queryParam.sni || ''); opt.set(dom_prefix + 'tls_allowInsecure', true); - if (queryParam.allowinsecure === '0' || queryParam.insecure === '0') { + if ((queryParam.allowinsecure ?? '0') === '0' && (queryParam.insecure ?? '0') === '0') { opt.set(dom_prefix + 'tls_allowInsecure', false); } if (queryParam.fp && queryParam.fp.trim() != "") { @@ -1360,7 +1356,7 @@ local hysteria2_type = map:get("@global_subscribe[0]", "hysteria2_type") or "sin if (queryParam.security == "reality") { opt.set(dom_prefix + 'tls', true); opt.set(dom_prefix + 'reality', true); - opt.set(dom_prefix + 'flow', queryParam.flow || ''); + opt.set(dom_prefix + 'flow', (queryParam.flow || '').replace('-udp443', '')); opt.set(dom_prefix + 'alpn', queryParam.alpn || 'default'); opt.set(dom_prefix + 'tls_serverName', queryParam.sni || ''); if (queryParam.fp && queryParam.fp.trim() != "") { @@ -1539,7 +1535,7 @@ local hysteria2_type = map:get("@global_subscribe[0]", "hysteria2_type") or "sin opt.set(dom_prefix + 'tuic_alpn', queryParam.alpn || 'default'); opt.set(dom_prefix + 'tls_serverName', queryParam.sni || ''); opt.set(dom_prefix + 'tls_allowInsecure', true); - if (queryParam.allowinsecure === '0' || queryParam.insecure === '0') { + if ((queryParam.allowinsecure ?? '0') === '0' && (queryParam.insecure ?? '0') === '0') { opt.set(dom_prefix + 'tls_allowInsecure', false); } if (hash) { @@ -1579,11 +1575,10 @@ local hysteria2_type = map:get("@global_subscribe[0]", "hysteria2_type") or "sin if (queryParam.security == "tls") { opt.set(dom_prefix + 'tls', true); opt.set(dom_prefix + 'reality', false); - opt.set(dom_prefix + 'flow', queryParam.flow || ''); opt.set(dom_prefix + 'alpn', queryParam.alpn || 'default'); opt.set(dom_prefix + 'tls_serverName', queryParam.sni || ''); opt.set(dom_prefix + 'tls_allowInsecure', true); - if (queryParam.allowinsecure === '0' || queryParam.insecure === '0') { + if ((queryParam.allowinsecure ?? '0') === '0' && (queryParam.insecure ?? '0') === '0') { opt.set(dom_prefix + 'tls_allowInsecure', false); } if (queryParam.fp && queryParam.fp.trim() != "") { @@ -1594,7 +1589,6 @@ local hysteria2_type = map:get("@global_subscribe[0]", "hysteria2_type") or "sin if (queryParam.security == "reality") { opt.set(dom_prefix + 'tls', true); opt.set(dom_prefix + 'reality', true); - opt.set(dom_prefix + 'flow', queryParam.flow || ''); opt.set(dom_prefix + 'alpn', queryParam.alpn || 'default'); opt.set(dom_prefix + 'tls_serverName', queryParam.sni || ''); if (queryParam.fp && queryParam.fp.trim() != "") { diff --git a/small/luci-app-passwall2/po/zh-cn/passwall2.po b/small/luci-app-passwall2/po/zh-cn/passwall2.po index 4db28139df..c3ac43cdce 100644 --- a/small/luci-app-passwall2/po/zh-cn/passwall2.po +++ b/small/luci-app-passwall2/po/zh-cn/passwall2.po @@ -1576,6 +1576,12 @@ msgstr "后量子对等证书签名方案" msgid "Disable adaptive sizing of TLS records" msgstr "禁用 TLS 记录的自适应大小调整" +msgid "ECH Query Policy" +msgstr "ECH 查询策略" + +msgid "Controls the policy used when performing DNS queries for ECH configuration." +msgstr "控制使用 DNS 查询 ECH 配置时的策略。" + msgid "Enable Multipath TCP, need to be enabled in both server and client configuration." msgstr "启用 Multipath TCP,需在服务端和客户端配置中同时启用。" diff --git a/small/luci-app-passwall2/root/usr/share/passwall2/app.sh b/small/luci-app-passwall2/root/usr/share/passwall2/app.sh index 89b4efbeea..814fa08004 100755 --- a/small/luci-app-passwall2/root/usr/share/passwall2/app.sh +++ b/small/luci-app-passwall2/root/usr/share/passwall2/app.sh @@ -336,6 +336,15 @@ eval_cache_var() { [ -s "$TMP_PATH/var" ] && eval $(cat "$TMP_PATH/var") } +has_1_65535() { + local val="$1" + val=${val//:/-} + case ",$val," in + *,1-65535,*) return 0 ;; + *) return 1 ;; + esac +} + run_xray() { local flag node redir_port tcp_proxy_way socks_address socks_port socks_username socks_password http_address http_port http_username http_password local dns_listen_port direct_dns_query_strategy remote_dns_protocol remote_dns_udp_server remote_dns_tcp_server remote_dns_doh remote_dns_client_ip remote_dns_detour remote_fakedns remote_dns_query_strategy dns_cache write_ipset_direct @@ -1146,11 +1155,10 @@ acl_app() { index=$(expr $index + 1) local enabled sid remarks sources interface tcp_no_redir_ports udp_no_redir_ports node direct_dns_query_strategy write_ipset_direct remote_dns_protocol remote_dns remote_dns_doh remote_dns_client_ip remote_dns_detour remote_fakedns remote_dns_query_strategy local _ip _mac _iprange _ipset _ip_or_mac source_list config_file - sid=$(uci -q show "${CONFIG}.${item}" | grep "=acl_rule" | awk -F '=' '{print $1}' | awk -F '.' '{print $2}') + local sid=$(uci -q show "${CONFIG}.${item}" | grep "=acl_rule" | awk -F '=' '{print $1}' | awk -F '.' '{print $2}') + [ "$(config_n_get $sid enabled)" = "1" ] || continue eval $(uci -q show "${CONFIG}.${item}" | cut -d'.' -sf 3-) - [ "$enabled" = "1" ] || continue - if [ -n "${sources}" ]; then for s in $sources; do local s2 @@ -1183,7 +1191,9 @@ acl_app() { udp_no_redir_ports=${udp_no_redir_ports:-default} [ "$tcp_no_redir_ports" = "default" ] && tcp_no_redir_ports=$TCP_NO_REDIR_PORTS [ "$udp_no_redir_ports" = "default" ] && udp_no_redir_ports=$UDP_NO_REDIR_PORTS - [ "$tcp_no_redir_ports" == "1:65535" ] && [ "$udp_no_redir_ports" == "1:65535" ] && unset node + if has_1_65535 "$tcp_no_redir_ports" && has_1_65535 "$udp_no_redir_ports"; then + unset node + fi [ -n "$node" ] && { tcp_proxy_mode="global" diff --git a/small/luci-app-passwall2/root/usr/share/passwall2/iptables.sh b/small/luci-app-passwall2/root/usr/share/passwall2/iptables.sh index c1e0759684..44cc493460 100755 --- a/small/luci-app-passwall2/root/usr/share/passwall2/iptables.sh +++ b/small/luci-app-passwall2/root/usr/share/passwall2/iptables.sh @@ -418,7 +418,7 @@ load_acl() { [ -n "${is_tproxy}" ] && ipt_tmp=$ipt_m [ "$tcp_no_redir_ports" != "disable" ] && { - if [ "$tcp_no_redir_ports" != "1:65535" ]; then + if ! has_1_65535 "$tcp_no_redir_ports"; then [ "$_ipv4" != "1" ] && add_port_rules "$ip6t_m -A PSW2 $(comment "$remarks") ${_ipt_source} -p tcp" $tcp_no_redir_ports "-j RETURN" 2>/dev/null add_port_rules "$ipt_tmp -A PSW2 $(comment "$remarks") ${_ipt_source} -p tcp" $tcp_no_redir_ports "-j RETURN" echolog " - ${msg}不代理 TCP 端口[${tcp_no_redir_ports}]" @@ -430,7 +430,7 @@ load_acl() { } [ "$udp_no_redir_ports" != "disable" ] && { - if [ "$udp_no_redir_ports" != "1:65535" ]; then + if ! has_1_65535 "$udp_no_redir_ports"; then [ "$_ipv4" != "1" ] && add_port_rules "$ip6t_m -A PSW2 $(comment "$remarks") ${_ipt_source} -p udp" $udp_no_redir_ports "-j RETURN" 2>/dev/null add_port_rules "$ipt_m -A PSW2 $(comment "$remarks") ${_ipt_source} -p udp" $udp_no_redir_ports "-j RETURN" echolog " - ${msg}不代理 UDP 端口[${udp_no_redir_ports}]" @@ -526,7 +526,7 @@ load_acl() { [ "$TCP_NO_REDIR_PORTS" != "disable" ] && { add_port_rules "$ip6t_m -A PSW2 $(comment "默认") -p tcp" $TCP_NO_REDIR_PORTS "-j RETURN" add_port_rules "$ipt_tmp -A PSW2 $(comment "默认") -p tcp" $TCP_NO_REDIR_PORTS "-j RETURN" - if [ "$TCP_NO_REDIR_PORTS" != "1:65535" ]; then + if ! has_1_65535 "$TCP_NO_REDIR_PORTS"; then echolog " - ${msg}不代理 TCP 端口[${TCP_NO_REDIR_PORTS}]" else TCP_PROXY_MODE="disable" @@ -537,7 +537,7 @@ load_acl() { [ "$UDP_NO_REDIR_PORTS" != "disable" ] && { add_port_rules "$ip6t_m -A PSW2 $(comment "默认") -p udp" $UDP_NO_REDIR_PORTS "-j RETURN" add_port_rules "$ipt_tmp -A PSW2 $(comment "默认") -p udp" $UDP_NO_REDIR_PORTS "-j RETURN" - if [ "$UDP_NO_REDIR_PORTS" != "1:65535" ]; then + if ! has_1_65535 "$UDP_NO_REDIR_PORTS"; then echolog " - ${msg}不代理 UDP 端口[${UDP_NO_REDIR_PORTS}]" else UDP_PROXY_MODE="disable" @@ -871,7 +871,7 @@ add_firewall_rule() { [ "$TCP_NO_REDIR_PORTS" != "disable" ] && { add_port_rules "$ipt_tmp -A PSW2_OUTPUT -p tcp" $TCP_NO_REDIR_PORTS "-j RETURN" add_port_rules "$ip6t_m -A PSW2_OUTPUT -p tcp" $TCP_NO_REDIR_PORTS "-j RETURN" - if [ "$TCP_NO_REDIR_PORTS" != "1:65535" ]; then + if ! has_1_65535 "$TCP_NO_REDIR_PORTS"; then echolog " - ${msg}不代理 TCP 端口[${TCP_NO_REDIR_PORTS}]" else unset TCP_LOCALHOST_PROXY @@ -882,7 +882,7 @@ add_firewall_rule() { [ "$UDP_NO_REDIR_PORTS" != "disable" ] && { add_port_rules "$ipt_m -A PSW2_OUTPUT -p udp" $UDP_NO_REDIR_PORTS "-j RETURN" add_port_rules "$ip6t_m -A PSW2_OUTPUT -p udp" $UDP_NO_REDIR_PORTS "-j RETURN" - if [ "$UDP_NO_REDIR_PORTS" != "1:65535" ]; then + if ! has_1_65535 "$UDP_NO_REDIR_PORTS"; then echolog " - ${msg}不代理 UDP 端口[${UDP_NO_REDIR_PORTS}]" else unset UDP_LOCALHOST_PROXY diff --git a/small/luci-app-passwall2/root/usr/share/passwall2/nftables.sh b/small/luci-app-passwall2/root/usr/share/passwall2/nftables.sh index 0ae46b3993..4d6b946d1b 100755 --- a/small/luci-app-passwall2/root/usr/share/passwall2/nftables.sh +++ b/small/luci-app-passwall2/root/usr/share/passwall2/nftables.sh @@ -432,7 +432,7 @@ load_acl() { msg="【$remarks】,${msg}" [ "$tcp_no_redir_ports" != "disable" ] && { - if [ "$tcp_no_redir_ports" != "1:65535" ]; then + if ! has_1_65535 "$tcp_no_redir_ports"; then nft "add rule $NFTABLE_NAME $nft_prerouting_chain ${_ipt_source} ip protocol tcp $(factor $tcp_no_redir_ports "tcp dport") counter return comment \"$remarks\"" [ "$_ipv4" != "1" ] && nft "add rule $NFTABLE_NAME PSW2_MANGLE_V6 ${_ipt_source} meta l4proto tcp $(factor $tcp_no_redir_ports "tcp dport") counter return comment \"$remarks\"" echolog " - ${msg}不代理 TCP 端口[${tcp_no_redir_ports}]" @@ -444,7 +444,7 @@ load_acl() { } [ "$udp_no_redir_ports" != "disable" ] && { - if [ "$udp_no_redir_ports" != "1:65535" ]; then + if ! has_1_65535 "$udp_no_redir_ports"; then nft "add rule $NFTABLE_NAME PSW2_MANGLE ip protocol udp ${_ipt_source} $(factor $udp_no_redir_ports "udp dport") counter return comment \"$remarks\"" [ "$_ipv4" != "1" ] && nft "add rule $NFTABLE_NAME PSW2_MANGLE_V6 meta l4proto udp ${_ipt_source} $(factor $udp_no_redir_ports "udp dport") counter return comment \"$remarks\"" 2>/dev/null echolog " - ${msg}不代理 UDP 端口[${udp_no_redir_ports}]" @@ -544,7 +544,7 @@ load_acl() { [ "$TCP_NO_REDIR_PORTS" != "disable" ] && { nft "add rule $NFTABLE_NAME $nft_prerouting_chain ip protocol tcp $(factor $TCP_NO_REDIR_PORTS "tcp dport") counter return comment \"默认\"" nft "add rule $NFTABLE_NAME PSW2_MANGLE_V6 meta l4proto tcp $(factor $TCP_NO_REDIR_PORTS "tcp dport") counter return comment \"默认\"" - if [ "$TCP_NO_REDIR_PORTS" != "1:65535" ]; then + if ! has_1_65535 "$TCP_NO_REDIR_PORTS"; then echolog " - ${msg}不代理 TCP 端口[${TCP_NO_REDIR_PORTS}]" else TCP_PROXY_MODE="disable" @@ -555,7 +555,7 @@ load_acl() { [ "$UDP_NO_REDIR_PORTS" != "disable" ] && { nft "add $NFTABLE_NAME PSW2_MANGLE ip protocol udp $(factor $UDP_NO_REDIR_PORTS "udp dport") counter return comment \"默认\"" nft "add $NFTABLE_NAME PSW2_MANGLE_V6 counter meta l4proto udp $(factor $UDP_NO_REDIR_PORTS "udp dport") counter return comment \"默认\"" - if [ "$UDP_NO_REDIR_PORTS" != "1:65535" ]; then + if ! has_1_65535 "$UDP_NO_REDIR_PORTS"; then echolog " - ${msg}不代理 UDP 端口[${UDP_NO_REDIR_PORTS}]" else UDP_PROXY_MODE="disable" @@ -893,7 +893,7 @@ add_firewall_rule() { [ "$TCP_NO_REDIR_PORTS" != "disable" ] && { nft "add rule $NFTABLE_NAME $nft_output_chain ip protocol tcp $(factor $TCP_NO_REDIR_PORTS "tcp dport") counter return" nft "add rule $NFTABLE_NAME PSW2_OUTPUT_MANGLE_V6 meta l4proto tcp $(factor $TCP_NO_REDIR_PORTS "tcp dport") counter return" - if [ "$TCP_NO_REDIR_PORTS" != "1:65535" ]; then + if ! has_1_65535 "$TCP_NO_REDIR_PORTS"; then echolog " - ${msg}不代理 TCP 端口[${TCP_NO_REDIR_PORTS}]" else unset TCP_LOCALHOST_PROXY @@ -904,7 +904,7 @@ add_firewall_rule() { [ "$UDP_NO_REDIR_PORTS" != "disable" ] && { nft "add rule $NFTABLE_NAME PSW2_OUTPUT_MANGLE ip protocol udp $(factor $UDP_NO_REDIR_PORTS "udp dport") counter return" nft "add rule $NFTABLE_NAME PSW2_OUTPUT_MANGLE_V6 meta l4proto udp $(factor $UDP_NO_REDIR_PORTS "udp dport") counter return" - if [ "$UDP_NO_REDIR_PORTS" != "1:65535" ]; then + if ! has_1_65535 "$UDP_NO_REDIR_PORTS"; then echolog " - ${msg}不代理 UDP 端口[${UDP_NO_REDIR_PORTS}]" else unset UDP_LOCALHOST_PROXY 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 25754a664b..2d37277d79 100755 --- a/small/luci-app-passwall2/root/usr/share/passwall2/subscribe.lua +++ b/small/luci-app-passwall2/root/usr/share/passwall2/subscribe.lua @@ -1042,8 +1042,8 @@ local function processData(szType, content, add_mode, add_from) end result.encryption = params.encryption or "none" - - result.flow = params.flow or nil + result.flow = params.flow and params.flow:gsub("-udp443", "") or nil + result.alpn = params.alpn if result.type == "sing-box" and (result.transport == "mkcp" or result.transport == "xhttp" or result.transport == "splithttp") then log("跳过节点:" .. result.remarks ..",因Sing-Box不支持" .. szType .. "协议的" .. result.transport .. "传输方式,需更换Xray。") @@ -1194,7 +1194,7 @@ local function processData(szType, content, add_mode, add_from) result.encryption = params.encryption or "none" - result.flow = params.flow or nil + result.flow = params.flow and params.flow:gsub("-udp443", "") or nil result.tls = "0" if params.security == "tls" or params.security == "reality" then @@ -1272,7 +1272,6 @@ local function processData(szType, content, add_mode, add_from) else result.address = host_port end - result.protocol = params.protocol result.hysteria_obfs = params.obfsParam result.hysteria_auth_type = "string" result.hysteria_auth_password = params.auth diff --git a/small/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua b/small/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua index b61c8af9e2..a66d45d859 100644 --- a/small/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua +++ b/small/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua @@ -408,6 +408,7 @@ o:depends("type", "ssr") -- [[ Hysteria2 ]]-- o = s:option(Value, "hy2_auth", translate("Users Authentication")) o:depends("type", "hysteria2") +o.password = true o.rmempty = false o = s:option(Flag, "flag_port_hopping", translate("Enable Port Hopping")) @@ -455,6 +456,7 @@ o.placeholder = "salamander" o = s:option(Value, "salamander", translate("Obfuscation Password")) o:depends({type = "hysteria2", flag_obfs = "1"}) +o.password = true o.rmempty = true o.placeholder = "cry_me_a_r1ver" @@ -575,6 +577,7 @@ o.default="auto" -- [[ TUIC ]] -- TuicNameId o = s:option(Value, "tuic_uuid", translate("TUIC User UUID")) +o.password = true o.rmempty = true o.default = uuid o:depends("type", "tuic") @@ -588,6 +591,7 @@ o:depends("type", "tuic") -- Tuic Password o = s:option(Value, "tuic_passwd", translate("TUIC User Password")) +o.password = true o.rmempty = true o.default = "" o:depends("type", "tuic") @@ -675,6 +679,7 @@ o:depends({type = "v2ray", v2ray_protocol = "vmess"}) -- VmessId o = s:option(Value, "vmess_id", translate("Vmess/VLESS ID (UUID)")) +o.password = true o.rmempty = true o.default = uuid o:depends({type = "v2ray", v2ray_protocol = "vmess"}) @@ -792,7 +797,7 @@ o:depends("transport", "splithttp") o.rmempty = true -- [[ XHTTP部分 ]]-- -o = s:option(ListValue, "xhttp_alpn", translate("XHTTP Alpn")) +o = s:option(ListValue, "xhttp_alpn", translate("XHTTP ALPN")) o.default = "" o:value("", translate("Default")) o:value("h3") @@ -1179,10 +1184,13 @@ o:depends("xtls", true) o:depends("reality", true) o.rmempty = true -o = s:option(DynamicList, "tls_alpn", translate("TLS ALPN")) +o = s:option(ListValue, "tls_alpn", translate("TLS ALPN")) +o.default = "" +o:value("", translate("Default")) +o:value("h3") +o:value("spdy/3.1") +o:value("h3,spdy/3.1") o:depends("type", "tuic") -o.default = "h3" -o.rmempty = true -- [[ allowInsecure ]]-- o = s:option(Flag, "insecure", translate("allowInsecure")) diff --git a/small/luci-app-ssr-plus/luasrc/view/shadowsocksr/ssrurl.htm b/small/luci-app-ssr-plus/luasrc/view/shadowsocksr/ssrurl.htm index b9dd51f7d0..407d8cb37c 100644 --- a/small/luci-app-ssr-plus/luasrc/view/shadowsocksr/ssrurl.htm +++ b/small/luci-app-ssr-plus/luasrc/view/shadowsocksr/ssrurl.htm @@ -480,7 +480,7 @@ function import_ssr_url(btn, urlname, sid) { document.getElementsByName('cbid.shadowsocksr.' + sid + '.xhttp_mode')[0].value = ssm.mode; document.getElementsByName('cbid.shadowsocksr.' + sid + '.xhttp_host')[0].value = ssm.host; document.getElementsByName('cbid.shadowsocksr.' + sid + '.xhttp_path')[0].value = ssm.path; - if (params.get("extra") && params.get("extra").trim() !== "") { + if (ssm.extra !== "" && ssm.extra !== undefined) { document.getElementsByName('cbid.shadowsocksr.' + sid + '.enable_xhttp_extra')[0].checked = true; // 设置 enable_xhttp_extra 为 true document.getElementsByName('cbid.shadowsocksr.' + sid + '.enable_xhttp_extra')[0].dispatchEvent(event); // 触发事件 document.getElementsByName('cbid.shadowsocksr.' + sid + '.xhttp_extra')[0].value = ssm.extra; @@ -500,16 +500,18 @@ function import_ssr_url(btn, urlname, sid) { if (ssm.tls == "tls") { document.getElementsByName('cbid.shadowsocksr.' + sid + '.tls')[0].checked = true; document.getElementsByName('cbid.shadowsocksr.' + sid + '.tls')[0].dispatchEvent(event); - document.getElementsByName('cbid.shadowsocksr.' + sid + '.fingerprint')[0].value = ssm.fp; + if (ssm.fq !== "" && ssm.fq !== undefined) { + document.getElementsByName('cbid.shadowsocksr.' + sid + '.fingerprint')[0].value = ssm.fp; + } if (ssm.net == "xhttp") { document.getElementsByName('cbid.shadowsocksr.' + sid + '.xhttp_alpn')[0].value = ssm.alpn; } document.getElementsByName('cbid.shadowsocksr.' + sid + '.tls_host')[0].value = ssm.sni || ssm.host; - } - if (ssm.tls == "tls") { - document.getElementsByName('cbid.shadowsocksr.' + sid + '.enable_ech')[0].checked = true; - document.getElementsByName('cbid.shadowsocksr.' + sid + '.enable_ech')[0].dispatchEvent(event); - document.getElementsByName('cbid.shadowsocksr.' + sid + '.ech_config')[0].value = ssm.ech; + if (ssm.ech !== "" && ssm.ech !== undefined) { + document.getElementsByName('cbid.shadowsocksr.' + sid + '.enable_ech')[0].checked = true; // 设置 enable_ech 为 true + document.getElementsByName('cbid.shadowsocksr.' + sid + '.enable_ech')[0].dispatchEvent(event); // 触发事件 + document.getElementsByName('cbid.shadowsocksr.' + sid + '.ech_config')[0].value = ssm.ech; + } } if (ssm.mux !== undefined) { document.getElementsByName('cbid.shadowsocksr.' + sid + '.mux')[0].checked = true; diff --git a/small/luci-app-ssr-plus/po/templates/ssr-plus.pot b/small/luci-app-ssr-plus/po/templates/ssr-plus.pot index de34a7e55b..77423bb71e 100644 --- a/small/luci-app-ssr-plus/po/templates/ssr-plus.pot +++ b/small/luci-app-ssr-plus/po/templates/ssr-plus.pot @@ -20,7 +20,7 @@ msgstr "" msgid "128 Threads" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1247 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1255 msgid "16" msgstr "" @@ -36,7 +36,7 @@ msgstr "" msgid "32 Threads" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1120 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1125 msgid "360" msgstr "" @@ -56,7 +56,7 @@ msgstr "" msgid "64 Threads" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1234 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1242 msgid "8" msgstr "" @@ -68,9 +68,9 @@ msgstr "" msgid "" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:831 -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1135 -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1162 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:836 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1140 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1167 msgid "" msgstr "" @@ -81,9 +81,9 @@ msgstr "" #: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/advanced.lua:151 #: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/advanced.lua:177 #: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/advanced.lua:211 -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1227 -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1240 -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1254 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1235 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1248 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1262 #: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client.lua:174 #: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client.lua:200 #: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client.lua:235 @@ -135,7 +135,7 @@ msgstr "" msgid "Allow subscribe Insecure nodes By default" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:670 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:674 msgid "AlterId" msgstr "" @@ -198,8 +198,8 @@ msgstr "" msgid "Auto Update Server subscription, GFW list and CHN route" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:604 -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1288 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:608 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1296 msgid "BBR" msgstr "" @@ -219,8 +219,8 @@ msgstr "" msgid "Baidu Public DNS (180.76.76.76)" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:946 -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:956 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:951 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:961 msgid "BitTorrent (uTP)" msgstr "" @@ -244,17 +244,17 @@ msgstr "" msgid "CNNIC SDNS (1.2.4.8)" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:605 -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1289 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:609 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1297 msgid "CUBIC" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:727 -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:952 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:732 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:957 msgid "Camouflage Type" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1195 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1203 msgid "Certificate fingerprint" msgstr "" @@ -319,9 +319,9 @@ msgid "Click here to view or manage the DNS list file" msgstr "" #: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/advanced.lua:382 -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:833 -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1137 -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1164 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:838 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1142 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1169 msgid "Click to the page" msgstr "" @@ -346,15 +346,15 @@ msgstr "" msgid "Collecting data..." msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:831 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:836 msgid "Configure XHTTP Extra Settings (JSON format), see:" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1005 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1010 msgid "Congestion" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:602 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:606 msgid "Congestion control algorithm" msgstr "" @@ -370,7 +370,7 @@ msgstr "" msgid "Connection Timeout" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1148 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1153 msgid "" "Controls the policy used when performing DNS queries for ECH configuration." msgstr "" @@ -383,11 +383,11 @@ msgstr "" msgid "Create Backup File" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1324 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1332 msgid "Create upload file error." msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1344 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1352 msgid "Current Certificate Path" msgstr "" @@ -446,30 +446,31 @@ msgstr "" msgid "DNSPod Public DNS (119.29.29.29)" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:948 -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:958 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:953 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:963 msgid "DTLS 1.2" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:797 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:802 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1189 msgid "Default" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1255 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1263 msgid "Default reject rejects traffic." msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:503 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:505 msgid "Default value 0 indicatesno heartbeat." msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1228 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1236 msgid "" "Default: disable. When entering a negative number, such as -1, The Mux " "module will not be used to carry TCP traffic." msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1241 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1249 msgid "" "Default:16. When entering a negative number, such as -1, The Mux module will " "not be used to carry UDP traffic, Use original UDP transmission method of " @@ -524,15 +525,15 @@ msgstr "" msgid "Disable IPv6 query mode" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:466 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:468 msgid "Disable QUIC path MTU discovery" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:646 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:650 msgid "Disable SNI" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:529 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:531 msgid "Disable TCP No_delay" msgstr "" @@ -561,23 +562,23 @@ msgstr "" msgid "Domestic DNS Server" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:982 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:987 msgid "Downlink Capacity(Default:Mbps)" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:657 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:661 msgid "Dual-stack Listening Socket" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1133 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1138 msgid "ECH Config" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1147 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1152 msgid "ECH Query Policy" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:764 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:769 msgid "Early Data Header Name" msgstr "" @@ -593,7 +594,7 @@ msgstr "" msgid "Enable" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:651 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:655 msgid "Enable 0-RTT QUIC handshake" msgstr "" @@ -602,29 +603,29 @@ msgid "Enable Authentication" msgstr "" #: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/advanced.lua:54 -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1358 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1366 msgid "Enable Auto Switch" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1128 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1133 msgid "Enable ECH(optional)" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:446 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:447 msgid "Enable Lazy Mode" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1155 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1160 msgid "Enable ML-DSA-65(optional)" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1273 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1281 msgid "" "Enable Multipath TCP, need to be enabled in both server and client " "configuration." msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1201 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1209 msgid "Enable Mux.Cool" msgstr "" @@ -632,7 +633,7 @@ msgstr "" msgid "Enable Netflix Mode" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:441 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:442 msgid "Enable Obfuscation" msgstr "" @@ -640,7 +641,7 @@ msgstr "" msgid "Enable Plugin" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:413 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:414 msgid "Enable Port Hopping" msgstr "" @@ -648,19 +649,19 @@ msgstr "" msgid "Enable Server" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:424 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:425 msgid "Enable Transport Protocol Settings" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:515 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:517 msgid "Enable V2 protocol." msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:514 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:516 msgid "Enable V3 protocol." msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1219 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1227 msgid "Enable Xudp Mux" msgstr "" @@ -672,11 +673,11 @@ msgstr "" msgid "Enable the SUoT protocol, requires server support." msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:824 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:829 msgid "Enable this option to configure XHTTP Extra (JSON format)." msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1010 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1015 msgid "Enabled Kernel virtual NIC TUN(optional)" msgstr "" @@ -684,17 +685,17 @@ msgstr "" msgid "Enabled Mixed" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:524 -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1267 -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1350 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:526 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1275 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1358 msgid "Enabling TCP Fast Open Requires Server Support." msgstr "" #: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:323 #: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:330 -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:556 -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:567 -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:690 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:558 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:569 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:695 #: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/server-config.lua:118 #: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/server-config.lua:125 #: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/server.lua:122 @@ -749,12 +750,12 @@ msgstr "" msgid "Filter Words splited by /" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1112 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1117 msgid "Finger Print" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1085 -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1098 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1090 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1103 msgid "Flow" msgstr "" @@ -768,7 +769,7 @@ msgstr "" msgid "For specific usage, see:" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:419 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:420 msgid "" "Format as 10000:20000 or 10000-20000 Multiple groups are separated by commas " "(,)." @@ -830,11 +831,11 @@ msgstr "" msgid "Game Mode UDP Server" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:622 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:626 msgid "Garbage collection interval(second)" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:628 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:632 msgid "Garbage collection lifetime(second)" msgstr "" @@ -887,15 +888,15 @@ msgstr "" msgid "Grant UCI access for luci-app-ssr-plus" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:887 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:892 msgid "Gun" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:906 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:911 msgid "H2 Read Idle Timeout" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:901 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:906 msgid "H2/gRPC Health Check" msgstr "" @@ -903,39 +904,39 @@ msgstr "" msgid "HTTP" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:734 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:739 msgid "HTTP Host" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:739 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:744 msgid "HTTP Path" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:869 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:874 msgid "HTTP/2 Host" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:874 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:879 msgid "HTTP/2 Path" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:941 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:946 msgid "Header" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:918 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:923 msgid "Health Check Timeout" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:610 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:614 msgid "Heartbeat interval(second)" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:773 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:778 msgid "Httpupgrade Host" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:778 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:783 msgid "Httpupgrade Path" msgstr "" @@ -943,7 +944,7 @@ msgstr "" msgid "Hysteria2" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:461 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:463 msgid "Hysterir QUIC parameters" msgstr "" @@ -955,27 +956,27 @@ msgstr "" msgid "If empty, Not change Apple domains parsing DNS (Default is empty)" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1135 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1140 msgid "" "If it is not empty, it indicates that the Client has enabled Encrypted " "Client, see:" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:658 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:662 msgid "If this option is not set, the socket behavior is platform dependent." msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1192 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1200 msgid "" "If true, allowss insecure connection at TLS client, e.g., TLS server uses " "unverifiable certificates." msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1308 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1316 msgid "If you have a self-signed certificate,please check the box" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/view/shadowsocksr/ssrurl.htm:661 +#: applications/luci-app-ssr-plus/luasrc/view/shadowsocksr/ssrurl.htm:663 msgid "Import" msgstr "" @@ -983,12 +984,12 @@ msgstr "" #: applications/luci-app-ssr-plus/luasrc/view/shadowsocksr/ssrurl.htm:303 #: applications/luci-app-ssr-plus/luasrc/view/shadowsocksr/ssrurl.htm:335 #: applications/luci-app-ssr-plus/luasrc/view/shadowsocksr/ssrurl.htm:434 -#: applications/luci-app-ssr-plus/luasrc/view/shadowsocksr/ssrurl.htm:522 -#: applications/luci-app-ssr-plus/luasrc/view/shadowsocksr/ssrurl.htm:652 +#: applications/luci-app-ssr-plus/luasrc/view/shadowsocksr/ssrurl.htm:524 +#: applications/luci-app-ssr-plus/luasrc/view/shadowsocksr/ssrurl.htm:654 msgid "Import configuration information successfully." msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:894 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:899 msgid "Initial Windows Size" msgstr "" @@ -1000,11 +1001,11 @@ msgstr "" msgid "Interface control" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:860 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:865 msgid "Invalid JSON format" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/view/shadowsocksr/ssrurl.htm:655 +#: applications/luci-app-ssr-plus/luasrc/view/shadowsocksr/ssrurl.htm:657 msgid "Invalid format." msgstr "" @@ -1012,19 +1013,19 @@ msgstr "" msgid "KcpTun" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1368 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1376 msgid "KcpTun Enable" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1385 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1393 msgid "KcpTun Param" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1380 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1388 msgid "KcpTun Password" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1374 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1382 msgid "KcpTun Port" msgstr "" @@ -1114,7 +1115,7 @@ msgid "Listen only on the given interface or, if unspecified, on all" msgstr "" #: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/advanced.lua:340 -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1362 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1370 msgid "Local Port" msgstr "" @@ -1122,7 +1123,7 @@ msgstr "" msgid "Local Servers" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1016 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1021 msgid "Local addresses" msgstr "" @@ -1138,15 +1139,15 @@ msgstr "" msgid "Loyalsoldier/v2ray-rules-dat" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1160 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1165 msgid "ML-DSA-65 Public key" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1273 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1281 msgid "MPTCP" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:962 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:967 msgid "MTU" msgstr "" @@ -1154,21 +1155,21 @@ msgstr "" msgid "Main Server" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:757 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:762 msgid "Max Early Data" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:663 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:667 msgid "Maximum packet size the socks5 server can receive from external" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1242 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1250 msgid "" "Min value is 1, Max value is 1024. When omitted or set to 0, Will same path " "as TCP traffic." msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1229 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1237 msgid "" "Min value is 1, Max value is 128. When omitted or set to 0, it equals 8." msgstr "" @@ -1182,7 +1183,7 @@ msgstr "" msgid "Muitiple DNS server can saperate with ','" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:888 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:893 msgid "Multi" msgstr "" @@ -1190,7 +1191,7 @@ msgstr "" msgid "Multi Threads Option" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1201 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1209 msgid "Mux" msgstr "" @@ -1242,7 +1243,7 @@ msgstr "" msgid "Network interface to use" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:606 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:610 msgid "New Reno" msgstr "" @@ -1256,7 +1257,7 @@ msgstr "" msgid "No new data!" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1340 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1348 msgid "No specify upload file." msgstr "" @@ -1265,10 +1266,10 @@ msgid "Noise" msgstr "" #: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:362 -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:729 -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:932 -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:944 -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:954 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:734 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:937 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:949 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:959 #: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/servers.lua:187 #: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/servers.lua:192 msgid "None" @@ -1305,15 +1306,15 @@ msgstr "" msgid "Obfs param (optional)" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1001 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1006 msgid "Obfuscate password (optional)" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:456 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:457 msgid "Obfuscation Password" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:451 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:452 msgid "Obfuscation Type" msgstr "" @@ -1373,7 +1374,7 @@ msgstr "" msgid "Paste sharing link here" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1031 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1036 msgid "Peer public key" msgstr "" @@ -1382,7 +1383,7 @@ msgstr "" msgid "Perform reset" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:924 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:929 msgid "Permit Without Stream" msgstr "" @@ -1390,7 +1391,7 @@ msgstr "" msgid "Ping Latency" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1347 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1355 msgid "Please confirm the current certificate path" msgstr "" @@ -1402,19 +1403,19 @@ msgstr "" msgid "Plugin Opts" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:435 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:436 msgid "Port Hopping Interval(Unit:Second)" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:418 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:419 msgid "Port hopping range" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1035 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1040 msgid "Pre-shared key" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1026 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1031 msgid "Private key" msgstr "" @@ -1432,35 +1433,35 @@ msgstr "" msgid "Proxy Ports" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1072 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1077 msgid "Public key" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:937 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:942 msgid "QUIC Key" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:930 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:935 msgid "QUIC Security" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:484 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:486 msgid "QUIC initConnReceiveWindow" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:472 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:474 msgid "QUIC initStreamReceiveWindow" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:490 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:492 msgid "QUIC maxConnReceiveWindow" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:496 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:498 msgid "QUIC maxIdleTimeout(Unit:second)" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:478 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:480 msgid "QUIC maxStreamReceiveWindow" msgstr "" @@ -1469,7 +1470,7 @@ msgstr "" msgid "Quad9 DNSCrypt SDNS" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1067 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1072 msgid "REALITY" msgstr "" @@ -1481,7 +1482,7 @@ msgstr "" msgid "RUNNING" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:989 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:994 msgid "Read Buffer Size" msgstr "" @@ -1524,11 +1525,11 @@ msgstr "" msgid "Refresh..." msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1290 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1298 msgid "Reno" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1021 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1026 msgid "Reserved bytes(optional)" msgstr "" @@ -1603,7 +1604,7 @@ msgstr "" msgid "Selection ShadowSocks Node Use Version." msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1300 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1308 msgid "Self-signed Certificate" msgstr "" @@ -1651,7 +1652,7 @@ msgstr "" msgid "Servers subscription and manage" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1061 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1066 msgid "Session Ticket" msgstr "" @@ -1664,7 +1665,7 @@ msgstr "" msgid "Shadow-TLS" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:541 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:543 msgid "Shadow-TLS ChainPoxy type" msgstr "" @@ -1685,7 +1686,7 @@ msgid "ShadowSocks-libev Version" msgstr "" #: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:223 -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:544 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:546 #: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/servers.lua:23 msgid "ShadowSocks-rust Version" msgstr "" @@ -1698,7 +1699,7 @@ msgstr "" msgid "ShadowSocksR Plus+ Settings" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:552 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:554 msgid "Shadowsocks password" msgstr "" @@ -1707,7 +1708,7 @@ msgstr "" msgid "ShadowsocksR" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1076 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1081 msgid "Short ID" msgstr "" @@ -1719,7 +1720,7 @@ msgstr "" msgid "Socks" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:698 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:703 msgid "Socks Version" msgstr "" @@ -1748,11 +1749,11 @@ msgstr "" msgid "Specifically for edit dnsproxy DNS parse files." msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:785 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:790 msgid "Splithttp Host" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:790 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:795 msgid "Splithttp Path" msgstr "" @@ -1792,9 +1793,9 @@ msgstr "" msgid "Switch check cycly(second)" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:524 -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1267 -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1350 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:526 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1275 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1358 #: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/server-config.lua:149 msgid "TCP Fast Open" msgstr "" @@ -1810,23 +1811,23 @@ msgstr "" msgid "TCP upstream" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1048 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1053 msgid "TLS" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:519 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:521 msgid "TLS 1.3 Strict mode" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1182 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1187 msgid "TLS ALPN" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1175 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1180 msgid "TLS Host" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:969 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:974 msgid "TTI" msgstr "" @@ -1834,23 +1835,23 @@ msgstr "" msgid "TUIC" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:583 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:586 msgid "TUIC Server IP Address" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:590 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:593 msgid "TUIC User Password" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:577 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:579 msgid "TUIC User UUID" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:640 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:644 msgid "TUIC receive window" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:634 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:638 msgid "TUIC send window" msgstr "" @@ -1859,7 +1860,7 @@ msgstr "" msgid "TWNIC-101 DNSCrypt SDNS" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1162 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1167 msgid "" "The client has not configured mldsa65Verify, but it will not perform the " "\"additional verification\" step and can still connect normally, see:" @@ -1869,7 +1870,7 @@ msgstr "" msgid "The content entered is incorrect!" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:502 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:504 msgid "The keep-alive period.(Unit:second)" msgstr "" @@ -1881,7 +1882,7 @@ msgstr "" msgid "Through proxy update list, Not Recommended" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:616 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:620 msgid "Timeout for establishing a connection to server(second)" msgstr "" @@ -1898,11 +1899,11 @@ msgstr "" msgid "Total Records:" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:707 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:712 msgid "Transport" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:429 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:430 msgid "Transport Protocol" msgstr "" @@ -1916,7 +1917,7 @@ msgstr "" msgid "Type" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:431 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:432 msgid "UDP" msgstr "" @@ -1930,7 +1931,7 @@ msgstr "" msgid "UDP over TCP" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:595 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:599 msgid "UDP relay mode" msgstr "" @@ -1982,11 +1983,11 @@ msgstr "" msgid "Update time (every day)" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:975 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:980 msgid "Uplink Capacity(Default:Mbps)" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1310 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1318 #: applications/luci-app-ssr-plus/luasrc/view/shadowsocksr/certupload.htm:3 msgid "Upload" msgstr "" @@ -2074,7 +2075,7 @@ msgstr "" msgid "VLESS" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:684 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:689 msgid "VLESS Encryption" msgstr "" @@ -2082,26 +2083,26 @@ msgstr "" msgid "VMess" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:945 -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:955 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:950 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:960 msgid "VideoCall (SRTP)" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1011 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1016 msgid "" "Virtual NIC TUN of Linux kernel can be used only when system supports and " "have root permission. If used, IPv6 routing table 1023 is occupied." msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:547 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:549 msgid "Vmess Protocol" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:562 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:564 msgid "Vmess UUID" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:677 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:681 msgid "Vmess/VLESS ID (UUID)" msgstr "" @@ -2117,16 +2118,16 @@ msgstr "" msgid "WAN White List IP" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:745 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:750 msgid "WebSocket Host" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:751 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:756 msgid "WebSocket Path" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:947 -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:957 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:952 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:962 msgid "WechatVideo" msgstr "" @@ -2152,40 +2153,40 @@ msgid "" msgstr "" #: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:263 -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:949 -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:959 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:954 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:964 msgid "WireGuard" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1041 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1046 msgid "Wireguard allows only traffic from specific source IP." msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1022 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1027 msgid "Wireguard reserved bytes." msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:995 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1000 msgid "Write Buffer Size" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:795 -msgid "XHTTP Alpn" +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:800 +msgid "XHTTP ALPN" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:823 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:828 msgid "XHTTP Extra" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:814 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:819 msgid "XHTTP Host" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:806 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:811 msgid "XHTTP Mode" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:818 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:823 msgid "XHTTP Path" msgstr "" @@ -2197,7 +2198,7 @@ msgstr "" msgid "Xray Noise Packets" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1219 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1227 msgid "Xudp Mux" msgstr "" @@ -2205,27 +2206,27 @@ msgstr "" msgid "adblock_url" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:933 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:938 msgid "aes-128-gcm" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1262 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1270 msgid "allow" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1256 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1264 msgid "allow: Allows use Mux connection." msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1188 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1196 msgid "allowInsecure" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1040 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1045 msgid "allowedIPs(optional)" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1118 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1123 msgid "android" msgstr "" @@ -2233,7 +2234,7 @@ msgstr "" msgid "anti-AD" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:934 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:939 msgid "chacha20-poly1305" msgstr "" @@ -2241,7 +2242,7 @@ msgstr "" msgid "china-operator-ip" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1114 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1119 msgid "chrome" msgstr "" @@ -2250,21 +2251,21 @@ msgstr "" msgid "cloudflare-dns.com DNSCrypt SDNS" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1287 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1295 msgid "comment_tcpcongestion_disable" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1225 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1233 msgid "concurrency" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1284 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1292 msgid "custom_tcpcongestion" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1124 -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1233 -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1246 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1129 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1241 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1254 msgid "disable" msgstr "" @@ -2273,7 +2274,7 @@ msgstr "" msgid "dns.sb DNSCrypt SDNS" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1119 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1124 msgid "edge" msgstr "" @@ -2286,19 +2287,19 @@ msgstr "" msgid "felixonmars/dnsmasq-china-list" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1115 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1120 msgid "firefox" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:912 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:917 msgid "gRPC Idle Timeout" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:885 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:890 msgid "gRPC Mode" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:879 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:884 msgid "gRPC Service Name" msgstr "" @@ -2310,7 +2311,7 @@ msgstr "" msgid "gfwlist/gfwlist" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1117 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1122 msgid "ios" msgstr "" @@ -2319,11 +2320,11 @@ msgstr "" msgid "load_balance" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:598 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:602 msgid "lossless UDP relay using QUIC streams" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:597 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:601 msgid "native UDP characteristics" msgstr "" @@ -2332,8 +2333,8 @@ msgid "nfip_url" msgstr "" #: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:334 -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1089 -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1102 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1094 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1107 msgid "none" msgstr "" @@ -2346,27 +2347,27 @@ msgstr "" msgid "parallel" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1121 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1126 msgid "qq" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1122 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1127 msgid "random" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1123 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1128 msgid "randomized" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1261 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1269 msgid "reject" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1116 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1121 msgid "safari" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:534 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:536 msgid "shadow-TLS SNI" msgstr "" @@ -2374,21 +2375,21 @@ msgstr "" msgid "shadow-tls" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:512 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:514 msgid "shadowTLS protocol Version" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1263 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1271 msgid "skip" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1257 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1265 msgid "" "skip: Not use Mux module to carry UDP 443 traffic, Use original UDP " "transmission method of proxy protocol." msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1080 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1085 msgid "spiderX" msgstr "" @@ -2412,14 +2413,14 @@ msgstr "" msgid "xray-plugin" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1104 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1109 msgid "xtls-rprx-vision" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1238 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1246 msgid "xudpConcurrency" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1252 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1260 msgid "xudpProxyUDP443" msgstr "" diff --git a/small/luci-app-ssr-plus/po/zh_Hans/ssr-plus.po b/small/luci-app-ssr-plus/po/zh_Hans/ssr-plus.po index c43abeb53f..ed1642c5c3 100644 --- a/small/luci-app-ssr-plus/po/zh_Hans/ssr-plus.po +++ b/small/luci-app-ssr-plus/po/zh_Hans/ssr-plus.po @@ -22,7 +22,7 @@ msgstr "单线程" msgid "128 Threads" msgstr "128 线程" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1247 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1255 msgid "16" msgstr "" @@ -38,7 +38,7 @@ msgstr "2 线程" msgid "32 Threads" msgstr "32 线程" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1120 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1125 msgid "360" msgstr "" @@ -58,7 +58,7 @@ msgstr "4 线程" msgid "64 Threads" msgstr "64 线程" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1234 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1242 msgid "8" msgstr "" @@ -70,9 +70,9 @@ msgstr "8 线程" msgid "" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:831 -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1135 -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1162 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:836 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1140 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1167 msgid "" msgstr "" @@ -83,9 +83,9 @@ msgstr "

支持 SS/SSR/V2RAY/XRAY/TROJAN/NAIVEPROXY/SOCKS5/TUN 等协议。 0 then + return alpn + else + return nil + end + end)() or nil, fingerprint = server.fingerprint, allowInsecure = (server.insecure == "1"), serverName = server.tls_host, @@ -580,7 +592,19 @@ local tuic = { timeout = server.timeout and server.timeout .. "s" or nil, gc_interval = server.gc_interval and server.gc_interval .. "s" or nil, gc_lifetime = server.gc_lifetime and server.gc_lifetime .. "s" or nil, - alpn = server.tls_alpn, + alpn = (server.type == "tuic") and (function() + local alpn = {} + if server.tls_alpn and server.tls_alpn ~= "" then + string.gsub(server.tls_alpn, '[^,]+', function(w) + table.insert(alpn, w) + end) + end + if #alpn > 0 then + return alpn + else + return nil + end + end)() or nil, disable_sni = (server.disable_sni == "1") and true or false, zero_rtt_handshake = (server.zero_rtt_handshake == "1") and true or false, send_window = tonumber(server.send_window), diff --git a/small/nikki/files/nikki.upgrade b/small/nikki/files/nikki.upgrade index 1d2a89fb4f..8fb9d1984c 100644 --- a/small/nikki/files/nikki.upgrade +++ b/small/nikki/files/nikki.upgrade @@ -3,5 +3,3 @@ /etc/nikki/mixin.yaml /etc/nikki/run/providers/rule/ /etc/nikki/run/providers/proxy/ -/etc/nikki/nftables/reserved_ip.nft -/etc/nikki/nftables/reserved_ip6.nft diff --git a/small/nikki/files/ucode/hijack.ut b/small/nikki/files/ucode/hijack.ut index dde34d64b5..4dcd4fb9c9 100644 --- a/small/nikki/files/ucode/hijack.ut +++ b/small/nikki/files/ucode/hijack.ut @@ -70,8 +70,8 @@ push(lan_access_control, access_control); }); - const reserved_ip = uci_array(uci.get('momo', 'proxy', 'reserved_ip')); - const reserved_ip6 = uci_array(uci.get('momo', 'proxy', 'reserved_ip6')); + const reserved_ip = uci_array(uci.get('nikki', 'proxy', 'reserved_ip')); + const reserved_ip6 = uci_array(uci.get('nikki', 'proxy', 'reserved_ip6')); const bypass_dscp = uci_array(uci.get('nikki', 'proxy', 'bypass_dscp')); const bypass_china_mainland_ip = uci_bool(uci.get('nikki', 'proxy', 'bypass_china_mainland_ip')); const proxy_tcp_dport = split((uci.get('nikki', 'proxy', 'proxy_tcp_dport') ?? '0-65535'), ' '); diff --git a/small/v2ray-geodata/Makefile b/small/v2ray-geodata/Makefile index 33371c3f79..18577fa5fd 100644 --- a/small/v2ray-geodata/Makefile +++ b/small/v2ray-geodata/Makefile @@ -21,13 +21,13 @@ define Download/geoip HASH:=54761d8691a5756fdb08d2cd4d0a9c889dbaab786e1cf758592e09fb00377f53 endef -GEOSITE_VER:=20250821075639 +GEOSITE_VER:=20250821174337 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:=b35fcc137b86b4db2ef23919a05c7f90267dc4783186b4e416ff10213cc62ff5 + HASH:=751dc96e9becf21e4fb49817c6f8d5fbd62f178868e3421bf40328185caed166 endef GEOSITE_IRAN_VER:=202508180044 diff --git a/yt-dlp/yt_dlp/cookies.py b/yt-dlp/yt_dlp/cookies.py index 459a4b7de0..4fdc0b8de7 100644 --- a/yt-dlp/yt_dlp/cookies.py +++ b/yt-dlp/yt_dlp/cookies.py @@ -125,6 +125,8 @@ def extract_cookies_from_browser(browser_name, profile=None, logger=YDLLogger(), def _extract_firefox_cookies(profile, container, logger): + MAX_SUPPORTED_DB_SCHEMA_VERSION = 16 + logger.info('Extracting cookies from firefox') if not sqlite3: logger.warning('Cannot extract cookies from firefox without sqlite3 support. ' @@ -159,9 +161,11 @@ def _extract_firefox_cookies(profile, container, logger): raise ValueError(f'could not find firefox container "{container}" in containers.json') with tempfile.TemporaryDirectory(prefix='yt_dlp') as tmpdir: - cursor = None - try: - cursor = _open_database_copy(cookie_database_path, tmpdir) + cursor = _open_database_copy(cookie_database_path, tmpdir) + with contextlib.closing(cursor.connection): + db_schema_version = cursor.execute('PRAGMA user_version;').fetchone()[0] + if db_schema_version > MAX_SUPPORTED_DB_SCHEMA_VERSION: + logger.warning(f'Possibly unsupported firefox cookies database version: {db_schema_version}') if isinstance(container_id, int): logger.debug( f'Only loading cookies from firefox container "{container}", ID {container_id}') @@ -180,6 +184,10 @@ def _extract_firefox_cookies(profile, container, logger): total_cookie_count = len(table) for i, (host, name, value, path, expiry, is_secure) in enumerate(table): progress_bar.print(f'Loading cookie {i: 6d}/{total_cookie_count: 6d}') + # FF142 upgraded cookies DB to schema version 16 and started using milliseconds for cookie expiry + # Ref: https://github.com/mozilla-firefox/firefox/commit/5869af852cd20425165837f6c2d9971f3efba83d + if db_schema_version >= 16 and expiry is not None: + expiry /= 1000 cookie = http.cookiejar.Cookie( version=0, name=name, value=value, port=None, port_specified=False, domain=host, domain_specified=bool(host), domain_initial_dot=host.startswith('.'), @@ -188,9 +196,6 @@ def _extract_firefox_cookies(profile, container, logger): jar.set_cookie(cookie) logger.info(f'Extracted {len(jar)} cookies from firefox') return jar - finally: - if cursor is not None: - cursor.connection.close() def _firefox_browser_dirs(): diff --git a/yt-dlp/yt_dlp/extractor/mediaklikk.py b/yt-dlp/yt_dlp/extractor/mediaklikk.py index 197e91d1d9..9a503fa98a 100644 --- a/yt-dlp/yt_dlp/extractor/mediaklikk.py +++ b/yt-dlp/yt_dlp/extractor/mediaklikk.py @@ -11,121 +11,65 @@ from ..utils import ( class MediaKlikkIE(InfoExtractor): _VALID_URL = r'''(?x)https?://(?:www\.)? - (?:mediaklikk|m4sport|hirado|petofilive)\.hu/.*?(?:videok?|cikk)/ + (?:mediaklikk|m4sport|hirado)\.hu/.*?(?:videok?|cikk)/ (?:(?P[0-9]{4})/(?P[0-9]{1,2})/(?P[0-9]{1,2})/)? (?P[^/#?_]+)''' _TESTS = [{ - 'url': 'https://mediaklikk.hu/filmajanlo/cikk/az-ajto/', + # mediaklikk + 'url': 'https://mediaklikk.hu/ajanlo/video/2025/08/04/heviz-dzsungel-a-viz-alatt-ajanlo-08-10/', 'info_dict': { - 'id': '668177', - 'title': 'Az ajtó', - 'display_id': 'az-ajto', + 'id': '8573769', + 'title': 'Hévíz - dzsungel a víz alatt – Ajánló (08.10.)', + 'display_id': 'heviz-dzsungel-a-viz-alatt-ajanlo-08-10', 'ext': 'mp4', - 'thumbnail': 'https://cdn.cms.mtv.hu/wp-content/uploads/sites/4/2016/01/vlcsnap-2023-07-31-14h18m52s111.jpg', + 'upload_date': '20250804', + 'thumbnail': 'https://cdn.cms.mtv.hu/wp-content/uploads/sites/4/2025/08/vlcsnap-2025-08-04-13h48m24s336.jpg', }, }, { - # (old) mediaklikk. date in html. - 'url': 'https://mediaklikk.hu/video/hazajaro-delnyugat-bacska-a-duna-menten-palankatol-doroszloig/', + # mediaklikk - date in html + 'url': 'https://mediaklikk.hu/video/hazajaro-bilo-hegyseg-verocei-barangolas-a-drava-menten/', 'info_dict': { - 'id': '4754129', - 'title': 'Hazajáró, DÉLNYUGAT-BÁCSKA – A Duna mentén Palánkától Doroszlóig', + 'id': '8482167', + 'title': 'Hazajáró, Bilo-hegység - Verőcei barangolás a Dráva mentén', + 'display_id': 'hazajaro-bilo-hegyseg-verocei-barangolas-a-drava-menten', 'ext': 'mp4', - 'upload_date': '20210901', - 'thumbnail': 'http://mediaklikk.hu/wp-content/uploads/sites/4/2014/02/hazajarouj_JO.jpg', + 'upload_date': '20250703', + 'thumbnail': 'https://cdn.cms.mtv.hu/wp-content/uploads/sites/4/2025/07/2024-000307-M0010-01_3700_cover_01.jpg', }, - 'skip': 'Webpage redirects to 404 page', - }, { - # mediaklikk. date in html. - 'url': 'https://mediaklikk.hu/video/hazajaro-fabova-hegyseg-kishont-koronaja/', - 'info_dict': { - 'id': '6696133', - 'title': 'Hazajáró, Fabova-hegység - Kishont koronája', - 'display_id': 'hazajaro-fabova-hegyseg-kishont-koronaja', - 'ext': 'mp4', - 'upload_date': '20230903', - 'thumbnail': 'https://mediaklikk.hu/wp-content/uploads/sites/4/2014/02/hazajarouj_JO.jpg', - }, - 'skip': 'Webpage redirects to 404 page', - }, { - # (old) m4sport - 'url': 'https://m4sport.hu/video/2021/08/30/gyemant-liga-parizs/', - 'info_dict': { - 'id': '4754999', - 'title': 'Gyémánt Liga, Párizs', - 'ext': 'mp4', - 'upload_date': '20210830', - 'thumbnail': 'http://m4sport.hu/wp-content/uploads/sites/4/2021/08/vlcsnap-2021-08-30-18h21m20s10-1024x576.jpg', - }, - 'skip': 'Webpage redirects to 404 page', }, { # m4sport - 'url': 'https://m4sport.hu/sportkozvetitesek/video/2023/09/08/atletika-gyemant-liga-brusszel/', + 'url': 'https://m4sport.hu/video/2025/08/07/holnap-kezdodik-a-12-vilagjatekok/', 'info_dict': { - 'id': '6711136', - 'title': 'Atlétika – Gyémánt Liga, Brüsszel', - 'display_id': 'atletika-gyemant-liga-brusszel', + 'id': '8581887', + 'title': 'Holnap kezdődik a 12. Világjátékok', + 'display_id': 'holnap-kezdodik-a-12-vilagjatekok', 'ext': 'mp4', - 'upload_date': '20230908', - 'thumbnail': 'https://m4sport.hu/wp-content/uploads/sites/4/2023/09/vlcsnap-2023-09-08-22h43m18s691.jpg', + 'upload_date': '20250807', + 'thumbnail': 'https://cdn.cms.mtv.hu/wp-content/uploads/sites/4/2025/08/vlcsnap-2025-08-06-20h30m48s817.jpg', }, - 'skip': 'Webpage redirects to 404 page', - }, { - # m4sport with *video/ url and no date - 'url': 'https://m4sport.hu/bl-video/real-madrid-chelsea-1-1/', - 'info_dict': { - 'id': '4492099', - 'title': 'Real Madrid - Chelsea 1-1', - 'display_id': 'real-madrid-chelsea-1-1', - 'ext': 'mp4', - 'thumbnail': 'https://m4sport.hu/wp-content/uploads/sites/4/2021/04/Sequence-01.Still001-1024x576.png', - }, - 'skip': 'Webpage redirects to 404 page', - }, { - # (old) hirado - 'url': 'https://hirado.hu/videok/felteteleket-szabott-a-fovaros/', - 'info_dict': { - 'id': '4760120', - 'title': 'Feltételeket szabott a főváros', - 'ext': 'mp4', - 'thumbnail': 'http://hirado.hu/wp-content/uploads/sites/4/2021/09/vlcsnap-2021-09-01-20h20m37s165.jpg', - }, - 'skip': 'Webpage redirects to video list page', }, { # hirado - 'url': 'https://hirado.hu/belfold/video/2023/09/11/marad-az-eves-elszamolas-a-napelemekre-beruhazo-csaladoknal', + 'url': 'https://hirado.hu/video/2025/08/09/idojaras-jelentes-2025-augusztus-9-2230', 'info_dict': { - 'id': '6716068', - 'title': 'Marad az éves elszámolás a napelemekre beruházó családoknál', - 'display_id': 'marad-az-eves-elszamolas-a-napelemekre-beruhazo-csaladoknal', + 'id': '8592033', + 'title': 'Időjárás-jelentés, 2025. augusztus 9. 22:30', + 'display_id': 'idojaras-jelentes-2025-augusztus-9-2230', 'ext': 'mp4', - 'upload_date': '20230911', - 'thumbnail': 'https://hirado.hu/wp-content/uploads/sites/4/2023/09/vlcsnap-2023-09-11-09h16m09s882.jpg', + 'upload_date': '20250809', + 'thumbnail': 'https://cdn.cms.mtv.hu/wp-content/uploads/sites/4/2025/08/Idojaras-jelentes-35-1.jpg', }, - 'skip': 'Webpage redirects to video list page', }, { - # (old) petofilive - 'url': 'https://petofilive.hu/video/2021/06/07/tha-shudras-az-akusztikban/', + # hirado - subcategory + 'url': 'https://hirado.hu/belfold/video/2025/08/09/nyitott-porta-napok-2025/', 'info_dict': { - 'id': '4571948', - 'title': 'Tha Shudras az Akusztikban', + 'id': '8590581', + 'title': 'Nyitott Porta Napok 2025', + 'display_id': 'nyitott-porta-napok-2025', 'ext': 'mp4', - 'upload_date': '20210607', - 'thumbnail': 'http://petofilive.hu/wp-content/uploads/sites/4/2021/06/vlcsnap-2021-06-07-22h14m23s915-1024x576.jpg', + 'upload_date': '20250809', + 'thumbnail': 'https://cdn.cms.mtv.hu/wp-content/uploads/sites/4/2025/08/vlcsnap-2025-08-09-10h35m01s887.jpg', }, - 'skip': 'Webpage redirects to empty page', - }, { - # petofilive - 'url': 'https://petofilive.hu/video/2023/09/09/futball-fesztival-a-margitszigeten/', - 'info_dict': { - 'id': '6713233', - 'title': 'Futball Fesztivál a Margitszigeten', - 'display_id': 'futball-fesztival-a-margitszigeten', - 'ext': 'mp4', - 'upload_date': '20230909', - 'thumbnail': 'https://petofilive.hu/wp-content/uploads/sites/4/2023/09/Clipboard11-2.jpg', - }, - 'skip': 'Webpage redirects to video list page', }] def _real_extract(self, url): @@ -133,9 +77,8 @@ class MediaKlikkIE(InfoExtractor): display_id = mobj.group('id') webpage = self._download_webpage(url, display_id) - player_data_str = self._html_search_regex( - r'mtva_player_manager\.player\(document.getElementById\(.*\),\s?(\{.*\}).*\);', webpage, 'player data') - player_data = self._parse_json(player_data_str, display_id, urllib.parse.unquote) + player_data = self._search_json( + r'loadPlayer\((?:\s*["\'][^"\']+["\']\s*,)?', webpage, 'player data', mobj) video_id = str(player_data['contentId']) title = player_data.get('title') or self._og_search_title(webpage, fatal=False) or \ self._html_search_regex(r']+\bclass="article_title">([^<]+)<', webpage, 'title') @@ -146,7 +89,7 @@ class MediaKlikkIE(InfoExtractor): upload_date = unified_strdate(self._html_search_regex( r']+\bclass="article_date">([^<]+)<', webpage, 'upload date', default=None)) - player_data['video'] = player_data.pop('token') + player_data['video'] = urllib.parse.unquote(player_data.pop('token')) player_page = self._download_webpage( 'https://player.mediaklikk.hu/playernew/player.php', video_id, query=player_data, headers={'Referer': url})