多层链路获取用户真实IP

我一直都没有修复这个问题,导致nginx获取到的IP都是cdn边缘节点的IP,网上的处理教程都很简单,在nginx设置一下 real_ip_header X-Forwarded-For; 就可以解决了,但是这种方法对于多层链路无效的。

获取方法基本上都是如下,我之前写的文章。

对于多层链路,就无效了。我的网站链路是这样的。

用户 → CDN 边缘节点 → 云WAF → 源站

按照网上教程结果拿到的还是 CDN 边缘节点的 IP,而不是用户的真实 IP。

这是因为:

  • X-Forwarded-For 是一个链式的 IP 列表,第一段才是用户真实 IP。
  • CDN 会先写自己的 X-Forwarded-For,WAF 再转发时可能又覆盖或追加了一层。
  • 你现在在源站 set_real_ip_from 信任的是 WAF 的 IP,所以 real_ip_header 会把 WAF 发来的 X-Forwarded-For 的第一个 IP 当成真实 IP,而这个第一个 IP 就是 CDN 的边缘节点。

解决方法

你需要让源站信任 CDN 和 WAF 两层的 IP,然后递归解析 X-Forwarded-For 中最前面的那个 IP。

例如:假设

  • CDN 节点 IP 段:1.1.1.0/24
  • WAF IP:2.2.2.2

源站 Nginx 配置应为:

# 信任 CDN 节点 IP 段
set_real_ip_from 1.1.1.0/24;

set_real_ip_from 1.1.1.0/24;
# 信任 WAF 服务器 IP
set_real_ip_from 2.2.2.2;
real_ip_header X-Forwarded-For;
real_ip_recursive on;

这样流程是:

  1. 源站看到 WAF 的 IP,因在 set_real_ip_from 里,信任它提供的 X-Forwarded-For。
  2. Nginx 递归解析 X-Forwarded-For,发现里面还有 CDN IP,且 CDN IP 也在信任列表中,于是继续向前找。
  3. 最前面的就是用户真实 IP。

注意事项:

  • CDN 的回源必须保留用户真实 IP(例如 Cloudflare、阿里云 CDN、腾讯云 CDN 都有保留或替换 X-Forwarded-For 的设置)。
  • 你必须把 所有中间层的 IP 段都放到 set_real_ip_from,否则 Nginx 不会继续向前解析。
  • 如果 CDN 使用的是 True-Client-IPCF-Connecting-IP 等自定义头,你可能需要改成:
real_ip_header CF-Connecting-IP;或者 real_ip_header True-Client-IP;

我可以帮你把 CDN + WAF + 源站的 IP 递归解析配置 整理成一个完整示例,这样你直接套上就能获取到用户的真实 IP。

然后重启nginx,再访问,就可以获取用户的IP了。

📮用邮箱订阅我的博客吧

评论

退出移动版