IP 与网络

REMOTE_ADDR vs CF-Connecting-IP:获取 Cloudflare 后面的真实访客 IP

如果你的 WordPress 安全插件或 PHP 应用在 Cloudflare 后面记录了错误的 IP,本文解释原因,并教你如何用 CF-Connecting-IP 而非 REMOTE_ADDR 或可伪造的 HTTP_CLIENT_IP 请求头安全地读取真实访客 IP。

6 分钟阅读·

如果某个 WordPress 安全插件提醒你注意「IP 检测设置」,或者你的 PHP 应用突然把每位访客都记录成同样的那几个 IP,原因几乎总是相同的:像 Cloudflare 这样的反向代理夹在访客和你的服务器之间。简短版结论——把 REMOTE_ADDR 作为默认值,永远不要盲目信任 HTTP_CLIENT_IP,只有在确认请求确实经过 Cloudflare 之后才去读取 CF-Connecting-IP。下面逐条解释这背后的原因。

每个值到底代表什么

在 PHP 中,这些值作为 $_SERVER 条目出现。它们并不能互换——它们来自完全不同的地方,而这种差别正是问题的全部所在:

  • REMOTE_ADDR —— 与你的服务器建立 TCP 连接的那一方的 IP 地址。Web 服务器直接从套接字本身填入这个值,所以客户端无法伪造它。这是唯一值得信任的值。
  • HTTP_CLIENT_IP HTTP_X_FORWARDED_FOR —— 普通的 HTTP 请求头。$_SERVER 中任何 HTTP_* 条目都只是客户端发来的请求头,这意味着任何人用一行 curl 就能把它设成任意值。
  • HTTP_CF_CONNECTING_IP —— Cloudflare 添加的 CF-Connecting-IP 请求头,包含真实的访客 IP。只有在你能保证请求确实经过 Cloudflare 时,它才值得信任。

为什么在 Cloudflare 后面 REMOTE_ADDR 是「错」的

当 Cloudflare 为你的域名做代理时,访客连接的是 Cloudflare 的边缘节点,再由 Cloudflare 向你的源服务器另开一条新连接。从你服务器的视角看,访客就是 Cloudflare——所以 REMOTE_ADDR 是一个 Cloudflare 边缘 IP,成千上万不同的人对应的都是同一个。这并没有出故障;代理只是在做它该做的事。

为了把原始访客交给你,Cloudflare 在每个请求上都附带 CF-Connecting-IP 请求头。所以在 Cloudflare 后面,正确的来源是 $_SERVER['HTTP_CF_CONNECTING_IP'],当该请求头不存在时再回退到 REMOTE_ADDR

安全陷阱:为什么你不能直接信任请求头

人们很容易写下「读取 HTTP_CLIENT_IP X-Forwarded-For,否则用 REMOTE_ADDR」然后就此了事。而这正是让网站被攻陷的那种写法。因为这些是客户端提供的请求头,攻击者可以发送:

curl https://your-site.example/wp-login.php \
  -H "X-Forwarded-For: 8.8.8.8" \
  -H "Client-IP: 1.1.1.1"

如果你的登录限流、防火墙或审计日志读取的是这些请求头,攻击者就能在每次请求时轮换一个假 IP——绕过速率限制、规避 IP 封禁,并污染你的日志。这正是好的安全插件在更改检测方式之前会提醒你的原因:「更方便」的那个设置往往就是不安全的那个。

CF-Connecting-IP 之所以能避免这个问题,只是因为多了一个额外条件:你的源站必须接受来自 Cloudflare 的流量。如果你的服务器同时还能通过其公网 IP 被直接访问,攻击者就可以跳过 Cloudflare、自行伪造 CF-Connecting-IP。用 Authenticated Origin Pulls 或一个只放行 Cloudflare IP 段的防火墙把源站锁死,这个请求头才会变得可信。

用大白话说,正确的设置是什么

  • 纯服务器、没有代理:REMOTE_ADDR。搞定。
  • 在 Cloudflare 后面:CF-Connecting-IPHTTP_CF_CONNECTING_IP),并把源站限制为只接受 Cloudflare 的流量,让这个请求头无法被伪造。
  • 在其他代理/CDN 或负载均衡器后面:用那个代理文档里说明的请求头(通常是 X-Forwarded-For,取最右侧那个可信跳数),同样要确保源站只接受来自该代理的流量。

在诸如 All-In-One Security 这类 WordPress 安全插件中,「IP 检测」设置控制的正是这个选择。除非你在 Cloudflare 后面,否则就保持 REMOTE_ADDR;如果在 Cloudflare 后面,就切换到 CF-Connecting-IP

如何验证你配置对了

最快的合理性检查,是把你服务器检测到的值和你真实的公网 IP 做对比。从同一台机器打开 whatsmy.fyi :它会显示外部世界看到的、你那个确切的公网 IP。如果你的插件或应用为你自己这次访问记录的 IP 与之相符,说明检测在正常工作。(whatsmy.fyi 本身就运行在 Cloudflare 上,所以它从 CF-Connecting-IP 读取你的地址,方式和一个正确配置的源站一样——而且它什么都不存储。)

如果你是在用程序方式调试,这个免密钥端点会为脚本返回相同的值:

curl https://whatsmy.fyi/ip
# → your real public IP, as seen at the edge

两个 IP 相符就说明你的检测是对的。如果你的服务器记录的是一个 Cloudflare IP,而 whatsmy.fyi 显示的是你真实的 IP,那你在代理后面读取的仍然是 REMOTE_ADDR——改用 CF-Connecting-IP。如果它们以其他任何方式不一致,那就是路径中有 VPN、IPv4/IPv6 分流或第二层代理——我们关于 为什么一个 IP 会显示错误位置 的说明涵盖了这些情况。

一句话要点

REMOTE_ADDR 是你的服务器不会被骗的那个真相; HTTP_CLIENT_IP 则是任何人都能提出的一个说法。在 Cloudflare 后面,优先用 CF-Connecting-IP,并把源站锁死以保持其可信——然后在 whatsmy.fyi 上对照你真实的地址确认结果。

即时查询您的 IP 地址、位置与隐私评分。

零日志。零追踪。零外部 API。

立即检测 →

相关文章

REMOTE_ADDR vs CF-Connecting-IP:获取 Cloudflare 后面的真实访客 IP | whatsmy.fyi