mirror of
https://github.com/XTLS/Xray-core.git
synced 2026-05-08 14:13:22 +00:00
Hysteria transport: Support range & random for interval in udphop as well (#5603)
https://github.com/XTLS/Xray-core/pull/5560#issuecomment-3794621260
This commit is contained in:
@@ -387,7 +387,7 @@ func (b Bandwidth) Bps() (uint64, error) {
|
|||||||
|
|
||||||
type UdpHop struct {
|
type UdpHop struct {
|
||||||
PortList json.RawMessage `json:"port"`
|
PortList json.RawMessage `json:"port"`
|
||||||
Interval int64 `json:"interval"`
|
Interval *Int32Range `json:"interval"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type HysteriaConfig struct {
|
type HysteriaConfig struct {
|
||||||
@@ -431,13 +431,19 @@ func (c *HysteriaConfig) Build() (proto.Message, error) {
|
|||||||
hop = &PortList{}
|
hop = &PortList{}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var inertvalMin, inertvalMax int64
|
||||||
|
if c.UdpHop.Interval != nil {
|
||||||
|
inertvalMin = int64(c.UdpHop.Interval.From)
|
||||||
|
inertvalMax = int64(c.UdpHop.Interval.To)
|
||||||
|
}
|
||||||
|
|
||||||
if up > 0 && up < 65536 {
|
if up > 0 && up < 65536 {
|
||||||
return nil, errors.New("Up must be at least 65536 Bps")
|
return nil, errors.New("Up must be at least 65536 Bps")
|
||||||
}
|
}
|
||||||
if down > 0 && down < 65536 {
|
if down > 0 && down < 65536 {
|
||||||
return nil, errors.New("Down must be at least 65536 Bps")
|
return nil, errors.New("Down must be at least 65536 Bps")
|
||||||
}
|
}
|
||||||
if c.UdpHop.Interval != 0 && c.UdpHop.Interval < 5 {
|
if (inertvalMin != 0 && inertvalMin < 5) || (inertvalMax != 0 && inertvalMax < 5) {
|
||||||
return nil, errors.New("Interval must be at least 5")
|
return nil, errors.New("Interval must be at least 5")
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -467,7 +473,8 @@ func (c *HysteriaConfig) Build() (proto.Message, error) {
|
|||||||
config.Up = up
|
config.Up = up
|
||||||
config.Down = down
|
config.Down = down
|
||||||
config.Ports = hop.Build().Ports()
|
config.Ports = hop.Build().Ports()
|
||||||
config.Interval = c.UdpHop.Interval
|
config.IntervalMin = inertvalMin
|
||||||
|
config.IntervalMax = inertvalMax
|
||||||
config.InitStreamReceiveWindow = c.InitStreamReceiveWindow
|
config.InitStreamReceiveWindow = c.InitStreamReceiveWindow
|
||||||
config.MaxStreamReceiveWindow = c.MaxStreamReceiveWindow
|
config.MaxStreamReceiveWindow = c.MaxStreamReceiveWindow
|
||||||
config.InitConnReceiveWindow = c.InitConnectionReceiveWindow
|
config.InitConnReceiveWindow = c.InitConnectionReceiveWindow
|
||||||
|
|||||||
@@ -29,14 +29,15 @@ type Config struct {
|
|||||||
Up uint64 `protobuf:"varint,4,opt,name=up,proto3" json:"up,omitempty"`
|
Up uint64 `protobuf:"varint,4,opt,name=up,proto3" json:"up,omitempty"`
|
||||||
Down uint64 `protobuf:"varint,5,opt,name=down,proto3" json:"down,omitempty"`
|
Down uint64 `protobuf:"varint,5,opt,name=down,proto3" json:"down,omitempty"`
|
||||||
Ports []uint32 `protobuf:"varint,6,rep,packed,name=ports,proto3" json:"ports,omitempty"`
|
Ports []uint32 `protobuf:"varint,6,rep,packed,name=ports,proto3" json:"ports,omitempty"`
|
||||||
Interval int64 `protobuf:"varint,7,opt,name=interval,proto3" json:"interval,omitempty"`
|
IntervalMin int64 `protobuf:"varint,7,opt,name=interval_min,json=intervalMin,proto3" json:"interval_min,omitempty"`
|
||||||
InitStreamReceiveWindow uint64 `protobuf:"varint,8,opt,name=init_stream_receive_window,json=initStreamReceiveWindow,proto3" json:"init_stream_receive_window,omitempty"`
|
IntervalMax int64 `protobuf:"varint,8,opt,name=interval_max,json=intervalMax,proto3" json:"interval_max,omitempty"`
|
||||||
MaxStreamReceiveWindow uint64 `protobuf:"varint,9,opt,name=max_stream_receive_window,json=maxStreamReceiveWindow,proto3" json:"max_stream_receive_window,omitempty"`
|
InitStreamReceiveWindow uint64 `protobuf:"varint,9,opt,name=init_stream_receive_window,json=initStreamReceiveWindow,proto3" json:"init_stream_receive_window,omitempty"`
|
||||||
InitConnReceiveWindow uint64 `protobuf:"varint,10,opt,name=init_conn_receive_window,json=initConnReceiveWindow,proto3" json:"init_conn_receive_window,omitempty"`
|
MaxStreamReceiveWindow uint64 `protobuf:"varint,10,opt,name=max_stream_receive_window,json=maxStreamReceiveWindow,proto3" json:"max_stream_receive_window,omitempty"`
|
||||||
MaxConnReceiveWindow uint64 `protobuf:"varint,11,opt,name=max_conn_receive_window,json=maxConnReceiveWindow,proto3" json:"max_conn_receive_window,omitempty"`
|
InitConnReceiveWindow uint64 `protobuf:"varint,11,opt,name=init_conn_receive_window,json=initConnReceiveWindow,proto3" json:"init_conn_receive_window,omitempty"`
|
||||||
MaxIdleTimeout int64 `protobuf:"varint,12,opt,name=max_idle_timeout,json=maxIdleTimeout,proto3" json:"max_idle_timeout,omitempty"`
|
MaxConnReceiveWindow uint64 `protobuf:"varint,12,opt,name=max_conn_receive_window,json=maxConnReceiveWindow,proto3" json:"max_conn_receive_window,omitempty"`
|
||||||
KeepAlivePeriod int64 `protobuf:"varint,13,opt,name=keep_alive_period,json=keepAlivePeriod,proto3" json:"keep_alive_period,omitempty"`
|
MaxIdleTimeout int64 `protobuf:"varint,13,opt,name=max_idle_timeout,json=maxIdleTimeout,proto3" json:"max_idle_timeout,omitempty"`
|
||||||
DisablePathMtuDiscovery bool `protobuf:"varint,14,opt,name=disable_path_mtu_discovery,json=disablePathMtuDiscovery,proto3" json:"disable_path_mtu_discovery,omitempty"`
|
KeepAlivePeriod int64 `protobuf:"varint,14,opt,name=keep_alive_period,json=keepAlivePeriod,proto3" json:"keep_alive_period,omitempty"`
|
||||||
|
DisablePathMtuDiscovery bool `protobuf:"varint,15,opt,name=disable_path_mtu_discovery,json=disablePathMtuDiscovery,proto3" json:"disable_path_mtu_discovery,omitempty"`
|
||||||
unknownFields protoimpl.UnknownFields
|
unknownFields protoimpl.UnknownFields
|
||||||
sizeCache protoimpl.SizeCache
|
sizeCache protoimpl.SizeCache
|
||||||
}
|
}
|
||||||
@@ -113,9 +114,16 @@ func (x *Config) GetPorts() []uint32 {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *Config) GetInterval() int64 {
|
func (x *Config) GetIntervalMin() int64 {
|
||||||
if x != nil {
|
if x != nil {
|
||||||
return x.Interval
|
return x.IntervalMin
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *Config) GetIntervalMax() int64 {
|
||||||
|
if x != nil {
|
||||||
|
return x.IntervalMax
|
||||||
}
|
}
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
@@ -173,7 +181,7 @@ var File_transport_internet_hysteria_config_proto protoreflect.FileDescriptor
|
|||||||
|
|
||||||
const file_transport_internet_hysteria_config_proto_rawDesc = "" +
|
const file_transport_internet_hysteria_config_proto_rawDesc = "" +
|
||||||
"\n" +
|
"\n" +
|
||||||
"(transport/internet/hysteria/config.proto\x12 xray.transport.internet.hysteria\"\xa7\x04\n" +
|
"(transport/internet/hysteria/config.proto\x12 xray.transport.internet.hysteria\"\xd1\x04\n" +
|
||||||
"\x06Config\x12\x18\n" +
|
"\x06Config\x12\x18\n" +
|
||||||
"\aversion\x18\x01 \x01(\x05R\aversion\x12\x12\n" +
|
"\aversion\x18\x01 \x01(\x05R\aversion\x12\x12\n" +
|
||||||
"\x04auth\x18\x02 \x01(\tR\x04auth\x12\x1e\n" +
|
"\x04auth\x18\x02 \x01(\tR\x04auth\x12\x1e\n" +
|
||||||
@@ -182,16 +190,17 @@ const file_transport_internet_hysteria_config_proto_rawDesc = "" +
|
|||||||
"congestion\x12\x0e\n" +
|
"congestion\x12\x0e\n" +
|
||||||
"\x02up\x18\x04 \x01(\x04R\x02up\x12\x12\n" +
|
"\x02up\x18\x04 \x01(\x04R\x02up\x12\x12\n" +
|
||||||
"\x04down\x18\x05 \x01(\x04R\x04down\x12\x14\n" +
|
"\x04down\x18\x05 \x01(\x04R\x04down\x12\x14\n" +
|
||||||
"\x05ports\x18\x06 \x03(\rR\x05ports\x12\x1a\n" +
|
"\x05ports\x18\x06 \x03(\rR\x05ports\x12!\n" +
|
||||||
"\binterval\x18\a \x01(\x03R\binterval\x12;\n" +
|
"\finterval_min\x18\a \x01(\x03R\vintervalMin\x12!\n" +
|
||||||
"\x1ainit_stream_receive_window\x18\b \x01(\x04R\x17initStreamReceiveWindow\x129\n" +
|
"\finterval_max\x18\b \x01(\x03R\vintervalMax\x12;\n" +
|
||||||
"\x19max_stream_receive_window\x18\t \x01(\x04R\x16maxStreamReceiveWindow\x127\n" +
|
"\x1ainit_stream_receive_window\x18\t \x01(\x04R\x17initStreamReceiveWindow\x129\n" +
|
||||||
"\x18init_conn_receive_window\x18\n" +
|
"\x19max_stream_receive_window\x18\n" +
|
||||||
" \x01(\x04R\x15initConnReceiveWindow\x125\n" +
|
" \x01(\x04R\x16maxStreamReceiveWindow\x127\n" +
|
||||||
"\x17max_conn_receive_window\x18\v \x01(\x04R\x14maxConnReceiveWindow\x12(\n" +
|
"\x18init_conn_receive_window\x18\v \x01(\x04R\x15initConnReceiveWindow\x125\n" +
|
||||||
"\x10max_idle_timeout\x18\f \x01(\x03R\x0emaxIdleTimeout\x12*\n" +
|
"\x17max_conn_receive_window\x18\f \x01(\x04R\x14maxConnReceiveWindow\x12(\n" +
|
||||||
"\x11keep_alive_period\x18\r \x01(\x03R\x0fkeepAlivePeriod\x12;\n" +
|
"\x10max_idle_timeout\x18\r \x01(\x03R\x0emaxIdleTimeout\x12*\n" +
|
||||||
"\x1adisable_path_mtu_discovery\x18\x0e \x01(\bR\x17disablePathMtuDiscoveryB\x82\x01\n" +
|
"\x11keep_alive_period\x18\x0e \x01(\x03R\x0fkeepAlivePeriod\x12;\n" +
|
||||||
|
"\x1adisable_path_mtu_discovery\x18\x0f \x01(\bR\x17disablePathMtuDiscoveryB\x82\x01\n" +
|
||||||
"$com.xray.transport.internet.hysteriaP\x01Z5github.com/xtls/xray-core/transport/internet/hysteria\xaa\x02 Xray.Transport.Internet.Hysteriab\x06proto3"
|
"$com.xray.transport.internet.hysteriaP\x01Z5github.com/xtls/xray-core/transport/internet/hysteria\xaa\x02 Xray.Transport.Internet.Hysteriab\x06proto3"
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
|||||||
@@ -13,14 +13,15 @@ message Config {
|
|||||||
uint64 up = 4;
|
uint64 up = 4;
|
||||||
uint64 down = 5;
|
uint64 down = 5;
|
||||||
repeated uint32 ports = 6;
|
repeated uint32 ports = 6;
|
||||||
int64 interval = 7;
|
int64 interval_min = 7;
|
||||||
|
int64 interval_max = 8;
|
||||||
|
|
||||||
uint64 init_stream_receive_window = 8;
|
uint64 init_stream_receive_window = 9;
|
||||||
uint64 max_stream_receive_window = 9;
|
uint64 max_stream_receive_window = 10;
|
||||||
uint64 init_conn_receive_window = 10;
|
uint64 init_conn_receive_window = 11;
|
||||||
uint64 max_conn_receive_window = 11;
|
uint64 max_conn_receive_window = 12;
|
||||||
int64 max_idle_timeout = 12;
|
int64 max_idle_timeout = 13;
|
||||||
int64 keep_alive_period = 13;
|
int64 keep_alive_period = 14;
|
||||||
bool disable_path_mtu_discovery = 14;
|
bool disable_path_mtu_discovery = 15;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -174,7 +174,7 @@ func (c *client) dial() error {
|
|||||||
IP: remote.(*net.UDPAddr).IP,
|
IP: remote.(*net.UDPAddr).IP,
|
||||||
Ports: c.config.Ports,
|
Ports: c.config.Ports,
|
||||||
}
|
}
|
||||||
pktConn, err = udphop.NewUDPHopPacketConn(addr, time.Duration(c.config.Interval)*time.Second, c.udphopDialer, pktConn, index)
|
pktConn, err = udphop.NewUDPHopPacketConn(addr, c.config.IntervalMin, c.config.IntervalMax, c.udphopDialer, pktConn, index)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.New("udphop err").Base(err)
|
return errors.New("udphop err").Base(err)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,6 +7,8 @@ import (
|
|||||||
"sync"
|
"sync"
|
||||||
"syscall"
|
"syscall"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/xtls/xray-core/common/crypto"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@@ -17,10 +19,11 @@ const (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type udpHopPacketConn struct {
|
type udpHopPacketConn struct {
|
||||||
Addr net.Addr
|
Addr net.Addr
|
||||||
Addrs []net.Addr
|
Addrs []net.Addr
|
||||||
HopInterval time.Duration
|
HopIntervalMin int64
|
||||||
ListenUDPFunc ListenUDPFunc
|
HopIntervalMax int64
|
||||||
|
ListenUDPFunc ListenUDPFunc
|
||||||
|
|
||||||
connMutex sync.RWMutex
|
connMutex sync.RWMutex
|
||||||
prevConn net.PacketConn
|
prevConn net.PacketConn
|
||||||
@@ -46,10 +49,12 @@ type udpPacket struct {
|
|||||||
|
|
||||||
type ListenUDPFunc = func(*net.UDPAddr) (net.PacketConn, error)
|
type ListenUDPFunc = func(*net.UDPAddr) (net.PacketConn, error)
|
||||||
|
|
||||||
func NewUDPHopPacketConn(addr *UDPHopAddr, hopInterval time.Duration, listenUDPFunc ListenUDPFunc, pktConn net.PacketConn, index int) (net.PacketConn, error) {
|
func NewUDPHopPacketConn(addr *UDPHopAddr, intervalMin int64, intervalMax int64, listenUDPFunc ListenUDPFunc, pktConn net.PacketConn, index int) (net.PacketConn, error) {
|
||||||
if hopInterval == 0 {
|
if intervalMin == 0 || intervalMax == 0 {
|
||||||
hopInterval = defaultHopInterval
|
intervalMin = int64(defaultHopInterval)
|
||||||
} else if hopInterval < 5*time.Second {
|
intervalMax = int64(defaultHopInterval)
|
||||||
|
}
|
||||||
|
if intervalMin < 5 || intervalMax < 5 {
|
||||||
return nil, errors.New("hop interval must be at least 5 seconds")
|
return nil, errors.New("hop interval must be at least 5 seconds")
|
||||||
}
|
}
|
||||||
// if listenUDPFunc == nil {
|
// if listenUDPFunc == nil {
|
||||||
@@ -69,15 +74,16 @@ func NewUDPHopPacketConn(addr *UDPHopAddr, hopInterval time.Duration, listenUDPF
|
|||||||
// return nil, err
|
// return nil, err
|
||||||
// }
|
// }
|
||||||
hConn := &udpHopPacketConn{
|
hConn := &udpHopPacketConn{
|
||||||
Addr: addr,
|
Addr: addr,
|
||||||
Addrs: addrs,
|
Addrs: addrs,
|
||||||
HopInterval: hopInterval,
|
HopIntervalMin: intervalMin,
|
||||||
ListenUDPFunc: listenUDPFunc,
|
HopIntervalMax: intervalMax,
|
||||||
prevConn: nil,
|
ListenUDPFunc: listenUDPFunc,
|
||||||
currentConn: pktConn,
|
prevConn: nil,
|
||||||
addrIndex: index,
|
currentConn: pktConn,
|
||||||
recvQueue: make(chan *udpPacket, packetQueueSize),
|
addrIndex: index,
|
||||||
closeChan: make(chan struct{}),
|
recvQueue: make(chan *udpPacket, packetQueueSize),
|
||||||
|
closeChan: make(chan struct{}),
|
||||||
bufPool: sync.Pool{
|
bufPool: sync.Pool{
|
||||||
New: func() interface{} {
|
New: func() interface{} {
|
||||||
return make([]byte, udpBufferSize)
|
return make([]byte, udpBufferSize)
|
||||||
@@ -115,12 +121,13 @@ func (u *udpHopPacketConn) recvLoop(conn net.PacketConn) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (u *udpHopPacketConn) hopLoop() {
|
func (u *udpHopPacketConn) hopLoop() {
|
||||||
ticker := time.NewTicker(u.HopInterval)
|
ticker := time.NewTicker(time.Duration(crypto.RandBetween(u.HopIntervalMin, u.HopIntervalMax)) * time.Second)
|
||||||
defer ticker.Stop()
|
defer ticker.Stop()
|
||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
case <-ticker.C:
|
case <-ticker.C:
|
||||||
u.hop()
|
u.hop()
|
||||||
|
ticker.Reset(time.Duration(crypto.RandBetween(u.HopIntervalMin, u.HopIntervalMax)) * time.Second)
|
||||||
case <-u.closeChan:
|
case <-u.closeChan:
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user