假设现在你的服务器结构是这样:
-
客户端真实公网 IP:
36.112.25.88 -
Nginx 网关 IP:
192.20.1.1 -
.NET 6 服务部署在本机 5000 端口
你在代码里这样获取 IP:
cs
var ip = HttpContext.Connection.RemoteIpAddress?.ToString();
结果打印出来的永远是
192.20.1.1
而不是
36.112.25.88
一、为什么会出现这种现象?
因为在反向代理结构下:
-
.NET 接收到的请求是来自 Nginx
-
网络层认为"请求发起者"就是 Nginx
-
因此
RemoteIpAddress返回的是网关 IP
换句话说:
反向代理改变了请求的直接来源。
这是一种正常行为,而不是程序错误。
二、真实 IP 在哪里?
Nginx 在转发请求时,会自动把客户端真实 IP 写入请求头:
cs
X-Forwarded-For: 36.112.25.88
X-Real-IP: 36.112.25.88
但默认情况下:
ASP.NET Core 不会自动解析这些头。
原因是 HTTP 头可以伪造,框架出于安全考虑默认关闭信任机制。
三、正确解决方案
解决思路:
-
Nginx 传递真实 IP
-
.NET 6 显式启用 ForwardedHeaders
第一步:Nginx 反向代理配置
cs
server {
listen 80;
server_name api.test.com;
location / {
proxy_pass http://127.0.0.1:5000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
关键配置:
cs
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
第二步:.NET 6 启用 ForwardedHeaders
在 Program.cs 中配置:
cs
using Microsoft.AspNetCore.HttpOverrides;
using System.Net;
var builder = WebApplication.CreateBuilder(args);
builder.Services.Configure<ForwardedHeadersOptions>(options =>
{
options.ForwardedHeaders =
ForwardedHeaders.XForwardedFor |
ForwardedHeaders.XForwardedProto;
// 指定你的 Nginx 网关 IP
options.KnownProxies.Add(IPAddress.Parse("192.20.1.1"));
});
var app = builder.Build();
// 必须放在最前面
app.UseForwardedHeaders();
app.MapControllers();
app.Run();
四、配置完成后的结果
请求仍然经过:
cs
36.112.25.88 → 192.20.1.1 → .NET
但现在:
-
.NET 会信任来自
192.20.1.1的转发信息 -
自动解析
X-Forwarded-For
此时:
cs
RemoteIpAddress
获取到的就是:
cs
36.112.25.88
五、核心总结
在 Nginx 反向代理结构下:
-
未配置时 → 获取到的是网关 IP
-
正确配置后 → 获取到的是真实客户端 IP
本质原因是:
请求的直接来源变成了 Nginx,需要显式启用转发头解析机制。