From 756a2d1327008190bac1da53a3a9efd094ede46d Mon Sep 17 00:00:00 2001 From: LjhAUMEM Date: Sun, 3 May 2026 15:18:23 +0800 Subject: [PATCH] Hysteria client: Fix `sendThrough` (#6063) And fixes https://github.com/XTLS/Xray-core/issues/6046 --- transport/internet/config.pb.go | 22 +----- transport/internet/config.proto | 4 - transport/internet/hysteria/dialer.go | 90 +++++++++++----------- transport/internet/hysteria/udphop/conn.go | 13 +--- transport/internet/kcp/dialer.go | 6 +- transport/internet/sockopt_darwin.go | 26 ------- transport/internet/sockopt_freebsd.go | 26 ------- transport/internet/sockopt_linux.go | 27 ------- transport/internet/sockopt_other.go | 4 - transport/internet/sockopt_windows.go | 4 - transport/internet/splithttp/dialer.go | 40 +++++----- transport/internet/splithttp/hub.go | 18 ++--- transport/internet/system_dialer.go | 25 +----- transport/internet/udp/dialer.go | 6 +- 14 files changed, 87 insertions(+), 224 deletions(-) diff --git a/transport/internet/config.pb.go b/transport/internet/config.pb.go index e2339fe8..ee696b43 100644 --- a/transport/internet/config.pb.go +++ b/transport/internet/config.pb.go @@ -730,8 +730,6 @@ type SocketConfig struct { // ReceiveOriginalDestAddress is for enabling IP_RECVORIGDSTADDR socket // option. This option is for UDP only. ReceiveOriginalDestAddress bool `protobuf:"varint,4,opt,name=receive_original_dest_address,json=receiveOriginalDestAddress,proto3" json:"receive_original_dest_address,omitempty"` - BindAddress []byte `protobuf:"bytes,5,opt,name=bind_address,json=bindAddress,proto3" json:"bind_address,omitempty"` - BindPort uint32 `protobuf:"varint,6,opt,name=bind_port,json=bindPort,proto3" json:"bind_port,omitempty"` AcceptProxyProtocol bool `protobuf:"varint,7,opt,name=accept_proxy_protocol,json=acceptProxyProtocol,proto3" json:"accept_proxy_protocol,omitempty"` DomainStrategy DomainStrategy `protobuf:"varint,8,opt,name=domain_strategy,json=domainStrategy,proto3,enum=xray.transport.internet.DomainStrategy" json:"domain_strategy,omitempty"` DialerProxy string `protobuf:"bytes,9,opt,name=dialer_proxy,json=dialerProxy,proto3" json:"dialer_proxy,omitempty"` @@ -811,20 +809,6 @@ func (x *SocketConfig) GetReceiveOriginalDestAddress() bool { return false } -func (x *SocketConfig) GetBindAddress() []byte { - if x != nil { - return x.BindAddress - } - return nil -} - -func (x *SocketConfig) GetBindPort() uint32 { - if x != nil { - return x.BindPort - } - return 0 -} - func (x *SocketConfig) GetAcceptProxyProtocol() bool { if x != nil { return x.AcceptProxyProtocol @@ -1066,14 +1050,12 @@ const file_transport_internet_config_proto_rawDesc = "" + "\x05level\x18\x03 \x01(\tR\x05level\x12\x10\n" + "\x03opt\x18\x04 \x01(\tR\x03opt\x12\x14\n" + "\x05value\x18\x05 \x01(\tR\x05value\x12\x12\n" + - "\x04type\x18\x06 \x01(\tR\x04type\"\x89\t\n" + + "\x04type\x18\x06 \x01(\tR\x04type\"\xc9\b\n" + "\fSocketConfig\x12\x12\n" + "\x04mark\x18\x01 \x01(\x05R\x04mark\x12\x10\n" + "\x03tfo\x18\x02 \x01(\x05R\x03tfo\x12H\n" + "\x06tproxy\x18\x03 \x01(\x0e20.xray.transport.internet.SocketConfig.TProxyModeR\x06tproxy\x12A\n" + - "\x1dreceive_original_dest_address\x18\x04 \x01(\bR\x1areceiveOriginalDestAddress\x12!\n" + - "\fbind_address\x18\x05 \x01(\fR\vbindAddress\x12\x1b\n" + - "\tbind_port\x18\x06 \x01(\rR\bbindPort\x122\n" + + "\x1dreceive_original_dest_address\x18\x04 \x01(\bR\x1areceiveOriginalDestAddress\x122\n" + "\x15accept_proxy_protocol\x18\a \x01(\bR\x13acceptProxyProtocol\x12P\n" + "\x0fdomain_strategy\x18\b \x01(\x0e2'.xray.transport.internet.DomainStrategyR\x0edomainStrategy\x12!\n" + "\fdialer_proxy\x18\t \x01(\tR\vdialerProxy\x125\n" + diff --git a/transport/internet/config.proto b/transport/internet/config.proto index ad23f047..c139111a 100644 --- a/transport/internet/config.proto +++ b/transport/internet/config.proto @@ -124,10 +124,6 @@ message SocketConfig { // option. This option is for UDP only. bool receive_original_dest_address = 4; - bytes bind_address = 5; - - uint32 bind_port = 6; - bool accept_proxy_protocol = 7; DomainStrategy domain_strategy = 8; diff --git a/transport/internet/hysteria/dialer.go b/transport/internet/hysteria/dialer.go index 408550a1..dfaac92f 100644 --- a/transport/internet/hysteria/dialer.go +++ b/transport/internet/hysteria/dialer.go @@ -3,6 +3,7 @@ package hysteria import ( "context" go_tls "crypto/tls" + "math/rand" "net/http" "net/url" "reflect" @@ -64,7 +65,7 @@ func (c *client) close() { c.udpSM = nil } -func (c *client) dial() error { +func (c *client) dial(ctx context.Context) error { status := c.status() if status == StatusActive { return nil @@ -113,30 +114,54 @@ func (c *client) dial() error { // quicConfig.KeepAlivePeriod = 10 * time.Second // } + udpHopDialer := func(addr *net.UDPAddr) (net.PacketConn, error) { + conn, err := internet.DialSystem(ctx, net.UDPDestination(net.IPAddress(addr.IP), net.Port(addr.Port)), c.socketConfig) + if err != nil { + errors.LogInfoInner(context.Background(), err, "skip hop: failed to dial to dest") + return nil, errors.New("") + } + + var pktConn net.PacketConn + + switch c := conn.(type) { + case *internet.PacketConnWrapper: + pktConn = c.PacketConn + default: + panic(reflect.TypeOf(c)) + } + + return pktConn, nil + } + var pktConn net.PacketConn var udpAddr *net.UDPAddr - var err error - udpAddr, err = net.ResolveUDPAddr("udp", c.dest.NetAddr()) - if err != nil { - return err - } if len(quicParams.UdpHop.Ports) > 0 { - pktConn, err = udphop.NewUDPHopPacketConn(udphop.ToAddrs(udpAddr.IP, quicParams.UdpHop.Ports), time.Duration(quicParams.UdpHop.IntervalMin)*time.Second, time.Duration(quicParams.UdpHop.IntervalMax)*time.Second, c.udpHopDialer) + 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 err - } - } else { - conn, err := internet.DialSystem(context.Background(), c.dest, c.socketConfig) - if err != nil { - return err + return errors.New("failed to dial to dest").Base(err) } switch c := conn.(type) { case *internet.PacketConnWrapper: pktConn = c.PacketConn - case *net.UDPConn: - pktConn = c + udpAddr = conn.RemoteAddr().(*net.UDPAddr) + default: + panic(reflect.TypeOf(c)) + } + 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)) } @@ -228,11 +253,11 @@ func (c *client) dial() error { return nil } -func (c *client) tcp() (stat.Connection, error) { +func (c *client) tcp(ctx context.Context) (stat.Connection, error) { c.Lock() defer c.Unlock() - err := c.dial() + err := c.dial(ctx) if err != nil { return nil, err } @@ -251,11 +276,11 @@ func (c *client) tcp() (stat.Connection, error) { }, nil } -func (c *client) udp() (stat.Connection, error) { +func (c *client) udp(ctx context.Context) (stat.Connection, error) { c.Lock() defer c.Unlock() - err := c.dial() + err := c.dial(ctx) if err != nil { return nil, err } @@ -271,29 +296,6 @@ func (c *client) clean() { c.Unlock() } -func (c *client) udpHopDialer(addr *net.UDPAddr) (net.PacketConn, error) { - conn, err := internet.DialSystem(context.Background(), net.UDPDestination(net.IPAddress(addr.IP), net.Port(addr.Port)), c.socketConfig) - if err != nil { - errors.LogInfoInner(context.Background(), err, "skip hop: failed to dial to dest") - return nil, errors.New("failed to dial to dest").Base(err) - } - - var pktConn net.PacketConn - - switch c := conn.(type) { - case *internet.PacketConnWrapper: - pktConn = c.PacketConn - case *net.UDPConn: - pktConn = c - default: - errors.LogInfo(context.Background(), "skip hop: invalid conn ", reflect.TypeOf(c)) - conn.Close() - return nil, errors.New("invalid conn ", reflect.TypeOf(c)) - } - - return pktConn, nil -} - type dialerConf struct { net.Destination *internet.MemoryStreamConfig @@ -356,9 +358,9 @@ func Dial(ctx context.Context, dest net.Destination, streamSettings *internet.Me } if datagram { - return c.udp() + return c.udp(ctx) } - return c.tcp() + return c.tcp(ctx) } func init() { diff --git a/transport/internet/hysteria/udphop/conn.go b/transport/internet/hysteria/udphop/conn.go index e60755f9..83a45a20 100644 --- a/transport/internet/hysteria/udphop/conn.go +++ b/transport/internet/hysteria/udphop/conn.go @@ -47,7 +47,7 @@ type udpPacket struct { Err error } -func NewUDPHopPacketConn(addrs []net.Addr, hopIntervalMin time.Duration, hopIntervalMax time.Duration, listenUDPFunc func(addr *net.UDPAddr) (net.PacketConn, error)) (net.PacketConn, error) { +func NewUDPHopPacketConn(addrs []net.Addr, hopIntervalMin time.Duration, hopIntervalMax time.Duration, listenUDPFunc func(addr *net.UDPAddr) (net.PacketConn, error), currentConn net.PacketConn, addrIndex int) net.PacketConn { if len(addrs) == 0 { panic("len(addrs) == 0") } @@ -75,8 +75,8 @@ func NewUDPHopPacketConn(addrs []net.Addr, hopIntervalMin time.Duration, hopInte HopIntervalMax: hopIntervalMax, ListenUDPFunc: listenUDPFunc, prevConn: nil, - currentConn: nil, - addrIndex: rand.Intn(len(addrs)), + currentConn: currentConn, + addrIndex: addrIndex, recvQueue: make(chan *udpPacket, packetQueueSize), closeChan: make(chan struct{}), bufPool: sync.Pool{ @@ -85,14 +85,9 @@ func NewUDPHopPacketConn(addrs []net.Addr, hopIntervalMin time.Duration, hopInte }, }, } - var err error - hConn.currentConn, err = listenUDPFunc(hConn.Addrs[hConn.addrIndex].(*net.UDPAddr)) - if err != nil { - return nil, err - } go hConn.recvLoop(hConn.currentConn) go hConn.hopLoop() - return hConn, nil + return hConn } func (u *UdpHopPacketConn) recvLoop(conn net.PacketConn) { diff --git a/transport/internet/kcp/dialer.go b/transport/internet/kcp/dialer.go index 3690f9e0..175998ec 100644 --- a/transport/internet/kcp/dialer.go +++ b/transport/internet/kcp/dialer.go @@ -58,14 +58,14 @@ func DialKCP(ctx context.Context, dest net.Destination, streamSettings *internet if streamSettings.UdpmaskManager != nil { var pktConn net.PacketConn - var udpAddr = conn.RemoteAddr().(*net.UDPAddr) + var udpAddr *net.UDPAddr switch c := conn.(type) { case *internet.PacketConnWrapper: pktConn = c.PacketConn - case *net.UDPConn: - pktConn = c + 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)) } diff --git a/transport/internet/sockopt_darwin.go b/transport/internet/sockopt_darwin.go index bcae2f3f..46995711 100644 --- a/transport/internet/sockopt_darwin.go +++ b/transport/internet/sockopt_darwin.go @@ -288,32 +288,6 @@ func applyInboundSocketOptions(network string, fd uintptr, config *SocketConfig) return nil } -func bindAddr(fd uintptr, address []byte, port uint32) error { - setReuseAddr(fd) - setReusePort(fd) - - var sockaddr unix.Sockaddr - - switch len(address) { - case net.IPv4len: - a4 := &unix.SockaddrInet4{ - Port: int(port), - } - copy(a4.Addr[:], address) - sockaddr = a4 - case net.IPv6len: - a6 := &unix.SockaddrInet6{ - Port: int(port), - } - copy(a6.Addr[:], address) - sockaddr = a6 - default: - return errors.New("unexpected length of ip") - } - - return unix.Bind(int(fd), sockaddr) -} - func setReuseAddr(fd uintptr) error { if err := unix.SetsockoptInt(int(fd), unix.SOL_SOCKET, unix.SO_REUSEADDR, 1); err != nil { return errors.New("failed to set SO_REUSEADDR").Base(err).AtWarning() diff --git a/transport/internet/sockopt_freebsd.go b/transport/internet/sockopt_freebsd.go index 4d490a40..635c25da 100644 --- a/transport/internet/sockopt_freebsd.go +++ b/transport/internet/sockopt_freebsd.go @@ -222,32 +222,6 @@ func applyInboundSocketOptions(network string, fd uintptr, config *SocketConfig) return nil } -func bindAddr(fd uintptr, ip []byte, port uint32) error { - setReuseAddr(fd) - setReusePort(fd) - - var sockaddr syscall.Sockaddr - - switch len(ip) { - case net.IPv4len: - a4 := &syscall.SockaddrInet4{ - Port: int(port), - } - copy(a4.Addr[:], ip) - sockaddr = a4 - case net.IPv6len: - a6 := &syscall.SockaddrInet6{ - Port: int(port), - } - copy(a6.Addr[:], ip) - sockaddr = a6 - default: - return errors.New("unexpected length of ip") - } - - return syscall.Bind(int(fd), sockaddr) -} - func setReuseAddr(fd uintptr) error { if err := syscall.SetsockoptInt(int(fd), syscall.SOL_SOCKET, syscall.SO_REUSEADDR, 1); err != nil { return errors.New("failed to set SO_REUSEADDR").Base(err).AtWarning() diff --git a/transport/internet/sockopt_linux.go b/transport/internet/sockopt_linux.go index 9a305a40..f1fb3f81 100644 --- a/transport/internet/sockopt_linux.go +++ b/transport/internet/sockopt_linux.go @@ -2,7 +2,6 @@ package internet import ( "context" - "net" "runtime" "strconv" "strings" @@ -12,32 +11,6 @@ import ( "golang.org/x/sys/unix" ) -func bindAddr(fd uintptr, ip []byte, port uint32) error { - setReuseAddr(fd) - setReusePort(fd) - - var sockaddr syscall.Sockaddr - - switch len(ip) { - case net.IPv4len: - a4 := &syscall.SockaddrInet4{ - Port: int(port), - } - copy(a4.Addr[:], ip) - sockaddr = a4 - case net.IPv6len: - a6 := &syscall.SockaddrInet6{ - Port: int(port), - } - copy(a6.Addr[:], ip) - sockaddr = a6 - default: - return errors.New("unexpected length of ip") - } - - return syscall.Bind(int(fd), sockaddr) -} - // applyOutboundSocketOptions applies socket options for outbound connection. // note that unlike other part of Xray, this function needs network with speified network stack(tcp4/tcp6/udp4/udp6) func applyOutboundSocketOptions(network string, address string, fd uintptr, config *SocketConfig) error { diff --git a/transport/internet/sockopt_other.go b/transport/internet/sockopt_other.go index 7e91110e..9cce3df2 100644 --- a/transport/internet/sockopt_other.go +++ b/transport/internet/sockopt_other.go @@ -11,10 +11,6 @@ func applyInboundSocketOptions(network string, fd uintptr, config *SocketConfig) return nil } -func bindAddr(fd uintptr, ip []byte, port uint32) error { - return nil -} - func setReuseAddr(fd uintptr) error { return nil } diff --git a/transport/internet/sockopt_windows.go b/transport/internet/sockopt_windows.go index 1389ca06..3555b399 100644 --- a/transport/internet/sockopt_windows.go +++ b/transport/internet/sockopt_windows.go @@ -181,10 +181,6 @@ func applyInboundSocketOptions(network string, fd uintptr, config *SocketConfig) return nil } -func bindAddr(fd uintptr, ip []byte, port uint32) error { - return nil -} - func setReuseAddr(fd uintptr) error { return nil } diff --git a/transport/internet/splithttp/dialer.go b/transport/internet/splithttp/dialer.go index e85bd7b3..f89c71ed 100644 --- a/transport/internet/splithttp/dialer.go +++ b/transport/internet/splithttp/dialer.go @@ -5,6 +5,7 @@ import ( gotls "crypto/tls" "fmt" "io" + "math/rand" "net/http" "net/http/httptrace" "net/url" @@ -199,7 +200,7 @@ func createHTTPClient(dest net.Destination, streamSettings *internet.MemoryStrea conn, err := internet.DialSystem(ctx, net.UDPDestination(net.IPAddress(addr.IP), net.Port(addr.Port)), streamSettings.SocketSettings) if err != nil { errors.LogInfoInner(context.Background(), err, "skip hop: failed to dial to dest") - return nil, errors.New("failed to dial to dest").Base(err) + return nil, errors.New("") } var pktConn net.PacketConn @@ -207,12 +208,8 @@ func createHTTPClient(dest net.Destination, streamSettings *internet.MemoryStrea switch c := conn.(type) { case *internet.PacketConnWrapper: pktConn = c.PacketConn - case *net.UDPConn: - pktConn = c default: - errors.LogInfo(context.Background(), "skip hop: invalid conn ", reflect.TypeOf(c)) - conn.Close() - return nil, errors.New("invalid conn ", reflect.TypeOf(c)) + panic(reflect.TypeOf(c)) } return pktConn, nil @@ -220,28 +217,33 @@ func createHTTPClient(dest net.Destination, streamSettings *internet.MemoryStrea var pktConn net.PacketConn var udpAddr *net.UDPAddr - var err error - udpAddr, err = net.ResolveUDPAddr("udp", dest.NetAddr()) - if err != nil { - return nil, err - } if len(quicParams.UdpHop.Ports) > 0 { - pktConn, err = udphop.NewUDPHopPacketConn(udphop.ToAddrs(udpAddr.IP, quicParams.UdpHop.Ports), time.Duration(quicParams.UdpHop.IntervalMin)*time.Second, time.Duration(quicParams.UdpHop.IntervalMax)*time.Second, udpHopDialer) - if err != nil { - return nil, err - } - } else { + 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, err + return nil, errors.New("failed to dial to dest").Base(err) } switch c := conn.(type) { case *internet.PacketConnWrapper: pktConn = c.PacketConn - case *net.UDPConn: - pktConn = c + udpAddr = conn.RemoteAddr().(*net.UDPAddr) + default: + panic(reflect.TypeOf(c)) + } + 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)) } diff --git a/transport/internet/splithttp/hub.go b/transport/internet/splithttp/hub.go index 10b6005e..9744a985 100644 --- a/transport/internet/splithttp/hub.go +++ b/transport/internet/splithttp/hub.go @@ -441,7 +441,7 @@ type Listener struct { server http.Server h3server *http3.Server listener net.Listener - h3listener Qface + h3listener http3.QUICListener config *Config addConn internet.ConnHandler isH3 bool @@ -519,8 +519,8 @@ func ListenXH(ctx context.Context, address net.Address, port net.Port, streamSet return nil, errors.New("failed to listen QUIC for XHTTP/3 on ", address, ":", port).Base(err) } l.h3listener = &QListener{ - Qface: l.h3listener, - quicParams: quicParams, + QUICListener: l.h3listener, + quicParams: quicParams, } errors.LogInfo(ctx, "listening QUIC for XHTTP/3 on ", address, ":", port) @@ -615,21 +615,13 @@ func init() { common.Must(internet.RegisterTransportListener(protocolName, ListenXH)) } -type Qface interface { - Accept(ctx context.Context) (*quic.Conn, error) - Addr() net.Addr - Close() error -} - -var _ Qface = (*quic.EarlyListener)(nil) - type QListener struct { - Qface + http3.QUICListener quicParams *internet.QuicParams } func (l *QListener) Accept(ctx context.Context) (*quic.Conn, error) { - conn, err := l.Qface.Accept(ctx) + conn, err := l.QUICListener.Accept(ctx) if err != nil { return nil, err } diff --git a/transport/internet/system_dialer.go b/transport/internet/system_dialer.go index 41c832dc..35dc55fa 100644 --- a/transport/internet/system_dialer.go +++ b/transport/internet/system_dialer.go @@ -44,14 +44,10 @@ func resolveSrcAddr(network net.Network, src net.Address) net.Addr { } } -func hasBindAddr(sockopt *SocketConfig) bool { - return sockopt != nil && len(sockopt.BindAddress) > 0 && sockopt.BindPort > 0 -} - func (d *DefaultSystemDialer) Dial(ctx context.Context, src net.Address, dest net.Destination, sockopt *SocketConfig) (net.Conn, error) { errors.LogDebug(ctx, "dialing to "+dest.String()) - if dest.Network == net.Network_UDP && !hasBindAddr(sockopt) { + if dest.Network == net.Network_UDP { srcAddr := resolveSrcAddr(net.Network_UDP, src) if srcAddr == nil { srcAddr = &net.UDPAddr{ @@ -132,11 +128,6 @@ func (d *DefaultSystemDialer) Dial(ctx context.Context, src net.Address, dest ne if err := applyOutboundSocketOptions(network, address, fd, sockopt); err != nil { errors.LogInfoInner(ctx, err, "failed to apply socket options") } - if dest.Network == net.Network_UDP && hasBindAddr(sockopt) { - if err := bindAddr(fd, sockopt.BindAddress, sockopt.BindPort); err != nil { - errors.LogInfoInner(ctx, err, "failed to bind source address to ", sockopt.BindAddress) - } - } } }) } @@ -228,7 +219,7 @@ type FakePacketConn struct { func (c *FakePacketConn) ReadFrom(p []byte) (n int, addr net.Addr, err error) { n, err = c.Read(p) - return n, c.RemoteAddr(), err + return n, &net.UDPAddr{IP: c.Conn.RemoteAddr().(*net.TCPAddr).IP, Port: c.Conn.RemoteAddr().(*net.TCPAddr).Port}, err } func (c *FakePacketConn) WriteTo(p []byte, _ net.Addr) (n int, err error) { @@ -236,15 +227,5 @@ func (c *FakePacketConn) WriteTo(p []byte, _ net.Addr) (n int, err error) { } func (c *FakePacketConn) LocalAddr() net.Addr { - return &net.UDPAddr{ - IP: []byte{0, 0, 0, 0}, - Port: 0, - } -} - -func (c *FakePacketConn) RemoteAddr() net.Addr { - return &net.UDPAddr{ - IP: []byte{0, 0, 0, 0}, - Port: 0, - } + return &net.UDPAddr{IP: c.Conn.LocalAddr().(*net.TCPAddr).IP, Port: c.Conn.LocalAddr().(*net.TCPAddr).Port} } diff --git a/transport/internet/udp/dialer.go b/transport/internet/udp/dialer.go index 79649ed7..a81d2223 100644 --- a/transport/internet/udp/dialer.go +++ b/transport/internet/udp/dialer.go @@ -26,14 +26,14 @@ func init() { if streamSettings != nil && streamSettings.UdpmaskManager != nil { var pktConn net.PacketConn - var udpAddr = conn.RemoteAddr().(*net.UDPAddr) + var udpAddr *net.UDPAddr switch c := conn.(type) { case *internet.PacketConnWrapper: pktConn = c.PacketConn - case *net.UDPConn: - pktConn = c + 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)) }