From c62a1da1611ed6a52893bc81108c31788b625065 Mon Sep 17 00:00:00 2001 From: fatedier Date: Fri, 6 Mar 2026 15:18:38 +0800 Subject: [PATCH] fix: close connections on error paths to prevent resource leaks (#5202) Fix connection leaks in multiple error paths across client and server: - server/proxy/http: close tmpConn when WithEncryption fails - client/proxy: close localConn when ProxyProtocol WriteTo fails - client/visitor/sudp: close visitorConn on all error paths in getNewVisitorConn - client/visitor/xtcp: close tunnelConn when WithEncryption fails - client/visitor/xtcp: close lConn when NewKCPConnFromUDP fails - pkg/plugin/client/unix_domain_socket: close localConn and connInfo.Conn when WriteTo fails, close connInfo.Conn when DialUnix fails - pkg/plugin/client/tls2raw: close tlsConn when Handshake or Dial fails --- client/proxy/proxy.go | 1 + client/visitor/sudp.go | 4 ++++ client/visitor/xtcp.go | 2 ++ pkg/plugin/client/tls2raw.go | 2 ++ pkg/plugin/client/unix_domain_socket.go | 3 +++ server/proxy/http.go | 1 + 6 files changed, 13 insertions(+) diff --git a/client/proxy/proxy.go b/client/proxy/proxy.go index 8faff38d..ca7d905b 100644 --- a/client/proxy/proxy.go +++ b/client/proxy/proxy.go @@ -209,6 +209,7 @@ func (pxy *BaseProxy) HandleTCPWorkConnection(workConn net.Conn, m *msg.StartWor if connInfo.ProxyProtocolHeader != nil { if _, err := connInfo.ProxyProtocolHeader.WriteTo(localConn); err != nil { workConn.Close() + localConn.Close() xl.Errorf("write proxy protocol header to local conn error: %v", err) return } diff --git a/client/visitor/sudp.go b/client/visitor/sudp.go index 67b4c214..a341da8a 100644 --- a/client/visitor/sudp.go +++ b/client/visitor/sudp.go @@ -217,6 +217,7 @@ func (sv *SUDPVisitor) getNewVisitorConn() (net.Conn, error) { } err = msg.WriteMsg(visitorConn, newVisitorConnMsg) if err != nil { + visitorConn.Close() return nil, fmt.Errorf("frpc send newVisitorConnMsg to frps error: %v", err) } @@ -224,11 +225,13 @@ func (sv *SUDPVisitor) getNewVisitorConn() (net.Conn, error) { _ = visitorConn.SetReadDeadline(time.Now().Add(10 * time.Second)) err = msg.ReadMsgInto(visitorConn, &newVisitorConnRespMsg) if err != nil { + visitorConn.Close() return nil, fmt.Errorf("frpc read newVisitorConnRespMsg error: %v", err) } _ = visitorConn.SetReadDeadline(time.Time{}) if newVisitorConnRespMsg.Error != "" { + visitorConn.Close() return nil, fmt.Errorf("start new visitor connection error: %s", newVisitorConnRespMsg.Error) } @@ -238,6 +241,7 @@ func (sv *SUDPVisitor) getNewVisitorConn() (net.Conn, error) { remote, err = libio.WithEncryption(remote, []byte(sv.cfg.SecretKey)) if err != nil { xl.Errorf("create encryption stream error: %v", err) + visitorConn.Close() return nil, err } } diff --git a/client/visitor/xtcp.go b/client/visitor/xtcp.go index dcfba505..2273a271 100644 --- a/client/visitor/xtcp.go +++ b/client/visitor/xtcp.go @@ -211,6 +211,7 @@ func (sv *XTCPVisitor) handleConn(userConn net.Conn) { muxConnRWCloser, err = libio.WithEncryption(muxConnRWCloser, []byte(sv.cfg.SecretKey)) if err != nil { xl.Errorf("create encryption stream error: %v", err) + tunnelConn.Close() tunnelErr = err return } @@ -373,6 +374,7 @@ func (ks *KCPTunnelSession) Init(listenConn *net.UDPConn, raddr *net.UDPAddr) er } remote, err := netpkg.NewKCPConnFromUDP(lConn, true, raddr.String()) if err != nil { + lConn.Close() return fmt.Errorf("create kcp connection from udp connection error: %v", err) } diff --git a/pkg/plugin/client/tls2raw.go b/pkg/plugin/client/tls2raw.go index 445b6c91..ccb75149 100644 --- a/pkg/plugin/client/tls2raw.go +++ b/pkg/plugin/client/tls2raw.go @@ -62,11 +62,13 @@ func (p *TLS2RawPlugin) Handle(ctx context.Context, connInfo *ConnectionInfo) { if err := tlsConn.Handshake(); err != nil { xl.Warnf("tls handshake error: %v", err) + tlsConn.Close() return } rawConn, err := net.Dial("tcp", p.opts.LocalAddr) if err != nil { xl.Warnf("dial to local addr error: %v", err) + tlsConn.Close() return } diff --git a/pkg/plugin/client/unix_domain_socket.go b/pkg/plugin/client/unix_domain_socket.go index 52d9c652..3046aade 100644 --- a/pkg/plugin/client/unix_domain_socket.go +++ b/pkg/plugin/client/unix_domain_socket.go @@ -54,10 +54,13 @@ func (uds *UnixDomainSocketPlugin) Handle(ctx context.Context, connInfo *Connect localConn, err := net.DialUnix("unix", nil, uds.UnixAddr) if err != nil { xl.Warnf("dial to uds %s error: %v", uds.UnixAddr, err) + connInfo.Conn.Close() return } if connInfo.ProxyProtocolHeader != nil { if _, err := connInfo.ProxyProtocolHeader.WriteTo(localConn); err != nil { + localConn.Close() + connInfo.Conn.Close() return } } diff --git a/server/proxy/http.go b/server/proxy/http.go index 2c4f1fd4..6f0eb008 100644 --- a/server/proxy/http.go +++ b/server/proxy/http.go @@ -168,6 +168,7 @@ func (pxy *HTTPProxy) GetRealConn(remoteAddr string) (workConn net.Conn, err err rwc, err = libio.WithEncryption(rwc, pxy.encryptionKey) if err != nil { xl.Errorf("create encryption stream error: %v", err) + tmpConn.Close() return } }