1433 字
7 分钟
Nginx 和 Apache 如何获取用户真实 IP

你的网站日志里全是 Cloudflare IP?一文教你 Nginx 和 Apache 如何获取用户真实 IP#

前言:日志里的“陌生访客”#

如果你和我一样,喜欢分析网站的访问日志来了解访客来源,或者部署了像 Fail2ban 这样的安全工具,那么当你启用了 Cloudflare 的 CDN 加速(橙色云朵)后,你可能会发现一个“诡异”的现象:网站访问日志里所有的访客 IP,都变成了 Cloudflare 的官方 IP 地址段,例如 172.68.x.x104.21.x.x 等。

这意味着你失去了追踪真实访客来源的能力,更严重的是,安全工具可能会因为误判而封禁整个 Cloudflare 节点,导致成千上万的正常用户无法访问你的网站。

这究竟是为什么?又该如何解决呢?别担心,这篇教程将为你彻底揭秘背后的原理,并提供 Nginx 和 Apache 两种主流 Web 服务器的“一站式”解决方案。

问题的根源:反向代理与“传话人”#

当你开启 Cloudflare 的 CDN 代理后,你的网站访问流程发生了变化:

用户 -> Cloudflare 全球节点 -> 你的源站服务器

在这个流程中,Cloudflare 扮演了一个“中间人”或“传话人”的角色。它接收了用户的请求,然后用自己的名义来向你的服务器请求内容,最后再把内容返回给用户。

因此,你的服务器(Nginx/Apache)直接看到的连接,就是由 Cloudflare 服务器发起的。日志里记录下它的 IP,也就顺理成章了。

解决方案:信任“传话人”递来的“小纸条”#

幸运的是,Cloudflare 在向你的服务器“传话”时,非常贴心地附上了一张“小纸条”(即 HTTP Header),上面清晰地写着真实访客的信息。

我们需要做的,就是教会我们的 Web 服务器去读取这张“小纸条”,并信任上面的内容

Cloudflare 主要通过以下 HTTP Header 来传递真实 IP:

  • CF-Connecting-IP: 用户的真实 IP 地址。
  • X-Forwarded-For: 包含了用户 IP 和所有中间代理 IP 的链条。

我们的目标,就是让 Nginx 或 Apache 将 CF-Connecting-IP 里的地址,作为真实的客户端 IP 来处理。


Nginx 解决方案#

对于 Nginx,我们需要使用 ngx_http_realip_module 模块,这个模块在绝大多数编译版本中都是默认开启的。

操作步骤:

  1. 找到 Nginx 主配置文件 通常位于 /etc/nginx/nginx.conf。如果你使用宝塔面板,可以在 软件商店 -> Nginx -> 设置 -> 配置修改 中找到它。

  2. http 配置块中添加代码 找到 http { ... } 这个配置段,在它的内部(比如 server_tokens off; 的下一行)添加以下内容:

    # ===================================================
    # Cloudflare Real IP Configuration
    # ===================================================
    # 优先从 CF-Connecting-IP Header 获取真实 IP
    real_ip_header CF-Connecting-IP;
    # (可选,作为备用)如果上面的 Header 不存在,则从 X-Forwarded-For 中获取
    # real_ip_header X-Forwarded-For;
    # 设置所有 Cloudflare 的 IP 地址段为可信代理
    # 只有来自这些 IP 的请求,我们才信任它提供的 real_ip_header
    set_real_ip_from 173.245.48.0/20;
    set_real_ip_from 103.21.244.0/22;
    set_real_ip_from 103.22.200.0/22;
    set_real_ip_from 103.31.4.0/22;
    set_real_ip_from 141.101.64.0/18;
    set_real_ip_from 108.162.192.0/18;
    set_real_ip_from 190.93.240.0/20;
    set_real_ip_from 188.114.96.0/20;
    set_real_ip_from 197.234.240.0/22;
    set_real_ip_from 198.41.128.0/17;
    set_real_ip_from 162.158.0.0/15;
    set_real_ip_from 104.16.0.0/13;
    set_real_ip_from 104.24.0.0/14;
    set_real_ip_from 172.64.0.0/13;
    set_real_ip_from 131.0.72.0/22;
    set_real_ip_from 2400:cb00::/32;
    set_real_ip_from 2606:4700::/32;
    set_real_ip_from 2803:f800::/32;
    set_real_ip_from 2405:b500::/32;
    set_real_ip_from 2405:8100::/32;
    set_real_ip_from 2a06:98c0::/29;
    set_real_ip_from 2c0f:f248::/32;
    # ===================================================

    提示: Cloudflare 的 IP 段可能会更新,你可以随时在 Cloudflare 官网 - IP Ranges 页面获取最新的列表。

  3. 保存并重载 Nginx 配置

    Terminal window
    # 检查配置语法是否正确
    sudo nginx -t
    # 重载配置
    sudo systemctl reload nginx

    如果你使用宝塔面板,直接保存并重启 Nginx 即可。

配置完成后,你的 Nginx 访问日志和后端应用(如 PHP 的 $_SERVER['REMOTE_ADDR'])获取到的就都是用户的真实 IP 了!


Apache 解决方案#

对于 Apache,我们需要启用一个名为 mod_remoteip 的模块。

操作步骤:

  1. 启用 remoteip_module 在大多数现代的 Linux 发行版中,这个模块已经安装好了,只需要启用它。

    Terminal window
    # 对于 Debian/Ubuntu
    sudo a2enmod remoteip
    sudo systemctl restart apache2
    # 对于 CentOS/RHEL,通常是默认编译的,检查 httpd.conf 中的 LoadModule 指令
  2. 创建或修改配置文件 在 Apache 的主配置文件(httpd.confapache2.conf)或者在 conf-available 目录下创建一个新的配置文件,例如 remoteip.conf

    Terminal window
    # 创建新配置文件
    sudo nano /etc/apache2/conf-available/remoteip.conf
  3. 添加配置内容 将以下内容粘贴到文件中:

    # ===================================================
    # Cloudflare Real IP Configuration for Apache
    # ===================================================
    # 告诉 remoteip 模块,真实 IP 存在于 'CF-Connecting-IP' Header 中
    RemoteIPHeader CF-Connecting-IP
    # 添加所有 Cloudflare 的 IP 段为可信代理
    RemoteIPTrustedProxy 173.245.48.0/20
    RemoteIPTrustedProxy 103.21.244.0/22
    RemoteIPTrustedProxy 103.22.200.0/22
    # ... 将 Nginx 部分的所有 IP 段,都以 'RemoteIPTrustedProxy' 开头写在这里 ...
    RemoteIPTrustedProxy 2c0f:f248::/32
    # ===================================================

    注意: 你需要把 Nginx 方案中 set_real_ip_from 列表里的所有 IP 段,都转换成 RemoteIPTrustedProxy 的格式。

  4. 启用配置并重启 Apache

    Terminal window
    # 启用新的配置文件
    sudo a2enconf remoteip
    # 重启 Apache 使配置生效
    sudo systemctl restart apache2
  5. 修改日志格式(可选但推荐) 为了让访问日志也显示真实 IP,你需要修改 LogFormat 指令,将 %h (远程主机) 替换为 %a (客户端 IP)。 例如,将: LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined 修改为: LogFormat "%a %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined

总结#

通过以上简单的配置,我们就能轻松“穿透”Cloudflare 的代理,让我们的服务器重新记录下每一个访客的真实足迹。这不仅能让我们的数据分析更精准,更能让我们的安全策略(如 Fail2ban)发挥出应有的作用。

如果你也在使用 Cloudflare,强烈建议你花几分钟时间检查并应用此配置。希望这篇教程对你有所帮助!