Cloudflare WAF 配置完全指南:Ruleset API、Terraform、Pulumi 与 Dashboard 多路径部署实战
【免费下载链接】skillsSkills Catalog for Codex项目地址: https://gitcode.com/GitHub_Trending/skills4/skills
Cloudflare WAF(Web Application Firewall)通过自定义规则、托管规则集与速率限制为 Web 应用提供攻击防护。本文以 skills 仓库中 cloudflare-deploy 技能(cloudflare-deploy 参考目录)的 WAF 配置文档为骨架,系统讲解从 API Token 准备、TypeScript SDK、Terraform、Pulumi 到 Dashboard 控制台的全部配置路径,并结合仓库中的 api.md、patterns.md 与 gotchas.md 补充表达式语法、动作表、阶段执行顺序与限额等底层细节。读完本文,你将掌握在 Cloudflare 上独立完成 WAF 规则集编排、托管规则集部署与速率限制配置的完整能力。
前置条件:API Token 与 Zone ID
无论使用 SDK、Terraform 还是 Pulumi,调用 Cloudflare API 管理 WAF 之前都需要两样东西:一个具备 WAF 编辑权限的 API Token,以及目标 Zone(站点)的 ID。
API Token 创建(地址:https://dash.cloudflare.com/profile/api-tokens):
- 权限(Permission):
Zone.WAF Edit或Zone.Firewall Services Edit - Zone 资源(Zone Resources):可限定为指定 Zone,也可选择所有 Zone
Zone ID 获取:登录 Cloudflare Dashboard 后,进入对应站点 >Overview> 右侧边栏的API区域即可看到。
将二者配置为环境变量:
# 设置环境变量 export CF_API_TOKEN="your_api_token_here" export ZONE_ID="your_zone_id_here"安全提示:参考 API 配置参考 中的约定,切勿把 Token 提交到版本库;建议使用
.env文件(加入.gitignore)或密钥管理器保管,例如在仓库内的 WAF 排错文档 gotchas.md 中同样强调先以log模式验证再上线。
理解 Ruleset:阶段(Phase)、动作(Action)与表达式
Cloudflare WAF 的底层是 Ruleset 引擎,所有规则都以「规则集」为单位挂在某个阶段上。阶段决定了规则的执行时机,动作决定命中的处理方式,表达式(基于 Wirefilter 语法)决定哪些请求被匹配。这是配置一切的基础。
阶段与执行顺序
仓库中的 api.md 明确了阶段(Phase)概念——它们是固定顺序、不可调整的:
http_request_firewall_custom— 自定义规则(第一道防线)http_request_firewall_managed— 托管规则集(预置防护)http_ratelimit— 速率限制(请求节流)http_request_sbfm— Super Bot Fight Mode(Pro+ 套餐)
在同一阶段内,规则按从上到下、首个命中生效(first match wins)的规则执行,除非遇到skip动作。
动作(Action)与阶段的兼容性
来自 api.md 的动作矩阵决定了每个阶段能使用哪些动作:
| 动作 | 自定义规则 | 托管规则集 | 速率限制 | 说明 |
|---|---|---|---|---|
block | ✅ | ❌ | ✅ | 以 403 拒绝请求 |
challenge | ✅ | ❌ | ✅ | 展示 CAPTCHA 验证 |
js_challenge | ✅ | ❌ | ✅ | JS 方式挑战 |
managed_challenge | ✅ | ❌ | ✅ | 智能挑战(推荐) |
log | ✅ | ❌ | ✅ | 仅记录、不拦截 |
skip | ✅ | ❌ | ❌ | 跳过后续规则评估 |
execute | ❌ | ✅ | ❌ | 部署托管规则集 |
常用表达式字段与操作符
表达式是 WAF 规则的核心语言,常用的字段(来源 api.md):
// 请求属性 http.request.method // GET、POST 等 http.request.uri.path // /api/users http.host // example.com // IP 与地理信息 ip.src // 192.0.2.1 ip.geoip.country // US、GB 等 ip.geoip.continent // NA、EU 等 // 攻击检测评分 cf.waf.score // 0-100 攻击评分 cf.waf.score.sqli // SQL 注入评分 cf.waf.score.xss // XSS 评分 // 请求头与 Cookie http.request.headers["authorization"][0] http.request.cookies["session"][0] lower(http.user_agent) // 小写化 User-Agent操作符分为三类:比较类(eq、ne、lt、le、gt、ge)、字符串匹配类(contains、matches、starts_with、ends_with)、逻辑与集合类(in、not、and、or)。组合示例:
'cf.waf.score gt 40' // 攻击评分 'http.request.uri.path eq "/api/login" and http.request.method eq "POST"' // 路径 + 方法 'ip.src in {192.0.2.0/24 203.0.113.0/24}' // IP 段拦截 'ip.geoip.country in {"CN" "RU" "KP"}' // 国家/地区拦截 'http.user_agent contains "bot"' // User-Agent 匹配 'not http.request.headers["authorization"][0]' // 请求头存在性检查 '(cf.waf.score.sqli gt 20 or cf.waf.score.xss gt 20) and http.request.uri.path starts_with "/api"' // 复杂组合托管规则集 ID 速查
仓库 waf/README.md 给出了三个官方托管规则集的 ID 与覆盖范围:
| 规则集名称 | ID | 覆盖范围 |
|---|---|---|
| Cloudflare Managed | efb7b8c949ac4650a09736fc376e9aee | OWASP Top 10、CVE |
| OWASP Core Ruleset | 4814384a9e5d4991b9815dcfc25d2f1f | OWASP ModSecurity CRS |
| Exposed Credentials Check | c2e184081120413c86c3ab7e14069605 | 撞库(Credential stuffing)检测 |
TypeScript SDK 配置:自定义规则、托管规则集与速率限制
Cloudflare 官方 TypeScript SDK 是代码化配置 WAF 最直接的方式。先安装依赖:
npm install cloudflare然后初始化客户端:
import Cloudflare from 'cloudflare'; const client = new Cloudflare({ apiToken: process.env.CF_API_TOKEN });自定义规则(Custom Rules)
自定义规则挂在http_request_firewall_custom阶段,用于按攻击评分、路径或地理信息等条件精确处置:
await client.rulesets.create({ zone_id: process.env.ZONE_ID, kind: 'zone', phase: 'http_request_firewall_custom', name: 'Custom WAF', rules: [ { action: 'block', expression: 'cf.waf.score gt 50', enabled: true }, { action: 'challenge', expression: 'http.request.uri.path eq "/admin"', enabled: true }, ], });实战中更常见的做法是分级处置,来自 patterns.md:
rules: [ // 攻击评分分级处置 { action: 'block', expression: 'cf.waf.score gt 50', enabled: true }, { action: 'challenge', expression: 'cf.waf.score gt 20', enabled: true }, // 特定攻击类型 { action: 'block', expression: 'cf.waf.score.sqli gt 30 or cf.waf.score.xss gt 30', enabled: true }, // 地理拦截 { action: 'block', expression: 'ip.geoip.country in {"CN" "RU"}', enabled: true }, ]部署托管规则集(Managed Ruleset)
托管规则集挂在http_request_firewall_managed阶段,通过execute动作部署,action_parameters.id指向规则集 ID:
await client.rulesets.create({ zone_id: process.env.ZONE_ID, phase: 'http_request_firewall_managed', rules: [{ action: 'execute', action_parameters: { id: 'efb7b8c949ac4650a09736fc376e9aee' }, expression: 'true', }], });expression: 'true'表示对所有请求生效;也可以改成'http.request.uri.path starts_with "/api"'仅对 API 路径生效。若要微调托管规则集中的单条规则或某个分类(如wordpress、sqli、xss、rce),使用overrides:
action_parameters: { id: 'efb7b8c949ac4650a09736fc376e9aee', overrides: { rules: [ { id: '5de7edfa648c4d6891dc3e7f84534ffa', action: 'log', enabled: true }, ], categories: [ { category: 'wordpress', enabled: false }, { category: 'sqli', action: 'log' }, ], }, }速率限制(Rate Limiting)
速率限制挂在http_ratelimit阶段。核心参数(含义见 api.md):
characteristics:识别唯一请求方的特征组合,如ip.src、cf.colo.id、http.request.headers["key"][0]、http.request.cookies["session"][0];推荐「按 IP × 按数据中心」组合period:统计时间窗口(秒)requests_per_period:窗口内允许的最大请求数mitigation_timeout:触发后拦截持续时长(秒)counting_expression(可选):仅统计符合条件的请求requests_to_origin:是否只统计回源请求
await client.rulesets.create({ zone_id: process.env.ZONE_ID, phase: 'http_ratelimit', rules: [{ action: 'block', expression: 'http.request.uri.path starts_with "/api"', action_parameters: { ratelimit: { characteristics: ['cf.colo.id', 'ip.src'], period: 60, requests_per_period: 100, mitigation_timeout: 600, }, }, }], });patterns.md 还提供了登录接口收紧限速、仅统计写请求等进阶模式:
// 登录接口更严格 { action: 'block', expression: 'http.request.uri.path eq "/api/login"', action_parameters: { ratelimit: { characteristics: ['ip.src'], period: 60, requests_per_period: 5, mitigation_timeout: 600 } } }, // 仅统计非 GET 请求(counting_expression 用法) { action: 'block', expression: 'http.request.uri.path starts_with "/api"', action_parameters: { ratelimit: { characteristics: ['cf.colo.id', 'ip.src'], period: 60, requests_per_period: 50, counting_expression: 'http.request.method ne "GET"' } } },其他常用 SDK 方法
来自 api.md 的完整方法集:
// 列出规则集 await client.rulesets.list({ zone_id: 'zone_id', phase: 'http_request_firewall_managed' }); // 获取规则集详情 await client.rulesets.get({ zone_id: 'zone_id', ruleset_id: 'ruleset_id' }); // 更新规则集(携带 rule id 保留既有规则,省略 id 则为新增规则) await client.rulesets.update({ zone_id: 'zone_id', ruleset_id: 'ruleset_id', rules: [ { id: 'rule_id', action: 'block', expression: 'cf.waf.score gt 40', enabled: true }, { action: 'challenge', expression: 'http.request.uri.path contains "/admin"', enabled: true }, ], }); // 删除规则集 await client.rulesets.delete({ zone_id: 'zone_id', ruleset_id: 'ruleset_id' });⚠️注意:
update()会整体替换规则列表。更新前务必先get()取回既有规则再合并写入,否则会误删其他规则(详见下文「常见坑位与排错」)。
Terraform 配置:基础设施即代码管理 WAF
对需要版本化管理、审计或团队协作的场景,Terraform 的cloudflareProvider 是推荐选择。Provider 与资源的完整说明可参考 Terraform 配置参考。
先配置 Provider:
provider "cloudflare" { api_token = var.cloudflare_api_token }自定义规则资源
resource "cloudflare_ruleset" "waf_custom" { zone_id = var.zone_id kind = "zone" phase = "http_request_firewall_custom" rules { action = "block" expression = "cf.waf.score gt 50" } }托管规则集与覆盖(Managed Ruleset & Override)
resource "cloudflare_ruleset" "waf_managed" { zone_id = var.zone_id name = "Managed Ruleset" kind = "zone" phase = "http_request_firewall_managed" rules { action = "execute" action_parameters { id = "efb7b8c949ac4650a09736fc376e9aee" overrides { rules { id = "5de7edfa648c4d6891dc3e7f84534ffa" action = "log" } } } expression = "true" } }overrides既可按单条规则 ID 覆盖(rules),也可按分类覆盖(categories,如{ category = "wordpress", enabled = false })。
速率限制资源
resource "cloudflare_ruleset" "rate_limiting" { zone_id = var.zone_id phase = "http_ratelimit" rules { action = "block" expression = "http.request.uri.path starts_with \"/api\"" ratelimit { characteristics = ["cf.colo.id", "ip.src"] period = 60 requests_per_period = 100 mitigation_timeout = 600 } } }Terraform 同样遵循「一个阶段一个 ruleset 资源」的模型:自定义规则、托管规则集、速率限制分属三个cloudflare_ruleset资源,与 SDK 的分阶段创建完全对应。
Pulumi 配置:TypeScript 化的 WAF 资源编排
Pulumi 以编程语言表达基础设施,适合希望用 TypeScript 统一应用与基础设施代码的团队。其资源映射与 Terraform 一一对应,可参考 Pulumi 资源配置参考。
import * as cloudflare from '@pulumi/cloudflare'; const zoneId = 'zone_id'; // 自定义规则 const wafCustom = new cloudflare.Ruleset('waf-custom', { zoneId, phase: 'http_request_firewall_custom', rules: [ { action: 'block', expression: 'cf.waf.score gt 50', enabled: true }, { action: 'challenge', expression: 'http.request.uri.path eq "/admin"', enabled: true }, ], }); // 托管规则集 const wafManaged = new cloudflare.Ruleset('waf-managed', { zoneId, phase: 'http_request_firewall_managed', rules: [{ action: 'execute', actionParameters: { id: 'efb7b8c949ac4650a09736fc376e9aee' }, expression: 'true', }], }); // 速率限制 const rateLimiting = new cloudflare.Ruleset('rate-limiting', { zoneId, phase: 'http_ratelimit', rules: [{ action: 'block', expression: 'http.request.uri.path starts_with "/api"', ratelimit: { characteristics: ['cf.colo.id', 'ip.src'], period: 60, requestsPerPeriod: 100, mitigationTimeout: 600, }, }], });Dashboard 控制台配置与验证
不写代码的团队可直接在 Cloudflare 控制台完成同等配置:
- 进入Security>WAF
- 选择标签页:
- Managed rules— 部署/配置托管规则集
- Custom rules— 创建自定义规则
- Rate limiting rules— 配置速率限制
- 点击Deploy或Create rule完成创建
测试建议:在正式部署前,使用Security Events(安全事件)功能验证表达式是否符合预期——这也是 gotchas.md 反复强调的实践:先log观察再拦截,可显著降低误杀风险。
Wrangler 集成:Worker 自动受益与 API 查询
WAF 配置是Zone 级别的,并非 Worker 专属。Worker 部署后自动处于该 Zone 的 WAF 防护之下,无需修改任何 Worker 代码即可获得防护能力。配置方式即上文四种:Dashboard UI、Cloudflare API(SDK)、Terraform/Pulumi(IaC)。
若 Worker 运行时需要读取或查询 WAF 配置,可直接调用 Cloudflare API(注意将 Token 与 Zone ID 放入 Worker 的环境变量/密钥,参考 Wrangler 配置参考 的 secrets 机制):
export default { async fetch(request: Request, env: Env): Promise<Response> { return fetch(`https://api.cloudflare.com/client/v4/zones/${env.ZONE_ID}/rulesets`, { headers: { 'Authorization': `Bearer ${env.CF_API_TOKEN}` }, }); }, };常见坑位与排错指南
来自仓库 gotchas.md 的实战排错要点,是配置过程中最容易被绊倒的地方。
1. 阶段与动作混用导致部署失败
每个阶段有专属动作:execute只能出现在http_request_firewall_managed,ratelimit参数只能出现在http_ratelimit阶段。错误的做法是在自定义规则阶段里塞execute:
// 错误:阶段内混用阶段专属动作 await client.rulesets.create({ phase: 'http_request_firewall_custom', rules: [ { action: 'block', expression: 'cf.waf.score gt 50' }, { action: 'execute', action_parameters: { id: 'managed_id' } }, // 错误! ], });正确做法是按阶段拆分规则集:
await client.rulesets.create({ phase: 'http_request_firewall_custom', rules: [...] }); await client.rulesets.create({ phase: 'http_request_firewall_managed', rules: [...] });2. 表达式常见语法错误
'http.request.path' → 'http.request.uri.path' // 字段名错误 'ip.geoip.country eq US' → 'ip.geoip.country eq "US"' // 字符串必须加引号 'http.user_agent eq "Mozilla"' → 'lower(http.user_agent) contains "mozilla"' // 大小写敏感 'matches ".*[.jpg"' → 'matches ".*\\.jpg$"' // 正则必须合法3. Skip 规则的作用域误区
ruleset: 'current':仅跳过当前规则集的剩余规则phases: ['http_request_firewall_managed', 'http_ratelimit']:整体跳过指定阶段
由于执行顺序,自定义阶段里的ruleset: 'current'只能跳过自定义规则,无法影响后续托管规则集阶段;若要放行可信 IP 的托管与限速检查,必须显式列出phases。
4. update() 会整体替换规则
// 错误:会删除既有全部规则 await client.rulesets.update({ zone_id, ruleset_id, rules: [{ action: 'block', expression: 'cf.waf.score gt 50' }] }); // 正确:先取回旧规则再合并 const ruleset = await client.rulesets.get({ zone_id, ruleset_id }); await client.rulesets.update({ zone_id, ruleset_id, rules: [...ruleset.rules, { action: 'block', expression: 'cf.waf.score gt 50' }] });5. 覆盖(Override)不生效
先确认规则 ID 与分类名是否正确。可通过 SDK 列出托管规则集中的实际规则:
const ruleset = await client.rulesets.get({ zone_id: 'zone_id', ruleset_id: 'efb7b8c949ac4650a09736fc376e9aee', }); console.log(ruleset.rules.map(r => ({ id: r.id, description: r.description })));6. 误杀(False Positive)处理三步走
- 先用
log模式(overrides: { action: 'log' })观察 - 在 Security Events 中甄别误杀请求
- 对特定规则覆盖:
overrides: { rules: [{ id: 'rule_id', action: 'log' }] }
7. NAT 场景下限速误伤
多用户共享同一出口 IP 时,仅按 IP 限速会误伤。解决方式是在characteristics中加入更多维度(User-Agent、会话 Cookie、Authorization 头):
ratelimit: { characteristics: ['cf.colo.id', 'ip.src', 'http.request.cookies["session"][0]'], period: 60, requests_per_period: 100, }8. 性能优化建议
- 尽早用
skip放行静态资源:expression: 'http.request.uri.path matches "\\.(jpg|css|js)$"' - 按路径收窄托管规则集范围(仅
/api、/admin) - 关闭未使用的分类:
{ category: 'wordpress', enabled: false } - 优先用字符串操作符(
starts_with、contains),避免matches正则带来的额外开销
9. 限额与配额参考
以下为各套餐的规则数量与表达式长度限制(来源 gotchas.md,以仓库记录为准):
| 资源 | Free | Pro | Business | Enterprise |
|---|---|---|---|---|
| 自定义规则 | 5 | 20 | 100 | 1000 |
| 速率限制规则 | 1 | 10 | 25 | 100 |
| 规则表达式长度 | 4096 字符 | 4096 字符 | 4096 字符 | 4096 字符 |
| 每个规则集规则数 | 75 | 75 | 400 | 1000 |
| 托管规则集 | 支持 | 支持 | 支持 | 支持 |
| 限速特征数量 | 2 | 3 | 5 | 5 |
10. 常见 API 报错速查
// "Invalid phase" → 使用准确的阶段名 phase: 'http_request_firewall_custom' // "Ruleset already exists" → 先 list 再 update const rulesets = await client.rulesets.list({ zone_id, phase: 'http_request_firewall_custom' }); if (rulesets.result.length > 0) { await client.rulesets.update({ zone_id, ruleset_id: rulesets.result[0].id, rules: [...] }); } // "Expression parse error" → 常见修复 'ip.geoip.country eq "US"' // 字符串加引号 'cf.waf.score gt 40' // 用 gt 而不是 > 'http.request.uri.path' // 不是 http.request.path完整示例:三阶段一体化防护
将三种阶段组合,构成「放行可信来源 → 评分拦截 → 托管规则 → 限速」的完整防护链(来自 patterns.md 的 Complete Setup Example):
const client = new Cloudflare({ apiToken: process.env.CF_API_TOKEN }); const zoneId = process.env.ZONE_ID; // 1. 自定义规则(最先执行) await client.rulesets.create({ zone_id: zoneId, phase: 'http_request_firewall_custom', rules: [ { action: 'skip', action_parameters: { phases: ['http_request_firewall_managed', 'http_ratelimit'] }, expression: 'ip.src in {192.0.2.0/24}' }, { action: 'block', expression: 'cf.waf.score gt 50' }, { action: 'managed_challenge', expression: 'cf.waf.score gt 20' }, ], }); // 2. 托管规则集(其次执行) await client.rulesets.create({ zone_id: zoneId, phase: 'http_request_firewall_managed', rules: [{ action: 'execute', action_parameters: { id: 'efb7b8c949ac4650a09736fc376e9aee', overrides: { categories: [{ category: 'wordpress', enabled: false }] } }, expression: 'true', }], }); // 3. 速率限制(最后执行) await client.rulesets.create({ zone_id: zoneId, phase: 'http_ratelimit', rules: [ { action: 'block', expression: 'true', action_parameters: { ratelimit: { characteristics: ['cf.colo.id', 'ip.src'], period: 60, requests_per_period: 100, mitigation_timeout: 600 } } }, { action: 'block', expression: 'http.request.uri.path eq "/api/login"', action_parameters: { ratelimit: { characteristics: ['ip.src'], period: 60, requests_per_period: 5, mitigation_timeout: 600 } } }, ], });相关参考
- WAF 参考文档总览 — 技能概览、托管规则集 ID 与阅读顺序
- WAF API 参考 — SDK 方法、表达式字段、动作表与参数详解
- WAF 常用模式 — 托管规则、覆盖、限速、跳过与完整示例
- WAF 排错指南 — 执行顺序、限额、表达式错误与 API 报错
- Terraform 配置参考 — Provider 与全部资源写法
- Pulumi 配置参考 — Pulumi 资源映射
- API 客户端配置参考 — SDK 超时、重试与环境变量规范
- Wrangler 配置参考 — wrangler.jsonc、密钥与部署
【免费下载链接】skillsSkills Catalog for Codex项目地址: https://gitcode.com/GitHub_Trending/skills4/skills
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考