From 8934cb6b1c3564be0c6154ae360cd3b84cfaabce Mon Sep 17 00:00:00 2001 From: ginuerzh Date: Fri, 20 Sep 2024 21:26:21 +0800 Subject: [PATCH] add tls handshake for recorder --- go.mod | 2 +- go.sum | 4 +-- handler/redirect/tcp/handler.go | 61 ++++++++++++++++++--------------- handler/sni/handler.go | 35 +++++++++++++++++-- 4 files changed, 70 insertions(+), 32 deletions(-) diff --git a/go.mod b/go.mod index b073dff3..d51abbec 100644 --- a/go.mod +++ b/go.mod @@ -14,7 +14,7 @@ require ( github.com/go-gost/gosocks5 v0.4.2 github.com/go-gost/plugin v0.1.1 github.com/go-gost/relay v0.5.0 - github.com/go-gost/tls-dissector v0.0.2-0.20220408131628-aac992c27451 + github.com/go-gost/tls-dissector v0.1.0 github.com/go-redis/redis/v8 v8.11.5 github.com/gobwas/glob v0.2.3 github.com/golang/snappy v0.0.4 diff --git a/go.sum b/go.sum index a7b0fd90..3b92688b 100644 --- a/go.sum +++ b/go.sum @@ -63,8 +63,8 @@ github.com/go-gost/plugin v0.1.1 h1:LNoc/Rqwb3ceGhhxwhpjf1SeeYBGe80MJ9E4lpM3qak= github.com/go-gost/plugin v0.1.1/go.mod h1:oN23l+yGDCIP9G3KnDl/I/0zVGOobZUDCB2Z5yYYXts= github.com/go-gost/relay v0.5.0 h1:JG1tgy/KWiVXS0ukuVXvbM0kbYuJTWxYpJ5JwzsCf/c= github.com/go-gost/relay v0.5.0/go.mod h1:lcX+23LCQ3khIeASBo+tJ/WbwXFO32/N5YN6ucuYTG8= -github.com/go-gost/tls-dissector v0.0.2-0.20220408131628-aac992c27451 h1:xj8gUZGYO3nb5+6Bjw9+tsFkA9sYynrOvDvvC4uDV2I= -github.com/go-gost/tls-dissector v0.0.2-0.20220408131628-aac992c27451/go.mod h1:/9QfdewqmHdaE362Hv5nDaSWLx3pCmtD870d6GaquXs= +github.com/go-gost/tls-dissector v0.1.0 h1:hpgzC/Qt9MMGGie+hLeBAZ379OG72sSc1TRiG7+rahI= +github.com/go-gost/tls-dissector v0.1.0/go.mod h1:/9QfdewqmHdaE362Hv5nDaSWLx3pCmtD870d6GaquXs= github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ= github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s= diff --git a/handler/redirect/tcp/handler.go b/handler/redirect/tcp/handler.go index 7b03ecf9..f955a2a3 100644 --- a/handler/redirect/tcp/handler.go +++ b/handler/redirect/tcp/handler.go @@ -25,13 +25,14 @@ import ( xio "github.com/go-gost/x/internal/io" netpkg "github.com/go-gost/x/internal/net" xhttp "github.com/go-gost/x/internal/net/http" + tls_util "github.com/go-gost/x/internal/util/tls" rate_limiter "github.com/go-gost/x/limiter/rate" xrecorder "github.com/go-gost/x/recorder" "github.com/go-gost/x/registry" ) const ( - defaultBodySize = 1024 * 1024 * 10 // 10MB + defaultBodySize = 1024 * 1024 // 1MB ) func init() { @@ -100,7 +101,9 @@ func (h *redirectHandler) Handle(ctx context.Context, conn net.Conn, opts ...han ro.Err = err.Error() } ro.Duration = time.Since(start) - ro.Record(ctx, h.recorder.Recorder) + if err := ro.Record(ctx, h.recorder.Recorder); err != nil { + log.Errorf("record: %v", err) + } } log.WithFields(map[string]any{ @@ -309,14 +312,21 @@ func (h *redirectHandler) handleHTTP(ctx context.Context, rw io.ReadWriter, radd func (h *redirectHandler) handleHTTPS(ctx context.Context, rw io.ReadWriter, raddr, dstAddr net.Addr, ro *xrecorder.HandlerRecorderObject, log logger.Logger) error { buf := new(bytes.Buffer) - host, err := h.getServerName(ctx, io.TeeReader(rw, buf)) + + clientHello, err := dissector.ParseClientHello(io.TeeReader(rw, buf)) if err != nil { - log.Error(err) return err } + ro.TLS = &xrecorder.TLSRecorderObject{ + ServerName: clientHello.ServerName, + } + if len(clientHello.SupportedProtos) > 0 { + ro.TLS.Proto = clientHello.SupportedProtos[0] + } var cc io.ReadWriteCloser + host := clientHello.ServerName if host != "" { if _, _, err := net.SplitHostPort(host); err != nil { _, port, _ := net.SplitHostPort(dstAddr.String()) @@ -354,9 +364,28 @@ func (h *redirectHandler) handleHTTPS(ctx context.Context, rw io.ReadWriter, rad } defer cc.Close() + if _, err := buf.WriteTo(cc); err != nil { + return err + } + + if serverHello, _ := dissector.ParseServerHello(io.TeeReader(cc, buf)); serverHello != nil { + ro.TLS.CipherSuite = tls_util.CipherSuite(serverHello.CipherSuite).String() + ro.TLS.CompressionMethod = serverHello.CompressionMethod + if serverHello.Proto != "" { + ro.TLS.Proto = serverHello.Proto + } + if serverHello.Version > 0 { + ro.TLS.Version = tls_util.Version(serverHello.Version).String() + } + } + + if _, err := buf.WriteTo(rw); err != nil { + return err + } + t := time.Now() log.Infof("%s <-> %s", raddr, host) - netpkg.Transport(xio.NewReadWriter(io.MultiReader(buf, rw), rw), cc) + netpkg.Transport(rw, cc) log.WithFields(map[string]any{ "duration": time.Since(t), }).Infof("%s >-< %s", raddr, host) @@ -364,28 +393,6 @@ func (h *redirectHandler) handleHTTPS(ctx context.Context, rw io.ReadWriter, rad return nil } -func (h *redirectHandler) getServerName(_ context.Context, r io.Reader) (host string, err error) { - record, err := dissector.ReadRecord(r) - if err != nil { - return - } - - clientHello := dissector.ClientHelloMsg{} - if err = clientHello.Decode(record.Opaque); err != nil { - return - } - - for _, ext := range clientHello.Extensions { - if ext.Type() == dissector.ExtServerName { - snExtension := ext.(*dissector.ServerNameExtension) - host = snExtension.Name - break - } - } - - return -} - func (h *redirectHandler) checkRateLimit(addr net.Addr) bool { if h.options.RateLimiter == nil { return true diff --git a/handler/sni/handler.go b/handler/sni/handler.go index abdccb71..d2204a26 100644 --- a/handler/sni/handler.go +++ b/handler/sni/handler.go @@ -27,13 +27,14 @@ import ( xio "github.com/go-gost/x/internal/io" netpkg "github.com/go-gost/x/internal/net" xhttp "github.com/go-gost/x/internal/net/http" + tls_util "github.com/go-gost/x/internal/util/tls" rate_limiter "github.com/go-gost/x/limiter/rate" xrecorder "github.com/go-gost/x/recorder" "github.com/go-gost/x/registry" ) const ( - defaultBodySize = 1024 * 1024 * 10 // 10MB + defaultBodySize = 1024 * 1024 // 1MB ) func init() { @@ -262,6 +263,17 @@ func (h *sniHandler) handleHTTPS(ctx context.Context, rw io.ReadWriter, raddr ne return err } + clientHello, err := dissector.ParseClientHello(bytes.NewReader(buf.Bytes())) + if err != nil { + return err + } + ro.TLS = &xrecorder.TLSRecorderObject{ + ServerName: clientHello.ServerName, + } + if len(clientHello.SupportedProtos) > 0 { + ro.TLS.Proto = clientHello.SupportedProtos[0] + } + if _, _, err := net.SplitHostPort(host); err != nil { host = net.JoinHostPort(strings.Trim(host, "[]"), "443") } @@ -290,9 +302,28 @@ func (h *sniHandler) handleHTTPS(ctx context.Context, rw io.ReadWriter, raddr ne } defer cc.Close() + if _, err := buf.WriteTo(cc); err != nil { + return err + } + + if serverHello, _ := dissector.ParseServerHello(io.TeeReader(cc, buf)); serverHello != nil { + ro.TLS.CipherSuite = tls_util.CipherSuite(serverHello.CipherSuite).String() + ro.TLS.CompressionMethod = serverHello.CompressionMethod + if serverHello.Proto != "" { + ro.TLS.Proto = serverHello.Proto + } + if serverHello.Version > 0 { + ro.TLS.Version = tls_util.Version(serverHello.Version).String() + } + } + + if _, err := buf.WriteTo(rw); err != nil { + return err + } + t := time.Now() log.Infof("%s <-> %s", raddr, host) - netpkg.Transport(xio.NewReadWriter(io.MultiReader(buf, rw), rw), cc) + netpkg.Transport(rw, cc) log.WithFields(map[string]any{ "duration": time.Since(t), }).Infof("%s >-< %s", raddr, host)