关键是在location中用proxy_set_header透传x-real-ip和x-forwarded-for,并配合http/server块的set_real_ip_from、real_ip_header及real_ip_recursive指令,使nginx自身识别真实ip且后端可靠获取。

在 Nginx 的 location 块中获取和传递客户端真实 IP,关键不是“在 location 里单独写逻辑”,而是通过全局或 location 级别的 proxy_set_header 和 realip 模块配合实现——既要让 Nginx 自身日志/变量反映真实 IP,也要让后端服务能可靠拿到它。
location 中透传真实 IP:用 proxy_set_header 设置标准请求头
当 Nginx 作为反向代理(即配置了 proxy_pass)时,在 location 块中必须显式设置透传头,否则后端只能看到 Nginx 本机的内网 IP:
-
proxy_set_header X-Real-IP $remote_addr;:把与 Nginx 直连的客户端或上一级可信代理的 IP 写入该头。适用于首层代理,简单直接 -
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;:安全追加 IP 到已有 XFF 链。若上游已带X-Forwarded-For: 203.0.113.5,且当前 $remote_addr 是10.0.1.20,则结果为X-Forwarded-For: 203.0.113.5, 10.0.1.20 - 避免写
$http_x_forwarded_for直接赋值——它可被客户端伪造,不安全
location 中让 Nginx 自身识别真实 IP:启用 realip 模块解析
仅设 header 不够;Nginx 默认仍以 TCP 连接对端(如负载均衡器 IP)为 $remote_addr。要在 location 或更上层(server/http)启用真实 IP 解析:
- 先声明可信代理网段:
set_real_ip_from 10.0.0.0/8;、set_real_ip_from 192.168.0.0/16;(必须匹配你实际的 CDN、SLB 或前置 Nginx 的出口 IP) - 指定来源头:
real_ip_header X-Forwarded-For;(或X-Real-IP,按上游设备实际写的头选) - 开启递归解析:
real_ip_recursive on;,确保取最左边未被伪造的原始客户端 IP - 生效后,
$remote_addr、$realip_remote_addr等变量就代表真实客户端 IP,可用于日志、限流、geoip 等
验证是否生效:检查日志与后端接收
光配不对,得验证:
- 在
log_format中加入$http_x_forwarded_for、$realip_remote_addr、$remote_addr对比,确认解析正确 - 后端应用不能依赖
request.getRemoteAddr()或$_SERVER['REMOTE_ADDR'],而要读X-Real-IP或X-Forwarded-For的第一个非私有 IP - 测试时用 curl 模拟多级代理:
curl -H "X-Forwarded-For: 192.0.2.1, 203.0.113.10" http://your-site/,观察日志是否取到192.0.2.1
常见误区提醒
容易出错的地方往往藏在细节里:
- 没配
set_real_ip_from就用real_ip_header:Nginx 会忽略该头,$remote_addr仍是代理 IP - 把
set_real_ip_from写成公网 IP 段(如 1.0.0.0/24):导致所有请求都被误判为可信,失去防护意义 - 在多个 location 中重复配置
proxy_set_header却漏掉某一个:该路径下后端收不到真实 IP - CDN 场景下,只信 CDN 提供的 IP 段(如 Cloudflare 的 173.245.48.0/20),别把所有公网都设为
set_real_ip_from











