Nginx+Docker部署模式下 asp.net core 獲取真實的客戶端ip

[toc]php

場景

線上環境使用Nginx(安裝在宿主機)+Docker進行部署,應用獲取客戶端ip地址不正確,獲取客戶端IP的代碼爲Request.HttpContext.Connection.RemoteIpAddress.MapToIPv4()html

過程還原

搭建一個webapi示例環境

建立一個新項目nginx

dotnet new webapi -o getRealClientIp

修改模板中的ValuesControllerGet方法web

// GET api/values
[HttpGet]
public ActionResult<string> Get()
{
   return this.Request.HttpContext.Connection.RemoteIpAddress.MapToIPv4().ToString();
}

容器相關配置

docker-compose.ymldocker

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.confapi

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是配置的容器的網關地址,能獲取到正確的ipapp

訪問經過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以後,asp.net

修改代碼以下
// 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;
}

從新編譯運行curl

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的值,需求單獨處理。

參考資料

相關文章
相關標籤/搜索