Skip to content

Commit e8fddd8

Browse files
committed
fix: vless packetaddr not working
1 parent f04af73 commit e8fddd8

File tree

6 files changed

+72
-111
lines changed

6 files changed

+72
-111
lines changed

adapter/outbound/vless.go

Lines changed: 3 additions & 108 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,10 @@ package outbound
33
import (
44
"context"
55
"crypto/tls"
6-
"encoding/binary"
7-
"errors"
86
"fmt"
9-
"io"
107
"net"
118
"net/http"
129
"strconv"
13-
"sync"
1410

1511
"github.com/metacubex/mihomo/common/convert"
1612
N "github.com/metacubex/mihomo/common/net"
@@ -30,11 +26,6 @@ import (
3026
M "github.com/metacubex/sing/common/metadata"
3127
)
3228

33-
const (
34-
// max packet length
35-
maxLength = 1024 << 3
36-
)
37-
3829
type Vless struct {
3930
*Base
4031
client *vless.Client
@@ -188,9 +179,6 @@ func (v *Vless) streamConnContext(ctx context.Context, c net.Conn, metadata *C.M
188179
}
189180
}
190181
conn, err = v.client.StreamConn(c, parseVlessAddr(metadata, v.option.XUDP))
191-
if v.option.PacketAddr {
192-
conn = packetaddr.NewBindConn(conn)
193-
}
194182
} else {
195183
conn, err = v.client.StreamConn(c, parseVlessAddr(metadata, false))
196184
}
@@ -352,12 +340,11 @@ func (v *Vless) ListenPacketOnStreamConn(ctx context.Context, c net.Conn, metada
352340
), v), nil
353341
} else if v.option.PacketAddr {
354342
return newPacketConn(N.NewThreadSafePacketConn(
355-
packetaddr.NewConn(&vlessPacketConn{
356-
Conn: c, rAddr: metadata.UDPAddr(),
357-
}, M.SocksaddrFromNet(metadata.UDPAddr())),
343+
packetaddr.NewConn(v.client.PacketConn(c, metadata.UDPAddr()),
344+
M.SocksaddrFromNet(metadata.UDPAddr())),
358345
), v), nil
359346
}
360-
return newPacketConn(N.NewThreadSafePacketConn(&vlessPacketConn{Conn: c, rAddr: metadata.UDPAddr()}), v), nil
347+
return newPacketConn(N.NewThreadSafePacketConn(v.client.PacketConn(c, metadata.UDPAddr())), v), nil
361348
}
362349

363350
// SupportUOT implements C.ProxyAdapter
@@ -408,98 +395,6 @@ func parseVlessAddr(metadata *C.Metadata, xudp bool) *vless.DstAddr {
408395
}
409396
}
410397

411-
type vlessPacketConn struct {
412-
net.Conn
413-
rAddr net.Addr
414-
remain int
415-
mux sync.Mutex
416-
cache [2]byte
417-
}
418-
419-
func (c *vlessPacketConn) writePacket(payload []byte) (int, error) {
420-
binary.BigEndian.PutUint16(c.cache[:], uint16(len(payload)))
421-
422-
if _, err := c.Conn.Write(c.cache[:]); err != nil {
423-
return 0, err
424-
}
425-
426-
return c.Conn.Write(payload)
427-
}
428-
429-
func (c *vlessPacketConn) WriteTo(b []byte, addr net.Addr) (int, error) {
430-
total := len(b)
431-
if total == 0 {
432-
return 0, nil
433-
}
434-
435-
if total <= maxLength {
436-
return c.writePacket(b)
437-
}
438-
439-
offset := 0
440-
441-
for offset < total {
442-
cursor := offset + maxLength
443-
if cursor > total {
444-
cursor = total
445-
}
446-
447-
n, err := c.writePacket(b[offset:cursor])
448-
if err != nil {
449-
return offset + n, err
450-
}
451-
452-
offset = cursor
453-
if offset == total {
454-
break
455-
}
456-
}
457-
458-
return total, nil
459-
}
460-
461-
func (c *vlessPacketConn) ReadFrom(b []byte) (int, net.Addr, error) {
462-
c.mux.Lock()
463-
defer c.mux.Unlock()
464-
465-
if c.remain > 0 {
466-
length := len(b)
467-
if c.remain < length {
468-
length = c.remain
469-
}
470-
471-
n, err := c.Conn.Read(b[:length])
472-
if err != nil {
473-
return 0, c.rAddr, err
474-
}
475-
476-
c.remain -= n
477-
return n, c.rAddr, nil
478-
}
479-
480-
if _, err := c.Conn.Read(b[:2]); err != nil {
481-
return 0, c.rAddr, err
482-
}
483-
484-
total := int(binary.BigEndian.Uint16(b[:2]))
485-
if total == 0 {
486-
return 0, c.rAddr, nil
487-
}
488-
489-
length := len(b)
490-
if length > total {
491-
length = total
492-
}
493-
494-
if _, err := io.ReadFull(c.Conn, b[:length]); err != nil {
495-
return 0, c.rAddr, errors.New("read packet error")
496-
}
497-
498-
c.remain = total - length
499-
500-
return length, c.rAddr, nil
501-
}
502-
503398
func NewVless(option VlessOption) (*Vless, error) {
504399
var addons *vless.Addons
505400
if option.Network != "ws" && len(option.Flow) >= 16 {

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ require (
3131
github.com/metacubex/sing-shadowsocks2 v0.2.5
3232
github.com/metacubex/sing-shadowtls v0.0.0-20250503063515-5d9f966d17a2
3333
github.com/metacubex/sing-tun v0.4.7-0.20250721020617-8e7c37ed3d97
34-
github.com/metacubex/sing-vmess v0.2.3
34+
github.com/metacubex/sing-vmess v0.2.4-0.20250731011226-ea28d589924d
3535
github.com/metacubex/sing-wireguard v0.0.0-20250503063753-2dc62acc626f
3636
github.com/metacubex/smux v0.0.0-20250503055512-501391591dee
3737
github.com/metacubex/tfo-go v0.0.0-20250516165257-e29c16ae41d4

go.sum

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -131,8 +131,8 @@ github.com/metacubex/sing-shadowtls v0.0.0-20250503063515-5d9f966d17a2 h1:gXU+MY
131131
github.com/metacubex/sing-shadowtls v0.0.0-20250503063515-5d9f966d17a2/go.mod h1:mbfboaXauKJNIHJYxQRa+NJs4JU9NZfkA+I33dS2+9E=
132132
github.com/metacubex/sing-tun v0.4.7-0.20250721020617-8e7c37ed3d97 h1:YYpc60UZE2G0pUeHbRw9erDrUDZrPQy8QzWFqA3kHsk=
133133
github.com/metacubex/sing-tun v0.4.7-0.20250721020617-8e7c37ed3d97/go.mod h1:2YywXPWW8Z97kTH7RffOeykKzU+l0aiKlglWV1PAS64=
134-
github.com/metacubex/sing-vmess v0.2.3 h1:QKLdIk5A2FcR3Y7m2/JO1XhfzgDA8tF4W9/ffsH9opo=
135-
github.com/metacubex/sing-vmess v0.2.3/go.mod h1:21R5R1u90uUvBQF0owoooEu96/SAYYD56nDrwm6nFaM=
134+
github.com/metacubex/sing-vmess v0.2.4-0.20250731011226-ea28d589924d h1:koSVAQiYqU/qtJ527e+wbsEPvTaM39HW75LSvh04IT0=
135+
github.com/metacubex/sing-vmess v0.2.4-0.20250731011226-ea28d589924d/go.mod h1:21R5R1u90uUvBQF0owoooEu96/SAYYD56nDrwm6nFaM=
136136
github.com/metacubex/sing-wireguard v0.0.0-20250503063753-2dc62acc626f h1:Sr/DYKYofKHKc4GF3qkRGNuj6XA6c0eqPgEDN+VAsYU=
137137
github.com/metacubex/sing-wireguard v0.0.0-20250503063753-2dc62acc626f/go.mod h1:jpAkVLPnCpGSfNyVmj6Cq4YbuZsFepm/Dc+9BAOcR80=
138138
github.com/metacubex/smux v0.0.0-20250503055512-501391591dee h1:lp6hJ+4wCLZu113awp7P6odM2okB5s60HUyF0FMqKmo=

listener/sing/sing.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import (
1616

1717
mux "github.com/metacubex/sing-mux"
1818
vmess "github.com/metacubex/sing-vmess"
19+
"github.com/metacubex/sing-vmess/packetaddr"
1920
"github.com/metacubex/sing/common"
2021
"github.com/metacubex/sing/common/buf"
2122
"github.com/metacubex/sing/common/bufio"
@@ -145,6 +146,10 @@ func (h *ListenerHandler) NewConnection(ctx context.Context, conn net.Conn, meta
145146
}
146147

147148
func (h *ListenerHandler) NewPacketConnection(ctx context.Context, conn network.PacketConn, metadata M.Metadata) error {
149+
if metadata.Destination.Fqdn == packetaddr.SeqPacketMagicAddress {
150+
conn = packetaddr.NewConn(bufio.NewNetPacketConn(conn), M.Socksaddr{})
151+
}
152+
148153
defer func() { _ = conn.Close() }()
149154
mutex := sync.Mutex{}
150155
writer := bufio.NewNetPacketWriter(conn) // a new interface to set nil in defer

transport/vless/packet.go

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
package vless
2+
3+
import (
4+
"encoding/binary"
5+
"io"
6+
"net"
7+
8+
"github.com/metacubex/mihomo/common/pool"
9+
)
10+
11+
type PacketConn struct {
12+
net.Conn
13+
rAddr net.Addr
14+
}
15+
16+
func (c *PacketConn) WriteTo(b []byte, addr net.Addr) (int, error) {
17+
err := binary.Write(c.Conn, binary.BigEndian, uint16(len(b)))
18+
if err != nil {
19+
return 0, err
20+
}
21+
22+
return c.Conn.Write(b)
23+
}
24+
25+
func (c *PacketConn) ReadFrom(b []byte) (int, net.Addr, error) {
26+
var length uint16
27+
err := binary.Read(c.Conn, binary.BigEndian, &length)
28+
if err != nil {
29+
return 0, nil, err
30+
}
31+
if len(b) < int(length) {
32+
return 0, nil, io.ErrShortBuffer
33+
}
34+
n, err := io.ReadFull(c.Conn, b[:length])
35+
return n, c.rAddr, err
36+
}
37+
38+
func (c *PacketConn) WaitReadFrom() (data []byte, put func(), addr net.Addr, err error) {
39+
var length uint16
40+
err = binary.Read(c.Conn, binary.BigEndian, &length)
41+
if err != nil {
42+
return
43+
}
44+
readBuf := pool.Get(int(length))
45+
put = func() {
46+
_ = pool.Put(readBuf)
47+
}
48+
n, err := io.ReadFull(c.Conn, readBuf)
49+
if err != nil {
50+
put()
51+
put = nil
52+
return
53+
}
54+
data = readBuf[:n]
55+
addr = c.rAddr
56+
return
57+
}

transport/vless/vless.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,10 @@ func (c *Client) StreamConn(conn net.Conn, dst *DstAddr) (net.Conn, error) {
5151
return newConn(conn, c, dst)
5252
}
5353

54+
func (c *Client) PacketConn(conn net.Conn, rAddr net.Addr) net.PacketConn {
55+
return &PacketConn{conn, rAddr}
56+
}
57+
5458
// NewClient return Client instance
5559
func NewClient(uuidStr string, addons *Addons) (*Client, error) {
5660
uid, err := utils.UUIDMap(uuidStr)

0 commit comments

Comments
 (0)