【IT 运维】Apache 使用 mod_remoteip 恢复 Cloudflare 后的真实访客 IP

前言

当你的网站使用 Cloudflare CDN 时,Apache 日志中记录的 IP 地址会变成 Cloudflare 代理节点的 IP,而不是访客的真实 IP。这会导致:

  • 网站统计(如 Google Analytics)失去精确度
  • 无法根据 IP 进行地域分析
  • 防火墙/WAF 规则无法准确拦截
  • 日志审计追踪困难

Cloudflare 早已弃用 mod_cloudflare 模块,官方推荐使用 Apache 内置的 mod_remoteip 来解决这个问题。

本文基于 Rocky Linux 8.10 + Apache 2.4.37 环境,完整记录配置过程。


环境说明

项目 信息
操作系统 Rocky Linux 8.10 (Green Obsidian)
Web 服务器 Apache 2.4.37
模块状态 mod_remoteip 已加载,未配置
目标 恢复 Cloudflare 后的真实访客 IP

第一步:检查 mod_remoteip 模块

bash 复制代码
# 检查模块是否已加载
httpd -M | grep remoteip

输出 remoteip_module (shared) 表示模块已启用。如果未加载,在 /etc/httpd/conf.modules.d/ 中添加:

apache 复制代码
LoadModule remoteip_module modules/mod_remoteip.so

第二步:创建 remoteip 配置文件

创建 /etc/httpd/conf.d/remoteip.conf

apache 复制代码
# Cloudflare mod_remoteip 配置
# 从 CF-Connecting-IP 请求头恢复真实访客 IP

RemoteIPHeader CF-Connecting-IP

# Cloudflare IPv4 地址段
RemoteIPTrustedProxy 173.245.48.0/20
RemoteIPTrustedProxy 103.21.244.0/22
RemoteIPTrustedProxy 103.22.200.0/22
RemoteIPTrustedProxy 103.31.4.0/22
RemoteIPTrustedProxy 141.101.64.0/18
RemoteIPTrustedProxy 108.162.192.0/18
RemoteIPTrustedProxy 190.93.240.0/20
RemoteIPTrustedProxy 188.114.96.0/20
RemoteIPTrustedProxy 197.234.240.0/22
RemoteIPTrustedProxy 198.41.128.0/17
RemoteIPTrustedProxy 162.158.0.0/15
RemoteIPTrustedProxy 104.16.0.0/12
RemoteIPTrustedProxy 172.64.0.0/13
RemoteIPTrustedProxy 131.0.72.0/22

# Cloudflare IPv6 地址段
RemoteIPTrustedProxy 2400:cb00::/32
RemoteIPTrustedProxy 2606:4700::/32
RemoteIPTrustedProxy 2803:f800::/32
RemoteIPTrustedProxy 2405:b500::/32
RemoteIPTrustedProxy 2405:8100::/32
RemoteIPTrustedProxy 2a06:98c0::/29
RemoteIPTrustedProxy 2c0f:f248::/32

关键指令说明

指令 作用
RemoteIPHeader 指定从哪个 HTTP 请求头获取真实 IP。Cloudflare 使用 CF-Connecting-IP
RemoteIPTrustedProxy 声明哪些代理 IP 是可信的,只有来自这些 IP 的请求才会被替换 IP

⚠️ 安全提示 :不要使用 RemoteIPTrustedProxy 0.0.0.0/0 等通配规则,攻击者可以伪造 CF-Connecting-IP 请求头来欺骗服务器。


第三步:修改日志格式(推荐)

%h 替换为 %a,这让日志语义更明确:

bash 复制代码
# 先备份
cp /etc/httpd/conf/httpd.conf /etc/httpd/conf/httpd.conf.bak

# 修改
sed -i 's/^    LogFormat "%h /    LogFormat "%a /' /etc/httpd/conf/httpd.conf

修改前后对比:

diff 复制代码
- 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
占位符 含义
%h 远程主机名(默认情况下即对端 IP)
%a 经过 mod_remoteip 处理后的真实客户端 IP

💡 实际上 mod_remoteip 配置正确后,%h 也会显示真实 IP。但使用 %a 语义更清晰,是 Cloudflare 官方推荐的最佳实践。


第四步:测试并重启

bash 复制代码
# 1. 检查配置语法
apachectl configtest
# 输出: Syntax OK

# 2. 重启 Apache
systemctl restart httpd

# 3. 确认服务状态
systemctl status httpd

第五步:验证效果

方法一:curl 模拟测试

bash 复制代码
curl -s -H "CF-Connecting-IP: 1.2.3.4" http://localhost/ -o /dev/null
tail -1 /var/log/httpd/access_log

访问日志中应显示 1.2.3.4 而非 127.0.0.1

方法二:实际访问验证

从外部访问网站,检查日志中的 IP 是否为真实访客 IP(而非 Cloudflare 的 IP 段)。


常见问题

Q: 配置后仍然显示 Cloudflare IP?

  1. 确认 remoteip.conf 放在了 /etc/httpd/conf.d/ 目录下
  2. 检查 Cloudflare IP 段是否最新:https://www.cloudflare.com/ips/
  3. 确认请求确实经过了 Cloudflare(检查是否存在 CF-Connecting-IP 请求头)

Q: mod_remoteip 和 mod_cloudflare 有什么区别?

对比 mod_cloudflare mod_remoteip
维护状态 已弃用 活跃维护
来源 第三方模块 Apache 内置
安装方式 需手动编译 系统自带

Q: 需要定期更新 Cloudflare IP 段吗?

建议定期检查。Cloudflare 的 IP 段不常变动,但偶尔会有新增。可以考虑编写 cron 脚本自动拉取更新:

bash 复制代码
# 示例:每月自动更新 Cloudflare IP 段
curl -s https://www.cloudflare.com/ips-v4/ > /tmp/cf-ips.txt

总结

通过三步即可完成配置:

  1. 创建 remoteip.conf --- 信任 Cloudflare IP 段,使用 CF-Connecting-IP
  2. 修改 LogFormat --- %h%a(最佳实践)
  3. 重启 Apache --- 使配置生效

配置完成后,Apache 日志将正确记录访客的真实 IP,便于后续的日志分析和安全审计。


参考链接


相关推荐
C++ 老炮儿的技术栈1 小时前
Qt工控实战:自研机器人TCP长连接客户端(粘包处理+心跳保活+自动重连完整源码解析)
qt·tcp/ip·机器人
王二端茶倒水1 小时前
智慧园区网络运营:认证、分权、运维和安全闭环
运维·物联网·架构
爱就是恒久忍耐2 小时前
现代CMake的build方式
linux·运维·服务器
三8442 小时前
重定向/管道符/通配符/转义字符/VI/VIM
运维·服务器
小坏蛋至尊宝2 小时前
如何优化文件传输的性能?
运维·服务器
爱学习的程序媛3 小时前
DevOps 深度解析:从文化理念到落地实践
运维·devops
snow@li3 小时前
服务器:配置中心 Nacos / Apollo 详解
运维·服务器
SEO_juper3 小时前
不同国家服务器、域名选择,提升本地谷歌抓取优先级
运维·服务器·seo·外贸·geo·独立站·跨境电商独立站
浮云中的神马-潘帅3 小时前
魔兽世界自动化打地鼠方案
运维·自动化