【问题标题】:Can't get client's real IP when using Nginx reverse proxy使用 Nginx 反向代理时无法获取客户端的真实 IP
【发布时间】:2020-10-21 03:56:23
【问题描述】:

问题描述:
当我访问应该返回我的远程客户端 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 中添加了一些行,但似乎没有什么不同。

【问题讨论】:

  • 您是否正在实施可用的中间件来进行标头转发? docs.microsoft.com/en-us/aspnet/core/host-and-deploy/…
  • 没有。我尝试按照链接的“转发标头中间件顺序”部分进行操作,但在编译时不断出错。 (当前上下文中不存在名称“ForwardedHeaders”)是否缺少一些 using 语句?
  • 你需要添加一个 using for Microsoft.AspNetCore.HttpOverrides
  • 你能详细说明一些示例代码吗?仍然得到构建错误。顺便说一句 - 作为测试,我打开了 kestrel 端口 80,如果我不使用 nginx 作为反向代理,代码确实可以工作。
  • 当您要求 nginx 将 IP 转发为 X-Real-IP 标头时,直接在您的代码中读取它。

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


【解决方案1】:

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

  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

【讨论】:

  • 写得很好,很有帮助。非常感谢。
  • 如果有人有类似我的情况。我在使用 Javalin 公开一个 REST API 的 Java 后端应用程序中遇到了同样的问题。我的解决方案是第 3 步,非常感谢您的详细解释。
【解决方案2】:

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

还有一个旧的 x-forwarded-for 示例来自:https://plone.lucidsolutions.co.nz/web/reverseproxyandcache/setting-nginx-http-x-forward-headers-for-reverse-proxy

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;
}

【讨论】:

  • 感谢您的回复。我尝试使用您推荐的设置更新 nginx.conf(用我自己的设置替换上游),但它仍然给我 ngiix 内部 docker ip。
猜你喜欢
  • 2020-05-31
  • 1970-01-01
  • 2021-09-06
  • 2021-09-01
  • 1970-01-01
  • 2011-09-02
  • 1970-01-01
  • 1970-01-01
  • 2018-05-14
相关资源
最近更新 更多