技术热点落地:Cloudflare 静默注入 Web Analytics——免费计划默认开启的 RUM 与自检关闭清单(2026-08-17)
技术热点落地:Cloudflare 静默注入 Web Analytics——免费计划默认开启的 RUM 与自检关闭清单
热点来源:8/16 Hacker News 用户 stagas 发帖《Tell HN: Cloudflare silently injects its analytics when you switch nameservers》(HN 讨论,525 分 / 146 评论,Algolia API 实测)。他把 nameserver 切到 Cloudflare(为了用 R2 桶在自己子域名上托管静态站 textlog.cc),结果发现这个「HTML-only、无 JS」的站点被静默注入了一段 JS 分析脚本;更离谱的是,Dashboard 里必须先「开启」Web Analytics 才能找到「关闭」入口。Cloudflare 员工 leinwand 在帖内回应确认:免费计划自 2025 年 9 月起默认开启 Web Analytics(RUM),付费计划才是 opt-in;官方博客《The RUM Diaries: enabling Web Analytics by default》(2025-09-17 发布)写明 2025-10-15 起所有免费域名默认开启。一句话剧情:你以为只是「换个 DNS 托管」,实际默认进入了「边缘 HTML 改写 + 真实用户遥测(RUM)」——对追求 HTML 纯净、隐私合规、字节可控的站点,这是一次必须主动处理的隐性变更;本文给出 30 分钟完成的识别 → 关闭 → 验证全流程,以及一份「CDN 信任边界」审计清单。
前情提要:
- 8/17 快报:AI 热点快报:Stripe 70 亿美元收购 OpenRouter——“AI 界的 Stripe”终成 Stripe(2026-08-17)——模型网关这类「中间层」正在被金融化;本文是另一类中间层——CDN 的边缘改写与遥测,同样在「过路收数据」
- 8/13:技术热点落地:SQLite WAL-Reset 十六年潜伏 Bug 复盘——数据完整性自查与防静默丢写落地清单(2026-08-13)——同为「静默行为」排查:SQLite 静默丢写 vs Cloudflare 静默注入,自查清单的写法可直接迁移
- 8/09:技术热点落地:AI 智能体”意外攻击”防线——OpenAI 误攻 Hugging Face 完整时间线与运行时隔离清单(2026-08-09)——信任边界主题:第三方基础设施的隐式权限与默认信任
- 8/16:技术热点落地:Qwen3.8-27B 本地部署实战——FP8/GGUF/NVFP4 选型与消费级显卡避坑清单(2026-08-16)——「数据不出机器」的本地化路线,是「托管中间层」的另一种回答
适用场景与目标
它解决什么问题?迁移到 Cloudflare(换 nameserver / R2 自定义域名 / Pages / 套 CDN)后,你的站点 HTML 可能被边缘静默改写:免费计划默认开启 Web Analytics,Cloudflare 会在每个 HTML 响应的 </body> 前插入一段指向 static.cloudflareinsights.com 的 JS(beacon),自动采集真实用户性能数据(RUM),上报到你自己域名下的 /cdn-cgi/rum。对「HTML 纯净(无 JS)、隐私合规、内容字节可控」的站点,这是不可接受的隐性变更。目标:30 分钟内完成识别 → 关闭 → 验证,并把「注入检查」沉淀进迁移 SOP。
| 场景 | 风险 | 建议 |
|---|---|---|
| 换 nameserver 到 CF / 加 R2 自定义域名(OP 场景) | 🔴 高 | 迁移后立即 curl 检查,默认即注入 |
| 免费计划、全站橙云(proxied) | 🔴 高 | 2025-10-15 起默认开启,按本文第 2 步关闭 |
| 付费计划(Pro/Biz/ENT) | 🟢 低 | opt-in 才采集,不会自动注入,无需处理 |
| 纯 HTML / 无 JS / 静态导出站点 | 🟠 高 | 注入与站点理念直接冲突,关闭 + no-transform 双保险 |
| 隐私/合规敏感(医疗、金融、政务) | 🟠 高 | 关闭是默认动作,别依赖官方「无个人数据」口径 |
| 想要免费性能数据(Observatory) | 🟡 中 | 可主动保留:白拿 RUM + 实验室测试结合的性能面板 |
不适合的场景(诚实版)
- 付费计划用户:本来就不会被默认注入,无需折腾。
- DNS-only(灰云)记录:流量不经过 CF 代理,CF 没有改写能力,天然无注入。
- 已主动使用 Web Analytics 且依赖 RUM 数据的团队:关掉就没有数据了,请评估后再动手。
- 只有静态资源/CDN 加速、无 HTML 业务页:注入只发生在 HTML 响应上,资产不受影响。
最小可行方案(MVP)步骤
先跑通(10 分钟):识别 → 关闭 → 验证
-
识别:curl 检查 HTML 是否被注入
curl -s https://yourdomain.com | grep -c cloudflareinsights # >0 = 已注入 curl -s https://yourdomain.com | grep -o 'beacon.min.js[^"]*' # 拿到脚本版本路径 curl -s https://yourdomain.com | grep -o "data-cf-beacon='[^']*'" # 拿到 zone token被注入时,
</body>前会出现类似这样的一段(边缘改写,客户端看到的就是这个):<script type="module" src="https://static.cloudflareinsights.com/beacon.min.js/v4513226..." integrity="sha512-ZE9pZaUXND66v380QUtch/5sE9tPFh2zg45pR2PB0CVkCtOREv2AJKkSidISWkysEuQ0EH8faUU5du78bx87UQ==" data-cf-beacon='{"version":"2024.11.0","token":"c0859b..."}'></script>实测:帖子主角 textlog.cc 现在
grep -c cloudflareinsights返回 0——OP 已关闭,证明「可关、且关得掉」。 -
关闭(Dashboard 路径):登录 Cloudflare → 左侧 Analytics & Logs → Web Analytics(域名级左侧菜单也有 Web Analytics 入口)→ Manage Site / Manage RUM Settings → 选 Disable;要彻底移除,点 Advanced Options → Delete。官方博客明确承诺:「一旦你关闭过一次,我们不会再次自动开启它」。
-
验证:
curl -s https://yourdomain.com | grep -c cloudflareinsights # 期望 0再开浏览器 DevTools → Network,刷新后过滤
beacon,不应再有beacon.min.js请求;/cdn-cgi/rum不应再收到 POST。
再优化:API 批量关闭(多 zone / 脚本化)
-
API 路径(适合账号下有多个 zone 的情况,官方博客原文命令):
# ① 先创建 auto_install=false 的配置(这一步不会注入脚本) curl -X POST https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/rum/site_info \ -H 'Content-Type: application/json' \ -H "X-Auth-Email: $CF_EMAIL" -H "X-Auth-Key: $CF_TOKEN" \ -d '{"auto_install": false, "host": "example.com", "zone_tag": "ZONE_ID"}' # 响应里拿到 site_tag(对应下面 $SITE_ID)后二选一: # ② 禁用(enabled=false) curl -X PUT https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/rum/site_info/$SITE_ID \ -H 'Content-Type: application/json' \ -H "X-Auth-Email: $CF_EMAIL" -H "X-Auth-Key: $CF_TOKEN" \ -d '{"auto_install": true, "enabled": false, "host": "example.com", "zone_tag": "ZONE_ID"}' # ③ 或直接删除配置 curl -X DELETE https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/rum/site_info/$SITE_ID \ -H "X-Auth-Email: $CF_EMAIL" -H "X-Auth-Key: $CF_TOKEN" -
源头规避(不改配置也不被注入):官方文档明确——如果源站返回
Cache-Control: public, no-transform,Cloudflare 代理将无法修改原始 payload,beacon 不会被注入(Web Analytics 也随之失效)。对纯静态站点(nginx / Caddy / R2),给 HTML 响应加这个头即可一劳永逸;注意它会同时禁用其他边缘改写(见避坑 5)。
关键实现细节
注入机制(root cause):你换 nameserver 时,Cloudflare 默认把记录设为橙云(proxied)——所有 HTTP 流量先经过 CF 边缘。Web Analytics 的 automatic setup 就是在这条链路上做响应改写:识别 HTML 响应 → 在 </body> 前插入 <script type="module" src="https://static.cloudflareinsights.com/beacon.min.js/...">(带 SRI integrity 与 data-cf-beacon 载荷,内含 zone token)→ 浏览器加载后向你自己域名的 /cdn-cgi/rum 端点上报 RUM 数据(自动安装模式),再由 CF 汇聚到面板。所以「换 nameserver」不是 DNS 变更,而是把响应字节的修改权交给了第三方。
为什么默认开启:2025-09-17 官方博客宣布,2025-10-15 起所有免费域名默认开启 Web Analytics(RUM),默认版本排除 EU/UK 访客流量;官方口径强调「无 cookie、无 localStorage、不按 IP/UA 指纹追踪用户,按『访问事件』而非唯一用户计数」——即 privacy-first 的遥测。官方给免费用户的理由是「性能洞察 + Observatory 免费送」(HN 员工回应原文)。付费计划(Pro/Biz/ENT)是 opt-in,需要手动选择 hostname 与 Automatic Setup 才会注入。
为什么「先开启才能关闭」:官方博客的 opt-out 步骤本身就是「先选 Enable Globally 或 Exclude EU 激活功能 → 再进 Manage RUM Settings → 选 Disable」。10/15 之后免费 zone 的配置处于「已创建但未激活」的中间态,Dashboard 交互上必须激活一次才能进入关闭页——这个 UX 对用户完全不透明,HN 上 csomar 直接说「很难找到关闭这个 JS 的设置」。
判断是否走代理(橙云):dig +short yourdomain.com 返回 CF 网段(如 104.16.x.x / 172.64.x.x)即为 proxied;返回源站 IP 则为 DNS-only。只有 proxied 才存在注入风险。
常见坑与规避清单
| # | 坑 | 表现 | 规避 |
|---|---|---|---|
| 1 | 把 CDN 当「DNS 服务商」 | 以为只改了解析,实际把响应改写权交给了第三方 | 橙云 = 边缘可改写内容,按「中间人」审计 |
| 2 | 关闭入口难找 / 先开启才能关 | 找不到 Disable 按钮 | 走官方路径:Analytics & Logs → Web Analytics → Manage RUM Settings → Disable;或 API |
| 3 | 免费/付费默认不同 | 免费默认遥测、付费 opt-in,换计划后行为变化 | 迁移当天按免费计划规则处理 |
| 4 | 关了不验证 / 边缘缓存残留 | 旧 HTML 仍在 CDN 缓存里带脚本 | 关闭后 Purge Cache 再 curl + DevTools 复查 |
| 5 | no-transform 一刀切 | 所有边缘 HTML 改写全失效 | 只用于「纯静态、不需要 CF 改写」的站点,先看有没有用 Polish/Rocket Loader |
| 6 | RUM 数据有偏 | ad-block 用户(Brave/DDG/adblockplus)不贡献数据 | 性能决策别只依赖 RUM,结合实验室测试 |
| 7 | 手动 + 自动双装 | 双 beacon 重复上报/渲染冲突 | 只保留一种安装方式(自动或手动 snippet) |
| 8 | 误伤 CSP | 以为 CSP 能「阻止注入」 | CSP 只能阻止脚本执行,标签仍在 HTML 源码里,审计以源码 grep 为准 |
⚠️ 坑 1:Caching 不等于可以修改我的站点(HN 第一怀疑点)
帖子高赞回复 purpleidea 直接甩出被注入的脚本原文并总结:「Caching does not mean modifying my site」。zx8080 更直白:「MITM attack, that’s why this is not in the news」。JoshTriplett 补了一刀:「他们本来就在代理你的 HTML,不修改内容也能统计请求,何必注入 JS」。结论:技术可行 ≠ 默认可做;对内容创作者,「字节是否可控」是原则问题,跟性能数据无关。
⚠️ 坑 2:「免费」的隐性代价是默认遥测
chrisweekly 认为「免费计划 opt-out、付费 opt-in 不算邪恶」,matherial 反驳:「如果『不邪恶』是标准,那我称之为 sleazy(下作)」。员工回应的措辞是「easy to disable」,但 OP 与 csomar 的实际体验都是「找不到开关」。结论:免费计划的默认值就是产品策略的一部分,别指望它贴心,主动处理。
⚠️ 坑 3:关闭后要验证,缓存会骗你
关闭操作改的是配置,但 CF 边缘缓存里可能还躺着旧 HTML(带 beacon 的版本)。只 curl 一次看到 0 也可能是因为关闭前就已经 Purge 过;稳妥顺序:关闭 → Purge Cache → 再 curl → DevTools 确认无 beacon.min.js 请求、/cdn-cgi/rum 无 POST。本文写完后实测 textlog.cc 已为 0,说明这条链路真实可验证。
⚠️ 坑 4:no-transform 是双刃剑
Cache-Control: public, no-transform 是文档明说的「注入免疫」手段,但它的语义是禁止任何中间层修改 payload——Cloudflare 的 Polish(图片优化)、Rocket Loader(JS 延迟加载)、HTML minification、Email Obfuscation 等边缘改写会一起失效,缓存命中策略也可能变化。只在「确定不需要任何边缘改写」的静态站点上用;不确定就先关 Web Analytics 而不是上 no-transform。
⚠️ 坑 5:域名匹配规则与数据偏差
Web Analytics 按 hostname postfix 匹配(配置 example.com 会覆盖 www.example.com、blog.staging.example.com),hostname 不一致会在控制台报 CORS 错——多子域站点关闭时别漏配。另外 FAQ 明说 beacon 会被 adblockplus、Brave、DuckDuckGo 扩展拦截:「无广告用户」恰好是 RUM 数据里缺失的那部分人,用它做性能基线会系统性偏差。
成本 / 性能 / 维护权衡
| 方案 | 成本 | 性能影响 | 数据/隐私 | 维护 |
|---|---|---|---|---|
| 接受默认 RUM(免费) | 0 | 每 HTML 页多一个第三方脚本请求(SRI + module,可缓存) | 默认排除 EU/UK、无 cookie;ad-block 用户缺失 | 白拿 Web Analytics + Observatory 面板 |
| Dashboard/API 关闭 | 0 | 无注入 | 无采集 | 每个新 zone 一次;官方承诺关闭后不再自动重开 |
| no-transform 响应头 | 0 | 无注入 | 无采集 | 禁所有边缘 HTML 改写;缓存策略要重新评估 |
| 付费计划(Pro+) | 付费 | 无自动注入 | opt-in 才采集 | 无需处理 |
权衡要点:① 对「HTML 纯净」站点这是原则问题,不是性能问题——OP 的 textlog.cc 是 JS-free 站点,注入本身就是内容被篡改;② RUM 数据有真实价值(真实用户感知的 Core Web Vitals、Observatory 免费),但「免费送」的数据也意味着「免费出」的数据,合规自评别省;③ 关闭的边际成本极低(一次 Dashboard 操作 + 一个检查脚本),收益是字节可控;④ 「默认开启」模式意味着每一个新 zone / 新迁移都要查一次——把检查写进迁移 SOP 比记在脑子里可靠。
一周内可执行行动清单
- Day 1:列出账号下所有 zone(含即将迁移的),逐个跑
curl -s https://<域名> | grep -c cloudflareinsights,输出注入清单 - Day 2:免费 zone 全部关闭:Dashboard(Manage RUM Settings → Disable)或 API 脚本批量处理(
PUT .../rum/site_info/$SITE_IDenabled=false) - Day 3:Purge Cache 后复查 curl=0,DevTools 确认无 beacon 请求、
/cdn-cgi/rum无上报 - Day 4:静态托管(nginx/Caddy/R2)加
Cache-Control: public, no-transform(仅当不需要边缘改写),A/B 验证注入确实消失 - Day 5:把检查脚本接进 CI/CD 或定时任务:
curl -s $URL | grep -c cloudflareinsights断言为 0,非 0 告警 - Day 6:更新迁移 SOP:换 nameserver / 加 R2 自定义域名 / 上线新 zone 后,必做「注入审计 + 关闭 + 验证」三步
- Day 7:复盘决策:是否主动启用 RUM(保留数据与 Observatory)?还是彻底关闭走 no-transform?把结论写进团队 wiki
参考资源
- HN 讨论帖(525 分 / 146 评论)
- Cloudflare 官方博客:The RUM Diaries: enabling Web Analytics by default(2025-09-17)
- Cloudflare Web Analytics 文档:Enabling(get-started,含 no-transform 说明)
- Cloudflare Web Analytics 文档:FAQ(含 ad-block 拦截、CORS、双 beacon 说明)
- beacon 脚本本体 static.cloudflareinsights.com/beacon.min.js
写在最后:Cloudflare 默认开启 Web Analytics 不是「事故」而是产品策略——2025-09-17 的博客写得明明白白。真正值得记取的教训是:任何「免费托管 + 代理」的中间层,默认值都是数据与改写权限的让渡。切换 nameserver 的当天花 30 分钟做一次注入审计,你就把「站点字节归谁」这个问题重新握回自己手里。