From 1b5a576d9671e06b2c3de123aa3c10f4ca923d2a Mon Sep 17 00:00:00 2001 From: null Date: Wed, 14 Jan 2026 14:38:01 +0800 Subject: [PATCH 1/4] fix --- transport/internet/hysteria/dialer.go | 28 ++++++++++++++++++--------- 1 file changed, 19 insertions(+), 9 deletions(-) diff --git a/transport/internet/hysteria/dialer.go b/transport/internet/hysteria/dialer.go index 5a694aa4236b..4cbb862d941d 100644 --- a/transport/internet/hysteria/dialer.go +++ b/transport/internet/hysteria/dialer.go @@ -163,10 +163,15 @@ func (c *client) dial() error { remote := raw.RemoteAddr() - pktConn, ok := raw.(net.PacketConn) - if !ok { - raw.Close() - return errors.New("raw is not PacketConn") + var pktConn net.PacketConn + if conn, ok := raw.(*internet.PacketConnWrapper); ok { + pktConn = conn.Conn + } else { + pktConn, ok = raw.(net.PacketConn) + if !ok { + raw.Close() + return errors.New("raw is not PacketConn") + } } if len(c.config.Ports) > 0 { @@ -331,11 +336,16 @@ func (c *client) udphopDialer(addr *net.UDPAddr) (net.PacketConn, error) { return nil, errors.New() } - pktConn, ok := raw.(net.PacketConn) - if !ok { - errors.LogDebug(c.ctx, "raw is not PacketConn skip hop") - raw.Close() - return nil, errors.New() + var pktConn net.PacketConn + if conn, ok := raw.(*internet.PacketConnWrapper); ok { + pktConn = conn.Conn + } else { + pktConn, ok = raw.(net.PacketConn) + if !ok { + errors.LogDebug(c.ctx, "raw is not PacketConn skip hop") + raw.Close() + return nil, errors.New() + } } return pktConn, nil From f97c4626933ec5eee98642b4b04caaa14e3c791c Mon Sep 17 00:00:00 2001 From: null Date: Wed, 14 Jan 2026 14:56:00 +0800 Subject: [PATCH 2/4] fix 2 --- transport/internet/hysteria/dialer.go | 28 +++++++--------------- transport/internet/hysteria/udphop/conn.go | 19 +++++++-------- 2 files changed, 18 insertions(+), 29 deletions(-) diff --git a/transport/internet/hysteria/dialer.go b/transport/internet/hysteria/dialer.go index 4cbb862d941d..5a694aa4236b 100644 --- a/transport/internet/hysteria/dialer.go +++ b/transport/internet/hysteria/dialer.go @@ -163,15 +163,10 @@ func (c *client) dial() error { remote := raw.RemoteAddr() - var pktConn net.PacketConn - if conn, ok := raw.(*internet.PacketConnWrapper); ok { - pktConn = conn.Conn - } else { - pktConn, ok = raw.(net.PacketConn) - if !ok { - raw.Close() - return errors.New("raw is not PacketConn") - } + pktConn, ok := raw.(net.PacketConn) + if !ok { + raw.Close() + return errors.New("raw is not PacketConn") } if len(c.config.Ports) > 0 { @@ -336,16 +331,11 @@ func (c *client) udphopDialer(addr *net.UDPAddr) (net.PacketConn, error) { return nil, errors.New() } - var pktConn net.PacketConn - if conn, ok := raw.(*internet.PacketConnWrapper); ok { - pktConn = conn.Conn - } else { - pktConn, ok = raw.(net.PacketConn) - if !ok { - errors.LogDebug(c.ctx, "raw is not PacketConn skip hop") - raw.Close() - return nil, errors.New() - } + pktConn, ok := raw.(net.PacketConn) + if !ok { + errors.LogDebug(c.ctx, "raw is not PacketConn skip hop") + raw.Close() + return nil, errors.New() } return pktConn, nil diff --git a/transport/internet/hysteria/udphop/conn.go b/transport/internet/hysteria/udphop/conn.go index 5615ec5b8942..e8485e4d0b00 100644 --- a/transport/internet/hysteria/udphop/conn.go +++ b/transport/internet/hysteria/udphop/conn.go @@ -5,7 +5,6 @@ import ( "math/rand" "net" "sync" - "syscall" "time" ) @@ -266,15 +265,15 @@ func (u *udpHopPacketConn) SetWriteBuffer(bytes int) error { return trySetWriteBuffer(u.currentConn, bytes) } -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 (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 trySetReadBuffer(pc net.PacketConn, bytes int) error { sc, ok := pc.(interface { From c91c8349ca283b8e630320bea3dc18421be90893 Mon Sep 17 00:00:00 2001 From: null Date: Wed, 14 Jan 2026 15:08:28 +0800 Subject: [PATCH 3/4] fix 3 --- transport/internet/hysteria/udphop/conn.go | 19 ++++++++++--------- transport/internet/system_dialer.go | 8 ++++++++ 2 files changed, 18 insertions(+), 9 deletions(-) diff --git a/transport/internet/hysteria/udphop/conn.go b/transport/internet/hysteria/udphop/conn.go index e8485e4d0b00..5615ec5b8942 100644 --- a/transport/internet/hysteria/udphop/conn.go +++ b/transport/internet/hysteria/udphop/conn.go @@ -5,6 +5,7 @@ import ( "math/rand" "net" "sync" + "syscall" "time" ) @@ -265,15 +266,15 @@ func (u *udpHopPacketConn) SetWriteBuffer(bytes int) error { return trySetWriteBuffer(u.currentConn, bytes) } -// 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 (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 trySetReadBuffer(pc net.PacketConn, bytes int) error { sc, ok := pc.(interface { diff --git a/transport/internet/system_dialer.go b/transport/internet/system_dialer.go index 27f3c9a9274d..015675762eec 100644 --- a/transport/internet/system_dialer.go +++ b/transport/internet/system_dialer.go @@ -195,6 +195,14 @@ func (c *PacketConnWrapper) SetWriteDeadline(t time.Time) error { return c.Conn.SetWriteDeadline(t) } +func (c *PacketConnWrapper) SyscallConn() (syscall.RawConn, error) { + sc, ok := c.Conn.(syscall.Conn) + if !ok { + return nil, syscall.EINVAL + } + return sc.SyscallConn() +} + type SystemDialerAdapter interface { Dial(network string, address string) (net.Conn, error) } From 6df8f5fee5ad69c4e92081b597bef458876e635e Mon Sep 17 00:00:00 2001 From: null Date: Wed, 14 Jan 2026 17:40:31 +0800 Subject: [PATCH 4/4] version 2 --- infra/conf/hysteria.go | 8 +++++++- infra/conf/transport_internet.go | 2 +- proxy/hysteria/config.pb.go | 17 +++++++++++++---- proxy/hysteria/config.proto | 3 ++- 4 files changed, 23 insertions(+), 7 deletions(-) diff --git a/infra/conf/hysteria.go b/infra/conf/hysteria.go index 6512d1050d5f..f690c363945e 100644 --- a/infra/conf/hysteria.go +++ b/infra/conf/hysteria.go @@ -1,19 +1,25 @@ package conf import ( + "github.com/xtls/xray-core/common/errors" "github.com/xtls/xray-core/common/protocol" "github.com/xtls/xray-core/proxy/hysteria" "google.golang.org/protobuf/proto" ) type HysteriaClientConfig struct { + Version int32 `json:"version"` Address *Address `json:"address"` Port uint16 `json:"port"` } func (c *HysteriaClientConfig) Build() (proto.Message, error) { - config := new(hysteria.ClientConfig) + if c.Version != 2 { + return nil, errors.New("version != 2") + } + config := &hysteria.ClientConfig{} + config.Version = c.Version config.Server = &protocol.ServerEndpoint{ Address: c.Address.Build(), Port: uint32(c.Port), diff --git a/infra/conf/transport_internet.go b/infra/conf/transport_internet.go index 742c7df5a940..3b21e383094c 100644 --- a/infra/conf/transport_internet.go +++ b/infra/conf/transport_internet.go @@ -453,7 +453,7 @@ func (c *HysteriaConfig) Build() (proto.Message, error) { } config := &hysteria.Config{} - config.Version = int32(c.Version) + config.Version = c.Version config.Auth = c.Auth config.Up = up config.Down = down diff --git a/proxy/hysteria/config.pb.go b/proxy/hysteria/config.pb.go index d58022cc2d63..ef61eb29507b 100644 --- a/proxy/hysteria/config.pb.go +++ b/proxy/hysteria/config.pb.go @@ -24,7 +24,8 @@ const ( type ClientConfig struct { state protoimpl.MessageState `protogen:"open.v1"` - Server *protocol.ServerEndpoint `protobuf:"bytes,1,opt,name=server,proto3" json:"server,omitempty"` + Version int32 `protobuf:"varint,1,opt,name=version,proto3" json:"version,omitempty"` + Server *protocol.ServerEndpoint `protobuf:"bytes,2,opt,name=server,proto3" json:"server,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } @@ -59,6 +60,13 @@ func (*ClientConfig) Descriptor() ([]byte, []int) { return file_proxy_hysteria_config_proto_rawDescGZIP(), []int{0} } +func (x *ClientConfig) GetVersion() int32 { + if x != nil { + return x.Version + } + return 0 +} + func (x *ClientConfig) GetServer() *protocol.ServerEndpoint { if x != nil { return x.Server @@ -70,9 +78,10 @@ var File_proxy_hysteria_config_proto protoreflect.FileDescriptor const file_proxy_hysteria_config_proto_rawDesc = "" + "\n" + - "\x1bproxy/hysteria/config.proto\x12\x13xray.proxy.hysteria\x1a!common/protocol/server_spec.proto\"L\n" + - "\fClientConfig\x12<\n" + - "\x06server\x18\x01 \x01(\v2$.xray.common.protocol.ServerEndpointR\x06serverB[\n" + + "\x1bproxy/hysteria/config.proto\x12\x13xray.proxy.hysteria\x1a!common/protocol/server_spec.proto\"f\n" + + "\fClientConfig\x12\x18\n" + + "\aversion\x18\x01 \x01(\x05R\aversion\x12<\n" + + "\x06server\x18\x02 \x01(\v2$.xray.common.protocol.ServerEndpointR\x06serverB[\n" + "\x17com.xray.proxy.hysteriaP\x01Z(github.com/xtls/xray-core/proxy/hysteria\xaa\x02\x13Xray.Proxy.Hysteriab\x06proto3" var ( diff --git a/proxy/hysteria/config.proto b/proxy/hysteria/config.proto index c54c0ead0cd0..2a71ac53733c 100644 --- a/proxy/hysteria/config.proto +++ b/proxy/hysteria/config.proto @@ -9,5 +9,6 @@ option java_multiple_files = true; import "common/protocol/server_spec.proto"; message ClientConfig { - xray.common.protocol.ServerEndpoint server = 1; + int32 version = 1; + xray.common.protocol.ServerEndpoint server = 2; }