Skip to content

Commit 0eb05f3

Browse files
committed
Also add port hopping to hysteria 1
1 parent 38b68fd commit 0eb05f3

File tree

3 files changed

+76
-47
lines changed

3 files changed

+76
-47
lines changed

hysteria/client.go

Lines changed: 73 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,10 @@ import (
77
"net"
88
"os"
99
"runtime"
10+
"strconv"
11+
"strings"
1012
"sync"
13+
"time"
1114

1215
"github.com/sagernet/quic-go"
1316
"github.com/sagernet/sing-quic"
@@ -28,6 +31,8 @@ type ClientOptions struct {
2831
Logger logger.Logger
2932
BrutalDebug bool
3033
ServerAddress M.Socksaddr
34+
ServerPorts []string
35+
HopInterval time.Duration
3136
SendBPS uint64
3237
ReceiveBPS uint64
3338
XPlusPassword string
@@ -48,6 +53,8 @@ type Client struct {
4853
logger logger.Logger
4954
brutalDebug bool
5055
serverAddr M.Socksaddr
56+
serverPorts []uint16
57+
hopInterval time.Duration
5158
sendBPS uint64
5259
receiveBPS uint64
5360
xplusPassword string
@@ -95,12 +102,22 @@ func NewClient(options ClientOptions) (*Client, error) {
95102
} else if options.ReceiveBPS < MinSpeedBPS {
96103
return nil, E.New("invalid download speed")
97104
}
105+
var serverPorts []uint16
106+
if len(options.ServerPorts) > 0 {
107+
var err error
108+
serverPorts, err = ParsePorts(options.ServerPorts)
109+
if err != nil {
110+
return nil, err
111+
}
112+
}
98113
return &Client{
99114
ctx: options.Context,
100115
dialer: options.Dialer,
101116
logger: options.Logger,
102117
brutalDebug: options.BrutalDebug,
103118
serverAddr: options.ServerAddress,
119+
serverPorts: serverPorts,
120+
hopInterval: options.HopInterval,
104121
sendBPS: options.SendBPS,
105122
receiveBPS: options.ReceiveBPS,
106123
xplusPassword: options.XPlusPassword,
@@ -111,6 +128,38 @@ func NewClient(options ClientOptions) (*Client, error) {
111128
}, nil
112129
}
113130

131+
func ParsePorts(serverPorts []string) ([]uint16, error) {
132+
var portList []uint16
133+
for _, portRange := range serverPorts {
134+
if !strings.Contains(portRange, ":") {
135+
return nil, E.New("bad port range: ", portRange)
136+
}
137+
subIndex := strings.Index(portRange, ":")
138+
var (
139+
start, end uint64
140+
err error
141+
)
142+
if subIndex > 0 {
143+
start, err = strconv.ParseUint(portRange[:subIndex], 10, 16)
144+
if err != nil {
145+
return nil, E.Cause(err, E.Cause(err, "bad port range: ", portRange))
146+
}
147+
}
148+
if subIndex == len(portRange)-1 {
149+
end = math.MaxUint16
150+
} else {
151+
end, err = strconv.ParseUint(portRange[subIndex+1:], 10, 16)
152+
if err != nil {
153+
return nil, E.Cause(err, E.Cause(err, "bad port range: ", portRange))
154+
}
155+
}
156+
for i := start; i <= end; i++ {
157+
portList = append(portList, uint16(i))
158+
}
159+
}
160+
return portList, nil
161+
}
162+
114163
func (c *Client) offer(ctx context.Context) (*clientQUICConnection, error) {
115164
conn := c.conn
116165
if conn != nil && conn.active() {
@@ -130,18 +179,33 @@ func (c *Client) offer(ctx context.Context) (*clientQUICConnection, error) {
130179
}
131180

132181
func (c *Client) offerNew(ctx context.Context) (*clientQUICConnection, error) {
133-
udpConn, err := c.dialer.DialContext(c.ctx, "udp", c.serverAddr)
182+
dialFunc := func(serverAddr M.Socksaddr) (net.PacketConn, error) {
183+
udpConn, err := c.dialer.DialContext(c.ctx, "udp", serverAddr)
184+
if err != nil {
185+
return nil, err
186+
}
187+
var packetConn net.PacketConn
188+
packetConn = bufio.NewUnbindPacketConn(udpConn)
189+
if c.xplusPassword != "" {
190+
packetConn = NewXPlusPacketConn(packetConn, []byte(c.xplusPassword))
191+
}
192+
return packetConn, nil
193+
}
194+
var (
195+
packetConn net.PacketConn
196+
err error
197+
)
198+
if len(c.serverPorts) == 0 {
199+
packetConn, err = dialFunc(c.serverAddr)
200+
} else {
201+
packetConn, err = NewHopPacketConn(dialFunc, c.serverAddr, c.serverPorts, c.hopInterval)
202+
}
134203
if err != nil {
135204
return nil, err
136205
}
137-
var packetConn net.PacketConn
138-
packetConn = bufio.NewUnbindPacketConn(udpConn)
139-
if c.xplusPassword != "" {
140-
packetConn = NewXPlusPacketConn(packetConn, []byte(c.xplusPassword))
141-
}
142-
quicConn, err := qtls.Dial(c.ctx, packetConn, udpConn.RemoteAddr(), c.tlsConfig, c.quicConfig)
206+
quicConn, err := qtls.Dial(c.ctx, packetConn, c.serverAddr, c.tlsConfig, c.quicConfig)
143207
if err != nil {
144-
udpConn.Close()
208+
packetConn.Close()
145209
return nil, err
146210
}
147211
controlStream, err := quicConn.OpenStreamSync(ctx)
@@ -170,7 +234,7 @@ func (c *Client) offerNew(ctx context.Context) (*clientQUICConnection, error) {
170234
quicConn.SetCongestionControl(hyCC.NewBrutalSender(uint64(math.Min(float64(serverHello.RecvBPS), float64(c.sendBPS))), c.brutalDebug, c.logger))
171235
conn := &clientQUICConnection{
172236
quicConn: quicConn,
173-
rawConn: udpConn,
237+
rawConn: packetConn,
174238
connDone: make(chan struct{}),
175239
udpDisabled: !quicConn.ConnectionState().SupportsDatagrams,
176240
udpConnMap: make(map[uint32]*udpPacketConn),

hysteria2/hop.go renamed to hysteria/hop.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package hysteria2
1+
package hysteria
22

33
import (
44
"errors"

hysteria2/client.go

Lines changed: 2 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,11 @@ package hysteria2
33
import (
44
"context"
55
"io"
6-
"math"
76
"net"
87
"net/http"
98
"net/url"
109
"os"
1110
"runtime"
12-
"strconv"
13-
"strings"
1411
"sync"
1512
"time"
1613

@@ -86,7 +83,7 @@ func NewClient(options ClientOptions) (*Client, error) {
8683
var serverPorts []uint16
8784
if len(options.ServerPorts) > 0 {
8885
var err error
89-
serverPorts, err = parsePorts(options.ServerPorts)
86+
serverPorts, err = hysteria.ParsePorts(options.ServerPorts)
9087
if err != nil {
9188
return nil, err
9289
}
@@ -109,38 +106,6 @@ func NewClient(options ClientOptions) (*Client, error) {
109106
}, nil
110107
}
111108

112-
func parsePorts(serverPorts []string) ([]uint16, error) {
113-
var portList []uint16
114-
for _, portRange := range serverPorts {
115-
if !strings.Contains(portRange, ":") {
116-
return nil, E.New("bad port range: ", portRange)
117-
}
118-
subIndex := strings.Index(portRange, ":")
119-
var (
120-
start, end uint64
121-
err error
122-
)
123-
if subIndex > 0 {
124-
start, err = strconv.ParseUint(portRange[:subIndex], 10, 16)
125-
if err != nil {
126-
return nil, E.Cause(err, E.Cause(err, "bad port range: ", portRange))
127-
}
128-
}
129-
if subIndex == len(portRange)-1 {
130-
end = math.MaxUint16
131-
} else {
132-
end, err = strconv.ParseUint(portRange[subIndex+1:], 10, 16)
133-
if err != nil {
134-
return nil, E.Cause(err, E.Cause(err, "bad port range: ", portRange))
135-
}
136-
}
137-
for i := start; i <= end; i++ {
138-
portList = append(portList, uint16(i))
139-
}
140-
}
141-
return portList, nil
142-
}
143-
144109
func (c *Client) offer(ctx context.Context) (*clientQUICConnection, error) {
145110
conn := c.conn
146111
if conn != nil && conn.active() {
@@ -179,7 +144,7 @@ func (c *Client) offerNew(ctx context.Context) (*clientQUICConnection, error) {
179144
if len(c.serverPorts) == 0 {
180145
packetConn, err = dialFunc(c.serverAddr)
181146
} else {
182-
packetConn, err = NewHopPacketConn(dialFunc, c.serverAddr, c.serverPorts, c.hopInterval)
147+
packetConn, err = hysteria.NewHopPacketConn(dialFunc, c.serverAddr, c.serverPorts, c.hopInterval)
183148
}
184149
if err != nil {
185150
return nil, err

0 commit comments

Comments
 (0)