From 066f6813b2201286cc5cd6224704d6a3b7aeb9cb Mon Sep 17 00:00:00 2001 From: ginuerzh Date: Fri, 5 Jun 2026 11:18:26 +0800 Subject: [PATCH] fix(handler/sni): add sniff deadline, log sniff errors, nil Router guard - Set read deadline before/after sniffing.Sniff to prevent goroutine leak from slow clients (matches redirect/tcp and ss patterns) - Log sniff errors at Debug level instead of silently discarding them - Add nil Router check in dial closure to prevent NPE panic --- handler/sni/handler.go | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/handler/sni/handler.go b/handler/sni/handler.go index 2f505a4d..1ea899ce 100644 --- a/handler/sni/handler.go +++ b/handler/sni/handler.go @@ -120,11 +120,23 @@ func (h *sniHandler) Handle(ctx context.Context, conn net.Conn, opts ...handler. return rate_limiter.ErrRateLimit } + if h.md.readTimeout > 0 { + conn.SetReadDeadline(time.Now().Add(h.md.readTimeout)) + } br := bufio.NewReader(conn) - proto, _ := sniffing.Sniff(ctx, br) + proto, sniffErr := sniffing.Sniff(ctx, br) + if h.md.readTimeout > 0 { + conn.SetReadDeadline(time.Time{}) + } + if sniffErr != nil { + log.Debugf("sniff: %v", sniffErr) + } ro.Proto = proto dial := func(ctx context.Context, network, address string) (net.Conn, error) { + if h.options.Router == nil { + return nil, errors.New("sni: router not available") + } var buf bytes.Buffer cc, err := h.options.Router.Dial(ictx.ContextWithBuffer(ctx, &buf), "tcp", address) ro.Route = buf.String()