From 325869bdb5ce467bc896e6644437557ac5f2b8b9 Mon Sep 17 00:00:00 2001 From: Toby Date: Fri, 4 Nov 2022 13:27:49 -0700 Subject: [PATCH] feat: add hop interval to client config, default 10s --- cmd/client.go | 2 +- cmd/config.go | 9 +++++++++ pkg/transport/pktconns/funcs.go | 13 +++++++------ pkg/transport/pktconns/udp/hop.go | 10 +++++----- 4 files changed, 22 insertions(+), 12 deletions(-) diff --git a/cmd/client.go b/cmd/client.go index 533f1dd..d35f3b3 100644 --- a/cmd/client.go +++ b/cmd/client.go @@ -102,7 +102,7 @@ func client(config *clientConfig) { "protocol": config.Protocol, }).Fatal("Unsupported protocol") } - pktConnFunc := pktConnFuncFactory(config.Obfs) + pktConnFunc := pktConnFuncFactory(config.Obfs, time.Duration(config.HopInterval)*time.Second) // Resolve preference if len(config.ResolvePreference) > 0 { pref, err := transport.ResolvePreferenceFromString(config.ResolvePreference) diff --git a/cmd/config.go b/cmd/config.go index 78f1461..ad6f1b5 100644 --- a/cmd/config.go +++ b/cmd/config.go @@ -24,6 +24,8 @@ const ( ServerMaxIdleTimeoutSec = 60 DefaultClientIdleTimeoutSec = 20 + + DefaultClientHopIntervalSec = 10 ) var rateStringRegexp = regexp.MustCompile(`^(\d+)\s*([KMGT]?)([Bb])ps$`) @@ -168,6 +170,7 @@ type clientConfig struct { QuitOnDisconnect bool `json:"quit_on_disconnect"` HandshakeTimeout int `json:"handshake_timeout"` IdleTimeout int `json:"idle_timeout"` + HopInterval int `json:"hop_interval"` SOCKS5 struct { Listen string `json:"listen"` Timeout int `json:"timeout"` @@ -258,6 +261,9 @@ func (c *clientConfig) Check() error { if c.IdleTimeout != 0 && c.IdleTimeout < 4 { return errors.New("invalid idle timeout") } + if c.HopInterval != 0 && c.HopInterval < 8 { + return errors.New("invalid hop interval") + } if c.SOCKS5.Timeout != 0 && c.SOCKS5.Timeout < 4 { return errors.New("invalid SOCKS5 timeout") } @@ -333,6 +339,9 @@ func (c *clientConfig) Fill() { if c.IdleTimeout == 0 { c.IdleTimeout = DefaultClientIdleTimeoutSec } + if c.HopInterval == 0 { + c.HopInterval = DefaultClientHopIntervalSec + } } func (c *clientConfig) String() string { diff --git a/pkg/transport/pktconns/funcs.go b/pkg/transport/pktconns/funcs.go index 2df10aa..0a30597 100644 --- a/pkg/transport/pktconns/funcs.go +++ b/pkg/transport/pktconns/funcs.go @@ -3,6 +3,7 @@ package pktconns import ( "net" "strings" + "time" "github.com/HyNetwork/hysteria/pkg/transport/pktconns/faketcp" "github.com/HyNetwork/hysteria/pkg/transport/pktconns/obfs" @@ -16,15 +17,15 @@ type ( ) type ( - ClientPacketConnFuncFactory func(obfsPassword string) ClientPacketConnFunc + ClientPacketConnFuncFactory func(obfsPassword string, hopInterval time.Duration) ClientPacketConnFunc ServerPacketConnFuncFactory func(obfsPassword string) ServerPacketConnFunc ) -func NewClientUDPConnFunc(obfsPassword string) ClientPacketConnFunc { +func NewClientUDPConnFunc(obfsPassword string, hopInterval time.Duration) ClientPacketConnFunc { if obfsPassword == "" { return func(server string) (net.PacketConn, net.Addr, error) { if isMultiPortAddr(server) { - return udp.NewObfsUDPHopClientPacketConn(server, nil) + return udp.NewObfsUDPHopClientPacketConn(server, hopInterval, nil) } sAddr, err := net.ResolveUDPAddr("udp", server) if err != nil { @@ -37,7 +38,7 @@ func NewClientUDPConnFunc(obfsPassword string) ClientPacketConnFunc { return func(server string) (net.PacketConn, net.Addr, error) { if isMultiPortAddr(server) { ob := obfs.NewXPlusObfuscator([]byte(obfsPassword)) - return udp.NewObfsUDPHopClientPacketConn(server, ob) + return udp.NewObfsUDPHopClientPacketConn(server, hopInterval, ob) } sAddr, err := net.ResolveUDPAddr("udp", server) if err != nil { @@ -53,7 +54,7 @@ func NewClientUDPConnFunc(obfsPassword string) ClientPacketConnFunc { } } -func NewClientWeChatConnFunc(obfsPassword string) ClientPacketConnFunc { +func NewClientWeChatConnFunc(obfsPassword string, hopInterval time.Duration) ClientPacketConnFunc { if obfsPassword == "" { return func(server string) (net.PacketConn, net.Addr, error) { sAddr, err := net.ResolveUDPAddr("udp", server) @@ -82,7 +83,7 @@ func NewClientWeChatConnFunc(obfsPassword string) ClientPacketConnFunc { } } -func NewClientFakeTCPConnFunc(obfsPassword string) ClientPacketConnFunc { +func NewClientFakeTCPConnFunc(obfsPassword string, hopInterval time.Duration) ClientPacketConnFunc { if obfsPassword == "" { return func(server string) (net.PacketConn, net.Addr, error) { sAddr, err := net.ResolveTCPAddr("tcp", server) diff --git a/pkg/transport/pktconns/udp/hop.go b/pkg/transport/pktconns/udp/hop.go index 9404733..1936eb3 100644 --- a/pkg/transport/pktconns/udp/hop.go +++ b/pkg/transport/pktconns/udp/hop.go @@ -14,15 +14,14 @@ import ( const ( packetQueueSize = 1024 - - portHoppingInterval = 30 * time.Second ) // ObfsUDPHopClientPacketConn is the UDP port-hopping packet connection for client side. -// It hops to a different local & server port every once in a while (portHoppingInterval). +// It hops to a different local & server port every once in a while. type ObfsUDPHopClientPacketConn struct { serverAddr net.Addr // Combined udpHopAddr serverAddrs []net.Addr + hopInterval time.Duration obfs obfs.Obfuscator @@ -54,7 +53,7 @@ type udpPacket struct { addr net.Addr } -func NewObfsUDPHopClientPacketConn(server string, obfs obfs.Obfuscator) (*ObfsUDPHopClientPacketConn, net.Addr, error) { +func NewObfsUDPHopClientPacketConn(server string, hopInterval time.Duration, obfs obfs.Obfuscator) (*ObfsUDPHopClientPacketConn, net.Addr, error) { host, ports, err := parseAddr(server) if err != nil { return nil, nil, err @@ -76,6 +75,7 @@ func NewObfsUDPHopClientPacketConn(server string, obfs obfs.Obfuscator) (*ObfsUD conn := &ObfsUDPHopClientPacketConn{ serverAddr: &hopAddr, serverAddrs: serverAddrs, + hopInterval: hopInterval, obfs: obfs, addrIndex: rand.Intn(len(serverAddrs)), recvQueue: make(chan *udpPacket, packetQueueSize), @@ -118,7 +118,7 @@ func (c *ObfsUDPHopClientPacketConn) recvRoutine(conn net.PacketConn) { } func (c *ObfsUDPHopClientPacketConn) hopRoutine() { - ticker := time.NewTicker(portHoppingInterval) + ticker := time.NewTicker(c.hopInterval) defer ticker.Stop() for { select {