Nginx多级反向代理获取真实IP

客户端可以随便伪造的请求头X-Forwarded-For,直接代码获取X-Forwarded-For拿取第一个IP可能是伪造的。

要在 Nginx 多级代理链中准确把真实客户端 IP 传到后端应用,关键不是“层层加头”,而是建立一条可信、可验证、不中断的传递路径。漏掉任一环节——比如某层没透传 X-Forwarded-For,或最后入口没启用 realip 校验——IP 就会失真。

每层代理必须透传 X-Forwarded-For

这是全链路 IP 追踪的基础。所有中间 Nginx(CDN、WAF、LB、网关)都需确保该头完整延续:

  • 首层代理(直连公网或 CDN)用 proxy_set_header X-Forwarded-For $remote_addr; 初始化,写入用户真实 IP
  • 后续每一层统一使用 proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; ——它会自动在已有值末尾追加本层看到的 $remote_addr,形成类似 1.1.1.1, 10.0.0.5, 10.0.0.6 的格式
  • 禁止清空、覆盖、手动拼接 X-Forwarded-For;任何一层缺失,链路即断裂

最后一层 Nginx 必须启用 realip 模块校验

  • 确认编译时已启用 –with-http_realip_module
nginx -V 2>&1 | grep http_realip_module
输出包含 –with-http_realip_module → 支持 set_real_ip_from(这个指令属于 ngx_http_realip_module)
Debian/Ubuntu、CentOS 官方源直接装的 nginx,一般自带这个模块;自己源码编译、极简镜像容易不带。
  • 在Nginx的 http或server或location 块中配置可信代理段,指定解析来源,开启递归解析
  • Nginx 将从右往左跳过所有可信 IP,取第一个非可信地址作为真实客户端 IP,并自动更新 $remote_addr
set_real_ip_from 10.0.0.0/8;
set_real_ip_from 172.16.0.0/12;
set_real_ip_from 192.168.0.0/16;
set_real_ip_from 173.245.48.0/20;
real_ip_header X-Forwarded-For;
real_ip_recursive on;

按实际代理出口 IP 精确填写,不建议用宽泛范围

后端应读取经 realip 修正后的值

  • 优先读 X-Real-IP(由 Nginx 注入,等价于修正后的 $remote_addr)
  • 若框架支持,也可直接用 request.getRemoteAddr()(PHP 的 $_SERVER[‘REMOTE_ADDR’]、Java 的 HttpServletRequest.getRemoteAddr()),前提是 realip 已生效