php必须先校验$_server['remote_addr']是否属于cloudflare官方ip段,再提取并过滤$_server['http_cf_connecting_ip'];否则伪造该头可轻易冒充任意ip,导致风控失效。

PHP 无法直接信任 $_SERVER['REMOTE_ADDR'] 获取真实用户 IP,因为 Cloudflare 会把请求代理过来,此时它显示的是 Cloudflare 节点的 IP —— 你需要从 HTTP_CF_CONNECTING_IP(或其它 CF 头)里取值,但必须校验来源可信。
为什么不能直接用 HTTP_CF_CONNECTING_IP
这个头是 Cloudflare 在转发请求时自动添加的,格式为 HTTP_CF_CONNECTING_IP: 203.0.113.45。但它完全由客户端可控:攻击者只要伪造该请求头,就能轻易冒充任意 IP。所以 PHP 中读取前必须确认请求确实来自 Cloudflare 的合法节点。
- Cloudflare 官方明确要求:只在源站 IP 白名单校验通过后,才信任
HTTP_CF_CONNECTING_IP - 未校验就使用,会导致登录限流、地理围栏、风控规则全部失效
-
HTTP_X_FORWARDED_FOR更不可靠 —— 它可能被多层代理污染,且 Cloudflare 不保证始终设置
PHP 中安全获取真实 IP 的完整判断逻辑
核心是两步:先验证请求来源 IP 是否属于 Cloudflare 官方 IP 段,再提取并过滤 HTTP_CF_CONNECTING_IP。Cloudflare 公布的 IPv4/IPv6 列表需定期更新(建议用脚本自动拉取 https://www.cloudflare.com/ips-v*)。
- 检查
$_SERVER['REMOTE_ADDR']是否落在 Cloudflare 官方 IP 段内(用filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE)辅助排除私有地址) - 若匹配,再取
$_SERVER['HTTP_CF_CONNECTING_IP'],并用filter_var(..., FILTER_VALIDATE_IP)二次校验格式 - 不匹配则回退到
$_SERVER['REMOTE_ADDR'](比如本地开发或直连场景) - 避免使用
getenv('HTTP_CF_CONNECTING_IP')—— 在某些 SAPI(如 PHP-FPM 配置不当)下可能为空
常见错误写法及后果
很多人一行代码搞定:$ip = $_SERVER['HTTP_CF_CONNECTING_IP'] ?? $_SERVER['REMOTE_ADDR']; —— 这等于裸奔。
立即学习“PHP免费学习笔记(深入)”;
- 没做来源 IP 校验 → 攻击者发
curl -H "CF-Connecting-IP: 1.2.3.4" https://yoursite.com就能伪造 - 没过滤空格或多个 IP(如
"192.0.2.1, 198.51.100.2")→filter_var会失败,可能触发 Notice 或返回 false - 误用
HTTP_X_REAL_IP→ Nginx 需手动配置set_real_ip_from,且 Cloudflare 默认不发这个头 - 在 CLI 环境下读
$_SERVER头 → 返回 null 或空字符串,导致逻辑崩坏
真实用户 IP 是安全链路的起点,一旦这里松动,后续所有基于 IP 的逻辑(如封禁、限速、地域判断)都会失准。Cloudflare 的头只是“信封上的备注”,关键是你得亲手拆开信封、核对寄件人身份证——而不是看到字就信。











