必须在 server 或 http 块顶部配置 set_real_ip_from、real_ip_header 和 real_ip_recursive,三者缺一不可;location 块仅负责透传头和记录日志,不参与 ip 解析。

要在 Nginx 的 location 块中正确获取 CDN 后的真实 IP,关键不是在 location 里“单独配置 IP 获取逻辑”,而是确保整个 Nginx 实例已正确启用 realip 模块并完成全局可信代理识别——location 块本身只负责转发头或日志记录,不参与真实 IP 的解析。很多人的配置失败,正是因为把 set_real_ip_from 等指令错误地写进了 location,导致完全不生效。
必须在 server 或 http 块顶部配置 realip 指令
realip 相关指令必须出现在 server { 或 http { 的最开始位置(任何 location 之前),否则 Nginx 不会执行 IP 替换:
-
set_real_ip_from:填 CDN 官方公布的回源 IP 段(如 Cloudflare、腾讯云、阿里云 CDN 都有公开列表),绝不能写成0.0.0.0/0,否则可被伪造 X-Forwarded-For 绕过 -
real_ip_header X-Forwarded-For:告诉 Nginx 从哪个请求头读取原始 IP 列表 -
real_ip_recursive on:开启后,Nginx 会从右往左跳过所有可信 CDN IP,取第一个非可信 IP 作为真实客户端 IP
location 中只需正确透传和记录,不负责解析
location 块的作用是配合上游行为,确保头信息不丢失、日志能体现真实 IP:
- 如果后端是 PHP(如宝塔面板默认),需确认
fastcgi_param REMOTE_ADDR $remote_addr保持原样(Nginx 解析完真实 IP 后,$remote_addr已更新) - 若需向后端传递额外头,可在
location内加:proxy_set_header X-Real-IP $remote_addr;proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - 如要自定义访问日志显示真实 IP,用
$remote_addr即可(realip 生效后它已是用户真实 IP),例如:log_format main '$remote_addr - $remote_user [$time_local] "$request" ...';
验证是否生效的简单方法
部署后,用 curl 模拟带 CDN 头的请求测试:
- 执行:
curl -H "X-Forwarded-For: 1.2.3.4, 192.168.1.100" http://your-domain.com/test.php - test.php 中输出:
<?php echo $_SERVER['REMOTE_ADDR']; ?> - 若返回
1.2.3.4(而非 CDN 节点 IP),说明 realip 配置成功 - 若返回中间某个 IP 或 CDN 节点 IP,检查
real_ip_recursive是否开启、set_real_ip_from是否覆盖了全部 CDN 回源段
常见 CDN 的 X-Forwarded-For 行为差异
不同 CDN 对 X-Forwarded-For 的构造方式略有不同,影响取值逻辑:
- Cloudflare 默认使用
CF-Connecting-IP头传递真实 IP,此时应设real_ip_header CF-Connecting-IP,并把 Cloudflare 回源段加入set_real_ip_from - 腾讯云 CDN、阿里云 CDN 通常用标准
X-Forwarded-For,但可能在多层节点中追加多个 IP,所以real_ip_recursive on是必需的 - 部分私有 CDN 或自建反向代理,可能用自定义头如
X-Custom-Real-IP,对应修改real_ip_header即可











