|
|
@@ -143,6 +143,10 @@ type socks5UDPSession struct {
|
|
|
udpConn *net.UDPConn
|
|
|
}
|
|
|
|
|
|
+// Bounds dial plus the greeting/auth/associate reads: an accepted-but-silent
|
|
|
+// server otherwise parks Handle, and with it the tunnel's delivery path.
|
|
|
+var socks5AssociateTimeout = 5 * time.Second
|
|
|
+
|
|
|
// newSocks5UDPSession performs the SOCKS5 greeting, username/password auth,
|
|
|
// and UDP ASSOCIATE request/reply by hand: golang.org/x/net/proxy's SOCKS5
|
|
|
// client (used by RelayTCP above) only implements CONNECT, and xray-core's
|
|
|
@@ -150,11 +154,13 @@ type socks5UDPSession struct {
|
|
|
// types, not reusable as a standalone dialer -- so this is a small, direct,
|
|
|
// from-the-RFC implementation rather than an existing library call.
|
|
|
func newSocks5UDPSession(addr, user, password string) (*socks5UDPSession, error) {
|
|
|
- dialer := net.Dialer{Timeout: 5 * time.Second}
|
|
|
+ deadline := time.Now().Add(socks5AssociateTimeout)
|
|
|
+ dialer := net.Dialer{Deadline: deadline}
|
|
|
ctrl, err := dialer.DialContext(context.Background(), "tcp", addr)
|
|
|
if err != nil {
|
|
|
return nil, fmt.Errorf("amneziawgnet: dial SOCKS5 control connection: %w", err)
|
|
|
}
|
|
|
+ _ = ctrl.SetDeadline(deadline)
|
|
|
if err := socks5Handshake(ctrl, user, password); err != nil {
|
|
|
ctrl.Close()
|
|
|
return nil, err
|
|
|
@@ -171,6 +177,7 @@ func newSocks5UDPSession(addr, user, password string) (*socks5UDPSession, error)
|
|
|
ctrl.Close()
|
|
|
return nil, err
|
|
|
}
|
|
|
+ _ = ctrl.SetDeadline(time.Time{})
|
|
|
|
|
|
udpConn, err := net.DialUDP("udp", nil, net.UDPAddrFromAddrPort(bind))
|
|
|
if err != nil {
|