如果某个 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-IP(HTTP_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 上对照你真实的地址确认结果。


