博客迁移到github上后图片使用了Cloudflare R2来做存储。 R2以其“零出口流量费用”的巨大优势,成为众多开发者和博主的对象存储首选。然而,将图片、视频等公开资源放在 R2 上,如何防止被恶意盗链、高频访问(刷流量),从而保护我们的服务和成本,是每个使用者都必须面对的问题。
本文将为您提供一套完全免费、行之有效的终极防护方案,通过组合 Cloudflare 的免费功能,为您的 R2 存储桶构建一个坚不可摧的纵深防御体系。
核心理念:免费的多层防御
我们将利用 Cloudflare 免费套餐中提供的强大工具,构建三层防御:
- WAF 防火墙:作为门禁,精确识别并阻止非法来源的访问(防盗链)。
- 边缘缓存:作为缓冲垫,吸收绝大多数重复请求,天然防刷并极大提升访问速度。
- 速率限制:作为熔断器,捕获漏网的恶意高频探测,保护源站。
第一步:设置防盗链 (完全免费)
此步骤旨在阻止其他网站直接嵌入(盗链)您存储在 R2 上的图片。我们将使用 Cloudflare WAF 的自定义规则功能,免费版提供 5 条规则,完全足够。
- 登录 Cloudflare 控制台,选择您的域名。
- 在左侧菜单,进入 “安全性” (Security) -> “WAF”。
- 选择 “自定义规则” (Custom Rules) 选项卡,点击 “创建规则” (Create rule)。
- 为规则命名:例如
R2 图片防盗链
。 - 在 “如果…” (When incoming requests match…) 部分,配置以下三个条件,并确保它们之间用 “和” (And) 连接:
字段 (Field) | 运算符 (Operator) | 值 (Value) |
---|---|---|
主机名 (Hostname) | 等于 (equals) | r2.yourdomain.com |
And | ||
引用方 (Referer) | 不包含 (does not contain) | yourdomain.com |
And | ||
引用方 (Referer) | 不等于 (is not equal to) | "" (值留空) |
规则解释: 当一个请求访问你的图片域名 (
r2.yourdomain.com
),并且它的来源 (Referer
) 不是你自己的网站 (yourdomain.com
),同时也不是直接在浏览器打开(Referer
不为空),那么就判定为盗链。
- 在 “然后采取措施…” (Then take action…) 部分,选择
阻止 (Block)
。 - 点击 “部署” (Deploy)。
至此,您的防盗链门禁已经生效。
第二步:设置缓存以防刷 (完全免费)
对于图片这类静态资源,最好的防刷就是让请求根本到不了 R2 源站。我们将利用 Cloudflare 强大的边缘缓存,免费版提供 3 条页面规则。
- 在左侧菜单,进入 “规则” (Rules) -> “页面规则” (Page Rules)。
- 点击 “创建页面规则” (Create Page Rule)。
- 在 “如果 URL 匹配” (If the URL matches) 中,输入您的 R2 域名及通配符:
r2.yourdomain.com/*
- 在 “则设置为” (Then the settings are) 部分,添加以下两个设置:
- 缓存级别 (Cache Level): 选择
缓存所有内容 (Cache Everything)
- 边缘缓存 TTL (Edge Cache TTL): 选择一个较长的时间,例如
一个月 (a month)
- 缓存级别 (Cache Level): 选择
- 点击 “保存并部署” (Save and Deploy)。
配置完成后,任何图片在首次访问后,都会在全球 Cloudflare 节点上缓存一个月。后续所有重复请求都由 CDN 直接响应,极大减少了 R2 的 B 类操作(读请求)次数,天然地防御了刷流量攻击,并加速了全球用户的访问。
备选方案:使用 Cloudflare Workers (更灵活)
如果您的免费规则(5条自定义规则,3条页面规则)已用完,或者未来需要实现更复杂的逻辑(如动态添加水印),可以使用 Cloudflare Workers。其免费套餐提供每天 10 万次请求,足以支撑绝大多数博客。
在左侧菜单进入 “Workers 和 Pages”,创建一个新的 Worker。
将以下防盗链脚本粘贴进去,并修改
ALLOWED_REFERER
为您自己的域名。JAVASCRIPT// /workers/r2-hotlink-protection.js export default { async fetch(request, env, ctx) { // 允许访问的来源域名 (你的博客主站) const ALLOWED_REFERER = "yourdomain.com"; const referer = request.headers.get('Referer'); // 检查 Referer: 如果为空 (直接访问) 或包含你的域名,则放行 if (!referer || referer.includes(ALLOWED_REFERER)) { // 放行请求,让它正常访问 R2 资源 return fetch(request); } // 来源不被允许,返回 403 Forbidden 错误 return new Response(`403 Forbidden: Hotlinking is not allowed.`, { status: 403, statusText: 'Forbidden' }); }, };
保存并部署 Worker。
返回 Worker 的主界面,切换到 “触发器” (Triggers) 选项卡,在 “路由” (Routes) 部分添加一条路由:
- 路由 (Route):
r2.yourdomain.com/*
- 区域 (Zone): 选择您的主域名
- 路由 (Route):
这样,所有访问 r2.yourdomain.com
的请求都会先经过这个 Worker 脚本的检查。
重要操作:如何刷新缓存
当您更新了 R2 上的图片后,需要手动清除 Cloudflare 的缓存,才能让用户看到最新的版本。
强烈推荐使用“自定义清除”,避免影响主站。
- 在左侧菜单,进入 “缓存” (Caching) -> “配置” (Configuration)。
- 点击蓝色的 “自定义清除” (Custom Purge) 按钮。
- 在弹出的窗口中,选择 “主机名” (Hostname)。
- 在文本框中,精确输入您的 R2 自定义域名(不带协议和斜杠):
r2.yourdomain.com
- 点击 “清除” (Purge) 按钮。
大约 30 秒后,Cloudflare 全球节点上关于此域名的所有缓存都将被清除。
清除方式 | 使用场景 |
---|---|
自定义清除 - 按主机名 | 更新了 R2 上的大量图片。(最推荐) |
自定义清除 - 按 URL | 只更新了一两张特定的图片。 |
全部清除 | 紧急情况,会清除主站和所有子域的缓存,请谨慎使用。 |
结论
通过上述步骤,我们利用 Cloudflare 的免费服务,成功地为 R2 存储桶构建了一个集 WAF防盗链、缓存防刷 和 Workers灵活控制 于一体的、几乎零成本的、专业级的安全防护体系。现在,您可以安心地使用 Cloudflare R2,享受其带来的性能与成本优势,而无需担心被恶意流量所困扰。