diff --git a/listener/tun/ipstack/gvisor/tcp.go b/listener/tun/ipstack/gvisor/tcp.go
index 660912cb..b5dad6ea 100644
--- a/listener/tun/ipstack/gvisor/tcp.go
+++ b/listener/tun/ipstack/gvisor/tcp.go
@@ -1,10 +1,10 @@
-//go:build !no_gvisor
-
 package gvisor
 
 import (
+	"net"
 	"time"
 
+	"github.com/Dreamacro/clash/common/pool"
 	"github.com/Dreamacro/clash/listener/tun/ipstack/gvisor/adapter"
 	"github.com/Dreamacro/clash/listener/tun/ipstack/gvisor/option"
 	"github.com/Dreamacro/clash/log"
@@ -20,17 +20,17 @@ import (
 const (
 	// defaultWndSize if set to zero, the default
 	// receive window buffer size is used instead.
-	defaultWndSize = 0
+	defaultWndSize = pool.RelayBufferSize
 
 	// maxConnAttempts specifies the maximum number
 	// of in-flight tcp connection attempts.
-	maxConnAttempts = 2 << 10
+	maxConnAttempts = 1 << 10
 
 	// tcpKeepaliveCount is the maximum number of
 	// TCP keep-alive probes to send before giving up
 	// and killing the connection if no response is
 	// obtained from the other end.
-	tcpKeepaliveCount = 9
+	tcpKeepaliveCount = 8
 
 	// tcpKeepaliveIdle specifies the time a connection
 	// must remain idle before the first TCP keepalive
@@ -66,18 +66,26 @@ func withTCPHandler(handle adapter.TCPHandleFunc) option.Option {
 				r.Complete(true)
 				return
 			}
-			defer r.Complete(false)
 
 			err = setSocketOptions(s, ep)
 			if err != nil {
+				ep.Close()
 				r.Complete(true)
 				return
 			}
+			defer r.Complete(false)
 
 			conn := &tcpConn{
 				TCPConn: gonet.NewTCPConn(&wq, ep),
 				id:      id,
 			}
+
+			if conn.RemoteAddr() == nil {
+				log.Warnln("[STACK] endpoint is not connected, current state: %v", tcp.EndpointState(ep.State()))
+				_ = conn.Close()
+				return
+			}
+
 			handle(conn)
 		})
 		s.SetTransportProtocolHandler(tcp.ProtocolNumber, tcpForwarder.HandlePacket)
@@ -125,3 +133,17 @@ type tcpConn struct {
 func (c *tcpConn) ID() *stack.TransportEndpointID {
 	return &c.id
 }
+
+func (c *tcpConn) LocalAddr() net.Addr {
+	return &net.TCPAddr{
+		IP:   net.IP(c.id.LocalAddress),
+		Port: int(c.id.LocalPort),
+	}
+}
+
+func (c *tcpConn) RemoteAddr() net.Addr {
+	return &net.TCPAddr{
+		IP:   net.IP(c.id.RemoteAddress),
+		Port: int(c.id.RemotePort),
+	}
+}
diff --git a/listener/tun/ipstack/gvisor/udp.go b/listener/tun/ipstack/gvisor/udp.go
index f010ed8a..7abdd046 100644
--- a/listener/tun/ipstack/gvisor/udp.go
+++ b/listener/tun/ipstack/gvisor/udp.go
@@ -49,6 +49,20 @@ func (c *udpConn) ID() *stack.TransportEndpointID {
 	return &c.id
 }
 
+func (c *udpConn) LocalAddr() net.Addr {
+	return &net.UDPAddr{
+		IP:   net.IP(c.id.LocalAddress),
+		Port: int(c.id.LocalPort),
+	}
+}
+
+func (c *udpConn) RemoteAddr() net.Addr {
+	return &net.UDPAddr{
+		IP:   net.IP(c.id.RemoteAddress),
+		Port: int(c.id.RemotePort),
+	}
+}
+
 type packet struct {
 	pc      adapter.UDPConn
 	rAddr   net.Addr