如何在 Cloudflare 环境下准确检测 Tor 用户(PHP 实现)

16次阅读

如何在 Cloudflare 环境下准确检测 Tor 用户(PHP 实现)

本文详解为何在 cloudflare 代理后 tor 检测失效,并提供安全、可靠的 php 方案:通过正确获取真实客户端 ip(优先使用 `cf-connecting-ip`),再调用 tordnsel 进行权威 dns 黑名单验证,确保 tor 会话识别稳定有效。

在使用 Cloudflare 作为反向代理的 php 网站中,直接依赖 $_SERVER[‘REMOTE_ADDR’] 判断 Tor 用户往往失败——原因在于:Cloudflare 会将原始客户端 IP 替换为自身边缘节点 IP,而 mod_remoteip 若未针对 Cloudflare 的可信头(如 CF-Connecting-IP)正确配置,$_SERVER[‘REMOTE_ADDR’] 将始终返回 Cloudflare 的任一节点 IP(非真实出口节点),导致 TorDNSEL 查询的目标 IP 错误,自然无法命中 Tor 出口节点黑名单

✅ 正确做法是优先信任 Cloudflare 提供的 HTTP_CF_CONNECTING_IP 请求头(该头由 Cloudflare 自动注入,且仅在其可信链路中存在,不可被终端用户伪造),并将其作为 Tor 检测的真实源 IP:

apphpTorUtilsTorDNSEL;  require_once 'src/TorDNSEL.php';  // 显式声明是否启用 Cloudflare 支持(生产环境务必设为 true) $usingCloudflare = true;  // 安全获取真实客户端 IP $remote_addr = $_SERVER['REMOTE_ADDR']; if ($usingCloudflare && !empty($_SERVER['HTTP_CF_CONNECTING_IP'])) {     // Cloudflare 环境下,使用其提供的真实 IP     $remote_addr = filter_var($_SERVER['HTTP_CF_CONNECTING_IP'], FILTER_VALIDATE_IP);     if (!$remote_addr) {         error_log("Invalid CF-Connecting-IP received: " . $_SERVER['HTTP_CF_CONNECTING_IP']);         $remote_addr = $_SERVER['REMOTE_ADDR']; // 回退到默认值     } }  // 使用 TorDNSEL::isTor()(推荐)替代已弃用的 IpPort() // 注意:isTor() 内部自动处理端口逻辑,更简洁且兼容性更好 try {     if (TorDNSEL::isTor($remote_addr)) {         echo '';         // 可选:记录 Tor 访问日志、启用隐私友好模式、限制速率等     } } catch (Exception $e) {     error_log("TorDNSEL detection failed for IP {$remote_addr}: " . $e->getMessage()); }

⚠️ 关键注意事项:

  • 绝不直接信任 HTTP_X_FORWARDED_FOR 等易伪造头:Cloudflare 已明确建议仅使用 CF-Connecting-IP,它经过签名验证,安全性远高于通用代理头;
  • 禁用 mod_remoteip 或重新配置:若保留 mod_remoteip,需在 apache 配置中显式添加 RemoteIPTrustedproxy 指令,将所有 Cloudflare IP 段 加入可信列表,否则仍可能覆盖正确 IP;
  • TorDNSEL::IpPort() 已过时:当前 dapphp/torutils 推荐使用 TorDNSEL::isTor($ip),它自动执行 ip-port 查询(标准 Tor DNSBL 格式:.dnsel.torproject.org),无需手动传入端口或服务器地址;
  • DNS 解析稳定性:TorDNSEL 依赖外部 DNS 查询,建议在生产环境添加超时与重试逻辑(可封装为带缓存的工具函数),避免因 DNS 延迟阻塞页面响应。

? 总结:Tor 检测失效的根本症结不在 TorDNSEL 库本身,而在于 IP 源的准确性。只要在 Cloudflare 环境中严格采用 HTTP_CF_CONNECTING_IP 获取真实出口 IP,并配合 TorDNSEL::isTor() 进行标准化查询,即可实现高精度、低误报的 Tor 用户识别——这是兼顾安全性、兼容性与可维护性的最佳实践。

立即学习PHP免费学习笔记(深入)”;

text=ZqhQzanResources