跳转到主内容
websoft网络软件专家 - 深耕网络技术,打造实用软件!

php获取本机ip在负载均衡下不同_php识别lb环境取ip【技巧】

不能直接用$_SERVER['REMOTE_ADDR'],因为它返回的是负载均衡器到PHP服务器的内网IP;应按CF-Connecting-IP→X-Real-IP→X-Forwarded-For(取首个非私有IP)→REMOTE_ADDR优先级安全获取真实客户端IP。 PHP 在负载均衡下获取真实客户端 IP 为什么不能直接用 $_SERVER['REMOTE_ADDR'] 因为
$_SERVER['REMOTE_ADDR']
拿到的是 LB(如 Nginx、AWS ALB、Cloudflare)到 PHP 应用服务器的连接 IP,通常是内网地址(比如
10.0.1.5
或
127.0.0.1
),不是用户真实出口 IP。 LB 一般会把原始请求头(如
X-Forwarded-For
、
X-Real-IP
)透传过来,但必须确认 LB 确实配置了转发,且你的 PHP 服务处于可信内网——否则直接信任这些头会导致 IP 伪造漏洞。 务必只在 LB 和 PHP 之间是私有网络(无公网直连)时才启用头字段解析 不要无条件信任
$_SERVER['HTTP_X_FORWARDED_FOR']
,它可能被客户端篡改或含多个逗号分隔的 IP 不同 LB 默认行为不同:Nginx 需手动加
proxy_set_header X-Real-IP $remote_addr;
;Cloudflare 用
CF-Connecting-IP
;AWS ALB 默认带
X-Forwarded-For
如何安全提取真实客户端 IP(推荐判断链) 按可信度从高到低依次检查,并只取第一个合法 IPv4/IPv6 地址(跳过私有网段和无效格式): 优先用
$_SERVER['HTTP_CF_CONNECTING_IP']
(Cloudflare 环境独有,不可伪造) 其次看
$_SERVER['HTTP_X_REAL_IP']
(Nginx 显式设置,较可靠) 再 fallback 到
$_SERVER['HTTP_X_FORWARDED_FOR']
:取逗号分隔后的**第一个非私有 IP**(如
"203.0.113.1, 192.168.1.10"
→ 取
203.0.113.1
) 最后才回退到
$_SERVER['REMOTE_ADDR']
(仅作兜底,通常只是 LB 内网地址) 示例逻辑片段(不依赖扩展): 立即学习 “ PHP免费学习笔记(深入) ”;
// 注意:需确保运行在可信内网环境 function getRealIP() { $ip = $_SERVER['REMOTE_ADDR'] ?? '0.0.0.0'; if (!empty($_SERVER['HTTP_CF_CONNECTING_IP'])) { $ip = $_SERVER['HTTP_CF_CONNECTING_IP']; } elseif (!empty($_SERVER['HTTP_X_REAL_IP'])) { $ip = $_SERVER['HTTP_X_REAL_IP']; } elseif (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) { $ips = array_map('trim', explode(',', $_SERVER['HTTP_X_FORWARDED_FOR'])); foreach ($ips as $candidate) { if (filter_var($candidate, FILTER_VALIDATE_IP) && !filter_var($candidate, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE)) { $ip = $candidate; break; } } } return filter_var($ip, FILTER_VALIDATE_IP) ? $ip : '0.0.0.0'; }
为什么 filter_var(..., FILTER_FLAG_NO_PRIV_RANGE) 不能省略 很多 LB(尤其是自建 Nginx + proxy _pass)会把
X-Forwarded-For
做追加操作,例如: 用户 → LB → PHP,LB 把原始 IP 加到头里,但若 LB 自身也经过一层代理,就可能塞入内网 IP(如
10.0.2.3
)甚至恶意构造的
127.0.0.1
。 PHP 8.5.5 PHP 8.5.5 是 PHP 8.5 分支的维护更新版本。该版本延续了“小步快跑”的迭代逻辑,通过深度错误修复、底层性能微调以及安全加固,旨在为开发者提供一个更健壮、更高效的运行环境。该版本严格遵守语义化版本规范,不包含破坏性变更。 下载
FILTER_FLAG_NO_PRIV_RANGE
能过滤掉
10.0.0.0/8
、
172.16.0.0/12
、
192.168.0.0/16
、
127.0.0.0/8
等私有/环回地址 不加这层校验,攻击者可能伪造
X-Forwarded-For: 127.0.0.1
绕过 IP 限流或权限校验 注意:IPv6 的私有地址(如
fd00::/8
)需额外处理,
filter_var
不覆盖,生产环境建议用
ip_is_private()
类辅助函数 本地开发与测试时怎么模拟 LB 头 用 cURL 或 Postman 手动加请求头即可,例如:
curl -H "X-Real-IP: 203.0.113.45" \ -H "X-Forwarded-For: 203.0.113.45, 192.168.0.100" \ http://localhost/test-ip.php
在 Nginx 开发环境,可临时加配置验证头是否透传成功:
location / { proxy_pass http://php-upstream; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; }
关键点:别在没配 LB 的环境硬写逻辑去读
X-Forwarded-For
,否则本地调试时会拿到空值或错误值;上线前务必确认 LB 实际发送了哪些头,用
print_r($_SERVER)
快速验证。 最常被忽略的是 LB 是否真的转发了头、以及是否启用了「追加模式」而非「覆盖模式」——这两点不确认清楚,IP 就永远拿不准。

相关文章