From e8fddd85afaf35306e59784fb5de9f49d15fa0cf Mon Sep 17 00:00:00 2001 From: wwqgtxx Date: Thu, 31 Jul 2025 11:34:20 +0800 Subject: [PATCH] fix: vless packetaddr not working --- adapter/outbound/vless.go | 111 ++------------------------------------ go.mod | 2 +- go.sum | 4 +- listener/sing/sing.go | 5 ++ transport/vless/packet.go | 57 ++++++++++++++++++++ transport/vless/vless.go | 4 ++ 6 files changed, 72 insertions(+), 111 deletions(-) create mode 100644 transport/vless/packet.go diff --git a/adapter/outbound/vless.go b/adapter/outbound/vless.go index 9b5c65f9..decc32f1 100644 --- a/adapter/outbound/vless.go +++ b/adapter/outbound/vless.go @@ -3,14 +3,10 @@ package outbound import ( "context" "crypto/tls" - "encoding/binary" - "errors" "fmt" - "io" "net" "net/http" "strconv" - "sync" "github.com/metacubex/mihomo/common/convert" N "github.com/metacubex/mihomo/common/net" @@ -30,11 +26,6 @@ import ( M "github.com/metacubex/sing/common/metadata" ) -const ( - // max packet length - maxLength = 1024 << 3 -) - type Vless struct { *Base client *vless.Client @@ -188,9 +179,6 @@ func (v *Vless) streamConnContext(ctx context.Context, c net.Conn, metadata *C.M } } conn, err = v.client.StreamConn(c, parseVlessAddr(metadata, v.option.XUDP)) - if v.option.PacketAddr { - conn = packetaddr.NewBindConn(conn) - } } else { conn, err = v.client.StreamConn(c, parseVlessAddr(metadata, false)) } @@ -352,12 +340,11 @@ func (v *Vless) ListenPacketOnStreamConn(ctx context.Context, c net.Conn, metada ), v), nil } else if v.option.PacketAddr { return newPacketConn(N.NewThreadSafePacketConn( - packetaddr.NewConn(&vlessPacketConn{ - Conn: c, rAddr: metadata.UDPAddr(), - }, M.SocksaddrFromNet(metadata.UDPAddr())), + packetaddr.NewConn(v.client.PacketConn(c, metadata.UDPAddr()), + M.SocksaddrFromNet(metadata.UDPAddr())), ), v), nil } - return newPacketConn(N.NewThreadSafePacketConn(&vlessPacketConn{Conn: c, rAddr: metadata.UDPAddr()}), v), nil + return newPacketConn(N.NewThreadSafePacketConn(v.client.PacketConn(c, metadata.UDPAddr())), v), nil } // SupportUOT implements C.ProxyAdapter @@ -408,98 +395,6 @@ func parseVlessAddr(metadata *C.Metadata, xudp bool) *vless.DstAddr { } } -type vlessPacketConn struct { - net.Conn - rAddr net.Addr - remain int - mux sync.Mutex - cache [2]byte -} - -func (c *vlessPacketConn) writePacket(payload []byte) (int, error) { - binary.BigEndian.PutUint16(c.cache[:], uint16(len(payload))) - - if _, err := c.Conn.Write(c.cache[:]); err != nil { - return 0, err - } - - return c.Conn.Write(payload) -} - -func (c *vlessPacketConn) WriteTo(b []byte, addr net.Addr) (int, error) { - total := len(b) - if total == 0 { - return 0, nil - } - - if total <= maxLength { - return c.writePacket(b) - } - - offset := 0 - - for offset < total { - cursor := offset + maxLength - if cursor > total { - cursor = total - } - - n, err := c.writePacket(b[offset:cursor]) - if err != nil { - return offset + n, err - } - - offset = cursor - if offset == total { - break - } - } - - return total, nil -} - -func (c *vlessPacketConn) ReadFrom(b []byte) (int, net.Addr, error) { - c.mux.Lock() - defer c.mux.Unlock() - - if c.remain > 0 { - length := len(b) - if c.remain < length { - length = c.remain - } - - n, err := c.Conn.Read(b[:length]) - if err != nil { - return 0, c.rAddr, err - } - - c.remain -= n - return n, c.rAddr, nil - } - - if _, err := c.Conn.Read(b[:2]); err != nil { - return 0, c.rAddr, err - } - - total := int(binary.BigEndian.Uint16(b[:2])) - if total == 0 { - return 0, c.rAddr, nil - } - - length := len(b) - if length > total { - length = total - } - - if _, err := io.ReadFull(c.Conn, b[:length]); err != nil { - return 0, c.rAddr, errors.New("read packet error") - } - - c.remain = total - length - - return length, c.rAddr, nil -} - func NewVless(option VlessOption) (*Vless, error) { var addons *vless.Addons if option.Network != "ws" && len(option.Flow) >= 16 { diff --git a/go.mod b/go.mod index b99d3cd6..31c5d65b 100644 --- a/go.mod +++ b/go.mod @@ -31,7 +31,7 @@ require ( github.com/metacubex/sing-shadowsocks2 v0.2.5 github.com/metacubex/sing-shadowtls v0.0.0-20250503063515-5d9f966d17a2 github.com/metacubex/sing-tun v0.4.7-0.20250721020617-8e7c37ed3d97 - github.com/metacubex/sing-vmess v0.2.3 + github.com/metacubex/sing-vmess v0.2.4-0.20250731011226-ea28d589924d 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/go.sum b/go.sum index 5f9d256a..bdcb81d8 100644 --- a/go.sum +++ b/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-0.20250721020617-8e7c37ed3d97 h1:YYpc60UZE2G0pUeHbRw9erDrUDZrPQy8QzWFqA3kHsk= github.com/metacubex/sing-tun v0.4.7-0.20250721020617-8e7c37ed3d97/go.mod h1:2YywXPWW8Z97kTH7RffOeykKzU+l0aiKlglWV1PAS64= -github.com/metacubex/sing-vmess v0.2.3 h1:QKLdIk5A2FcR3Y7m2/JO1XhfzgDA8tF4W9/ffsH9opo= -github.com/metacubex/sing-vmess v0.2.3/go.mod h1:21R5R1u90uUvBQF0owoooEu96/SAYYD56nDrwm6nFaM= +github.com/metacubex/sing-vmess v0.2.4-0.20250731011226-ea28d589924d h1:koSVAQiYqU/qtJ527e+wbsEPvTaM39HW75LSvh04IT0= +github.com/metacubex/sing-vmess v0.2.4-0.20250731011226-ea28d589924d/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/listener/sing/sing.go b/listener/sing/sing.go index 2742da76..d2108fea 100644 --- a/listener/sing/sing.go +++ b/listener/sing/sing.go @@ -16,6 +16,7 @@ import ( mux "github.com/metacubex/sing-mux" vmess "github.com/metacubex/sing-vmess" + "github.com/metacubex/sing-vmess/packetaddr" "github.com/metacubex/sing/common" "github.com/metacubex/sing/common/buf" "github.com/metacubex/sing/common/bufio" @@ -145,6 +146,10 @@ func (h *ListenerHandler) NewConnection(ctx context.Context, conn net.Conn, meta } func (h *ListenerHandler) NewPacketConnection(ctx context.Context, conn network.PacketConn, metadata M.Metadata) error { + if metadata.Destination.Fqdn == packetaddr.SeqPacketMagicAddress { + conn = packetaddr.NewConn(bufio.NewNetPacketConn(conn), M.Socksaddr{}) + } + defer func() { _ = conn.Close() }() mutex := sync.Mutex{} writer := bufio.NewNetPacketWriter(conn) // a new interface to set nil in defer diff --git a/transport/vless/packet.go b/transport/vless/packet.go new file mode 100644 index 00000000..587e2727 --- /dev/null +++ b/transport/vless/packet.go @@ -0,0 +1,57 @@ +package vless + +import ( + "encoding/binary" + "io" + "net" + + "github.com/metacubex/mihomo/common/pool" +) + +type PacketConn struct { + net.Conn + rAddr net.Addr +} + +func (c *PacketConn) WriteTo(b []byte, addr net.Addr) (int, error) { + err := binary.Write(c.Conn, binary.BigEndian, uint16(len(b))) + if err != nil { + return 0, err + } + + return c.Conn.Write(b) +} + +func (c *PacketConn) ReadFrom(b []byte) (int, net.Addr, error) { + var length uint16 + err := binary.Read(c.Conn, binary.BigEndian, &length) + if err != nil { + return 0, nil, err + } + if len(b) < int(length) { + return 0, nil, io.ErrShortBuffer + } + n, err := io.ReadFull(c.Conn, b[:length]) + return n, c.rAddr, err +} + +func (c *PacketConn) WaitReadFrom() (data []byte, put func(), addr net.Addr, err error) { + var length uint16 + err = binary.Read(c.Conn, binary.BigEndian, &length) + if err != nil { + return + } + readBuf := pool.Get(int(length)) + put = func() { + _ = pool.Put(readBuf) + } + n, err := io.ReadFull(c.Conn, readBuf) + if err != nil { + put() + put = nil + return + } + data = readBuf[:n] + addr = c.rAddr + return +} diff --git a/transport/vless/vless.go b/transport/vless/vless.go index ce07cdb4..9fb54f92 100644 --- a/transport/vless/vless.go +++ b/transport/vless/vless.go @@ -51,6 +51,10 @@ func (c *Client) StreamConn(conn net.Conn, dst *DstAddr) (net.Conn, error) { return newConn(conn, c, dst) } +func (c *Client) PacketConn(conn net.Conn, rAddr net.Addr) net.PacketConn { + return &PacketConn{conn, rAddr} +} + // NewClient return Client instance func NewClient(uuidStr string, addons *Addons) (*Client, error) { uid, err := utils.UUIDMap(uuidStr)