fix: vless packetaddr not working
Some checks failed
Test / test (1.20, macos-13) (push) Has been cancelled
Test / test (1.20, macos-latest) (push) Has been cancelled
Test / test (1.20, ubuntu-24.04-arm) (push) Has been cancelled
Test / test (1.20, ubuntu-latest) (push) Has been cancelled
Test / test (1.20, windows-latest) (push) Has been cancelled
Test / test (1.21, macos-13) (push) Has been cancelled
Test / test (1.21, macos-latest) (push) Has been cancelled
Test / test (1.21, ubuntu-24.04-arm) (push) Has been cancelled
Test / test (1.21, ubuntu-latest) (push) Has been cancelled
Test / test (1.21, windows-latest) (push) Has been cancelled
Test / test (1.22, macos-13) (push) Has been cancelled
Test / test (1.22, macos-latest) (push) Has been cancelled
Test / test (1.22, ubuntu-24.04-arm) (push) Has been cancelled
Test / test (1.22, ubuntu-latest) (push) Has been cancelled
Test / test (1.22, windows-latest) (push) Has been cancelled
Test / test (1.23, macos-13) (push) Has been cancelled
Test / test (1.23, macos-latest) (push) Has been cancelled
Test / test (1.23, ubuntu-24.04-arm) (push) Has been cancelled
Test / test (1.23, ubuntu-latest) (push) Has been cancelled
Test / test (1.23, windows-latest) (push) Has been cancelled
Test / test (1.24, macos-13) (push) Has been cancelled
Test / test (1.24, macos-latest) (push) Has been cancelled
Test / test (1.24, ubuntu-24.04-arm) (push) Has been cancelled
Test / test (1.24, ubuntu-latest) (push) Has been cancelled
Test / test (1.24, windows-latest) (push) Has been cancelled
Trigger CMFA Update / trigger-CMFA-update (push) Has been cancelled

This commit is contained in:
wwqgtxx 2025-07-31 11:34:20 +08:00
parent f04af734e3
commit e8fddd85af
6 changed files with 72 additions and 111 deletions

View File

@ -3,14 +3,10 @@ package outbound
import ( import (
"context" "context"
"crypto/tls" "crypto/tls"
"encoding/binary"
"errors"
"fmt" "fmt"
"io"
"net" "net"
"net/http" "net/http"
"strconv" "strconv"
"sync"
"github.com/metacubex/mihomo/common/convert" "github.com/metacubex/mihomo/common/convert"
N "github.com/metacubex/mihomo/common/net" N "github.com/metacubex/mihomo/common/net"
@ -30,11 +26,6 @@ import (
M "github.com/metacubex/sing/common/metadata" M "github.com/metacubex/sing/common/metadata"
) )
const (
// max packet length
maxLength = 1024 << 3
)
type Vless struct { type Vless struct {
*Base *Base
client *vless.Client 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)) conn, err = v.client.StreamConn(c, parseVlessAddr(metadata, v.option.XUDP))
if v.option.PacketAddr {
conn = packetaddr.NewBindConn(conn)
}
} else { } else {
conn, err = v.client.StreamConn(c, parseVlessAddr(metadata, false)) 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 ), v), nil
} else if v.option.PacketAddr { } else if v.option.PacketAddr {
return newPacketConn(N.NewThreadSafePacketConn( return newPacketConn(N.NewThreadSafePacketConn(
packetaddr.NewConn(&vlessPacketConn{ packetaddr.NewConn(v.client.PacketConn(c, metadata.UDPAddr()),
Conn: c, rAddr: metadata.UDPAddr(), M.SocksaddrFromNet(metadata.UDPAddr())),
}, M.SocksaddrFromNet(metadata.UDPAddr())),
), v), nil ), 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 // 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) { func NewVless(option VlessOption) (*Vless, error) {
var addons *vless.Addons var addons *vless.Addons
if option.Network != "ws" && len(option.Flow) >= 16 { if option.Network != "ws" && len(option.Flow) >= 16 {

2
go.mod
View File

@ -31,7 +31,7 @@ require (
github.com/metacubex/sing-shadowsocks2 v0.2.5 github.com/metacubex/sing-shadowsocks2 v0.2.5
github.com/metacubex/sing-shadowtls v0.0.0-20250503063515-5d9f966d17a2 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-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/sing-wireguard v0.0.0-20250503063753-2dc62acc626f
github.com/metacubex/smux v0.0.0-20250503055512-501391591dee github.com/metacubex/smux v0.0.0-20250503055512-501391591dee
github.com/metacubex/tfo-go v0.0.0-20250516165257-e29c16ae41d4 github.com/metacubex/tfo-go v0.0.0-20250516165257-e29c16ae41d4

4
go.sum
View File

@ -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-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 h1:YYpc60UZE2G0pUeHbRw9erDrUDZrPQy8QzWFqA3kHsk=
github.com/metacubex/sing-tun v0.4.7-0.20250721020617-8e7c37ed3d97/go.mod h1:2YywXPWW8Z97kTH7RffOeykKzU+l0aiKlglWV1PAS64= 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.4-0.20250731011226-ea28d589924d h1:koSVAQiYqU/qtJ527e+wbsEPvTaM39HW75LSvh04IT0=
github.com/metacubex/sing-vmess v0.2.3/go.mod h1:21R5R1u90uUvBQF0owoooEu96/SAYYD56nDrwm6nFaM= 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 h1:Sr/DYKYofKHKc4GF3qkRGNuj6XA6c0eqPgEDN+VAsYU=
github.com/metacubex/sing-wireguard v0.0.0-20250503063753-2dc62acc626f/go.mod h1:jpAkVLPnCpGSfNyVmj6Cq4YbuZsFepm/Dc+9BAOcR80= 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= github.com/metacubex/smux v0.0.0-20250503055512-501391591dee h1:lp6hJ+4wCLZu113awp7P6odM2okB5s60HUyF0FMqKmo=

View File

@ -16,6 +16,7 @@ import (
mux "github.com/metacubex/sing-mux" mux "github.com/metacubex/sing-mux"
vmess "github.com/metacubex/sing-vmess" vmess "github.com/metacubex/sing-vmess"
"github.com/metacubex/sing-vmess/packetaddr"
"github.com/metacubex/sing/common" "github.com/metacubex/sing/common"
"github.com/metacubex/sing/common/buf" "github.com/metacubex/sing/common/buf"
"github.com/metacubex/sing/common/bufio" "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 { 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() }() defer func() { _ = conn.Close() }()
mutex := sync.Mutex{} mutex := sync.Mutex{}
writer := bufio.NewNetPacketWriter(conn) // a new interface to set nil in defer writer := bufio.NewNetPacketWriter(conn) // a new interface to set nil in defer

57
transport/vless/packet.go Normal file
View File

@ -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
}

View File

@ -51,6 +51,10 @@ func (c *Client) StreamConn(conn net.Conn, dst *DstAddr) (net.Conn, error) {
return newConn(conn, c, dst) 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 // NewClient return Client instance
func NewClient(uuidStr string, addons *Addons) (*Client, error) { func NewClient(uuidStr string, addons *Addons) (*Client, error) {
uid, err := utils.UUIDMap(uuidStr) uid, err := utils.UUIDMap(uuidStr)