From 3ec3362ac420d49e737f4396367c121a2c23149c Mon Sep 17 00:00:00 2001 From: ginuerzh Date: Sun, 21 Jun 2026 21:19:29 +0800 Subject: [PATCH] fix(handler): forward TLS connections in auto handler to chain router The auto handler only recognized SOCKS4 (0x04), SOCKS5 (0x05), and HTTP (first byte) as protocol indicators. TLS ClientHello bytes (0x16) fell through to the HTTP handler, which called http.ReadRequest() on binary TLS data and returned a malformed-HTTP error. Add protocol sniffing via sniffing.Sniff() to detect TLS. When detected, delegate to sniffing.Sniffer.HandleTLS() which parses the ClientHello for SNI, dials upstream through the chain router (respecting -F config), and proxies the TLS connection transparently. Fixes go-gost/gost#492 --- handler/auto/handler.go | 46 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 45 insertions(+), 1 deletion(-) diff --git a/handler/auto/handler.go b/handler/auto/handler.go index 63b7d386..e78e980c 100644 --- a/handler/auto/handler.go +++ b/handler/auto/handler.go @@ -2,6 +2,7 @@ package auto import ( "bufio" + "bytes" "context" "net" "time" @@ -12,7 +13,10 @@ import ( "github.com/go-gost/gosocks4" "github.com/go-gost/gosocks5" ctxvalue "github.com/go-gost/x/ctx" + ictx "github.com/go-gost/x/internal/ctx" xnet "github.com/go-gost/x/internal/net" + "github.com/go-gost/x/internal/util/sniffing" + xrecorder "github.com/go-gost/x/recorder" "github.com/go-gost/x/registry" ) @@ -94,6 +98,16 @@ func (h *autoHandler) Handle(ctx context.Context, conn net.Conn, opts ...handler } br := bufio.NewReader(conn) + proto, _ := sniffing.Sniff(ctx, br) + + conn = xnet.NewReadWriteConn(br, conn, conn) + + if proto == sniffing.ProtoTLS { + return h.handleTLS(ctx, conn, log) + } + + // Fall back to 1-byte peek for SOCKS4 (0x04) vs SOCKS5 (0x05) vs HTTP. + // Sniff() already read 5 bytes, but the buffered reader exposes them. b, err := br.Peek(1) if err != nil { log.Error(err) @@ -101,7 +115,6 @@ func (h *autoHandler) Handle(ctx context.Context, conn net.Conn, opts ...handler return err } - conn = xnet.NewReadWriteConn(br, conn, conn) switch b[0] { case gosocks4.Ver4: // socks4 if h.socks4Handler != nil { @@ -118,3 +131,34 @@ func (h *autoHandler) Handle(ctx context.Context, conn net.Conn, opts ...handler } return nil } + +// handleTLS forwards a TLS connection that arrived at the auto handler. +// It parses the ClientHello for SNI, dials upstream through the router, +// forwards the ClientHello, records ServerHello metadata, and pipes data +// bidirectionally. +func (h *autoHandler) handleTLS(ctx context.Context, conn net.Conn, log logger.Logger) error { + ro := &xrecorder.HandlerRecorderObject{ + Network: "tcp", + Service: h.options.Service, + RemoteAddr: conn.RemoteAddr().String(), + LocalAddr: conn.LocalAddr().String(), + SID: ctxvalue.SidFromContext(ctx).String(), + Time: time.Now(), + } + sniffer := &sniffing.Sniffer{} + dial := func(ctx context.Context, network, address string) (net.Conn, error) { + var buf bytes.Buffer + cc, err := h.options.Router.Dial(ictx.ContextWithBuffer(ctx, &buf), "tcp", address) + if err != nil { + return nil, err + } + ro.Route = buf.String() + return cc, nil + } + return sniffer.HandleTLS(ctx, "tcp", conn, + sniffing.WithDial(dial), + sniffing.WithBypass(h.options.Bypass), + sniffing.WithRecorderObject(ro), + sniffing.WithLog(log), + ) +}