string GetClientIP()
{
if (Request.ServerVariables["HTTP_VIA"] != null)
return Request.ServerVariables["HTTP_X_FORWARDED_FOR"].Split(',')[0];
else
return Request.ServerVariables["REMOTE_ADDR"];
}
HTTP_X_FORWARDED_FOR、HTTP_VIA、HTTP_CLIENT_IP 均來自客戶端發送的 HTTP 請求頭,完全可控、可偽造。X-Forwarded-For: 1.2.3.4REMOTE_ADDR 是 TCP 連接的源 IP(由 Web 服務器從 Socket 獲取),無法直接偽造(偽造將導致無法建立連接、收不到響應)。Request.UserHostAddress (即 REMOTE_ADDR)。proxy_set_header X-Real-IP $remote_addr;、proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;var forwarded = Request.Headers["X-Forwarded-For"];
var realIp = Request.Headers["X-Real-IP"];
// 驗證 Request.ServerVariables["REMOTE_ADDR"] 是否在受信代理白名單中
if (IsTrustedProxy(Request.UserHostAddress))
return !string.IsNullOrEmpty(realIp) ? realIp : forwarded?.Split(',')[0].Trim();
else
return Request.UserHostAddress;
// Startup.cs
services.Configure<ForwardedHeadersOptions>(options =>
{
options.ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto;
options.KnownNetworks.Add(new IPNetwork(IPAddress.Parse("10.0.0.0"), 8)); // 信任內網代理
options.KnownProxies.Add(IPAddress.Parse("192.168.1.100")); // 具體代理 IP
});
app.UseForwardedHeaders(); // 必須在 UseAuthentication 之前
// 控制器中
var ip = HttpContext.Connection.RemoteIpAddress; // 已經是真實客戶端 IP
X-Forwarded-For 用於權限控制、審計日志、風控決策。REMOTE_ADDR、X-Forwarded-For、User-Agent 完整鏈路,便於事後審計。HttpContext.Connection.RemoteIpAddress (Core) 或經過驗證的中間件。HTTP 頭部不可信是網絡編程鐵律。獲取真實客戶端 IP 的正確姿勢是:基礎設施層負責傳遞真實 IP,應用層只信任經過基礎設施驗證的數據。任何直接讀取請求頭作為客戶端 IP 的代碼,都是安全漏洞。