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
This commit is contained in:
+45
-1
@@ -2,6 +2,7 @@ package auto
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bufio"
|
"bufio"
|
||||||
|
"bytes"
|
||||||
"context"
|
"context"
|
||||||
"net"
|
"net"
|
||||||
"time"
|
"time"
|
||||||
@@ -12,7 +13,10 @@ import (
|
|||||||
"github.com/go-gost/gosocks4"
|
"github.com/go-gost/gosocks4"
|
||||||
"github.com/go-gost/gosocks5"
|
"github.com/go-gost/gosocks5"
|
||||||
ctxvalue "github.com/go-gost/x/ctx"
|
ctxvalue "github.com/go-gost/x/ctx"
|
||||||
|
ictx "github.com/go-gost/x/internal/ctx"
|
||||||
xnet "github.com/go-gost/x/internal/net"
|
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"
|
"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)
|
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)
|
b, err := br.Peek(1)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error(err)
|
log.Error(err)
|
||||||
@@ -101,7 +115,6 @@ func (h *autoHandler) Handle(ctx context.Context, conn net.Conn, opts ...handler
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
conn = xnet.NewReadWriteConn(br, conn, conn)
|
|
||||||
switch b[0] {
|
switch b[0] {
|
||||||
case gosocks4.Ver4: // socks4
|
case gosocks4.Ver4: // socks4
|
||||||
if h.socks4Handler != nil {
|
if h.socks4Handler != nil {
|
||||||
@@ -118,3 +131,34 @@ func (h *autoHandler) Handle(ctx context.Context, conn net.Conn, opts ...handler
|
|||||||
}
|
}
|
||||||
return nil
|
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),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user