CDN 与 WAF 精讲教程 / 第08章 Bot 管理
第08章 Bot 管理
本章全面讲解 Bot 流量管理,涵盖爬虫识别、验证挑战、速率限制等核心技术和策略。
8.1 Bot 流量概述
8.1.1 互联网 Bot 流量分布
全球互联网流量构成:
┌────────────────────────────────────────────────┐
│ │
│ ████████████████████████████ 约 50% 恶意 Bot│
│ ██████████████████ 约 30% 人类流量│
│ ████████████ 约 20% 善意 Bot│
│ │
└────────────────────────────────────────────────┘
数据来源: Imperva Bad Bot Report 2025
8.1.2 Bot 分类
| 类型 | 说明 | 示例 | 对待策略 |
|---|---|---|---|
| 善意 Bot | 合法爬虫/监控 | Googlebot、Bingbot、UptimeRobot | 允许 |
| 恶意 Bot | 攻击/欺诈工具 | 凭证填充、价格爬取、DDoS | 拦截 |
| 灰色 Bot | 未经授权但无害 | 数据聚合、SEO 工具 | 限速/观察 |
| 自动化工具 | 脚本/程序 | Selenium、Puppeteer、curl | 按场景决定 |
8.2 爬虫识别技术
8.2.1 识别方法
Bot 识别技术栈:
┌──────────────────────────────────────────────────────────┐
│ Layer 1: 基础特征匹配 │
│ ├── User-Agent 字符串 │
│ ├── IP 地址反向 DNS │
│ └── 已知 Bot IP 段 │
└──────────────────────────────────────────────────────────┘
│
┌────────────────────────▼─────────────────────────────────┐
│ Layer 2: HTTP 特征分析 │
│ ├── 请求头顺序 / 头部完整性 │
│ ├── TLS 指纹 (JA3/JA4) │
│ ├── Accept / Accept-Language / Accept-Encoding 一致性 │
│ └── Cookie / Referer 行为 │
└──────────────────────────────────────────────────────────┘
│
┌────────────────────────▼─────────────────────────────────┐
│ Layer 3: 行为分析 │
│ ├── 请求频率(过高/过低) │
│ ├── 访问模式(顺序遍历 vs 自然浏览) │
│ ├── 会话深度(无深度 vs 正常浏览深度) │
│ └── 时间分布(24h 不间断 vs 人类作息) │
└──────────────────────────────────────────────────────────┘
│
┌────────────────────────▼─────────────────────────────────┐
│ Layer 4: 客户端验证 │
│ ├── JavaScript 挑战 │
│ ├── Canvas / WebGL 指纹 │
│ ├── 鼠标/键盘/触摸事件分析 │
│ └── 设备环境检测(WebDriver/Headless 检测) │
└──────────────────────────────────────────────────────────┘
8.2.2 TLS 指纹识别 (JA3/JA4)
JA3 指纹原理:
TLS ClientHello 包含:
├── TLS 版本
├── 支持的密码套件列表
├── 扩展列表
├── 椭圆曲线
└── 椭圆曲线点格式
→ 对以上字段做 MD5 哈希,生成 32 位指纹
示例:
┌──────────────────┬──────────────────────────┐
│ 客户端 │ JA3 指纹 │
├──────────────────┼──────────────────────────┤
│ Chrome 120 │ e7d705a3286e19ea42f587b3 │
│ Firefox 121 │ cd08e31494f9531f76565810 │
│ curl │ 72a589b77a49f496d0230281 │
│ Python requests │ a0e9f5d64349fb13f36b8526 │
│ Headless Chrome │ 与正常 Chrome 不同 │
└──────────────────┴──────────────────────────┘
8.2.3 User-Agent 验证
# 搜索引擎 Bot 验证:反向 DNS 查询
# 声称是 Googlebot 的 IP: 66.249.66.1
# 步骤1: 反向 DNS
$ dig -x 66.249.66.1
66.249.66.1.in-addr.arpa. 86400 IN PTR crawl-66-249-66-1.googlebot.com.
# 步骤2: 正向 DNS 验证
$ dig crawl-66-249-66-1.googlebot.com
crawl-66-249-66-1.googlebot.com. 300 IN A 66.249.66.1
# IP 匹配 → 确认是真正的 Googlebot ✅
8.3 验证挑战技术
8.3.1 挑战类型对比
| 挑战类型 | 用户体验 | 安全性 | 适用场景 |
|---|---|---|---|
| JavaScript 挑战 | 无感知 | 中 | 首次过滤,区分简单 Bot |
| Managed Challenge | 低感知 | 高 | Cloudflare 智能挑战 |
| CAPTCHA | 差 | 高 | 高安全场景 |
| Turnstile | 无感知 | 高 | Cloudflare 无感验证 |
| reCAPTCHA v3 | 无感知 | 中-高 | Google 评分验证 |
| hCaptcha | 中等 | 高 | 隐私友好验证 |
| Proof of Work | 无感知 | 高 | 增加 Bot 计算成本 |
8.3.2 JavaScript 挑战原理
JS 挑战流程:
客户端请求
│
▼
┌──────────────────────────────┐
│ WAF 检测到可疑请求 │
└──────────┬───────────────────┘
│
▼
┌──────────────────────────────┐
│ 返回 JS 挑战页面 (HTTP 403) │
│ <script> │
│ // 需要计算 PoW / 指纹收集 │
│ solveChallenge() │
│ </script> │
└──────────┬───────────────────┘
│
真实浏览器: 执行 JS → 完成挑战 → 获取 Token → 重新请求
简单 Bot: 无法执行 JS → 被拦截
│
▼
┌──────────────────────────────┐
│ 验证 Token → 放行 / 设置 Cookie │
└──────────────────────────────┘
8.3.3 Cloudflare Turnstile 示例
<!-- Turnstile 无感验证 -->
<script src="https://challenges.cloudflare.com/turnstile/v0/api.js" async defer></script>
<form action="/submit" method="POST">
<div class="cf-turnstile"
data-sitekey="your-site-key"
data-callback="onSuccess">
</div>
<button type="submit">提交</button>
</form>
<script>
function onSuccess(token) {
// Turnstile 验证成功后,token 会自动添加到表单
// 服务端需验证此 token
console.log('Turnstile token:', token);
}
</script>
8.4 Rate Limiting(速率限制)
8.4.1 限速维度
| 维度 | 说明 | 典型阈值 |
|---|---|---|
| IP | 单个 IP 每秒请求数 | 10-100 req/s |
| IP + URL | 单 IP 对单 URL 的请求频率 | 5-20 req/s |
| Session | 单会话(Cookie)请求频率 | 20-50 req/s |
| User | 登录用户的请求频率 | 30-100 req/s |
| API Key | 单 API 密钥限额 | 1000-10000 req/h |
| 全局 | 整个站点总 QPS | 按容量设计 |
8.4.2 限速算法
1. 固定窗口 (Fixed Window)
│←── 窗口1 (60s) ──→│←── 窗口2 (60s) ──→│
│ 请求计数: 95 │ 请求计数: 0 │ ← 窗口边界突发
│ 阈值: 100 │ 阈值: 100 │
2. 滑动窗口 (Sliding Window)
│←──── 60s 滑动窗口 ────→│
│ 持续统计最近 60s 请求数 │ ← 无边界突发
3. 令牌桶 (Token Bucket)
┌─────────────────────────────────────┐
│ 桶容量: 100 令牌 │
│ 填充速率: 10 令牌/秒 │
│ │
│ 每个请求消耗 1 令牌 │
│ 桶空 → 拒绝请求 │
│ │
│ 优点: 允许短时突发 │
└─────────────────────────────────────┘
4. 漏桶 (Leaky Bucket)
┌─────────────────────────────────────┐
│ 请求进入 ──→ 固定速率流出 │
│ ┌──────────────┐ │
│ │ 桶满 → 丢弃 │ ← 请求排队/丢弃 │
│ └──────────────┘ │
│ 优点: 平滑请求速率 │
└─────────────────────────────────────┘
8.4.3 Nginx 限速配置
# Nginx Rate Limiting 配置
# 定义限速区域
# 速率: 每秒 10 个请求,突发 20 个
http {
# 基于 IP 的限速
limit_req_zone $binary_remote_addr zone=per_ip:10m rate=10r/s;
# 基于 IP + URL 的限速(API 接口)
limit_req_zone $binary_remote_addr$uri zone=per_api:20m rate=5r/s;
# 基于 Server 的全局限速
limit_req_zone $server_name zone=global:10m rate=1000r/s;
server {
# 基本限速
location / {
limit_req zone=per_ip burst=20 nodelay;
limit_req_status 429;
}
# API 严格限速
location /api/ {
limit_req zone=per_api burst=10 nodelay;
limit_req_status 429;
# 返回限速头
add_header X-RateLimit-Limit "5" always;
add_header Retry-After "1" always;
}
}
}
8.4.4 Cloudflare Rate Limiting 规则
# Cloudflare 速率限制规则
# 登录接口防暴力破解
(http.request.uri.path eq "/api/login") and
(rate(1m) > 10)
→ Block (429 Too Many Requests)
# API 接口限速 (按 API Key)
(http.request.uri.path matches "^/api/v\\d+/" ) and
(http.request.headers["x-api-key"][0] ne "") and
(rate(1h) > 5000)
→ Throttle
# 搜索接口限速
(http.request.uri.path eq "/search") and
(rate(1m) > 30)
→ Managed Challenge
8.5 Bot 管理策略矩阵
8.5.1 分级策略
| Bot 类型 | 检测方式 | 处置 | 用户体验 |
|---|---|---|---|
| 已知恶意 Bot | IP/UA 签名 | 直接拦截 | — |
| 可疑自动化 | JS 挑战 | 验证后放行 | 低影响 |
| 高频请求 | 速率限制 | 429 / 挑战 | 正常用户无影响 |
| 搜索引擎 | DNS 验证 | 放行 | — |
| 正常用户 | 信任评分 | 直接放行 | 无感知 |
8.5.2 搜索引擎爬虫管理
合法搜索引擎验证流程:
声称 Googlebot 的请求
│
├── 1. IP 检查: 是否在 Google 官方 IP 段
│ 官方 IP: https://developers.google.com/search/docs/crawling-indexing/verifying-googlebot
│
├── 2. 反向 DNS 验证:
│ *.googlebot.com → ✅
│ 其他 → ❌
│
├── 3. 正向 DNS 验证:
│ IP → PTR → A → IP 匹配? → ✅
│
└── 4. 最终判定:
全部通过 → 允许,不限速
任一失败 → 拦截
8.6 无感验证方案对比
| 方案 | 厂商 | 原理 | 价格 | 隐私 |
|---|---|---|---|---|
| Turnstile | Cloudflare | JS 挑战 + 指纹 | 免费 | 不收集用户数据 |
| reCAPTCHA v3 | 行为评分 | 免费(有限额) | 收集用户行为数据 | |
| hCaptcha | Intuition Machines | 图片/JS 挑战 | 免费 | 隐私友好 |
| Friendly Captcha | Friendly Captcha | PoW | 付费 | 隐私友好 |
| AWS WAF CAPTCHA | AWS | 图片挑战 | 按使用量 | AWS 生态 |
8.7 注意事项
⚠️ 误伤正常用户:Bot 检测过严可能导致使用 VPN、公共 Wi-Fi 的正常用户被误判。
⚠️ 高级 Bot:使用 Puppeteer/Playwright + 指纹伪装的高级 Bot 可绕过 JS 挑战,需要结合行为分析。
⚠️ 验证码可访问性:传统 CAPTCHA 对残障用户不友好,建议提供替代验证方式。
⚠️ 隐私合规:Bot 检测涉及用户指纹收集,需符合 GDPR/CCPA 等隐私法规。
8.8 扩展阅读
- Cloudflare Bot Management — Cloudflare Bot 管理方案
- Google’s reCAPTCHA — Google 验证码服务
- OWASP Automated Threats — 自动化威胁分类
- JA3 TLS Fingerprinting — TLS 指纹识别技术
- Imperva Bad Bot Report — 年度恶意 Bot 报告
本章小结
| 主题 | 核心要点 |
|---|---|
| Bot 分类 | 善意 / 恶意 / 灰色,区别对待 |
| 识别技术 | UA 验证 + TLS 指纹 + 行为分析 + JS 挑战 |
| 验证挑战 | JS 挑战无感知,Turnstile 为最优方案 |
| Rate Limiting | 按 IP/URL/Session/API Key 多维度限速 |
| 策略 | 分级处置,搜索引擎白名单 |
下一章:第09章 DDoS 防护 →