
本文详解为何在 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免费学习笔记(深入)”;