【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,便于后续的日志分析和安全审计。


参考链接


相关推荐
古法老登瞎折腾15 分钟前
大数据智能运维实战(一):机器和任务数据都有了,如何用 MCP 搭建运维助手?
大数据·运维·spring boot·spring ai·mcp
海宇数据40 分钟前
零信任架构实战:基于海宇入职背调报告构建自动化即时配送与网约车众包运力准入鉴权网关
运维·人工智能·架构·自动化
姜鱼问生1 小时前
每次开机手动检查 6 样东西?我写了个 2 秒自检脚本
运维·网络·nginx·docker·容器
wangqiaowq1 小时前
PostgresSQL server Docker 安装部署
运维·docker·容器
南棋网络安全2 小时前
ssrf跨站请求伪造(保姆级教程)
运维·服务器·网络·网络安全
帷幕落秋2 小时前
进程服务与文件描述符
linux·运维·面试
帷幕落秋2 小时前
信号、Ctrl 组合键与进程状态
linux·运维·面试
开开心心就好2 小时前
文件被占用删不掉?解锁工具强制删除
java·运维·服务器·开发语言·前端·pdf·ocr
小超人诞生日记2 小时前
Linux 进程优先级
linux·运维·服务器
科技象限3 小时前
数据防泄漏系统:文件是怎么溜出门的,就该怎么堵
运维·网络·网络安全·安企神