[toc]
场景
线上环境使用Nginx(安装在宿主机)+Docker进行部署,应用获取客户端ip地址不正确,获取客户端IP的代码为Request.HttpContext.Connection.RemoteIpAddress.MapToIPv4()
过程还原
搭建一个webapi示例环境
创建一个新项目
dotnet new webapi -o getRealClientIp
修改模板中的ValuesController
的Get
方法
// GET api/values
[HttpGet]
public ActionResult<string> Get()
{
return this.Request.HttpContext.Connection.RemoteIpAddress.MapToIPv4().ToString();
}
容器相关配置
docker-compose.yml
version: '2'
services:
web:
image: microsoft/dotnet:2.1-aspnetcore-runtime
volumes:
- ./publish:/app #站点文件
command: dotnet /app/getRealClientIp.dll
ports:
- "5000:80"
networks:
test:
ipv4_address: 172.200.0.101
nginx:
image: nginx
networks:
test:
ipv4_address: 172.200.0.102
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf:ro # nginx配置文件
ports:
- "5001:80"
networks:
test:
ipam:
config:
- subnet: 172.200.0.0/16
gateway: 172.200.0.1
nginx.conf
http {
server {
listen 80;
access_log off;
location / {
proxy_pass http://172.200.0.101:80;
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 Via "nginx";
}
}
}
events {
worker_connections 1024;
}
运行查看效果
运行
dotnet publish -c Release -o ./publish #编译
docker-compose up #运行容器
直接访问站点
curl http://localhost:5000/api/values
172.200.0.1
返回的ip地址172.200.0.1
是配置的容器的网关地址,能获取到正确的ip
访问通过nginx代理的地址
curl http://localhost:5001/api/values
172.200.0.102
返回的ip地址172.200.0.102
是nginx容器的地址,没有获取到正确的ip
上面的nginx配置已经相关的转发参数,并且该参数配置之前能正常运行在php的环境;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
推断必须修改 asp.net core 相关代码,才能获取到真实的客户端ip地址,一番google之后,
修改代码如下
// GET api/values
[HttpGet]
public ActionResult<string> Get()
{
var ip = this.Request.Headers["X-Forwarded-For"].FirstOrDefault();
if (string.IsNullOrEmpty(ip))
{
ip = this.Request.HttpContext.Connection.RemoteIpAddress.MapToIPv4().ToString();
}
return ip;
}
重新编译运行
dotnet publish -c Release -o ./publish #编译
docker-compose up #运行容器
curl http://localhost:5001/api/values
172.200.0.1
curl http://localhost:5000/api/values
172.200.0.1
直接访问和通过nginx代理访问返回的ip地址均为172.200.0.1
,获取正确。
结论
asp.net core 使用 Request.HttpContext.Connection.RemoteIpAddress.MapToIPv4()
获取客户端ip,不会自动取Header中X-Forwarded-For
的值,需求单独处理。