跳到正文
记录,是一种生活方式

网站接了 Cloudflare 后看不到真实访客 IP?三种解决方法和一个安全坑

首页 / 技术笔记 / 网站接了 Cloudflare 后看不到真实访客 IP?三种解决方法和一个安全坑

网站接上 Cloudflare 之后,很多人会发现一件怪事:后台日志、评论记录、登录失败锁定里看到的访客 IP,全是 172.64.x.x、172.70.x.x、104.x.x.x 这类地址。这些不是访客,是 Cloudflare 的边缘节点。这篇讲清楚原因、三种拿到真实 IP 的方法,以及最容易踩的安全坑。

网站接了 Cloudflare 后看不到

为什么看到的都是 Cloudflare 的 IP

开启橙色云朵(代理模式)后,访客连的是 Cloudflare,Cloudflare 再代表访客去连你的服务器。对你的服务器来说,“对方”就是 Cloudflare 节点,所以 REMOTE_ADDR 永远是 Cloudflare 的 IP。真实访客 IP 被放进了请求头:

  • CF-Connecting-IP:Cloudflare 专用头,只有一个 IP,最推荐。
  • X-Forwarded-For:通用代理头,可能是一串 IP 列表。

如果不处理,后果不只是日志难看:按 IP 做的登录失败锁定、评论限流会把所有人当成同一批人,一个人输错几次密码,可能所有访客都被锁。

方法一:Nginx 用 realip 模块(推荐)

在 Nginx 层把真实 IP 还原,后面的 PHP、日志、限流全部自动生效。先用 nginx -V 确认编译参数里有 http_realip_module(宝塔/aaPanel 自带的 Nginx 一般都有),然后在 http 或 server 块里加:

# Cloudflare 官方 IP 段,见 cloudflare.com/ips
set_real_ip_from 173.245.48.0/20;
set_real_ip_from 103.21.244.0/22;
# ……把 ips-v4 和 ips-v6 里的每一段都列上
real_ip_header CF-Connecting-IP;

重载 Nginx 后,$remote_addr 就是访客真实 IP,PHP 里的 REMOTE_ADDR 也一样。原始的 Cloudflare 节点地址还能通过 $realip_remote_addr 拿到。Cloudflare 的 IP 段偶尔会更新,建议写个定时任务定期拉取官方列表重新生成这段配置。

方法二:Apache 用 mod_remoteip

RemoteIPHeader CF-Connecting-IP
RemoteIPTrustedProxy 173.245.48.0/20
# ……同样列上 Cloudflare 全部 IP 段

启用 mod_remoteip 后重启 Apache 即可。日志格式里记得把 %h 换成 %a,否则日志还是记代理地址。

方法三:在程序里判断

没法改服务器配置时,可以在代码里处理,但一定要先确认请求确实来自 Cloudflare:

function real_ip() {
    $ip = $_SERVER['REMOTE_ADDR'];
    // ip_in_cloudflare() 需自行实现:判断 $ip 是否落在 Cloudflare 官方 IP 段内
    if (ip_in_cloudflare($ip) && !empty($_SERVER['HTTP_CF_CONNECTING_IP'])) {
        return $_SERVER['HTTP_CF_CONNECTING_IP'];
    }
    return $ip;
}

很多博客、论坛程序提供一个“信任代理”开关,打开后直接读 X-Forwarded-For。这能解决问题,但有下面这个坑。

最大的坑:请求头可以伪造

X-Forwarded-For 和 CF-Connecting-IP 只是普通请求头,任何人都能自己填。如果你的源站 IP 暴露了,攻击者可以绕过 Cloudflare 直连源站,在请求头里随便写一个 IP,冒充别人、绕过封禁和限流。

所以真正稳妥的做法是两步一起做:

  1. 只信任 Cloudflare 的 IP 段(方法一、二本身就做到了这一点;方法三里的 IP 段判断不能省)。
  2. 源站防火墙只放行 Cloudflare:80 和 443 端口只允许 Cloudflare 的 IP 段访问,其余一律拒绝。更进一步可以开 Cloudflare 的 Authenticated Origin Pulls,让源站只接受带 Cloudflare 客户端证书的请求。

怎么验证配置生效

  • 用手机流量访问一次网站,看访问日志里记下的是不是你手机的公网 IP。
  • 故意在后台输错一次密码,确认失败记录里的 IP 是你自己的,而不是 172.x 开头的地址。
  • 从另一台机器直连源站 IP 并伪造 X-Forwarded-For,确认要么连不上,要么记录的仍是真实来源。

小结

能改服务器配置就用 realip / remoteip,在最前面一次解决;只能改代码就一定要校验来源 IP 段。无论哪种方式,源站只对 Cloudflare 开放这一步都值得做,它同时解决了伪造 IP 和源站被直接打两个问题。

本文由 Lingshi 发布,转载请注明出处。

0 条评论

还没有评论,来说两句吧。