diff --git a/go.mod b/go.mod index bd66e157..c539506b 100644 --- a/go.mod +++ b/go.mod @@ -9,7 +9,7 @@ require ( github.com/asaskevich/govalidator v0.0.0-20210307081110-f21760c49a8d github.com/gin-contrib/cors v1.6.0 github.com/gin-gonic/gin v1.9.1 - github.com/go-gost/core v0.1.6 + github.com/go-gost/core v0.1.7 github.com/go-gost/gosocks4 v0.0.1 github.com/go-gost/gosocks5 v0.4.2 github.com/go-gost/plugin v0.1.1 diff --git a/go.sum b/go.sum index 83b6c35c..967566e0 100644 --- a/go.sum +++ b/go.sum @@ -53,8 +53,8 @@ github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI= github.com/gin-gonic/gin v1.9.1 h1:4idEAncQnU5cB7BeOkPtxjfCSye0AAm1R0RVIqJ+Jmg= github.com/gin-gonic/gin v1.9.1/go.mod h1:hPrL7YrpYKXt5YId3A/Tnip5kqbEAP+KLuI3SUcPTeU= -github.com/go-gost/core v0.1.6 h1:0Vdck2qrcfi1jz5f7fhfj+Uu0qvZhCdTdIisa5NDa98= -github.com/go-gost/core v0.1.6/go.mod h1:WGI43jOka7FAsSAwi/fSMaqxdR+E339ycb4NBGlFr6A= +github.com/go-gost/core v0.1.7 h1:EP2Ux2SZR1omV6362MfTZG+oZTuaAODGqc0M9c/ZdEI= +github.com/go-gost/core v0.1.7/go.mod h1:WGI43jOka7FAsSAwi/fSMaqxdR+E339ycb4NBGlFr6A= github.com/go-gost/gosocks4 v0.0.1 h1:+k1sec8HlELuQV7rWftIkmy8UijzUt2I6t+iMPlGB2s= github.com/go-gost/gosocks4 v0.0.1/go.mod h1:3B6L47HbU/qugDg4JnoFPHgJXE43Inz8Bah1QaN9qCc= github.com/go-gost/gosocks5 v0.4.2 h1:IianxHTkACPqCwiOAT3MHoMdSUl+SEPSRu1ikawC1Pc= diff --git a/handler/dns/handler.go b/handler/dns/handler.go index 4b61e3c9..3004b340 100644 --- a/handler/dns/handler.go +++ b/handler/dns/handler.go @@ -16,11 +16,13 @@ import ( "github.com/go-gost/core/hosts" "github.com/go-gost/core/logger" md "github.com/go-gost/core/metadata" + "github.com/go-gost/core/observer/stats" "github.com/go-gost/core/recorder" ctxvalue "github.com/go-gost/x/ctx" xhop "github.com/go-gost/x/hop" resolver_util "github.com/go-gost/x/internal/util/resolver" rate_limiter "github.com/go-gost/x/limiter/rate" + stats_wrapper "github.com/go-gost/x/observer/stats/wrapper" xrecorder "github.com/go-gost/x/recorder" "github.com/go-gost/x/registry" "github.com/go-gost/x/resolver/exchanger" @@ -152,11 +154,17 @@ func (h *dnsHandler) Handle(ctx context.Context, conn net.Conn, opts ...handler. }) log.Infof("%s <> %s", conn.RemoteAddr(), conn.LocalAddr()) + + pStats := stats.Stats{} + conn = stats_wrapper.WrapConn(conn, &pStats) + defer func() { ro.Duration = time.Since(start) if err != nil { ro.Err = err.Error() } + ro.InputBytes = pStats.Get(stats.KindInputBytes) + ro.OutputBytes = pStats.Get(stats.KindOutputBytes) if err := ro.Record(ctx, h.recorder.Recorder); err != nil { log.Warnf("recorder: %v", err) } diff --git a/handler/http/handler.go b/handler/http/handler.go index f2a83f44..b923b81c 100644 --- a/handler/http/handler.go +++ b/handler/http/handler.go @@ -119,10 +119,16 @@ func (h *httpHandler) Handle(ctx context.Context, conn net.Conn, opts ...handler "sid": ctxvalue.SidFromContext(ctx), }) log.Infof("%s <> %s", conn.RemoteAddr(), conn.LocalAddr()) + + pStats := stats.Stats{} + conn = stats_wrapper.WrapConn(conn, &pStats) + defer func() { if err != nil { ro.Err = err.Error() } + ro.InputBytes = pStats.Get(stats.KindInputBytes) + ro.OutputBytes = pStats.Get(stats.KindOutputBytes) ro.Duration = time.Since(start) if err := ro.Record(ctx, h.recorder.Recorder); err != nil { log.Error("record: %v", err) diff --git a/handler/redirect/tcp/handler.go b/handler/redirect/tcp/handler.go index 247d7fe0..4f39a800 100644 --- a/handler/redirect/tcp/handler.go +++ b/handler/redirect/tcp/handler.go @@ -12,6 +12,7 @@ import ( "github.com/go-gost/core/handler" md "github.com/go-gost/core/metadata" + "github.com/go-gost/core/observer/stats" "github.com/go-gost/core/recorder" xbypass "github.com/go-gost/x/bypass" ctxvalue "github.com/go-gost/x/ctx" @@ -19,14 +20,11 @@ import ( "github.com/go-gost/x/internal/util/sniffing" tls_util "github.com/go-gost/x/internal/util/tls" rate_limiter "github.com/go-gost/x/limiter/rate" + stats_wrapper "github.com/go-gost/x/observer/stats/wrapper" xrecorder "github.com/go-gost/x/recorder" "github.com/go-gost/x/registry" ) -const ( - defaultBodySize = 1024 * 1024 // 1MB -) - func init() { registry.HandlerRegistry().Register("red", NewHandler) registry.HandlerRegistry().Register("redir", NewHandler) @@ -90,12 +88,17 @@ func (h *redirectHandler) Handle(ctx context.Context, conn net.Conn, opts ...han "local": conn.LocalAddr().String(), "sid": ctxvalue.SidFromContext(ctx), }) - log.Infof("%s <> %s", conn.RemoteAddr(), conn.LocalAddr()) + + pStats := stats.Stats{} + conn = stats_wrapper.WrapConn(conn, &pStats) + defer func() { if err != nil { ro.Err = err.Error() } + ro.InputBytes = pStats.Get(stats.KindInputBytes) + ro.OutputBytes = pStats.Get(stats.KindOutputBytes) ro.Duration = time.Since(start) if err := ro.Record(ctx, h.recorder.Recorder); err != nil { log.Errorf("record: %v", err) diff --git a/handler/redirect/udp/handler.go b/handler/redirect/udp/handler.go index c878766b..0df07406 100644 --- a/handler/redirect/udp/handler.go +++ b/handler/redirect/udp/handler.go @@ -9,11 +9,13 @@ import ( "github.com/go-gost/core/handler" md "github.com/go-gost/core/metadata" + "github.com/go-gost/core/observer/stats" "github.com/go-gost/core/recorder" xbypass "github.com/go-gost/x/bypass" ctxvalue "github.com/go-gost/x/ctx" xnet "github.com/go-gost/x/internal/net" rate_limiter "github.com/go-gost/x/limiter/rate" + stats_wrapper "github.com/go-gost/x/observer/stats/wrapper" xrecorder "github.com/go-gost/x/recorder" "github.com/go-gost/x/registry" ) @@ -75,12 +77,20 @@ func (h *redirectHandler) Handle(ctx context.Context, conn net.Conn, opts ...han }) log.Infof("%s <> %s", conn.RemoteAddr(), conn.LocalAddr()) + + pStats := stats.Stats{} + conn = stats_wrapper.WrapConn(conn, &pStats) + defer func() { if err != nil { ro.Err = err.Error() } ro.Duration = time.Since(start) - ro.Record(ctx, h.recorder.Recorder) + ro.InputBytes = pStats.Get(stats.KindInputBytes) + ro.OutputBytes = pStats.Get(stats.KindOutputBytes) + if err := ro.Record(ctx, h.recorder.Recorder); err != nil { + log.Error("record: %v", err) + } log.WithFields(map[string]any{ "duration": time.Since(start), diff --git a/handler/relay/handler.go b/handler/relay/handler.go index f61c2423..9075624a 100644 --- a/handler/relay/handler.go +++ b/handler/relay/handler.go @@ -11,6 +11,7 @@ import ( "github.com/go-gost/core/hop" "github.com/go-gost/core/limiter/traffic" md "github.com/go-gost/core/metadata" + "github.com/go-gost/core/observer/stats" "github.com/go-gost/core/recorder" "github.com/go-gost/relay" ctxvalue "github.com/go-gost/x/ctx" @@ -18,6 +19,7 @@ import ( stats_util "github.com/go-gost/x/internal/util/stats" tls_util "github.com/go-gost/x/internal/util/tls" rate_limiter "github.com/go-gost/x/limiter/rate" + stats_wrapper "github.com/go-gost/x/observer/stats/wrapper" xrecorder "github.com/go-gost/x/recorder" "github.com/go-gost/x/registry" ) @@ -112,12 +114,19 @@ func (h *relayHandler) Handle(ctx context.Context, conn net.Conn, opts ...handle log.Infof("%s <> %s", conn.RemoteAddr(), conn.LocalAddr()) + pStats := stats.Stats{} + conn = stats_wrapper.WrapConn(conn, &pStats) + defer func() { if err != nil { ro.Err = err.Error() } + ro.InputBytes = pStats.Get(stats.KindInputBytes) + ro.OutputBytes = pStats.Get(stats.KindOutputBytes) 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{ "duration": time.Since(start), diff --git a/handler/sni/handler.go b/handler/sni/handler.go index b77aa3bc..a78b6248 100644 --- a/handler/sni/handler.go +++ b/handler/sni/handler.go @@ -11,20 +11,18 @@ import ( "github.com/go-gost/core/handler" md "github.com/go-gost/core/metadata" + "github.com/go-gost/core/observer/stats" "github.com/go-gost/core/recorder" ctxvalue "github.com/go-gost/x/ctx" xnet "github.com/go-gost/x/internal/net" "github.com/go-gost/x/internal/util/sniffing" tls_util "github.com/go-gost/x/internal/util/tls" rate_limiter "github.com/go-gost/x/limiter/rate" + stats_wrapper "github.com/go-gost/x/observer/stats/wrapper" xrecorder "github.com/go-gost/x/recorder" "github.com/go-gost/x/registry" ) -const ( - defaultBodySize = 1024 * 1024 // 1MB -) - func init() { registry.HandlerRegistry().Register("sni", NewHandler) } @@ -90,10 +88,16 @@ func (h *sniHandler) Handle(ctx context.Context, conn net.Conn, opts ...handler. }) log.Infof("%s <> %s", conn.RemoteAddr(), conn.LocalAddr()) + + pStats := stats.Stats{} + conn = stats_wrapper.WrapConn(conn, &pStats) + defer func() { if err != nil { ro.Err = err.Error() } + ro.InputBytes = pStats.Get(stats.KindInputBytes) + ro.OutputBytes = pStats.Get(stats.KindOutputBytes) ro.Duration = time.Since(start) if err := ro.Record(ctx, h.recorder.Recorder); err != nil { log.Errorf("record: %v", err) diff --git a/handler/socks/v4/handler.go b/handler/socks/v4/handler.go index ff8304a0..c390131d 100644 --- a/handler/socks/v4/handler.go +++ b/handler/socks/v4/handler.go @@ -112,14 +112,21 @@ func (h *socks4Handler) Handle(ctx context.Context, conn net.Conn, opts ...handl "local": conn.LocalAddr().String(), "sid": ctxvalue.SidFromContext(ctx), }) - log.Infof("%s <> %s", conn.RemoteAddr(), conn.LocalAddr()) + + pStats := stats.Stats{} + conn = stats_wrapper.WrapConn(conn, &pStats) + defer func() { if err != nil { ro.Err = err.Error() } + ro.InputBytes = pStats.Get(stats.KindInputBytes) + ro.OutputBytes = pStats.Get(stats.KindOutputBytes) 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{ "duration": time.Since(start), diff --git a/handler/socks/v5/handler.go b/handler/socks/v5/handler.go index 20613d1f..f57efd69 100644 --- a/handler/socks/v5/handler.go +++ b/handler/socks/v5/handler.go @@ -9,6 +9,7 @@ import ( "github.com/go-gost/core/handler" "github.com/go-gost/core/limiter/traffic" md "github.com/go-gost/core/metadata" + "github.com/go-gost/core/observer/stats" "github.com/go-gost/core/recorder" "github.com/go-gost/gosocks5" ctxvalue "github.com/go-gost/x/ctx" @@ -17,6 +18,7 @@ import ( stats_util "github.com/go-gost/x/internal/util/stats" tls_util "github.com/go-gost/x/internal/util/tls" rate_limiter "github.com/go-gost/x/limiter/rate" + stats_wrapper "github.com/go-gost/x/observer/stats/wrapper" xrecorder "github.com/go-gost/x/recorder" "github.com/go-gost/x/registry" ) @@ -110,14 +112,21 @@ func (h *socks5Handler) Handle(ctx context.Context, conn net.Conn, opts ...handl "local": conn.LocalAddr().String(), "sid": ctxvalue.SidFromContext(ctx), }) - log.Infof("%s <> %s", conn.RemoteAddr(), conn.LocalAddr()) + + pStats := stats.Stats{} + conn = stats_wrapper.WrapConn(conn, &pStats) + defer func() { if err != nil { ro.Err = err.Error() } + ro.InputBytes = pStats.Get(stats.KindInputBytes) + ro.OutputBytes = pStats.Get(stats.KindOutputBytes) 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{ "duration": time.Since(start), diff --git a/handler/ss/handler.go b/handler/ss/handler.go index d2dfa5ca..57b11264 100644 --- a/handler/ss/handler.go +++ b/handler/ss/handler.go @@ -11,6 +11,7 @@ import ( "github.com/go-gost/core/handler" md "github.com/go-gost/core/metadata" + "github.com/go-gost/core/observer/stats" "github.com/go-gost/core/recorder" "github.com/go-gost/gosocks5" ctxvalue "github.com/go-gost/x/ctx" @@ -19,6 +20,7 @@ import ( "github.com/go-gost/x/internal/util/ss" tls_util "github.com/go-gost/x/internal/util/tls" rate_limiter "github.com/go-gost/x/limiter/rate" + stats_wrapper "github.com/go-gost/x/observer/stats/wrapper" xrecorder "github.com/go-gost/x/recorder" "github.com/go-gost/x/registry" "github.com/shadowsocks/go-shadowsocks2/core" @@ -94,14 +96,21 @@ func (h *ssHandler) Handle(ctx context.Context, conn net.Conn, opts ...handler.H "local": conn.LocalAddr().String(), "sid": ctxvalue.SidFromContext(ctx), }) - log.Infof("%s <> %s", conn.RemoteAddr(), conn.LocalAddr()) + + pStats := stats.Stats{} + conn = stats_wrapper.WrapConn(conn, &pStats) + defer func() { if err != nil { ro.Err = err.Error() } + ro.InputBytes = pStats.Get(stats.KindInputBytes) + ro.OutputBytes = pStats.Get(stats.KindOutputBytes) 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{ "duration": time.Since(start), diff --git a/handler/sshd/handler.go b/handler/sshd/handler.go index b961d5a6..06ce5b58 100644 --- a/handler/sshd/handler.go +++ b/handler/sshd/handler.go @@ -15,6 +15,7 @@ import ( "github.com/go-gost/core/handler" "github.com/go-gost/core/logger" md "github.com/go-gost/core/metadata" + "github.com/go-gost/core/observer/stats" "github.com/go-gost/core/recorder" xbypass "github.com/go-gost/x/bypass" ctxvalue "github.com/go-gost/x/ctx" @@ -23,6 +24,7 @@ import ( sshd_util "github.com/go-gost/x/internal/util/sshd" tls_util "github.com/go-gost/x/internal/util/tls" rate_limiter "github.com/go-gost/x/limiter/rate" + stats_wrapper "github.com/go-gost/x/observer/stats/wrapper" xrecorder "github.com/go-gost/x/recorder" "github.com/go-gost/x/registry" "golang.org/x/crypto/ssh" @@ -94,14 +96,21 @@ func (h *forwardHandler) Handle(ctx context.Context, conn net.Conn, opts ...hand "local": conn.LocalAddr().String(), "sid": ctxvalue.SidFromContext(ctx), }) - log.Infof("%s <> %s", conn.RemoteAddr(), conn.LocalAddr()) + + pStats := stats.Stats{} + conn = stats_wrapper.WrapConn(conn, &pStats) + defer func() { if err != nil { ro.Err = err.Error() } + ro.InputBytes = pStats.Get(stats.KindInputBytes) + ro.OutputBytes = pStats.Get(stats.KindOutputBytes) 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{ "duration": time.Since(start), diff --git a/handler/unix/handler.go b/handler/unix/handler.go index 01ddb110..837c04de 100644 --- a/handler/unix/handler.go +++ b/handler/unix/handler.go @@ -14,12 +14,14 @@ import ( "github.com/go-gost/core/hop" "github.com/go-gost/core/logger" md "github.com/go-gost/core/metadata" + "github.com/go-gost/core/observer/stats" "github.com/go-gost/core/recorder" ctxvalue "github.com/go-gost/x/ctx" xio "github.com/go-gost/x/internal/io" xnet "github.com/go-gost/x/internal/net" "github.com/go-gost/x/internal/util/sniffing" tls_util "github.com/go-gost/x/internal/util/tls" + stats_wrapper "github.com/go-gost/x/observer/stats/wrapper" xrecorder "github.com/go-gost/x/recorder" "github.com/go-gost/x/registry" ) @@ -91,14 +93,21 @@ func (h *unixHandler) Handle(ctx context.Context, conn net.Conn, opts ...handler "local": conn.LocalAddr().String(), "sid": ctxvalue.SidFromContext(ctx), }) - log.Infof("%s <> %s", conn.RemoteAddr(), conn.LocalAddr()) + + pStats := stats.Stats{} + conn = stats_wrapper.WrapConn(conn, &pStats) + defer func() { if err != nil { ro.Err = err.Error() } + ro.InputBytes = pStats.Get(stats.KindInputBytes) + ro.OutputBytes = pStats.Get(stats.KindOutputBytes) 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{ "duration": time.Since(start), diff --git a/internal/util/sniffing/sniffer.go b/internal/util/sniffing/sniffer.go index cddf9979..b78964ac 100644 --- a/internal/util/sniffing/sniffer.go +++ b/internal/util/sniffing/sniffer.go @@ -19,6 +19,7 @@ import ( "github.com/go-gost/core/bypass" "github.com/go-gost/core/logger" + "github.com/go-gost/core/observer/stats" "github.com/go-gost/core/recorder" dissector "github.com/go-gost/tls-dissector" xbypass "github.com/go-gost/x/bypass" @@ -26,6 +27,7 @@ import ( xnet "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" + stats_wrapper "github.com/go-gost/x/observer/stats/wrapper" xrecorder "github.com/go-gost/x/recorder" "golang.org/x/net/http2" ) @@ -100,17 +102,22 @@ func (h *Sniffer) HandleHTTP(ctx context.Context, conn net.Conn, opts ...HandleO opt(&o) } + ro := o.RecorderObject + log := o.Log + + pStats := stats.Stats{} + conn = stats_wrapper.WrapConn(conn, &pStats) + br := bufio.NewReader(conn) req, err := http.ReadRequest(br) if err != nil { return err } - if o.Log.IsLevelEnabled(logger.TraceLevel) { + if log.IsLevelEnabled(logger.TraceLevel) { dump, _ := httputil.DumpRequest(req, false) - o.Log.Trace(string(dump)) + log.Trace(string(dump)) } - ro := o.RecorderObject host := req.Host if host != "" { if _, _, err := net.SplitHostPort(host); err != nil { @@ -118,7 +125,7 @@ func (h *Sniffer) HandleHTTP(ctx context.Context, conn net.Conn, opts ...HandleO } ro.Host = host - o.Log = o.Log.WithFields(map[string]any{ + log = log.WithFields(map[string]any{ "host": host, }) @@ -168,7 +175,7 @@ func (h *Sniffer) HandleHTTP(ctx context.Context, conn net.Conn, opts ...HandleO recorder: h.Recorder, recorderOptions: h.RecorderOptions, recorderObject: ro, - log: o.Log, + log: log, }, }) return nil @@ -186,12 +193,14 @@ func (h *Sniffer) HandleHTTP(ctx context.Context, conn net.Conn, opts ...HandleO ro.Time = time.Time{} - shouldClose, err := h.httpRoundTrip(ctx, conn, cc, req, &o) + shouldClose, err := h.httpRoundTrip(ctx, conn, cc, req, ro, &pStats, log) if err != nil || shouldClose { return err } for { + pStats.Reset() + req, err := http.ReadRequest(br) if err != nil { if errors.Is(err, io.EOF) || errors.Is(err, net.ErrClosed) { @@ -200,35 +209,38 @@ func (h *Sniffer) HandleHTTP(ctx context.Context, conn net.Conn, opts ...HandleO return err } - if o.Log.IsLevelEnabled(logger.TraceLevel) { + if log.IsLevelEnabled(logger.TraceLevel) { dump, _ := httputil.DumpRequest(req, false) - o.Log.Trace(string(dump)) + log.Trace(string(dump)) } - if shouldClose, err := h.httpRoundTrip(ctx, conn, cc, req, &o); err != nil || shouldClose { + if shouldClose, err := h.httpRoundTrip(ctx, conn, cc, req, ro, &pStats, log); err != nil || shouldClose { return err } } } -func (h *Sniffer) httpRoundTrip(ctx context.Context, rw, cc io.ReadWriter, req *http.Request, o *HandleOptions) (close bool, err error) { +func (h *Sniffer) httpRoundTrip(ctx context.Context, rw, cc io.ReadWriter, req *http.Request, ro *xrecorder.HandlerRecorderObject, pStats *stats.Stats, log logger.Logger) (close bool, err error) { close = true - ro := &xrecorder.HandlerRecorderObject{} - *ro = *o.RecorderObject + ro2 := &xrecorder.HandlerRecorderObject{} + *ro2 = *ro + ro = ro2 ro.Time = time.Now() - o.Log.Infof("%s <-> %s", ro.RemoteAddr, req.Host) + log.Infof("%s <-> %s", ro.RemoteAddr, req.Host) defer func() { - ro.Duration = time.Since(ro.Time) if err != nil { ro.Err = err.Error() } + ro.InputBytes = pStats.Get(stats.KindInputBytes) + ro.OutputBytes = pStats.Get(stats.KindOutputBytes) + ro.Duration = time.Since(ro.Time) if err := ro.Record(ctx, h.Recorder); err != nil { - o.Log.Errorf("record: %v", err) + log.Errorf("record: %v", err) } - o.Log.WithFields(map[string]any{ + log.WithFields(map[string]any{ "duration": time.Since(ro.Time), }).Infof("%s >-< %s", ro.RemoteAddr, req.Host) }() @@ -281,7 +293,7 @@ func (h *Sniffer) httpRoundTrip(ctx context.Context, rw, cc io.ReadWriter, req * xio.SetReadDeadline(cc, time.Now().Add(h.ReadTimeout)) resp, err := http.ReadResponse(bufio.NewReader(cc), req) if err != nil { - o.Log.Errorf("read response: %v", err) + log.Errorf("read response: %v", err) return } defer resp.Body.Close() @@ -291,9 +303,9 @@ func (h *Sniffer) httpRoundTrip(ctx context.Context, rw, cc io.ReadWriter, req * ro.HTTP.Response.Header = resp.Header ro.HTTP.Response.ContentLength = resp.ContentLength - if o.Log.IsLevelEnabled(logger.TraceLevel) { + if log.IsLevelEnabled(logger.TraceLevel) { dump, _ := httputil.DumpResponse(resp, false) - o.Log.Trace(string(dump)) + log.Trace(string(dump)) } // HTTP/1.0 @@ -316,7 +328,7 @@ func (h *Sniffer) httpRoundTrip(ctx context.Context, rw, cc io.ReadWriter, req * } if err = resp.Write(rw); err != nil { - o.Log.Errorf("write response: %v", err) + log.Errorf("write response: %v", err) return } @@ -467,6 +479,10 @@ func (h *Sniffer) terminateTLS(ctx context.Context, conn, cc net.Conn, clientHel nextProtos = []string{negotiatedProtocol} } + // cache the tls server handshake record. + wb := &bytes.Buffer{} + conn = xnet.NewReadWriteConn(conn, io.MultiWriter(wb, conn), conn) + serverConn := tls.Server(conn, &tls.Config{ NextProtos: nextProtos, GetCertificate: func(chi *tls.ClientHelloInfo) (*tls.Certificate, error) { @@ -504,7 +520,13 @@ func (h *Sniffer) terminateTLS(ctx context.Context, conn, cc net.Conn, clientHel }, nil }, }) - if err := serverConn.HandshakeContext(ctx); err != nil { + err := serverConn.HandshakeContext(ctx) + if record, _ := dissector.ReadRecord(wb); record != nil { + wb.Reset() + record.WriteTo(wb) + ro.TLS.ServerHello = hex.EncodeToString(wb.Bytes()) + } + if err != nil { return err } diff --git a/recorder/recorder.go b/recorder/recorder.go index ba8b0d8a..1a3b70f2 100644 --- a/recorder/recorder.go +++ b/recorder/recorder.go @@ -59,23 +59,25 @@ type DNSRecorderObject struct { } type HandlerRecorderObject struct { - Node string `json:"node,omitempty"` - Service string `json:"service"` - Network string `json:"network"` - RemoteAddr string `json:"remote"` - LocalAddr string `json:"local"` - Host string `json:"host"` - Proto string `json:"proto,omitempty"` - ClientIP string `json:"clientIP"` - ClientID string `json:"clientID,omitempty"` - HTTP *HTTPRecorderObject `json:"http,omitempty"` - TLS *TLSRecorderObject `json:"tls,omitempty"` - DNS *DNSRecorderObject `json:"dns,omitempty"` - Route string `json:"route,omitempty"` - Err string `json:"err,omitempty"` - SID string `json:"sid"` - Duration time.Duration `json:"duration"` - Time time.Time `json:"time"` + Node string `json:"node,omitempty"` + Service string `json:"service"` + Network string `json:"network"` + RemoteAddr string `json:"remote"` + LocalAddr string `json:"local"` + Host string `json:"host"` + Proto string `json:"proto,omitempty"` + ClientIP string `json:"clientIP"` + ClientID string `json:"clientID,omitempty"` + HTTP *HTTPRecorderObject `json:"http,omitempty"` + TLS *TLSRecorderObject `json:"tls,omitempty"` + DNS *DNSRecorderObject `json:"dns,omitempty"` + Route string `json:"route,omitempty"` + InputBytes uint64 `json:"inputBytes"` + OutputBytes uint64 `json:"outputBytes"` + Err string `json:"err,omitempty"` + SID string `json:"sid"` + Duration time.Duration `json:"duration"` + Time time.Time `json:"time"` } func (p *HandlerRecorderObject) Record(ctx context.Context, r recorder.Recorder) error {