Loading... # 网站访客 PHP:**双套 IP 黑名单屏蔽** 与 **CC 防护** 实战(工程化方案)🔒🚧 下面给出**架构、原理表、工作流程图、阈值策略表、可直接部署的 PHP+Redis 中间件代码、以及 ipset 同步脚本**。每段命令/代码都做**逐行详细解释**,便于立即落地。重点词用**红色**标注以便在 vditor 中检索。✨ --- ## 核心思路(一句话) 使用 **双套黑名单**(边缘网络/操作系统层 + 应用动态层)配合 **基于 Redis 的滑动窗口/令牌桶限速**、挑战(如验证码/JS 验证)、临时封禁与持久封禁策略,实现低成本且高效的 CC 防护与恶意 IP 屏蔽。 --- ## 工作流程(Mermaid 流程图) ```mermaid flowchart LR A[请求到达:Nginx/CDN] --> B{边缘黑名单/ipset 检查} B -->|通过| C[应用层 PHP 中间件检查] C --> D{速率/行为 判定} D -->|正常| E[正常响应] D -->|可疑| F[挑战(JS/CAPTCHA)] F -->|失败| G[临时封禁 -> 写入 Redis 动态黑名单] G --> H[(可选)同步入 ipset 持久黑名单] ``` --- ## 原理解释表(关键模块) | 模块 | 作用 | 工程关注点 | | --------------------------------------: | --------------------- | -------------------------------------------- | | **边缘黑名单(ipset/防火墙)** | 拦截最早、节省资源 | 适合**长期/严重**攻击 IP;需 root 权限 | | **应用动态黑名单(Redis set)** | 快速响应、细粒度 | 支持临时封禁、阈值调整、回溯审计 | | **速率限制(滑动窗口 / 令牌桶)** | 检测 CC(短时高并发) | 精确度 vs 内存开销权衡 | | **挑战与验证** | 阻断自动化攻击 | JS 指纹、短期验证码、Cookie 校验 | --- ## 策略阈值示例(推荐起点,可调) | 场景 | 阈值 | 动作 | | --------------------- | ----------------: | ------------------------------ | | 单 IP 单 URI 10s 请求 | > 50 次 | 返回 429,触发 JS 验证 | | 单 IP 全站 60s 请求 | > 500 次 | 临时封禁 10 分钟(写入 Redis) | | 持续恶意(24h) | 触发 5 次短期封禁 | 升级为永久黑名单写入 ipset | > 红色提示:把**阈值**设为过低会误伤正常用户,过高则放任攻击。务必结合日志回溯调整。 --- ## PHP 中间件(使用 PHP Redis 扩展)——完整示例与逐行解释 ```php <?php // 1. 入口放在应用最前面(auto_prepend 或框架中间件) $redis = new Redis(); // 创建 Redis 客户端实例 $redis->connect('127.0.0.1', 6379); // 连接本地 Redis(可用 socket 提升性能) $ip = $_SERVER['REMOTE_ADDR']; // 获取访客 IP $uri = $_SERVER['REQUEST_URI']; // 当前请求 URI $now = microtime(true); // 当前时间戳(浮点秒) // 2. 检查应用层永久黑名单 if ($redis->sIsMember('blacklist:permanent', $ip)) { http_response_code(403); // 返回 403 禁止访问 exit('Forbidden'); } // 3. 滑动窗口:按 IP+URI 计数(短窗口) $key_short = "rl:short:{$ip}:".md5($uri); // 键:短窗口(10s) $window = 10; // 窗口秒数 $limit_short = 50; // 短窗口阈值 // 使用 ZSET 保存时间戳,精确滑动窗口 $redis->zAdd($key_short, $now, $now); // 添加当前时间戳为 score 和 member $redis->zRemRangeByScore($key_short, 0, $now - $window); // 清理过期条目 $cnt = $redis->zCard($key_short); // 统计当前窗口命中数 if ($cnt > $limit_short) { // 记录可疑次数,临时封禁 $tmpKey = "ban:temp:{$ip}"; $redis->incr($tmpKey); $redis->expire($tmpKey, 3600); // 计数过期 1 小时 // 阈值超出:临时封禁 600s if ($redis->get($tmpKey) >= 3) { $redis->sAdd('blacklist:temporary', $ip); $redis->setex("ban:until:{$ip}", 600, time() + 600); // 封禁到期 } http_response_code(429); // Too Many Requests echo 'Rate limit exceeded'; exit; } // 4. 检查临时黑名单(可以放在上面更早) if ($redis->sIsMember('blacklist:temporary', $ip)) { $until = $redis->get("ban:until:{$ip}"); if ($until && time() < $until) { http_response_code(429); exit('Temporarily banned'); } else { $redis->sRem('blacklist:temporary', $ip); // 到期解封 $redis->del("ban:until:{$ip}"); } } // 5. 继续正常业务 // ... 后续应用逻辑 ``` **逐行解释要点:** * `Redis` 实例与连接:用本地 Redis,生产可用集群或 sentinel。 * `sIsMember('blacklist:permanent', $ip)`:检查**持久黑名单**(由运维/脚本写入)。 * 使用 **ZSET**(有序集合)保存时间戳,利用 `zRemRangeByScore` 做滑动窗口清理,`zCard` 得到当前窗口计数——这是精确滑动窗口实现。 * 超阈值后先递增临时计数 `ban:temp:IP`,达到 N 次则写入 `blacklist:temporary` 并设置过期 `ban:until:IP`(600 秒)。 * 临时黑名单过期自动解封;严重者由运维脚本升级为永久黑名单(同步到 ipset)。 --- ## 从应用到网卡:把动态黑名单同步到 ipset(Bash 示例)并解释 ```bash #!/bin/bash # 每分钟运行,将 Redis 中的永久黑名单同步到 ipset # 1. 导出 Redis 黑名单到临时文件 redis-cli SMEMBERS blacklist:permanent > /tmp/bad_ips.txt # 逐行加入 ipset(存在则忽略) while read ip; do ipset -q add my_blacklist $ip done < /tmp/bad_ips.txt # 确保 iptables 使用 ipset 拦截 iptables -I INPUT -m set --match-set my_blacklist src -j DROP ``` **解释:** * `redis-cli SMEMBERS`:取出 Redis 集合所有成员(永久黑名单)。 * `ipset -q add my_blacklist $ip`:把 IP 添加进 `my_blacklist` 集合;`-q` 静默模式避免重复错误。 * `iptables -I INPUT ... -j DROP`:将 ipset 集合作为匹配规则插入 iptables,匹配则直接丢弃包(系统层面拦截,最省资源)。 --- ## 额外建议与注意事项 ✅ 1. **日志与审计**:把触发封禁的事件写入每日日志(IP、URI、次数、时间窗口),便于回溯与误杀恢复。 2. **白名单/速率豁免**:为内网/爬虫/第三方设置白名单,避免误封关键用户。 3. **分布式部署**:多机时使用集中 Redis(或 cluster),保证计数一致性。 4. **挑战策略**:对可疑请求先返回 JS 校验或验证码,自动化脚本通常无法通过。🚫🤖 5. **阈值调优**:先在非高峰环境下压测与回放真实流量调整阈值,避免误伤。 --- ### 结尾要点(红色提示) * **双套黑名单** = **边缘持久黑名单(ipset)** + **应用动态黑名单(Redis)**,能在资源层和业务层同时拦截。 * **CC 防护核心** = **精确限速(滑动窗口/令牌桶) + 挑战验证 + 黑名单升级机制**。 需要我把上述 PHP 中间件封装成可直接 `composer` 安装的中间件包,或把 ipset 同步做成 systemd 定时服务脚本吗?我可以把示例扩展为生产级部署说明(含监控与回滚流程)。 最后修改:2025 年 09 月 03 日 © 允许规范转载 打赏 赞赏作者 支付宝微信 赞 如果觉得我的文章对你有用,请随意赞赏