当Nginx直连公网客户端时,配置proxy_set_header X-Real-IP $remote_addr可准确获取真实源IP;需在location中proxy_pass前设置X-Real-IP、X-Forwarded-For等头,后端代码显式读取,并建议增加私有IP过滤与调试验证。

如果 Nginx 是直接面向公网客户端(即没有 CDN、WAF 或负载均衡器在它前面),那么配置 proxy_set_header X-Real-IP $remote_addr 就能准确捕获真实单级源 IP。这种场景最简单,也最可控。
前端 Nginx(直连客户端)必须设置 X-Real-IP
在 location 块中、proxy_pass 指令之前添加:
-
proxy_set_header X-Real-IP $remote_addr;—— 此时$remote_addr就是用户真实 IP -
proxy_set_header X-Forwarded-For $remote_addr;—— 补充标准头,便于日志和兼容性 -
proxy_set_header Host $host;和proxy_set_header X-Forwarded-Proto $scheme;—— 保障协议与域名正确传递
后端服务需主动读取 X-Real-IP 头
Nginx 只负责透传,后端不会自动改写 REMOTE_ADDR。必须在代码中显式获取:
- PHP:
$_SERVER['HTTP_X_REAL_IP'] ?? $_SERVER['REMOTE_ADDR'] - Python(Flask):
request.headers.get('X-Real-IP') - Node.js(Express):
req.headers['x-real-ip'] || req.ip(需启用app.set('trust proxy', true)) - Java(Spring Boot):
request.getHeader("X-Real-IP")
无需 realip_module,但建议加基础防护
因为是单级直连,不存在中间代理伪造问题,所以不用配置 set_real_ip_from 或 real_ip_header。但为防内网直连或测试流量绕过,可加一层轻量校验:
- 在 Nginx 中用
if ($remote_addr ~ ^(127\.0\.0\.1|10\.\d+\.\d+\.\d+|192\.168\.\d+\.\d+|172\.(1[6-9]|2[0-9]|3[0-1])\.\d+\.\d+)$) { return 403; }拒绝明显私有地址发起的代理请求 - 后端收到
X-Real-IP后,先做filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE)判断是否为公网可路由地址
验证是否生效
快速确认配置结果:
- 在 Nginx 配置里临时加一行:
add_header X-Debug-Real-IP $remote_addr;,访问后看响应头值是否为你本地公网 IP - 后端打印
X-Real-IP请求头内容,排除空值、127.0.0.1或内网段 - 检查 Nginx 访问日志中
$remote_addr是否已反映真实 IP(此时无需修改日志格式)











