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
This commit is contained in:
ginuerzh
2026-06-05 11:18:26 +08:00
parent c6d3238b15
commit 066f6813b2
+13 -1
View File
@@ -120,11 +120,23 @@ func (h *sniHandler) Handle(ctx context.Context, conn net.Conn, opts ...handler.
return rate_limiter.ErrRateLimit return rate_limiter.ErrRateLimit
} }
if h.md.readTimeout > 0 {
conn.SetReadDeadline(time.Now().Add(h.md.readTimeout))
}
br := bufio.NewReader(conn) 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 ro.Proto = proto
dial := func(ctx context.Context, network, address string) (net.Conn, error) { 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 var buf bytes.Buffer
cc, err := h.options.Router.Dial(ictx.ContextWithBuffer(ctx, &buf), "tcp", address) cc, err := h.options.Router.Dial(ictx.ContextWithBuffer(ctx, &buf), "tcp", address)
ro.Route = buf.String() ro.Route = buf.String()