@@ -4,7 +4,6 @@ package internal
44import (
55 "bufio"
66 "context"
7- "crypto/rand"
87 "fmt"
98 "io"
109 "net"
@@ -114,7 +113,7 @@ func (c *Client) start() error {
114113 if err := c .initTunnelListener (); err == nil {
115114 return c .singleStart ()
116115 } else {
117- return c . hybridStart ( )
116+ return fmt . Errorf ( "start: initTunnelListener failed: %w" , err )
118117 }
119118 case "2" : // 双端模式
120119 return c .commonStart ()
@@ -224,81 +223,3 @@ func (c *Client) tunnelHandshake() error {
224223 c .logger .Info ("Tunnel handshaked: %v <-> %v" , c .tunnelTCPConn .LocalAddr (), c .tunnelTCPConn .RemoteAddr ())
225224 return nil
226225}
227-
228- // hybridStart 启动混合穿透模式
229- func (c * Client ) hybridStart () error {
230- udpConn , err := net .DialTimeout ("udp" , c .tunnelTCPAddr .String (), udpDialTimeout )
231- if err != nil {
232- return fmt .Errorf ("hybridStart: STUN dial failed: %w" , err )
233- }
234- defer udpConn .Close ()
235-
236- magic := [4 ]byte {0x21 , 0x12 , 0xA4 , 0x42 }
237-
238- // 构造STUN请求
239- req := make ([]byte , 20 )
240- req [0 ], req [1 ] = 0x00 , 0x01
241- req [4 ], req [5 ], req [6 ], req [7 ] = magic [0 ], magic [1 ], magic [2 ], magic [3 ]
242- rand .Read (req [8 :20 ])
243-
244- // 发送STUN请求
245- if _ , err := udpConn .Write (req ); err != nil {
246- return fmt .Errorf ("hybridStart: STUN write failed: %w" , err )
247- }
248-
249- // 解析STUN响应
250- resp := make ([]byte , 1500 )
251- udpConn .SetReadDeadline (time .Now ().Add (udpReadTimeout ))
252- n , err := udpConn .Read (resp )
253- if err != nil {
254- return fmt .Errorf ("hybridStart: STUN read failed: %w" , err )
255- }
256- if n < 20 || resp [0 ] != 0x01 || resp [1 ] != 0x01 {
257- return fmt .Errorf ("hybridStart: invalid STUN response" )
258- }
259-
260- // 保活NAT映射
261- go func () {
262- dummy := []byte {0 }
263- ticker := time .NewTicker (time .Second )
264- defer ticker .Stop ()
265- for {
266- select {
267- case <- c .ctx .Done ():
268- return
269- case <- ticker .C :
270- udpConn .Write (dummy )
271- }
272- }
273- }()
274-
275- // 查找映射地址
276- var extAddr string
277- for pos := 20 ; pos + 4 <= n ; pos += 4 + int (uint16 (resp [pos + 2 ])<< 8 | uint16 (resp [pos + 3 ])) + (4 - int ((uint16 (resp [pos + 2 ])<< 8 | uint16 (resp [pos + 3 ]))% 4 )) {
278- if uint16 (resp [pos ])<< 8 | uint16 (resp [pos + 1 ]) == 0x0020 && pos + 12 <= n && resp [pos + 5 ] == 0x01 {
279- port := (uint16 (resp [pos + 6 ])<< 8 | uint16 (resp [pos + 7 ])) ^ 0x2112
280- extAddr = net .JoinHostPort (net .IPv4 (resp [pos + 8 ]^ magic [0 ], resp [pos + 9 ]^ magic [1 ], resp [pos + 10 ]^ magic [2 ], resp [pos + 11 ]^ magic [3 ]).String (), fmt .Sprintf ("%d" , port ))
281- break
282- }
283- }
284- if extAddr == "" {
285- return fmt .Errorf ("hybridStart: address not found in STUN response" )
286- }
287-
288- // 设置隧道地址
289- c .tunnelTCPAddr = & net.TCPAddr {IP : net .IPv4zero , Port : udpConn .LocalAddr ().(* net.UDPAddr ).Port }
290- c .tunnelUDPAddr = nil
291-
292- // 初始化隧道监听器
293- if err := c .initTunnelListener (); err != nil {
294- return fmt .Errorf ("hybridStart: initTunnelListener failed: %w" , err )
295- }
296-
297- // 输出映射地址信息
298- c .logger .Info ("External endpoint: %v -> %v -> %v" , extAddr , c .tunnelTCPAddr , c .getTargetAddrsString ())
299-
300- if err := c .singleControl (); err != nil {
301- return fmt .Errorf ("hybridStart: singleControl failed: %w" , err )
302- }
303- return nil
304- }
0 commit comments