CDN 与 WAF 精讲教程 / 第11章 Cloudflare 实战
第11章 Cloudflare 实战
Cloudflare 是全球最大的 CDN/WAF 服务商之一,免费套餐功能丰富,是中小型网站的首选。本章以实战角度讲解 Cloudflare 的核心功能配置。
11.1 Cloudflare 架构概述
11.1.1 Cloudflare 全球网络
Cloudflare 网络规模(2025):
┌──────────────────────────────────────────────────────────┐
│ 全球 PoP 节点: 300+ 城市 │
│ 网络带宽: 296+ Tbps │
│ Anycast IP: 全球统一 IP 地址 │
│ 数据中心: 覆盖 120+ 国家/地区 │
└──────────────────────────────────────────────────────────┘
核心服务栈:
┌──────────────────────────────────────────────────────────┐
│ 请求进入 │
│ ├── 1. DDoS 防护 (L3/L4 自动) │
│ ├── 2. DNS 解析 (权威 DNS) │
│ ├── 3. TLS 终结 (TLS 1.3) │
│ ├── 4. WAF 防护 (托管规则 + 自定义) │
│ ├── 5. Bot Management (Turnstile) │
│ ├── 6. Rate Limiting │
│ ├── 7. Page Rules / Cache Rules │
│ ├── 8. Workers (边缘计算) │
│ ├── 9. 缓存服务 │
│ └── 10. 回源到 Origin │
└──────────────────────────────────────────────────────────┘
11.1.2 套餐对比
| 功能 | Free | Pro ($20/月) | Business ($200/月) | Enterprise |
|---|---|---|---|---|
| CDN | ✅ | ✅ | ✅ | ✅ |
| SSL | ✅ Universal | ✅ | ✅ Custom | ✅ Custom |
| DDoS 防护 | ✅ 基础 | ✅ 增强 | ✅ 全面 | ✅ 全面 |
| WAF 托管规则 | ❌ | ✅ | ✅ | ✅ |
| 自定义 WAF 规则 | 5 条 | 20 条 | 100 条 | 1000 条 |
| Workers | 100K/天 | 10M/月 | 无限 | 无限 |
| Page Rules | 3 条 | 20 条 | 50 条 | 100 条 |
| Bot 管理 | ❌ | ❌ | ✅ | ✅ |
| Rate Limiting | 1 规则 | 2 规则 | 5 规则 | 100 规则 |
| 缓存规则 | 10 条 | 25 条 | 50 条 | 125 条 |
| Cache Reserve | ❌ | ❌ | ✅ | ✅ |
11.2 DNS 配置
11.2.1 DNS 记录类型
| 类型 | 用途 | 示例 |
|---|---|---|
| A | 域名 → IPv4 | example.com → 192.0.2.1 |
| AAAA | 域名 → IPv6 | example.com → 2001:db8::1 |
| CNAME | 域名 → 域名 | www → example.com |
| MX | 邮件服务器 | 10 mail.example.com |
| TXT | 文本记录 | SPF, DKIM, DMARC |
| SRV | 服务发现 | _http._tcp.example.com |
11.2.2 Cloudflare 代理配置
DNS 记录与代理状态:
┌──────────┬───────┬──────────────────┬──────────────────────────┐
│ 名称 │ 类型 │ 内容 │ 代理状态 │
├──────────┼───────┼──────────────────┼──────────────────────────┤
│ example.com │ A │ 192.0.2.1 │ ☁️ 已代理 (橙色云朵) │
│ www │ CNAME │ example.com │ ☁️ 已代理 (橙色云朵) │
│ api │ A │ 192.0.2.2 │ ☁️ 已代理 (橙色云朵) │
│ mail │ A │ 192.0.2.3 │ DNS only (灰色云朵) │
│ _dmarc │ TXT │ "v=DMARC1;..." │ DNS only │
└──────────┴───────┴──────────────────┴──────────────────────────┘
☁️ 已代理: 流量经 Cloudflare → CDN/WAF 生效
灰色云朵: 直连源站 → CDN/WAF 不生效
11.2.3 DNSSEC 配置
Cloudflare DNSSEC 一键启用:
1. Cloudflare Dashboard → DNS → Settings
2. 启用 DNSSEC
3. Cloudflare 自动生成 DS 记录
4. 在域名注册商处添加 DS 记录
5. 等待传播(24-48 小时)
验证:
$ dig +dnssec example.com
;; flags: qr rd ra; ad ← ad (Authenticated Data) 标志表示 DNSSEC 验证通过
11.3 SSL/TLS 配置
11.3.1 SSL 模式
| 模式 | 说明 | 安全性 | 推荐 |
|---|---|---|---|
| Off | 不加密 | ❌ 极不安全 | ❌ 禁用 |
| Flexible | 浏览器→CF 加密,CF→源站 不加密 | 低 | ❌ 不推荐 |
| Full | 全程加密,CF→源站不验证证书 | 中 | 临时使用 |
| Full (Strict) | 全程加密,验证源站证书 | 高 | ✅ 推荐 |
| Strict (SSL-only) | 最严格 + 强制 HTTPS | 最高 | ✅ 最佳 |
11.3.2 推荐配置
# Cloudflare SSL 推荐配置
SSL/TLS 加密模式: Full (Strict)
Edge Certificates:
- 通用证书: 启用 (自动)
- 专用证书: 按需购买
- 始终使用 HTTPS: 启用
- HTTP 严格传输安全 (HSTS):
max-age: 31536000
includeSubDomains: true
preload: true
源站证书:
- 使用 Cloudflare Origin CA(免费,有效期 15 年)
- 或 Let's Encrypt(需要定期续期)
最低 TLS 版本: TLS 1.2
TLS 1.3: 启用
自动 HTTPS 重写: 启用
证书透明度监控: 启用
11.3.3 Origin CA 证书生成
# 使用 Cloudflare API 生成 Origin CA 证书
# 生成私钥
openssl ecparam -genkey -name prime256v1 -out origin.key
# 生成 CSR
openssl req -new -sha256 -key origin.key -out origin.csr \
-subj "/C=CN/ST=Beijing/L=Beijing/O=MyCompany/CN=example.com"
# 调用 API 创建证书
curl -X POST "https://api.cloudflare.com/client/v4/certificates" \
-H "Authorization: Bearer {api_token}" \
-H "Content-Type: application/json" \
--data '{
"hostnames": ["example.com", "*.example.com"],
"requested_validity": 5475,
"request_type": "origin-ecc",
"csr": "'"$(cat origin.csr)"'"
}'
11.4 WAF 配置
11.4.1 托管规则集
Cloudflare WAF 托管规则集:
┌──────────────────────────────────────────────────────────┐
│ Cloudflare Managed Ruleset (默认启用) │
│ ├── OWASP 规则 │
│ ├── 已知漏洞利用签名 │
│ └── 协议异常检测 │
│ │
│ Cloudflare OWASP Core Ruleset (按需启用) │
│ ├── SQL 注入 │
│ ├── XSS │
│ └── RCE │
│ │
│ Cloudflare Free Managed Ruleset (免费套餐) │
│ └── 基础攻击防护 │
└──────────────────────────────────────────────────────────┘
11.4.2 自定义 WAF 规则
# Cloudflare Custom WAF Rules (通过 Dashboard 或 API 配置)
# 规则1: 阻止恶意爬虫
(http.user_agent contains "sqlmap") or
(http.user_agent contains "nikto") or
(http.user_agent contains "nmap") or
(http.user_agent contains "masscan")
→ Action: Block
# 规则2: 保护管理后台
(http.request.uri.path contains "/wp-admin") or
(http.request.uri.path contains "/admin") or
(http.request.uri.path contains "/phpmyadmin")
and not ip.src in {203.0.113.0/24}
→ Action: Block
# 规则3: 阻止敏感文件访问
(http.request.uri.path matches "\.(env|git|svn|bak|sql|log|conf)$") or
(http.request.uri.path contains "/.well-known/security.txt" and not http.request.method eq "GET")
→ Action: Block
# 规则4: 强制 HTTPS(如果未在 SSL 设置中启用)
(not ssl)
→ Action: Redirect (301) to https://${http.host}${http.request.uri}
# 规则5: Geo 限制
(http.request.uri.path contains "/api/") and
(ip.geoip.country in {"KP" "IR"})
→ Action: Block
11.5 缓存规则
11.5.1 Cache Rules vs Page Rules
| 特性 | Cache Rules | Page Rules |
|---|---|---|
| 数量限制 | Free: 10, Pro: 25 | Free: 3, Pro: 20 |
| 匹配维度 | 更丰富(Host/Path/Method/Headers) | 仅 URL |
| 优先级 | 更高 | 较低 |
| 功能 | 缓存行为精细控制 | 通用(缓存/性能/安全) |
| 推荐 | 新项目首选 | 旧版兼容 |
11.5.2 缓存规则配置
# Cache Rules
# 规则1: 静态资源长缓存
(http.request.uri.path matches "\.(css|js|woff2|ttf|eot|svg|ico)$") or
(http.request.uri.path matches "\.(jpg|jpeg|png|gif|webp|avif|mp4|webm)$")
→ Cache Level: Cache Everything
→ Edge TTL: Override → 2592000 (30天)
→ Browser TTL: Override → 86400 (1天)
# 规则2: API 接口不缓存
(http.request.uri.path contains "/api/")
→ Cache Level: Bypass
# 规则3: 首页短缓存
(http.request.uri.path eq "/") or
(http.request.uri.path eq "/index.html")
→ Cache Level: Cache Everything
→ Edge TTL: Override → 300 (5分钟)
→ Serve Stale: While Revalidate → 60s
# 规则4: 版本化静态资源永久缓存
(http.request.uri.path matches "^/assets/.*\.[a-f0-9]{8}\.")
→ Cache Level: Cache Everything
→ Edge TTL: Override → 31536000 (1年)
→ Browser TTL: Override → 31536000 (1年)
11.5.3 缓存状态检查
# 检查缓存状态
curl -sI https://example.com/image.jpg | grep -i "cf-cache-status"
# 常见状态:
# HIT - 缓存命中
# MISS - 缓存未命中(已回源)
# DYNAMIC - 动态内容,不缓存
# BYPASS - 被规则绕过
# EXPIRED - 缓存已过期
# REVALIDATED - 条件验证后返回缓存
# 手动清除缓存
curl -X POST "https://api.cloudflare.com/client/v4/zones/{zone_id}/purge_cache" \
-H "Authorization: Bearer {api_token}" \
-H "Content-Type: application/json" \
--data '{"files":["https://example.com/style.css"]}'
11.6 Workers(边缘计算)
11.6.1 Workers 架构
Cloudflare Workers 运行时:
┌────────────────────────────────────────────────────────┐
│ V8 Isolate (非容器) │
│ ├── 每个 Worker 运行在独立 V8 隔离环境 │
│ ├── 冷启动 < 5ms(远快于 Lambda 的 100-500ms) │
│ ├── 支持: JavaScript / TypeScript / Wasm │
│ ├── API: Fetch / Cache / KV / R2 / D1 / Queues │
│ └── 限制: CPU 10-50ms/请求, 内存 128MB │
└────────────────────────────────────────────────────────┘
11.6.2 实战:边缘 A/B 测试
// Workers A/B 测试示例
export default {
async fetch(request) {
const url = new URL(request.url);
// 仅对首页进行 A/B 测试
if (url.pathname !== '/') {
return fetch(request);
}
// 检查是否已有分组 Cookie
const cookie = request.headers.get('Cookie');
const existingGroup = cookie?.match(/ab-group=([AB])/)?.[1];
// 决定分组
const group = existingGroup || (Math.random() < 0.5 ? 'A' : 'B');
// 向源站请求并添加分组头
const modifiedRequest = new Request(request, {
headers: {
...Object.fromEntries(request.headers),
'X-AB-Group': group,
}
});
const response = await fetch(modifiedRequest);
// 设置分组 Cookie(如果没有的话)
if (!existingGroup) {
const newHeaders = new Headers(response.headers);
newHeaders.append('Set-Cookie', `ab-group=${group}; Path=/; Max-Age=86400`);
return new Response(response.body, {
status: response.status,
statusText: response.statusText,
headers: newHeaders
});
}
return response;
}
}
11.6.3 Workers KV / R2 / D1
| 服务 | 类型 | 用途 | 延迟 |
|---|---|---|---|
| KV | 键值存储 | 配置、会话、特性标志 | < 10ms |
| R2 | 对象存储 | 文件、图片、备份 | < 50ms |
| D1 | SQLite 数据库 | 结构化数据查询 | < 20ms |
| Queues | 消息队列 | 异步处理、事件驱动 | < 100ms |
| Durable Objects | 有状态计算 | 实时协作、WebSocket | < 50ms |
11.7 Cloudflare Pages
# Cloudflare Pages 配置(静态站点部署)
# 构建设置
Build command: hugo
Build output directory: public
Root directory: /
# 环境变量
HUGO_VERSION: 0.139.0
# 自定义域名
Custom domains:
- example.com
- www.example.com
# 部署钩子
Deploy hooks:
- URL: https://api.cloudflare.com/client/v4/accounts/{account_id}/pages/projects/{project}/deployments
- 可通过 Webhook 触发自动部署
# 功能
Functions: 支持 Workers (Pages Functions)
Preview: 每次 PR 自动生成预览 URL
11.8 注意事项
⚠️ 源站 IP 泄露:Cloudflare 代理后,源站 IP 仍可能通过 DNS 历史、邮件头、子域名等方式泄露。建议更换源站 IP 并使用 Cloudflare Origin CA。
⚠️ SSL 模式:Flexible 模式下 CF→源站不加密,攻击者可在中间链路窃听。始终使用 Full (Strict)。
⚠️ Workers 限制:CPU 时间限制严格(免费版 10ms),长耗时任务应使用 Queues 异步处理。
⚠️ 缓存清除:Purge All 操作影响全球所有节点的缓存命中率,大促期间慎用。
11.9 扩展阅读
- Cloudflare Docs — 官方文档
- Cloudflare Workers Examples — Workers 示例库
- Cloudflare Radar — 全球互联网流量分析
- Cloudflare Blog — 技术博客,深度架构文章
本章小结
| 主题 | 核心要点 |
|---|---|
| DNS | 代理模式(橙色云朵)启用 CDN/WAF |
| SSL | Full (Strict) 模式 + Origin CA 证书 |
| WAF | 托管规则 + 自定义规则组合 |
| 缓存 | Cache Rules 精细控制 TTL |
| Workers | 边缘计算,冷启动 < 5ms |
| Pages | 静态站点部署,PR 预览 |
下一章:第12章 自建方案 →