应从 X-Forwarded-For 请求头最左侧提取真实客户端 IP,Nginx 需配置 proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for 并用正则截取首 IP,后端服务须信任代理并解析该头,否则仍无法获取真实 IP。

直接用 $remote_addr 只能得到上一级代理的 IP,不是用户真实 IP。多层代理(比如 CDN → Nginx → 后端服务)下,必须从 X-Forwarded-For 字段中提取最左边的那个 IP 才是源头客户端地址。
正确传递并解析 X-Forwarded-For
前端代理(如 CDN 或上层 Nginx)应把用户真实 IP 加到 X-Forwarded-For 请求头最前面,格式为:X-Forwarded-For: 203.122.45.67, 192.168.1.10, 10.0.0.5
其中第一个 IP 就是真实客户端 IP。
Nginx 需在 location 块中明确设置:
-
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;—— 把当前请求头 + 自身 IP 拼接后传给下一级 -
proxy_set_header X-Real-IP $remote_addr;—— 这行本身没用,别依赖它获取真实 IP
用正则提取最左侧真实 IP
因为 $proxy_add_x_forwarded_for 是字符串,可能含多个逗号分隔的 IP,需用 set + if 提取第一个:
set $RealIP $proxy_add_x_forwarded_for;
if ($RealIP ~ ^(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}).*) {
set $RealIP $1;
}
proxy_set_header X-Real-IP $RealIP;
注意:Nginx 的 if 在 location 内可用,但不能嵌套;该写法兼容主流版本(1.10+),无需 Lua 模块。
后端服务必须信任并解析该头
只配 Nginx 不够,后端应用(如 Spring Boot、Tomcat、Node.js)要主动读 X-Real-IP 或 X-Forwarded-For,且需配置可信代理段,否则会拒绝或忽略该头:
- Spring Boot:加
server.forward-headers-strategy=framework,并设spring.cloud.gateway.x-forwarded.for-enabled=true(若用 Gateway) - Tomcat:在
server.xml的<valve></valve>中指定internalProxies为你的 Nginx IP 段,例如internalProxies="192\.168\.\d+\.\d+" - Node.js(Express):启用
app.set('trust proxy', true)或指定 CIDR
额外注意事项
有些场景还容易踩坑:
- 如果请求头含下划线(如
X_Signature),默认会被 Nginx 丢弃,需在http块加underscores_in_headers on; - 避免重复添加
X-Forwarded-For,否则会越积越长;确保上游代理不伪造该头(可通过白名单校验) - 日志中想记录真实 IP,改用
$http_x_real_ip或$http_x_forwarded_for,而不是$remote_addr


















