Hysteria & XHTTP/3 clients: udpHop supports dialerProxy (#6320)

https://github.com/XTLS/Xray-core/pull/6320#issuecomment-4725679616

Fixes https://github.com/XTLS/Xray-core/pull/6320#issuecomment-4699599655

---------

Co-authored-by: LjhAUMEM <llnu14702@gmail.com>
This commit is contained in:
Hossin Asaadi
2026-06-16 22:49:35 +01:00
committed by RPRX
parent 862631172d
commit 829d54d7be
3 changed files with 49 additions and 67 deletions
+23 -27
View File
@@ -126,6 +126,8 @@ func (c *client) dial(ctx context.Context) error {
switch c := conn.(type) {
case *internet.PacketConnWrapper:
pktConn = c.PacketConn
case *cnc.Connection:
pktConn = &internet.FakePacketConn{Conn: c}
default:
panic(reflect.TypeOf(c))
}
@@ -135,36 +137,30 @@ func (c *client) dial(ctx context.Context) error {
var pktConn net.PacketConn
var udpAddr *net.UDPAddr
var index int
if len(quicParams.UdpHop.Ports) > 0 {
index := rand.Intn(len(quicParams.UdpHop.Ports))
index = rand.Intn(len(quicParams.UdpHop.Ports))
c.dest.Port = net.Port(quicParams.UdpHop.Ports[index])
conn, err := internet.DialSystem(ctx, c.dest, c.socketConfig)
if err != nil {
return errors.New("failed to dial to dest").Base(err)
}
switch c := conn.(type) {
case *internet.PacketConnWrapper:
pktConn = c.PacketConn
udpAddr = conn.RemoteAddr().(*net.UDPAddr)
default:
panic(reflect.TypeOf(c))
}
}
raw, err := internet.DialSystem(ctx, c.dest, c.socketConfig)
if err != nil {
return errors.New("failed to dial to dest").Base(err)
}
switch c := raw.(type) {
case *internet.PacketConnWrapper:
pktConn = c.PacketConn
udpAddr = raw.RemoteAddr().(*net.UDPAddr)
case *cnc.Connection:
pktConn = &internet.FakePacketConn{Conn: c}
udpAddr = &net.UDPAddr{IP: c.RemoteAddr().(*net.TCPAddr).IP, Port: c.RemoteAddr().(*net.TCPAddr).Port}
default:
panic(reflect.TypeOf(c))
}
if len(quicParams.UdpHop.Ports) > 0 {
pktConn = udphop.NewUDPHopPacketConn(udphop.ToAddrs(udpAddr.IP, quicParams.UdpHop.Ports), time.Duration(quicParams.UdpHop.IntervalMin)*time.Second, time.Duration(quicParams.UdpHop.IntervalMax)*time.Second, udpHopDialer, pktConn, index)
} else {
conn, err := internet.DialSystem(ctx, c.dest, c.socketConfig)
if err != nil {
return errors.New("failed to dial to dest").Base(err)
}
switch c := conn.(type) {
case *internet.PacketConnWrapper:
pktConn = c.PacketConn
udpAddr = c.RemoteAddr().(*net.UDPAddr)
case *cnc.Connection:
pktConn = &internet.FakePacketConn{Conn: c}
udpAddr = &net.UDPAddr{IP: c.RemoteAddr().(*net.TCPAddr).IP, Port: c.RemoteAddr().(*net.TCPAddr).Port}
default:
panic(reflect.TypeOf(c))
}
}
if c.udpmaskManager != nil {
+3 -13
View File
@@ -5,7 +5,6 @@ import (
"math/rand"
"net"
"sync"
"syscall"
"time"
"github.com/xtls/xray-core/transport/internet/finalmask"
@@ -138,8 +137,8 @@ func (u *UdpHopPacketConn) hop() {
if u.closed {
return
}
u.addrIndex = rand.Intn(len(u.Addrs))
newConn, err := u.ListenUDPFunc(u.Addrs[u.addrIndex].(*net.UDPAddr))
addrIndex := rand.Intn(len(u.Addrs))
newConn, err := u.ListenUDPFunc(u.Addrs[addrIndex].(*net.UDPAddr))
if err != nil {
return
}
@@ -147,6 +146,7 @@ func (u *UdpHopPacketConn) hop() {
_ = u.prevConn.Close()
}
u.prevConn = u.currentConn
u.addrIndex = addrIndex
u.currentConn = newConn
if !u.deadline.IsZero() {
_ = u.currentConn.SetDeadline(u.deadline)
@@ -241,16 +241,6 @@ func (u *UdpHopPacketConn) SetWriteDeadline(t time.Time) error {
return u.currentConn.SetWriteDeadline(t)
}
func (u *UdpHopPacketConn) SyscallConn() (syscall.RawConn, error) {
u.connMutex.RLock()
defer u.connMutex.RUnlock()
sc, ok := u.currentConn.(syscall.Conn)
if !ok {
return nil, errors.New("not supported")
}
return sc.SyscallConn()
}
func ToAddrs(ip net.IP, ports []uint32) []net.Addr {
var addrs []net.Addr
for _, port := range ports {
+23 -27
View File
@@ -209,6 +209,8 @@ func createHTTPClient(dest net.Destination, streamSettings *internet.MemoryStrea
switch c := conn.(type) {
case *internet.PacketConnWrapper:
pktConn = c.PacketConn
case *cnc.Connection:
pktConn = &internet.FakePacketConn{Conn: c}
default:
panic(reflect.TypeOf(c))
}
@@ -218,36 +220,30 @@ func createHTTPClient(dest net.Destination, streamSettings *internet.MemoryStrea
var pktConn net.PacketConn
var udpAddr *net.UDPAddr
var index int
if len(quicParams.UdpHop.Ports) > 0 {
index := rand.Intn(len(quicParams.UdpHop.Ports))
index = rand.Intn(len(quicParams.UdpHop.Ports))
dest.Port = net.Port(quicParams.UdpHop.Ports[index])
conn, err := internet.DialSystem(ctx, dest, streamSettings.SocketSettings)
if err != nil {
return nil, errors.New("failed to dial to dest").Base(err)
}
switch c := conn.(type) {
case *internet.PacketConnWrapper:
pktConn = c.PacketConn
udpAddr = conn.RemoteAddr().(*net.UDPAddr)
default:
panic(reflect.TypeOf(c))
}
}
raw, err := internet.DialSystem(ctx, dest, streamSettings.SocketSettings)
if err != nil {
return nil, errors.New("failed to dial to dest").Base(err)
}
switch c := raw.(type) {
case *internet.PacketConnWrapper:
pktConn = c.PacketConn
udpAddr = raw.RemoteAddr().(*net.UDPAddr)
case *cnc.Connection:
pktConn = &internet.FakePacketConn{Conn: c}
udpAddr = &net.UDPAddr{IP: c.RemoteAddr().(*net.TCPAddr).IP, Port: c.RemoteAddr().(*net.TCPAddr).Port}
default:
panic(reflect.TypeOf(c))
}
if len(quicParams.UdpHop.Ports) > 0 {
pktConn = udphop.NewUDPHopPacketConn(udphop.ToAddrs(udpAddr.IP, quicParams.UdpHop.Ports), time.Duration(quicParams.UdpHop.IntervalMin)*time.Second, time.Duration(quicParams.UdpHop.IntervalMax)*time.Second, udpHopDialer, pktConn, index)
} else {
conn, err := internet.DialSystem(ctx, dest, streamSettings.SocketSettings)
if err != nil {
return nil, errors.New("failed to dial to dest").Base(err)
}
switch c := conn.(type) {
case *internet.PacketConnWrapper:
pktConn = c.PacketConn
udpAddr = c.RemoteAddr().(*net.UDPAddr)
case *cnc.Connection:
pktConn = &internet.FakePacketConn{Conn: c}
udpAddr = &net.UDPAddr{IP: c.RemoteAddr().(*net.TCPAddr).IP, Port: c.RemoteAddr().(*net.TCPAddr).Port}
default:
panic(reflect.TypeOf(c))
}
}
if streamSettings.UdpmaskManager != nil {