WAF 入门:免费计划能配出的第一层防护
WAF 在免费计划里不是"没有",而是"少了高级检测、留下了拦与放的控制权"。具体到手的是两块:一块是持续更新的 Cloudflare Free Managed Ruleset,另一块是几条自定义规则,用来按路径、方法、IP、国家做拦截或挑战。把这两块配好,能挡掉大部分无差别扫描和已知漏洞探测,剩下的靠速率限制与人机验证补。这篇按控制台的菜单顺序走一遍,最后用 Security Events 确认规则确实在拦流量。
前置条件只有两个:域名已经接入并在 Cloudflare 上处于 Active 状态(做法见 49-add-domain-to-cloudflare.md),以及记录是橙色云代理状态——灰云(仅 DNS)的流量不经过边缘,WAF 看不到。
1. 先看清免费档拿到的是什么
| 能力 | 免费档 | 付费档 |
|---|---|---|
| WAF 托管规则 | 仅 Free Managed Ruleset | Cloudflare Managed Ruleset、OWASP Core Ruleset 等 |
| 自定义规则条数 | 5 条 | Pro 20 条、Business 50 条、Enterprise 更多 |
| 速率限制规则 | 1 条(见 78-rate-limiting.md) | Pro 2 条、Business 5 条、Enterprise 100 条 |
| 自定义列表(IP / ASN 列表) | 支持 | 支持 |
| 泄露凭据检测、敏感数据检测 | 无 | 部分为付费附加 |
| 攻击评分(Attack Score) | 无 | 付费 |
自定义规则条数在控制台 WAF 页面底部会写明当前套餐配额,实际数字以控制台为准。
2. 打开免费托管规则集
控制台路径:Security → WAF → Managed rules,找到 Cloudflare Free Managed Ruleset,点 Deploy。
这套规则是官方维护的,跟着公开漏洞和常见攻击模式更新,不需要你写表达式。刚上线时建议不要直接全量 Block,先把动作设成 Managed Challenge 观察一两天。免费托管规则集的规则数量比付费版少,覆盖的是高危 CVE 与最常见 payload,对定制化的业务逻辑漏洞没有判断力。
3. 写第一条自定义规则
控制台路径:Security → WAF → Custom rules → Create rule。一条规则由三部分组成:匹配表达式、动作、以及可选的日志说明。
先挡后台扫描。表达式写成:
(http.request.uri.path contains "/wp-login.php") or
(http.request.uri.path contains "/xmlrpc.php") or
(http.request.uri.path contains "/.env")
动作选 Block。这类请求通常来自批量扫描器,正常用户不会访问,误伤概率低。
再保护管理入口,把来源限制到办公网段:
(http.request.uri.path contains "/admin" and ip.src ne 203.0.113.0/24)
动作选 Managed Challenge 而不是 Block。挑战对真人几乎无感,对脚本是硬门槛;万一网段写错,你自己还能通过一次挑战进去,不至于把自己锁在外面。
第三条可以按国家粗筛,但要谨慎——IP 地理位置只精确到国家,代理与移动网络会漂移:
(ip.geoip.country in {"CN" "RU"} and http.request.uri.path contains "/api/admin")
表达式里可用的字段在免费档有 ip.src、ip.geoip.country、ip.geoip.asnum、http.request.method、http.request.uri.path、http.request.uri.query、http.user_agent、http.referer、cf.threat_score、cf.client.bot。写的时候注意两点:字符串比较用 contains、eq、matches(正则,慎用,性能与误伤都要考虑);and 优先级高于 or,复杂条件用括号分组。
4. 五种动作的差别
| 动作 | 结果 | 适用场景 |
|---|---|---|
| Block | 直接返回 403 拦截页,页面带 Ray ID | 明确的恶意路径、已知攻击 IP |
| Managed Challenge | 非交互式挑战,多数真人无感通过 | 登录口、后台、可疑但不确定的流量 |
| JS Challenge | 下发 JS 让浏览器执行验证 | 老版本浏览器兼容场景 |
| Interactive Challenge | 需要点击复选框 | 疑似脚本但证据不足 |
| Log | 只记录不拦 | 新规则上线前的观察期 |
| Skip | 跳过后续指定安全功能 | 放过支付回调、Turnstile 验证接口 |
Skip 动作值得单独说。免费档的 Bot Fight Mode 会给部分自动化客户端下发挑战,如果你有 API 客户端、监控探针、支付回调要走同一域名,用 Skip 规则按路径或 User-Agent 把它们放出来,否则会看到"服务正常但客户端一直 403"。
5. 规则的执行顺序
自定义规则按列表顺序从上到下评估,命中 Block 之后不再往下走;托管规则在自定义规则之后评估。所以想放过某条流量,Skip 规则要放在拦截规则前面。拖动列表调整顺序即可,不用删了重建。
免费档的规则条数少,5 条以内要省着用:优先覆盖后台入口、已知漏洞路径、以及你自己的 API 前缀。自定义规则集(custom rulesets)本身所有套餐都能建,但它解决的是"同一套规则复用到多个域名",不会让单域名的条数变多。
6. 用 Security Events 验证
规则配完不等于生效。到 Security → Events 看最近一小时的事件,每条被拦的请求会带上规则 ID、动作、路径、IP、国家、User-Agent 和 Ray ID。验证方法很直接:用 curl 请求一条你刚拦的路径,看是否返回 403,再回 Events 里找到这条记录。
curl -s -o /dev/null -w "%{http_code}\n" https://example.com/wp-login.php
返回 403 说明规则命中。若返回 200,检查三件事:表达式是否拼错、规则是否处于 Enabled、记录是否走了代理(灰云不经过 WAF)。
排查攻击时的整体顺序见 86-attack-triage-order.md,日志侧的证据留存见 85-logpush-logs.md。
常见问题
免费托管规则集会不会误杀正常用户?
会。规则集里有一部分是针对特定 payload 特征的正则,业务表单里出现类似字符串时可能命中。上线初期把动作设成 Managed Challenge,观察一周的误杀记录,再决定要不要改成 Block。
自定义规则和速率限制规则哪个先执行?
自定义规则先。速率限制在 WAF 之后统计,所以被 Block 的请求不计入速率计数。两者叠加时的顺序细节见 78-rate-limiting.md。
Block 之后用户看到什么?
一个 403 页面,上面有 Ray ID 与"你被网站所有者阻止"的提示,错误码常见 1020。想给出更友好的提示,付费档支持自定义响应页;免费档只能拦或挑战。
小结
免费计划给的 WAF 是一套"手写规则 + 官方基础规则"的组合。它不做智能评分,也不会替你判断业务逻辑是否被绕过,但你可以在十分钟内把后台入口、常见漏洞路径和明显的批量扫描挡在边缘,省掉源站的一堆 404 与异常日志。
配置时把顺序理清楚:先 Skip 放行必要的自动化流量,再 Block 明确恶意的路径,剩下的用 Managed Challenge 兜底。规则数量有限,5 条以内就要按"最可能被打的地方"排优先级,而不是按"能想到的规则"铺满。
数据来源与检索时间
检索时间 2026-11-10,以下页面用 HTTPS 直接抓取,均返回 200。
| 来源 | URL | 对应数据 |
|---|---|---|
| WAF 概览 | https://developers.cloudflare.com/waf/ | 免费档"Free Managed Ruleset only"、速率限制 1 条、自定义列表全档可用 |
| 自定义规则 | https://developers.cloudflare.com/waf/custom-rules/ | 表达式与动作模型、规则按顺序评估、Skip 动作的作用 |
| 速率限制规则 | https://developers.cloudflare.com/waf/rate-limiting-rules/ | 各套餐规则条数、免费档可用字段 |
核验说明
- 三个官方页面为本机实际抓取(HTTP 200),文中套餐对照表取自页面里的 Availability 表格。
- 未执行:本机没有 Zone 权限(令牌只有 Workers / KV / 账户读取),控制台里的启用托管规则、创建自定义规则、查看 Security Events 都没有实际点过,步骤依据文档描述写成。
- 未验证:自定义规则条数 5 条来自公开文档与常见控制台提示,未在真实免费账号上确认;Block 拦截页的错误码 1020 为常见表现,未实测。