Cloudflare 开了 WAF,
表单反而收不到?
加了防护之后询盘变少,多半不是「客户不填了」,是请求在到达你之前就被拦了。三个最常见的误伤点:Bot 防护把真人当机器、缓存冻住了验证码、SMTP 后链路自己挂了。
加了防护之后询盘变少,第一反应往往是「最近行情差」或者「客户不填了」。但更常见的真相是:请求在到达你之前就被拦掉了,而拦它的正是你为了安全才打开的那一层。三个误伤点,从最容易查的开始。
先分清三种「收不到」
症状相同,原因完全不同,别混着查:
- 没人填。表单能点、能提交、有成功提示,就是没邮件。可能是流量掉了,也可能是表单在手机上根本点不到。
- 被拦了。提交后转圈、报错、或者页面刷新但没反应。请求没走到你的函数。
- 发出了没送达。函数日志显示成功,邮件却不在收件箱。可能在垃圾箱,也可能在对方服务商那里被丢。
区分方法:自己在无痕窗口提交一次,看浏览器开发者工具的 Network 里那个 POST 请求的返回码。2xx 就是通了,4xx/5xx 就是被拦或出错,一直 pending 是超时。
误伤点一:Bot 防护把真人当机器
这是最常见的一个。开启「Bot Fight Mode」或者把安全级别拉到「高」之后,来自某些地区、某些网络环境、或者用了隐私代理的真实访客,会被判成机器人。表现是页面能打开,但一提交就卡住,或者弹出一个永远过不去的验证。
为什么外贸站特别容易中:你的客户分布在全球,很多地区的网络出口是共享 IP,一个 IP 后面可能挂着几百个用户,其中只要有一个在刷别的东西,这个 IP 就被标记了。你的正经客户跟着遭殃。
排查动作:在 Cloudflare 后台的「安全性 → 事件」里,按时间倒序看最近的拦截记录。如果能看到你自己的测试提交被拦了,规则名字会直接告诉你哪一条命中。这一步比猜快得多。
调整方向:给提交表单的路径单独放行(比如 /api/contact 跳过 Bot 检查),而不是把全站防护关掉。安全是分层的,一个入口放行不等于整站裸奔。
误伤点二:页面被缓存,验证令牌跟着冻住
这一条最隐蔽,因为它「大部分时候是好的」。
表单页面里通常嵌着一个一次性令牌(人机验证的 token、或者防跨站提交的 nonce)。页面被 CDN 缓存之后,这个令牌也跟着被缓存了——第一个访客拿到的是有效令牌,第五十个访客拿到的是同一个已经过期的令牌。提交时服务端校验失败,用户看到的是「验证失败,请刷新重试」,刷新还是失败。
判断方法:连续在三个不同的无痕窗口里打开表单页,看页面源码里那个 token 值是不是完全一样。一样就说明被缓存了。
修法是给表单页设「不缓存」,或者在边缘函数里改由服务端下发令牌(页面本身可以缓存,令牌不缓存)。前一种简单,代价是表单页每次都要回源;后一种更优雅,但要动代码。
顺带说一句:静态站最容易踩这个坑,因为整站默认就是「全缓存」——这本来是优点。
误伤点三:前面的路都通了,卡在最后一段
请求进来了、校验过了、函数也返回 200,但邮件没到。这时候问题已经不在 Cloudflare,在邮件链路上。官方的排查建议很实在:
“When troubleshooting most 5XX errors, the correct course of action is to first contact your hosting provider or site administrator to troubleshoot and gather data.” “The cause of the error is not always found in the origin server's error logs.”
第一句讲的是 5xx 类错误的排查顺序:先找托管方或站点管理员收集数据。第二句更值得记住——原因不一定在源站的错误日志里。放到表单这个场景:邮件服务商那边拒收了,你的函数日志一片正常,因为从你的角度看请求确实成功了。
Cloudflare · 5xx 错误排查
要查的三处:邮件服务商后台的发送日志(有没有这次投递、对方返回什么)、收件邮箱的垃圾箱(尤其第一次发信)、以及发件域的认证记录(SPF / DKIM / DMARC 是否配全)。
这三处里,最常出问题的是第三处。认证没配全,你的邮件会被判成「疑似伪造」,轻则进垃圾箱,重则被静默丢弃——而发送方看到的仍然是「已投递」。
一张表,按症状定位
| 症状 | 最可能的原因 | 第一动作 |
|---|---|---|
| 转圈不动,最后超时 | 请求被 WAF / Bot 防护拦 | 看 Cloudflare 安全事件,找命中的规则名 |
| 提示「验证失败,刷新也没用」 | 页面被缓存,令牌过期 | 对比三个无痕窗口的 token 是否相同 |
| 提示成功,邮件没到 | 邮件链路或垃圾箱 | 查发送日志 + 垃圾箱 + SPF 记录 |
| 只有部分国家的客户提交失败 | 该地区 IP 段被策略命中 | 按国家看拦截记录,给表单路径放行 |
| 白天正常,晚上失败 | 配额或限流用完 | 看邮件服务的用量与频率限制 |
| 手机失败,电脑正常 | 不是防护问题,是前端 | 手机实测提交,看控制台报错 |
为什么它时好时坏?
这类问题最让人抓狂的地方是:测试的时候好用,客户那边不好用。
原因通常是变量太多。你的位置、你的网络、你的浏览器都是「干净」的,而客户的 IP 可能带着历史评分,网络可能经过代理,浏览器可能装了拦截插件。所以自测通过不代表没问题。
有效的验证方式是让真人从不同地方试:找三个不同国家的朋友各提交一次,或者用第三方监测服务从多个节点定时提交。前者一次性,后者能持续发现回归。
怎么配才能不误伤真人?
安全的默认值不是「最严」,是「按风险分级」。具体四条:
- 表单路径单列规则。对
/api/*这类提交端点,用自定义规则放行常见浏览器 UA,只挡明显的脚本特征。 - 用挑战,不用拦截。可疑请求给一个「点一下验证」的挑战,而不是直接 403。真人能过,机器过不去;直接拦截则是把真人也一起拒了。
- 表单页不缓存,其余照缓。带宽代价很小,换来的是令牌永远有效。
- 打开日志。没有日志的防护等于闭着眼开车。至少要能看到「谁被拦了、命中了哪条规则」。
还有一条原则:先观察再收紧。刚上线时把规则设成「仅记录不拦截」,跑一周看看会命中谁,确认没有误伤再切成拦截。反过来(先拦了再说)是丢单的标准剧本。
我们这套是怎么配的?
默认形态是:静态资源全缓存(这是静态站速度的来源)、表单页和提交端点不缓存、提交端点走「先限流、后挑战」的顺序、邮件走专业服务的 API 并配全 SPF / DKIM / DMARC。
失败的时候不装作成功:函数返回错误,页面明确告诉用户「提交没成功,请直接发邮件到 info@xxx」,同时给出 WhatsApp。这一条比任何防护配置都实在——宁可少收一封自动化提交,也不要让客户以为发了、实际丢了。
说清边界:我们不控制邮件服务商的投递策略,也没法保证客户的企业邮箱不把陌生发件人丢进垃圾箱。能保证的是链路上每一段都有日志、失败有明确反馈。
表单时好时坏,或者刚加完防护询盘就少了,把域名发我。我按这三层逐段查,通常半小时能定位。
资料来源
- Cloudflare · Web Application Firewall(自定义规则与托管规则的说明)
- Cloudflare · Bot management(Bot 评分与挑战机制)
- Cloudflare · Cache(缓存规则与按路径排除)
- Cloudflare · 5xx 错误排查