要让后端拿到客户端真实IP,需三步:Nginx识别真实IP(配置set_real_ip_from、real_ip_header、real_ip_recursive),透传真实IP(proxy_set_header X-Real-IP $remote_addr等),后端主动读取Header(如X-Real-IP)而非REMOTE_ADDR。

要让后端拿到客户端真实 IP,不能只在 proxy_set_header 里写两行就完事。核心是:Nginx 先“认出”真实 IP,再稳稳传出去,后端还得主动“拆包”读取——三者缺一不可。
先让 $remote_addr 变成真实 IP
默认情况下,$remote_addr 是上一跳代理(比如 CDN、SLB 或 WAF)的出口 IP,不是用户本身。必须告诉 Nginx:“哪些 IP 是我信得过的代理,它们传来的 X-Forwarded-For 或 X-Real-IP 我才认。”
- 在
http、server或location块中添加可信段,例如:set_real_ip_from 100.64.0.0/10;(阿里云私网回源段)set_real_ip_from 203.208.60.1;(某个 CDN 节点) - 指定从哪个 Header 解析真实 IP:
real_ip_header X-Forwarded-For;(推荐,兼容多层)
或real_ip_header X-Real-IP; - 启用递归解析:
real_ip_recursive on;
这样 Nginx 会从X-Forwarded-For的逗号分隔列表中,从右往左剔除所有已知代理 IP,最终把最左边那个非私有、非代理的 IP 设为新的$remote_addr和$realip_remote_addr
再用 proxy_set_header 把它透传出去
等 $remote_addr 已经是用户真实 IP 后,才能放心用它设置 header。注意:这些指令必须放在 proxy_pass 行之前。
安装并运行 Aperture(Lightning Labs 的 L402 闪电反向代理),用于创建 L402 付费墙、配置付费 API 端点、为其他代理托管付费内容或测试 L402 认证流程。
-
proxy_set_header X-Real-IP $remote_addr;
单值清晰,后端可直接读取,不建议用$http_x_real_ip等原始头,避免被伪造 -
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
自动追加当前真实 IP 到已有链路末尾,保留完整路径(如203.0.113.1, 198.51.100.2),后端取第一个即可
⚠️ 切忌写成$remote_addr直接赋给X-Forwarded-For,否则会覆盖上游已有的原始 IP
后端必须主动读取,不能依赖 REMOTE_ADDR
Nginx 只负责“发”,后端框架默认返回的仍是连接发起方地址(即 Nginx 的 IP),不是 header 里的值。
- Java(Servlet):
request.getHeader("X-Real-IP"),而非getRemoteAddr() - Python(Flask):
request.environ.get('HTTP_X_REAL_IP') - PHP:
$_SERVER['HTTP_X_REAL_IP'];若用X-Forwarded-For,需手动取逗号分隔后的首项 - Node.js(Express):
req.headers['x-real-ip']或req.headers['x-forwarded-for'].split(',')[0].trim()
顺便让 access_log 也记录真实 IP
如果希望日志里直接显示用户真实 IP(而不是 127.0.0.1 或代理 IP),需启用 real_ip_module 并复用上面的配置:
-
set_real_ip_from 127.0.0.1;(仅信任本机反向代理) real_ip_header X-Real-IP;real_ip_recursive on;
这样 $remote_addr 在日志变量中就已是真实 IP,无需再从 header 解析。

















