From b39aa63f75ca85c444abf3e14aea280a07eb8515 Mon Sep 17 00:00:00 2001 From: ginuerzh Date: Sun, 15 Sep 2024 18:28:24 +0800 Subject: [PATCH] add clientIP for handler recorder object --- handler/forward/local/handler.go | 6 ++++++ handler/forward/remote/handler.go | 6 ++++++ handler/http/handler.go | 8 +++++++- handler/http2/handler.go | 8 +++++++- handler/redirect/tcp/handler.go | 5 +++++ handler/relay/handler.go | 2 +- handler/sni/handler.go | 5 +++++ handler/socks/v4/handler.go | 5 +++-- handler/socks/v5/handler.go | 2 +- handler/tunnel/entrypoint.go | 9 ++++++++- internal/net/http/http.go | 26 ++++++++++++++++++++++++++ recorder/recorder.go | 3 ++- 12 files changed, 77 insertions(+), 8 deletions(-) create mode 100644 internal/net/http/http.go diff --git a/handler/forward/local/handler.go b/handler/forward/local/handler.go index 0981224f..990cd912 100644 --- a/handler/forward/local/handler.go +++ b/handler/forward/local/handler.go @@ -27,6 +27,7 @@ import ( ctxvalue "github.com/go-gost/x/ctx" xio "github.com/go-gost/x/internal/io" xnet "github.com/go-gost/x/internal/net" + xhttp "github.com/go-gost/x/internal/net/http" "github.com/go-gost/x/internal/util/forward" tls_util "github.com/go-gost/x/internal/util/tls" rate_limiter "github.com/go-gost/x/limiter/rate" @@ -90,6 +91,7 @@ func (h *forwardHandler) Handle(ctx context.Context, conn net.Conn, opts ...hand Time: start, SID: string(ctxvalue.SidFromContext(ctx)), } + ro.ClientIP, _, _ = net.SplitHostPort(conn.RemoteAddr().String()) log := h.options.Logger.WithFields(map[string]any{ "remote": conn.RemoteAddr().String(), @@ -252,6 +254,10 @@ func (h *forwardHandler) handleHTTP(ctx context.Context, rw io.ReadWriteCloser, Header: req.Header.Clone(), }, } + if clientIP := xhttp.GetClientIP(req); clientIP != nil { + ro.ClientIP = clientIP.String() + } + defer func() { if err != nil { ro.HTTP.StatusCode = resp.StatusCode diff --git a/handler/forward/remote/handler.go b/handler/forward/remote/handler.go index 7be1d169..6d1774e1 100644 --- a/handler/forward/remote/handler.go +++ b/handler/forward/remote/handler.go @@ -28,6 +28,7 @@ import ( ctxvalue "github.com/go-gost/x/ctx" xio "github.com/go-gost/x/internal/io" xnet "github.com/go-gost/x/internal/net" + xhttp "github.com/go-gost/x/internal/net/http" "github.com/go-gost/x/internal/net/proxyproto" "github.com/go-gost/x/internal/util/forward" tls_util "github.com/go-gost/x/internal/util/tls" @@ -91,6 +92,7 @@ func (h *forwardHandler) Handle(ctx context.Context, conn net.Conn, opts ...hand Time: start, SID: string(ctxvalue.SidFromContext(ctx)), } + ro.ClientIP, _, _ = net.SplitHostPort(conn.RemoteAddr().String()) log := h.options.Logger.WithFields(map[string]any{ "remote": conn.RemoteAddr().String(), @@ -252,6 +254,10 @@ func (h *forwardHandler) handleHTTP(ctx context.Context, rw io.ReadWriteCloser, Header: req.Header.Clone(), }, } + if clientIP := xhttp.GetClientIP(req); clientIP != nil { + ro.ClientIP = clientIP.String() + } + defer func() { if err != nil { ro.HTTP.StatusCode = resp.StatusCode diff --git a/handler/http/handler.go b/handler/http/handler.go index 832c472c..15f1ac88 100644 --- a/handler/http/handler.go +++ b/handler/http/handler.go @@ -29,6 +29,7 @@ import ( ctxvalue "github.com/go-gost/x/ctx" 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" limiter_util "github.com/go-gost/x/internal/util/limiter" stats_util "github.com/go-gost/x/internal/util/stats" rate_limiter "github.com/go-gost/x/limiter/rate" @@ -101,6 +102,7 @@ func (h *httpHandler) Handle(ctx context.Context, conn net.Conn, opts ...handler Time: start, SID: string(ctxvalue.SidFromContext(ctx)), } + ro.ClientIP, _, _ = net.SplitHostPort(conn.RemoteAddr().String()) log := h.options.Logger.WithFields(map[string]any{ "remote": conn.RemoteAddr().String(), @@ -133,6 +135,10 @@ func (h *httpHandler) Handle(ctx context.Context, conn net.Conn, opts ...handler } defer req.Body.Close() + if clientIP := xhttp.GetClientIP(req); clientIP != nil { + ro.ClientIP = clientIP.String() + } + return h.handleRequest(ctx, conn, req, ro, log) } @@ -179,7 +185,7 @@ func (h *httpHandler) handleRequest(ctx context.Context, conn net.Conn, req *htt if u, _, _ := h.basicProxyAuth(req.Header.Get("Proxy-Authorization")); u != "" { fields["user"] = u - ro.Client = u + ro.ClientID = u } log = log.WithFields(fields) diff --git a/handler/http2/handler.go b/handler/http2/handler.go index b28d05f1..d3c21592 100644 --- a/handler/http2/handler.go +++ b/handler/http2/handler.go @@ -29,6 +29,7 @@ import ( ctxvalue "github.com/go-gost/x/ctx" 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" limiter_util "github.com/go-gost/x/internal/util/limiter" stats_util "github.com/go-gost/x/internal/util/stats" rate_limiter "github.com/go-gost/x/limiter/rate" @@ -102,6 +103,7 @@ func (h *http2Handler) Handle(ctx context.Context, conn net.Conn, opts ...handle Time: start, SID: string(ctxvalue.SidFromContext(ctx)), } + ro.ClientIP, _, _ = net.SplitHostPort(conn.RemoteAddr().String()) log := h.options.Logger.WithFields(map[string]any{ "remote": conn.RemoteAddr().String(), @@ -165,6 +167,10 @@ func (h *http2Handler) roundTrip(ctx context.Context, w http.ResponseWriter, req } } + if clientIP := xhttp.GetClientIP(req); clientIP != nil { + ro.ClientIP = clientIP.String() + } + ro.Host = req.Host addr := req.Host if _, port, _ := net.SplitHostPort(addr); port == "" { @@ -176,7 +182,7 @@ func (h *http2Handler) roundTrip(ctx context.Context, w http.ResponseWriter, req } if u, _, _ := h.basicProxyAuth(req.Header.Get("Proxy-Authorization")); u != "" { fields["user"] = u - ro.Client = u + ro.ClientID = u } log = log.WithFields(fields) diff --git a/handler/redirect/tcp/handler.go b/handler/redirect/tcp/handler.go index d668f809..47b8cd01 100644 --- a/handler/redirect/tcp/handler.go +++ b/handler/redirect/tcp/handler.go @@ -24,6 +24,7 @@ import ( ctxvalue "github.com/go-gost/x/ctx" 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" rate_limiter "github.com/go-gost/x/limiter/rate" xrecorder "github.com/go-gost/x/recorder" "github.com/go-gost/x/registry" @@ -80,6 +81,7 @@ func (h *redirectHandler) Handle(ctx context.Context, conn net.Conn, opts ...han Time: start, SID: string(ctxvalue.SidFromContext(ctx)), } + ro.ClientIP, _, _ = net.SplitHostPort(conn.RemoteAddr().String()) log := h.options.Logger.WithFields(map[string]any{ "remote": conn.RemoteAddr().String(), @@ -190,6 +192,9 @@ func (h *redirectHandler) handleHTTP(ctx context.Context, rw io.ReadWriter, radd Header: req.Header, }, } + if clientIP := xhttp.GetClientIP(req); clientIP != nil { + ro.ClientIP = clientIP.String() + } if log.IsLevelEnabled(logger.TraceLevel) { dump, _ := httputil.DumpRequest(req, false) diff --git a/handler/relay/handler.go b/handler/relay/handler.go index e8014df6..d980f34f 100644 --- a/handler/relay/handler.go +++ b/handler/relay/handler.go @@ -164,7 +164,7 @@ func (h *relayHandler) Handle(ctx context.Context, conn net.Conn, opts ...handle } if user != "" { - ro.Client = user + ro.ClientID = user log = log.WithFields(map[string]any{"user": user}) } diff --git a/handler/sni/handler.go b/handler/sni/handler.go index b1ba860c..f71f1f6a 100644 --- a/handler/sni/handler.go +++ b/handler/sni/handler.go @@ -26,6 +26,7 @@ import ( ctxvalue "github.com/go-gost/x/ctx" 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" rate_limiter "github.com/go-gost/x/limiter/rate" xrecorder "github.com/go-gost/x/recorder" "github.com/go-gost/x/registry" @@ -82,6 +83,7 @@ func (h *sniHandler) Handle(ctx context.Context, conn net.Conn, opts ...handler. Time: start, SID: string(ctxvalue.SidFromContext(ctx)), } + ro.ClientIP, _, _ = net.SplitHostPort(conn.RemoteAddr().String()) log := h.options.Logger.WithFields(map[string]any{ "remote": conn.RemoteAddr().String(), @@ -139,6 +141,9 @@ func (h *sniHandler) handleHTTP(ctx context.Context, rw io.ReadWriter, raddr net Header: req.Header, }, } + if clientIP := xhttp.GetClientIP(req); clientIP != nil { + ro.ClientIP = clientIP.String() + } if log.IsLevelEnabled(logger.TraceLevel) { dump, _ := httputil.DumpRequest(req, false) diff --git a/handler/socks/v4/handler.go b/handler/socks/v4/handler.go index 5266760a..b2351748 100644 --- a/handler/socks/v4/handler.go +++ b/handler/socks/v4/handler.go @@ -135,13 +135,14 @@ func (h *socks4Handler) Handle(ctx context.Context, conn net.Conn, opts ...handl conn.SetReadDeadline(time.Time{}) if h.options.Auther != nil { - id, ok := h.options.Auther.Authenticate(ctx, string(req.Userid), "") + clientID, ok := h.options.Auther.Authenticate(ctx, string(req.Userid), "") if !ok { resp := gosocks4.NewReply(gosocks4.RejectedUserid, nil) log.Trace(resp) return resp.Write(conn) } - ctx = ctxvalue.ContextWithClientID(ctx, ctxvalue.ClientID(id)) + ctx = ctxvalue.ContextWithClientID(ctx, ctxvalue.ClientID(clientID)) + ro.ClientID = clientID } switch req.Cmd { diff --git a/handler/socks/v5/handler.go b/handler/socks/v5/handler.go index 5e52d034..3ad16cfc 100644 --- a/handler/socks/v5/handler.go +++ b/handler/socks/v5/handler.go @@ -136,7 +136,7 @@ func (h *socks5Handler) Handle(ctx context.Context, conn net.Conn, opts ...handl if clientID := sc.ID(); clientID != "" { ctx = ctxvalue.ContextWithClientID(ctx, ctxvalue.ClientID(clientID)) log = log.WithFields(map[string]any{"user": clientID}) - ro.Client = clientID + ro.ClientID = clientID } conn = sc diff --git a/handler/tunnel/entrypoint.go b/handler/tunnel/entrypoint.go index bbea4b47..84b1b696 100644 --- a/handler/tunnel/entrypoint.go +++ b/handler/tunnel/entrypoint.go @@ -23,6 +23,7 @@ import ( admission "github.com/go-gost/x/admission/wrapper" xio "github.com/go-gost/x/internal/io" xnet "github.com/go-gost/x/internal/net" + xhttp "github.com/go-gost/x/internal/net/http" "github.com/go-gost/x/internal/net/proxyproto" climiter "github.com/go-gost/x/limiter/conn/wrapper" metrics "github.com/go-gost/x/metrics/wrapper" @@ -102,6 +103,12 @@ func (ep *entrypoint) handle(ctx context.Context, conn net.Conn) error { }, }, } + if clientIP := xhttp.GetClientIP(req); clientIP != nil { + ro.ClientIP = clientIP.String() + } else { + ro.ClientIP, _, _ = net.SplitHostPort(conn.RemoteAddr().String()) + } + defer func() { if err != nil { d := time.Since(start) @@ -140,7 +147,7 @@ func (ep *entrypoint) handle(ctx context.Context, conn net.Conn) error { return err } - ro.Client = tunnelID.String() + ro.ClientID = tunnelID.String() if tunnelID.IsPrivate() { err = fmt.Errorf("access denied: tunnel %s is private for host %s", tunnelID, req.Host) diff --git a/internal/net/http/http.go b/internal/net/http/http.go new file mode 100644 index 00000000..520d8073 --- /dev/null +++ b/internal/net/http/http.go @@ -0,0 +1,26 @@ +package http + +import ( + "net" + "net/http" + "strings" +) + +func GetClientIP(req *http.Request) net.IP { + if req == nil { + return nil + } + // cloudflare CDN + sip := req.Header.Get("CF-Connecting-IP") + if sip == "" { + ss := strings.Split(req.Header.Get("X-Forwarded-For"), ",") + if len(ss) > 0 && ss[0] != "" { + sip = ss[0] + } + } + if sip == "" { + sip = req.Header.Get("X-Real-Ip") + } + + return net.ParseIP(sip) +} diff --git a/recorder/recorder.go b/recorder/recorder.go index a784c8d4..7e90481a 100644 --- a/recorder/recorder.go +++ b/recorder/recorder.go @@ -53,7 +53,8 @@ type HandlerRecorderObject struct { RemoteAddr string `json:"remote"` LocalAddr string `json:"local"` Host string `json:"host"` - Client string `json:"client,omitempty"` + ClientIP string `json:"clientIP"` + ClientID string `json:"clientID,omitempty"` HTTP *HTTPRecorderObject `json:"http,omitempty"` DNS *DNSRecorderObject `json:"dns,omitempty"` Err string `json:"err,omitempty"`