使用Nginx反向代理时无法获得客户端的真实IP

时间:2020-06-30 18:55:39

标签: docker asp.net-core nginx asp.net-core-mvc kestrel-http-server

问题描述:
当我访问应该返回远程客户端IP地址的Asp.net MVC Core 3.1网页时,我反而获得了Nginx容器的内部docker IP。我不确定问题是否出在asp.net核心中的代码,Nginx反向代理配置未将我的客户端ip转发到Kestrel容器等。

输出:

:: ffff:172.23.0.3

所需的输出(使用随机IP的示例):

231.43.6.124

设置:

  • 使用Ubuntu并运行Docker(即不在本地运行)远程VPS
  • 没有公共访问权的Kestrel docker容器
  • Nginx Docker容器,该容器在端口80上具有公共访问权限,并将请求转发到后端Kestrel服务器。

nginx.conf

http {
        upstream backendservers {
                server kestrel:80;
        }
        server {
                listen 80;
                location / {
                        proxy_pass http://backendservers/;
                        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-Host $host:443;
                        proxy_set_header X-Forwarded-Server $host;
                        proxy_set_header X-Forwarded-Port 443;
                        proxy_set_header X-Forwarded-Proto https;
                }
        }
}

events {

}

asp.net核心代码

// controller
public IActionResult GetIP()
{
   var ip = HttpContext.Connection.RemoteIpAddress.ToString();
   ViewBag.ip = ip;
   return View();
}

// view
@{
    ViewData["Title"] = "Get IP";
}

<div class="text-center">
   <p>@ViewBag.ip</p>
</div>

Docker启动:

docker network create --driver=bridge stacknet
docker run -d --name=kestrel --restart=always -h kestrel.local --network=stacknet mykestrelimage
docker run -d --name=nginx --restart=always  -p 80:80 -h nginx.local --network=stacknet mynginximage

更新1: 作为测试,我打开了Kestrel 80端口。当我直接打入Kestrel时,我可以获得客户端IP,但是当它通过Nginx反向代理传入时却无法获得。

更新2: 根据以下答复之一的建议,在ngix.conf中添加了几行,但似乎没有什么不同。

2 个答案:

答案 0 :(得分:2)

我有类似的问题,这是我尝试过的,它解决了我的问题。

  1. 转到/etc/nginx/sites-available/ 您将在默认文件中找到像这样配置服务器的地方。
server{
  server_name example.com;
  location / {
    proxy_pass http://localhost:4000;
    proxy_set_header X-Real-IP $remote_addr; <---Add this line
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; <---this line too
  }

2。/ nginx文件夹中将再有一个名为proxy_params的文件,请确保该文件中包含以下行。

proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $remote_addr
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
  1. 在后端代码中最重要的是获得这样的IP。
const ipAddress = req.headers['x-forwarded-for'] as string;

您还可以通过此命令检查请求ip。

$ sudo tail -f /var/log/nginx/access.log

答案 1 :(得分:1)

您可能需要转发原始IP。 这是NGinx关于此主题的文档:https://www.nginx.com/resources/wiki/start/topics/examples/forwarded/

还有来自https://plone.lucidsolutions.co.nz/web/reverseproxyandcache/setting-nginx-http-x-forward-headers-for-reverse-proxy

的较旧x-forward-for的示例
location / {
  proxy_pass              http://upstream/;
  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-Host   $host:443;
  proxy_set_header        X-Forwarded-Server $host;
  proxy_set_header        X-Forwarded-Port   443;
  proxy_set_header        X-Forwarded-Proto  https;
}