From f31c601c2057705cdcc62eb923272863de8c544e Mon Sep 17 00:00:00 2001 From: wood chen Date: Sat, 21 Jun 2025 22:39:04 +0800 Subject: [PATCH] =?UTF-8?q?=E6=9B=B4=E6=96=B0Go=E7=89=88=E6=9C=AC=E8=87=B3?= =?UTF-8?q?1.24=EF=BC=8C=E6=B7=BB=E5=8A=A0=E5=AF=B9github.com/woodchen-ink?= =?UTF-8?q?/go-web-utils=E7=9A=84=E4=BE=9D=E8=B5=96=EF=BC=8C=E4=BC=98?= =?UTF-8?q?=E5=8C=96IP=E8=8E=B7=E5=8F=96=E9=80=BB=E8=BE=91=EF=BC=8C?= =?UTF-8?q?=E7=BB=9F=E4=B8=80=E4=BD=BF=E7=94=A8iputil=E5=8C=85=E8=8E=B7?= =?UTF-8?q?=E5=8F=96=E5=AE=A2=E6=88=B7=E7=AB=AFIP=EF=BC=8C=E6=8F=90?= =?UTF-8?q?=E5=8D=87=E4=BB=A3=E7=A0=81=E4=B8=80=E8=87=B4=E6=80=A7=E5=92=8C?= =?UTF-8?q?=E5=8F=AF=E8=AF=BB=E6=80=A7=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- go.mod | 9 ++++++-- go.sum | 4 ++++ internal/handler/auth.go | 36 +++++++++++++++++--------------- internal/handler/mirror_proxy.go | 18 +++++++++------- internal/handler/proxy.go | 19 +++++++++-------- internal/handler/redirect.go | 4 +++- internal/handler/security.go | 5 +++-- internal/middleware/security.go | 5 +++-- internal/utils/utils.go | 21 ------------------- 9 files changed, 59 insertions(+), 62 deletions(-) diff --git a/go.mod b/go.mod index 0060733..4a79ee2 100644 --- a/go.mod +++ b/go.mod @@ -1,10 +1,15 @@ module proxy-go -go 1.23.1 +go 1.24 + +toolchain go1.24.4 require ( github.com/andybalholm/brotli v1.1.1 golang.org/x/net v0.40.0 ) -require golang.org/x/text v0.25.0 // indirect +require ( + github.com/woodchen-ink/go-web-utils v1.0.0 // indirect + golang.org/x/text v0.25.0 // indirect +) diff --git a/go.sum b/go.sum index 384bcaa..60695da 100644 --- a/go.sum +++ b/go.sum @@ -1,5 +1,9 @@ github.com/andybalholm/brotli v1.1.1 h1:PR2pgnyFznKEugtsUo0xLdDop5SKXd5Qf5ysW+7XdTA= github.com/andybalholm/brotli v1.1.1/go.mod h1:05ib4cKhjx3OQYUY22hTVd34Bc8upXjOLL2rKwwZBoA= +github.com/woodchen-ink/go-web-utils v0.0.0-20250621140947-08c57486fe2e h1:k/D90giyDyL5hDPJGGQexqZ423WmZqRUUxc/yQ6E8ws= +github.com/woodchen-ink/go-web-utils v0.0.0-20250621140947-08c57486fe2e/go.mod h1:d+L8rZ7xekLnf679XRvfwqpl4M8RCNdWSViaB3GmpnI= +github.com/woodchen-ink/go-web-utils v1.0.0 h1:Kybe0ZPhRI4w5FJ4bZdPcepNEKTmbw3to3xLR31e+ws= +github.com/woodchen-ink/go-web-utils v1.0.0/go.mod h1:hpiT30rd5Egj2LqRwYBqbEtUXjhjh/Qary0S14KCZgw= github.com/xyproto/randomstring v1.0.5 h1:YtlWPoRdgMu3NZtP45drfy1GKoojuR7hmRcnhZqKjWU= github.com/xyproto/randomstring v1.0.5/go.mod h1:rgmS5DeNXLivK7YprL0pY+lTuhNQW3iGxZ18UQApw/E= golang.org/x/net v0.40.0 h1:79Xs7wF06Gbdcg4kdCCIQArK11Z1hr5POQ6+fIYHNuY= diff --git a/internal/handler/auth.go b/internal/handler/auth.go index 1b3f38f..698be8f 100644 --- a/internal/handler/auth.go +++ b/internal/handler/auth.go @@ -14,6 +14,8 @@ import ( "strings" "sync" "time" + + "github.com/woodchen-ink/go-web-utils/iputil" ) const ( @@ -154,7 +156,7 @@ func (h *ProxyHandler) CheckAuth(token string) bool { func (h *ProxyHandler) LogoutHandler(w http.ResponseWriter, r *http.Request) { auth := r.Header.Get("Authorization") if auth == "" || !strings.HasPrefix(auth, "Bearer ") { - log.Printf("[Auth] ERR %s %s -> 401 (%s) no token from %s", r.Method, r.URL.Path, utils.GetClientIP(r), utils.GetRequestSource(r)) + log.Printf("[Auth] ERR %s %s -> 401 (%s) no token from %s", r.Method, r.URL.Path, iputil.GetClientIP(r), utils.GetRequestSource(r)) http.Error(w, "Unauthorized", http.StatusUnauthorized) return } @@ -162,7 +164,7 @@ func (h *ProxyHandler) LogoutHandler(w http.ResponseWriter, r *http.Request) { token := strings.TrimPrefix(auth, "Bearer ") h.auth.tokens.Delete(token) - log.Printf("[Auth] %s %s -> 200 (%s) logout success from %s", r.Method, r.URL.Path, utils.GetClientIP(r), utils.GetRequestSource(r)) + log.Printf("[Auth] %s %s -> 200 (%s) logout success from %s", r.Method, r.URL.Path, iputil.GetClientIP(r), utils.GetRequestSource(r)) w.Header().Set("Content-Type", "application/json") json.NewEncoder(w).Encode(map[string]string{ @@ -175,14 +177,14 @@ func (h *ProxyHandler) AuthMiddleware(next http.HandlerFunc) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { auth := r.Header.Get("Authorization") if auth == "" || !strings.HasPrefix(auth, "Bearer ") { - log.Printf("[Auth] ERR %s %s -> 401 (%s) no token from %s", r.Method, r.URL.Path, utils.GetClientIP(r), utils.GetRequestSource(r)) + log.Printf("[Auth] ERR %s %s -> 401 (%s) no token from %s", r.Method, r.URL.Path, iputil.GetClientIP(r), utils.GetRequestSource(r)) http.Error(w, "Unauthorized", http.StatusUnauthorized) return } token := strings.TrimPrefix(auth, "Bearer ") if !h.auth.validateToken(token) { - log.Printf("[Auth] ERR %s %s -> 401 (%s) invalid token from %s", r.Method, r.URL.Path, utils.GetClientIP(r), utils.GetRequestSource(r)) + log.Printf("[Auth] ERR %s %s -> 401 (%s) invalid token from %s", r.Method, r.URL.Path, iputil.GetClientIP(r), utils.GetRequestSource(r)) http.Error(w, "Invalid token", http.StatusUnauthorized) return } @@ -253,14 +255,14 @@ func (h *ProxyHandler) OAuthCallbackHandler(w http.ResponseWriter, r *http.Reque // 验证 state if !h.auth.validateState(state) { log.Printf("[Auth] ERR %s %s -> 400 (%s) invalid state '%s' from %s", - r.Method, r.URL.Path, utils.GetClientIP(r), state, utils.GetRequestSource(r)) + r.Method, r.URL.Path, iputil.GetClientIP(r), state, utils.GetRequestSource(r)) http.Error(w, "Invalid state", http.StatusBadRequest) return } // 验证code参数 if code == "" { - log.Printf("[Auth] ERR %s %s -> 400 (%s) missing code parameter from %s", r.Method, r.URL.Path, utils.GetClientIP(r), utils.GetRequestSource(r)) + log.Printf("[Auth] ERR %s %s -> 400 (%s) missing code parameter from %s", r.Method, r.URL.Path, iputil.GetClientIP(r), utils.GetRequestSource(r)) http.Error(w, "Missing code parameter", http.StatusBadRequest) return } @@ -272,7 +274,7 @@ func (h *ProxyHandler) OAuthCallbackHandler(w http.ResponseWriter, r *http.Reque // 验证OAuth配置 if clientID == "" || clientSecret == "" { - log.Printf("[Auth] ERR %s %s -> 500 (%s) missing OAuth credentials from %s", r.Method, r.URL.Path, utils.GetClientIP(r), utils.GetRequestSource(r)) + log.Printf("[Auth] ERR %s %s -> 500 (%s) missing OAuth credentials from %s", r.Method, r.URL.Path, iputil.GetClientIP(r), utils.GetRequestSource(r)) http.Error(w, "Server configuration error", http.StatusInternalServerError) return } @@ -290,7 +292,7 @@ func (h *ProxyHandler) OAuthCallbackHandler(w http.ResponseWriter, r *http.Reque "client_secret": {clientSecret}, }) if err != nil { - log.Printf("[Auth] ERR %s %s -> 500 (%s) failed to get access token: %v from %s", r.Method, r.URL.Path, utils.GetClientIP(r), err, utils.GetRequestSource(r)) + log.Printf("[Auth] ERR %s %s -> 500 (%s) failed to get access token: %v from %s", r.Method, r.URL.Path, iputil.GetClientIP(r), err, utils.GetRequestSource(r)) http.Error(w, "Failed to get access token", http.StatusInternalServerError) return } @@ -301,21 +303,21 @@ func (h *ProxyHandler) OAuthCallbackHandler(w http.ResponseWriter, r *http.Reque // 读取错误响应内容 bodyBytes, _ := io.ReadAll(resp.Body) log.Printf("[Auth] ERR %s %s -> %d (%s) OAuth server returned error: %s, response: %s", - r.Method, r.URL.Path, resp.StatusCode, utils.GetClientIP(r), resp.Status, string(bodyBytes)) + r.Method, r.URL.Path, resp.StatusCode, iputil.GetClientIP(r), resp.Status, string(bodyBytes)) http.Error(w, "OAuth server error: "+resp.Status, http.StatusInternalServerError) return } var token OAuthToken if err := json.NewDecoder(resp.Body).Decode(&token); err != nil { - log.Printf("[Auth] ERR %s %s -> 500 (%s) failed to parse token response: %v from %s", r.Method, r.URL.Path, utils.GetClientIP(r), err, utils.GetRequestSource(r)) + log.Printf("[Auth] ERR %s %s -> 500 (%s) failed to parse token response: %v from %s", r.Method, r.URL.Path, iputil.GetClientIP(r), err, utils.GetRequestSource(r)) http.Error(w, "Failed to parse token response", http.StatusInternalServerError) return } // 验证访问令牌 if token.AccessToken == "" { - log.Printf("[Auth] ERR %s %s -> 500 (%s) received empty access token from %s", r.Method, r.URL.Path, utils.GetClientIP(r), utils.GetRequestSource(r)) + log.Printf("[Auth] ERR %s %s -> 500 (%s) received empty access token from %s", r.Method, r.URL.Path, iputil.GetClientIP(r), utils.GetRequestSource(r)) http.Error(w, "Received invalid token", http.StatusInternalServerError) return } @@ -326,7 +328,7 @@ func (h *ProxyHandler) OAuthCallbackHandler(w http.ResponseWriter, r *http.Reque client := &http.Client{Timeout: 10 * time.Second} userResp, err := client.Do(req) if err != nil { - log.Printf("[Auth] ERR %s %s -> 500 (%s) failed to get user info: %v from %s", r.Method, r.URL.Path, utils.GetClientIP(r), err, utils.GetRequestSource(r)) + log.Printf("[Auth] ERR %s %s -> 500 (%s) failed to get user info: %v from %s", r.Method, r.URL.Path, iputil.GetClientIP(r), err, utils.GetRequestSource(r)) http.Error(w, "Failed to get user info", http.StatusInternalServerError) return } @@ -335,7 +337,7 @@ func (h *ProxyHandler) OAuthCallbackHandler(w http.ResponseWriter, r *http.Reque // 检查用户信息响应状态码 if userResp.StatusCode != http.StatusOK { log.Printf("[Auth] ERR %s %s -> %d (%s) userinfo endpoint returned error status: %s from %s", - r.Method, r.URL.Path, userResp.StatusCode, utils.GetClientIP(r), userResp.Status, utils.GetRequestSource(r)) + r.Method, r.URL.Path, userResp.StatusCode, iputil.GetClientIP(r), userResp.Status, utils.GetRequestSource(r)) http.Error(w, "Failed to get user info: "+userResp.Status, http.StatusInternalServerError) return } @@ -344,7 +346,7 @@ func (h *ProxyHandler) OAuthCallbackHandler(w http.ResponseWriter, r *http.Reque bodyBytes, err := io.ReadAll(userResp.Body) if err != nil { log.Printf("[Auth] ERR %s %s -> 500 (%s) failed to read user info response body: %v from %s", - r.Method, r.URL.Path, utils.GetClientIP(r), err, utils.GetRequestSource(r)) + r.Method, r.URL.Path, iputil.GetClientIP(r), err, utils.GetRequestSource(r)) http.Error(w, "Failed to read user info response", http.StatusInternalServerError) return } @@ -356,7 +358,7 @@ func (h *ProxyHandler) OAuthCallbackHandler(w http.ResponseWriter, r *http.Reque var rawUserInfo map[string]interface{} if err := json.Unmarshal(bodyBytes, &rawUserInfo); err != nil { log.Printf("[Auth] ERR %s %s -> 500 (%s) failed to parse raw user info: %v from %s", - r.Method, r.URL.Path, utils.GetClientIP(r), err, utils.GetRequestSource(r)) + r.Method, r.URL.Path, iputil.GetClientIP(r), err, utils.GetRequestSource(r)) http.Error(w, "Failed to parse user info", http.StatusInternalServerError) return } @@ -391,7 +393,7 @@ func (h *ProxyHandler) OAuthCallbackHandler(w http.ResponseWriter, r *http.Reque // 验证用户信息 if userInfo.Username == "" { log.Printf("[Auth] ERR %s %s -> 500 (%s) could not extract username from user info from %s", - r.Method, r.URL.Path, utils.GetClientIP(r), utils.GetRequestSource(r)) + r.Method, r.URL.Path, iputil.GetClientIP(r), utils.GetRequestSource(r)) http.Error(w, "Invalid user information: missing username", http.StatusInternalServerError) return } @@ -400,7 +402,7 @@ func (h *ProxyHandler) OAuthCallbackHandler(w http.ResponseWriter, r *http.Reque internalToken := h.auth.generateToken() h.auth.addToken(internalToken, userInfo.Username, tokenExpiry) - log.Printf("[Auth] %s %s -> 200 (%s) login success for user %s from %s", r.Method, r.URL.Path, utils.GetClientIP(r), userInfo.Username, utils.GetRequestSource(r)) + log.Printf("[Auth] %s %s -> 200 (%s) login success for user %s from %s", r.Method, r.URL.Path, iputil.GetClientIP(r), userInfo.Username, utils.GetRequestSource(r)) // 返回登录成功页面 w.Header().Set("Content-Type", "text/html") diff --git a/internal/handler/mirror_proxy.go b/internal/handler/mirror_proxy.go index 79f4286..af17f6b 100644 --- a/internal/handler/mirror_proxy.go +++ b/internal/handler/mirror_proxy.go @@ -11,6 +11,8 @@ import ( "proxy-go/internal/utils" "strings" "time" + + "github.com/woodchen-ink/go-web-utils/iputil" ) type MirrorProxyHandler struct { @@ -56,7 +58,7 @@ func (h *MirrorProxyHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { w.WriteHeader(http.StatusOK) log.Printf("| %-6s | %3d | %12s | %15s | %10s | %-30s | CORS Preflight", r.Method, http.StatusOK, time.Since(startTime), - utils.GetClientIP(r), "-", r.URL.Path) + iputil.GetClientIP(r), "-", r.URL.Path) return } @@ -66,7 +68,7 @@ func (h *MirrorProxyHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { http.Error(w, "Invalid URL", http.StatusBadRequest) log.Printf("| %-6s | %3d | %12s | %15s | %10s | %-30s | Invalid URL", r.Method, http.StatusBadRequest, time.Since(startTime), - utils.GetClientIP(r), "-", r.URL.Path) + iputil.GetClientIP(r), "-", r.URL.Path) return } @@ -80,7 +82,7 @@ func (h *MirrorProxyHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { http.Error(w, "Invalid URL", http.StatusBadRequest) log.Printf("| %-6s | %3d | %12s | %15s | %10s | %-30s | Parse URL error: %v", r.Method, http.StatusBadRequest, time.Since(startTime), - utils.GetClientIP(r), "-", actualURL, err) + iputil.GetClientIP(r), "-", actualURL, err) return } @@ -98,7 +100,7 @@ func (h *MirrorProxyHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { http.Error(w, "Error creating request", http.StatusInternalServerError) log.Printf("| %-6s | %3d | %12s | %15s | %10s | %-30s | Error creating request: %v", r.Method, http.StatusInternalServerError, time.Since(startTime), - utils.GetClientIP(r), "-", actualURL, err) + iputil.GetClientIP(r), "-", actualURL, err) return } @@ -131,7 +133,7 @@ func (h *MirrorProxyHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { return } http.ServeFile(w, r, item.FilePath) - collector.RecordRequest(r.URL.Path, http.StatusOK, time.Since(startTime), item.Size, utils.GetClientIP(r), r) + collector.RecordRequest(r.URL.Path, http.StatusOK, time.Since(startTime), item.Size, iputil.GetClientIP(r), r) return } } @@ -142,7 +144,7 @@ func (h *MirrorProxyHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { http.Error(w, "Error forwarding request", http.StatusBadGateway) log.Printf("| %-6s | %3d | %12s | %15s | %10s | %-30s | Error forwarding request: %v", r.Method, http.StatusBadGateway, time.Since(startTime), - utils.GetClientIP(r), "-", actualURL, err) + iputil.GetClientIP(r), "-", actualURL, err) return } defer resp.Body.Close() @@ -183,9 +185,9 @@ func (h *MirrorProxyHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { // 记录访问日志 log.Printf("| %-6s | %3d | %12s | %15s | %10s | %-30s | %s", r.Method, resp.StatusCode, time.Since(startTime), - utils.GetClientIP(r), utils.FormatBytes(written), + iputil.GetClientIP(r), utils.FormatBytes(written), utils.GetRequestSource(r), actualURL) // 记录统计信息 - collector.RecordRequest(r.URL.Path, resp.StatusCode, time.Since(startTime), written, utils.GetClientIP(r), r) + collector.RecordRequest(r.URL.Path, resp.StatusCode, time.Since(startTime), written, iputil.GetClientIP(r), r) } diff --git a/internal/handler/proxy.go b/internal/handler/proxy.go index 10f5750..e114e61 100644 --- a/internal/handler/proxy.go +++ b/internal/handler/proxy.go @@ -17,6 +17,7 @@ import ( "strings" "time" + "github.com/woodchen-ink/go-web-utils/iputil" "golang.org/x/net/http2" ) @@ -232,7 +233,7 @@ func (h *ProxyHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { if r.URL.Path == "/" { w.WriteHeader(http.StatusOK) fmt.Fprint(w, "Welcome to CZL proxy.") - log.Printf("[Proxy] %s %s -> %d (%s) from %s", r.Method, r.URL.Path, http.StatusOK, utils.GetClientIP(r), utils.GetRequestSource(r)) + log.Printf("[Proxy] %s %s -> %d (%s) from %s", r.Method, r.URL.Path, http.StatusOK, iputil.GetClientIP(r), utils.GetRequestSource(r)) return } @@ -258,7 +259,7 @@ func (h *ProxyHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { // 检查是否需要进行302跳转 if h.redirectHandler != nil && h.redirectHandler.HandleRedirect(w, r, pathConfig, decodedPath, h.client) { // 如果进行了302跳转,直接返回,不继续处理 - collector.RecordRequest(r.URL.Path, http.StatusFound, time.Since(start), 0, utils.GetClientIP(r), r) + collector.RecordRequest(r.URL.Path, http.StatusFound, time.Since(start), 0, iputil.GetClientIP(r), r) return } @@ -342,7 +343,7 @@ func (h *ProxyHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { } // 设置最小必要的代理头部 - clientIP := utils.GetClientIP(r) + clientIP := iputil.GetClientIP(r) proxyReq.Header.Set("X-Real-IP", clientIP) // 添加或更新 X-Forwarded-For - 减少重复获取客户端IP @@ -389,7 +390,7 @@ func (h *ProxyHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { return } http.ServeFile(w, r, item.FilePath) - collector.RecordRequest(r.URL.Path, http.StatusOK, time.Since(start), item.Size, utils.GetClientIP(r), r) + collector.RecordRequest(r.URL.Path, http.StatusOK, time.Since(start), item.Size, iputil.GetClientIP(r), r) return } } @@ -399,10 +400,10 @@ func (h *ProxyHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { if err != nil { if ctx.Err() == context.DeadlineExceeded { h.errorHandler(w, r, fmt.Errorf("request timeout after %v", proxyRespTimeout)) - log.Printf("[Proxy] ERR %s %s -> 408 (%s) timeout from %s", r.Method, r.URL.Path, utils.GetClientIP(r), utils.GetRequestSource(r)) + log.Printf("[Proxy] ERR %s %s -> 408 (%s) timeout from %s", r.Method, r.URL.Path, iputil.GetClientIP(r), utils.GetRequestSource(r)) } else { h.errorHandler(w, r, fmt.Errorf("proxy error: %v", err)) - log.Printf("[Proxy] ERR %s %s -> 502 (%s) proxy error from %s", r.Method, r.URL.Path, utils.GetClientIP(r), utils.GetRequestSource(r)) + log.Printf("[Proxy] ERR %s %s -> 502 (%s) proxy error from %s", r.Method, r.URL.Path, iputil.GetClientIP(r), utils.GetRequestSource(r)) } return } @@ -450,7 +451,7 @@ func (h *ProxyHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { written, err = io.CopyBuffer(w, resp.Body, buf) if err != nil && !isConnectionClosed(err) { - log.Printf("[Proxy] ERR %s %s -> write error (%s) from %s", r.Method, r.URL.Path, utils.GetClientIP(r), utils.GetRequestSource(r)) + log.Printf("[Proxy] ERR %s %s -> write error (%s) from %s", r.Method, r.URL.Path, iputil.GetClientIP(r), utils.GetRequestSource(r)) return } } @@ -461,13 +462,13 @@ func (h *ProxyHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { written, err = io.CopyBuffer(w, resp.Body, buf) if err != nil && !isConnectionClosed(err) { - log.Printf("[Proxy] ERR %s %s -> write error (%s) from %s", r.Method, r.URL.Path, utils.GetClientIP(r), utils.GetRequestSource(r)) + log.Printf("[Proxy] ERR %s %s -> write error (%s) from %s", r.Method, r.URL.Path, iputil.GetClientIP(r), utils.GetRequestSource(r)) return } } // 记录统计信息 - collector.RecordRequest(r.URL.Path, resp.StatusCode, time.Since(start), written, utils.GetClientIP(r), r) + collector.RecordRequest(r.URL.Path, resp.StatusCode, time.Since(start), written, iputil.GetClientIP(r), r) } func copyHeader(dst, src http.Header) { diff --git a/internal/handler/redirect.go b/internal/handler/redirect.go index df0b6c3..aca0169 100644 --- a/internal/handler/redirect.go +++ b/internal/handler/redirect.go @@ -8,6 +8,8 @@ import ( "proxy-go/internal/service" "proxy-go/internal/utils" "strings" + + "github.com/woodchen-ink/go-web-utils/iputil" ) // RedirectHandler 处理302跳转逻辑 @@ -99,7 +101,7 @@ func (rh *RedirectHandler) performRedirect(w http.ResponseWriter, r *http.Reques w.WriteHeader(http.StatusFound) // 记录跳转日志 - clientIP := utils.GetClientIP(r) + clientIP := iputil.GetClientIP(r) log.Printf("[Redirect] %s %s -> 302 %s (%s) from %s", r.Method, r.URL.Path, targetURL, clientIP, utils.GetRequestSource(r)) } diff --git a/internal/handler/security.go b/internal/handler/security.go index 2e729d7..5f618c8 100644 --- a/internal/handler/security.go +++ b/internal/handler/security.go @@ -4,8 +4,9 @@ import ( "encoding/json" "net/http" "proxy-go/internal/security" - "proxy-go/internal/utils" "time" + + "github.com/woodchen-ink/go-web-utils/iputil" ) // SecurityHandler 安全管理处理器 @@ -109,7 +110,7 @@ func (sh *SecurityHandler) CheckIPStatus(w http.ResponseWriter, r *http.Request) ip := r.URL.Query().Get("ip") if ip == "" { // 如果没有指定IP,使用请求的IP - ip = utils.GetClientIP(r) + ip = iputil.GetClientIP(r) } banned, banEndTime := sh.banManager.GetBanInfo(ip) diff --git a/internal/middleware/security.go b/internal/middleware/security.go index 3666175..920ffdc 100644 --- a/internal/middleware/security.go +++ b/internal/middleware/security.go @@ -4,8 +4,9 @@ import ( "fmt" "net/http" "proxy-go/internal/security" - "proxy-go/internal/utils" "time" + + "github.com/woodchen-ink/go-web-utils/iputil" ) // SecurityMiddleware 安全中间件 @@ -23,7 +24,7 @@ func NewSecurityMiddleware(banManager *security.IPBanManager) *SecurityMiddlewar // IPBanMiddleware IP封禁中间件 func (sm *SecurityMiddleware) IPBanMiddleware(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - clientIP := utils.GetClientIP(r) + clientIP := iputil.GetClientIP(r) // 检查IP是否被封禁 if sm.banManager.IsIPBanned(clientIP) { diff --git a/internal/utils/utils.go b/internal/utils/utils.go index 2b7dd7c..982293d 100644 --- a/internal/utils/utils.go +++ b/internal/utils/utils.go @@ -6,7 +6,6 @@ import ( "encoding/hex" "fmt" "log" - "net" "net/http" neturl "net/url" "path/filepath" @@ -93,26 +92,6 @@ func GenerateRequestID() string { return hex.EncodeToString(b) } -func GetClientIP(r *http.Request) string { - // 优先级1: Cloudflare 提供的原始客户端 IP(最准确) - if ip := r.Header.Get("CF-Connecting-IP"); ip != "" { - return ip - } - // 优先级2: 通用的真实 IP 头 - if ip := r.Header.Get("X-Real-IP"); ip != "" { - return ip - } - // 优先级3: 标准的转发链头部(取第一个 IP,即原始客户端 IP) - if ip := r.Header.Get("X-Forwarded-For"); ip != "" { - return strings.Split(ip, ",")[0] - } - // 优先级4: 直连 IP(兜底方案) - if ip, _, err := net.SplitHostPort(r.RemoteAddr); err == nil { - return ip - } - return r.RemoteAddr -} - // 获取请求来源 func GetRequestSource(r *http.Request) string { referer := r.Header.Get("Referer")