add tls handshake for recorder

This commit is contained in:
ginuerzh
2024-09-20 21:26:21 +08:00
parent e09ec08881
commit 8934cb6b1c
4 changed files with 70 additions and 32 deletions
+1 -1
View File
@@ -14,7 +14,7 @@ require (
github.com/go-gost/gosocks5 v0.4.2 github.com/go-gost/gosocks5 v0.4.2
github.com/go-gost/plugin v0.1.1 github.com/go-gost/plugin v0.1.1
github.com/go-gost/relay v0.5.0 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/go-redis/redis/v8 v8.11.5
github.com/gobwas/glob v0.2.3 github.com/gobwas/glob v0.2.3
github.com/golang/snappy v0.0.4 github.com/golang/snappy v0.0.4
+2 -2
View File
@@ -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/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 h1:JG1tgy/KWiVXS0ukuVXvbM0kbYuJTWxYpJ5JwzsCf/c=
github.com/go-gost/relay v0.5.0/go.mod h1:lcX+23LCQ3khIeASBo+tJ/WbwXFO32/N5YN6ucuYTG8= 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.1.0 h1:hpgzC/Qt9MMGGie+hLeBAZ379OG72sSc1TRiG7+rahI=
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/go.mod h1:/9QfdewqmHdaE362Hv5nDaSWLx3pCmtD870d6GaquXs=
github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ= 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-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s= github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s=
+34 -27
View File
@@ -25,13 +25,14 @@ import (
xio "github.com/go-gost/x/internal/io" xio "github.com/go-gost/x/internal/io"
netpkg "github.com/go-gost/x/internal/net" netpkg "github.com/go-gost/x/internal/net"
xhttp "github.com/go-gost/x/internal/net/http" 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" rate_limiter "github.com/go-gost/x/limiter/rate"
xrecorder "github.com/go-gost/x/recorder" xrecorder "github.com/go-gost/x/recorder"
"github.com/go-gost/x/registry" "github.com/go-gost/x/registry"
) )
const ( const (
defaultBodySize = 1024 * 1024 * 10 // 10MB defaultBodySize = 1024 * 1024 // 1MB
) )
func init() { func init() {
@@ -100,7 +101,9 @@ func (h *redirectHandler) Handle(ctx context.Context, conn net.Conn, opts ...han
ro.Err = err.Error() ro.Err = err.Error()
} }
ro.Duration = time.Since(start) 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{ 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 { 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) buf := new(bytes.Buffer)
host, err := h.getServerName(ctx, io.TeeReader(rw, buf))
clientHello, err := dissector.ParseClientHello(io.TeeReader(rw, buf))
if err != nil { if err != nil {
log.Error(err)
return 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 var cc io.ReadWriteCloser
host := clientHello.ServerName
if host != "" { if host != "" {
if _, _, err := net.SplitHostPort(host); err != nil { if _, _, err := net.SplitHostPort(host); err != nil {
_, port, _ := net.SplitHostPort(dstAddr.String()) _, port, _ := net.SplitHostPort(dstAddr.String())
@@ -354,9 +364,28 @@ func (h *redirectHandler) handleHTTPS(ctx context.Context, rw io.ReadWriter, rad
} }
defer cc.Close() 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() t := time.Now()
log.Infof("%s <-> %s", raddr, host) 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{ log.WithFields(map[string]any{
"duration": time.Since(t), "duration": time.Since(t),
}).Infof("%s >-< %s", raddr, host) }).Infof("%s >-< %s", raddr, host)
@@ -364,28 +393,6 @@ func (h *redirectHandler) handleHTTPS(ctx context.Context, rw io.ReadWriter, rad
return nil 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 { func (h *redirectHandler) checkRateLimit(addr net.Addr) bool {
if h.options.RateLimiter == nil { if h.options.RateLimiter == nil {
return true return true
+33 -2
View File
@@ -27,13 +27,14 @@ import (
xio "github.com/go-gost/x/internal/io" xio "github.com/go-gost/x/internal/io"
netpkg "github.com/go-gost/x/internal/net" netpkg "github.com/go-gost/x/internal/net"
xhttp "github.com/go-gost/x/internal/net/http" 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" rate_limiter "github.com/go-gost/x/limiter/rate"
xrecorder "github.com/go-gost/x/recorder" xrecorder "github.com/go-gost/x/recorder"
"github.com/go-gost/x/registry" "github.com/go-gost/x/registry"
) )
const ( const (
defaultBodySize = 1024 * 1024 * 10 // 10MB defaultBodySize = 1024 * 1024 // 1MB
) )
func init() { func init() {
@@ -262,6 +263,17 @@ func (h *sniHandler) handleHTTPS(ctx context.Context, rw io.ReadWriter, raddr ne
return err 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 { if _, _, err := net.SplitHostPort(host); err != nil {
host = net.JoinHostPort(strings.Trim(host, "[]"), "443") 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() 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() t := time.Now()
log.Infof("%s <-> %s", raddr, host) 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{ log.WithFields(map[string]any{
"duration": time.Since(t), "duration": time.Since(t),
}).Infof("%s >-< %s", raddr, host) }).Infof("%s >-< %s", raddr, host)