nginx 默认不透传真实客户端ip,需配置set_real_ip_from指定可信代理网段并设置real_ip_header x-forwarded-for,同时php中应读取$_server['remote_addr']而非http头,并在fastcgi_param中确保remote_addr $remote_addr正确传递。

因为 Nginx 默认不透传真实客户端 IP,Docker 容器里的 PHP 看到的是上游(Nginx)的连接来源 —— 也就是宿主机或容器网络网关的 IP,不是用户真实 IP。
nginx 配置里漏了 real_ip 指令
这是最常见原因:Nginx 没有告诉自己“哪些 IP 是可信代理”,也没把 X-Forwarded-For 或 X-Real-IP 头里的值当作真实客户端地址来用。
你需要在 http 或 server 块里加两行:
set_real_ip_from 172.17.0.0/16; # Docker bridge 默认网段 real_ip_header X-Forwarded-For;
注意:set_real_ip_from 必须写成你实际使用的 Docker 网络子网。比如你用 --network web-net,就得先查这个网络的网段:
docker network inspect web-net | grep Subnet- 如果输出是
"Subnet": "172.20.0.0/16",那就要写set_real_ip_from 172.20.0.0/16 - 不能只写
127.0.0.1—— 容器间通信走的是 Docker 网络 IP,不是 localhost
PHP 代码里没读对 $_SERVER 变量
Nginx 设置好 real_ip 后,会把真实 IP 写进 $_SERVER['REMOTE_ADDR'];但很多老项目仍习惯读 $_SERVER['HTTP_X_FORWARDED_FOR'],这反而可能被伪造、不可信。
正确做法是直接信任 $_SERVER['REMOTE_ADDR'](前提是 Nginx 的 real_ip 配置已生效)。
验证是否生效:
在 Linux 上通过 Docker 运行 OpenClaw,并使用 Tailscale 实现远程访问。⚠️ 涉及 sudo、Docker、Tailscale和凭证挂载——请先查阅安全章节...
- 在 PHP 中临时加一行:
error_log('REMOTE_ADDR: ' . $_SERVER['REMOTE_ADDR'], 4); - 访问后看 PHP 容器日志:
docker logs fn-php | tail -n 1 - 如果输出是类似
REMOTE_ADDR: 203.208.60.1(公网 IP),说明成功;如果是172.20.0.1或127.0.0.1,说明 Nginx 还没透传过去
fastcgi_param 没同步更新 REMOTE_ADDR
如果你用的是 Nginx → PHP-FPM(而非内置 php-cgi),光改 Nginx 的 real_ip 不够 —— 还得确保它把修正后的 REMOTE_ADDR 通过 FastCGI 协议传给 PHP。
检查你的 Nginx location ~ \.php 块里有没有这行:
fastcgi_param REMOTE_ADDR $remote_addr;
没有就加上。别用 $http_x_forwarded_for 替代,那是原始头,不可靠。
另外确认没覆盖这一行:
- 错误写法:
fastcgi_param REMOTE_ADDR $http_x_real_ip;($http_x_real_ip是空的,Nginx 不自动提取) - 正确逻辑链:
real_ip→ 覆盖$remote_addr→fastcgi_param REMOTE_ADDR $remote_addr→ PHP 收到
容器网络模式影响 real_ip 可信源范围
不同网络模式下,Nginx 和 PHP 容器之间的“上一跳” IP 不同,直接影响 set_real_ip_from 怎么写:
- 用
--network bridge(默认):PHP 容器看到的 Nginx IP 是 Docker 网桥网关(如172.17.0.1),要设set_real_ip_from 172.17.0.0/16 - 用
--network host:PHP 容器直接共享宿主机网络,Nginx IP 就是127.0.0.1,但这时set_real_ip_from 127.0.0.1不够 —— 因为所有请求都来自本地,必须配合real_ip_recursive on和多层X-Forwarded-For解析 - 用自定义 bridge(如
web-net):必须查该网络子网,不能硬编码
最容易被忽略的一点:Docker 容器重启后,bridge 网络的网关 IP 不变,但自定义网络的网关可能变 —— 所以不要把 set_real_ip_from 写死在配置文件里,最好用启动脚本动态注入。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!










