Home
avatar

Nax

详细说一下关于R2图床被刷的原理

大家好,我是nax。 Cloudflare 全家桶(域名、CDN、Worker 函数、R2 存储)搭建了个人图床,速度飞快,体验极佳。 但在享受免费额度的同时,很多人都听人说可能有坏人恶意的刷请求导致欠费,但是很多人都知道可能会被刷,也按照教程做了防护,但是并不清楚其中的内在逻辑---到底是怎么刷的? 我在这里就给大家讲一下,做到明明白白理解,清清楚楚防御

1. 攻击是如何发生的?

首先,我们来理解一下一个“朴素”的图床工作流程:

  1. 用户请求:浏览器访问 https://my-image-host.com/file/cat.jpg
  2. Cloudflare CDN:CDN 边缘节点检查有没有缓存这个图片。
    • 缓存命中 (Cache HIT):直接从最近的服务器返回图片,速度飞快,不产生任何费用。
    • 缓存未命中 (Cache MISS):缓存里没有。CDN 只能向源站请求,这个过程我们称之为“回源”。
  3. 回源到 Worker:请求被转发到我们的 Cloudflare Worker 函数。
  4. Worker 访问 R2:Worker 函数的任务就是去 R2 存储桶里找到 cat.jpg 这张图片。
  5. 返回图片:Worker 拿到图片后,返回给 CDN,CDN 再缓存起来并返回给用户。

这个流程看起来很完美。但问题出在第 2 步,如果一个攻击者请求的是一个根本不存在的文件呢?比如 https://my-image-host.com/file/a-random-string-123.jpg

流程会变成这样:

  1. 恶意请求:攻击者请求一个随机路径。
  2. CDN 缓存未命中:因为是随机路径,所以缓存里 100% 不存在。必须回源!
  3. 回源到 Worker:Worker 接收到请求。
  4. Worker 访问 R2:Worker 很“实在”地去 R2 存储桶里寻找 a-random-string-123.jpg
  5. R2 返回“空”:R2 找了一圈,发现文件不存在,返回一个 null
  6. Worker 返回 404:Worker 告诉 CDN 和用户:“对不起,找不到这个文件”。

危险就在第 4 步!

Cloudflare R2 的免费额度主要包含两部分:存储量和操作次数。其中“B 类操作”就是指读写等操作。即使文件不存在,我们去查询它的这个动作(R2.get()),就已经消耗掉了一次宝贵的 B 类操作额度!

一个攻击者可以写一个简单的脚本,每秒生成成千上万个不同的随机 URL 来访问我们的图床。每一次访问都会触发一次 R2 的 B 类操作,我们的免费额度会在短时间内被迅速耗尽,从而产生高额账单。

2. 速率限制的缺点

有朋友可能会问:“我在 Cloudflare 防火墙里开个速率限制,比如限制一个 IP 每分钟最多请求 100 次,不就行了吗?”

这是一个好问题,但答案是:不够,而且远非万全之策。

速率限制的原理是基于 IP 地址。但一个稍有经验的攻击者,根本不会用单个 IP 来攻击你。

  • 分布式攻击:他们可以使用成千上万个代理 IP 或“僵尸网络”来发起攻击。每个 IP 的请求频率都很低,远到不了你设置的阈值,但加起来的总量是巨大的。
  • IPv6 轮换攻击:这是一个更致命的威胁。攻击者可以轻易地获得一个庞大的 IPv6 地址段,这意味着他们可以为每一次请求都换一个新的 IP 地址。在这种情况下,基于 IP 的速率限制将形同虚设。

结论:速率限制是一个很好的辅助工具,但它无法从根本上防御这种特定类型的攻击。

防御方式原理对分布式/IPv6攻击效果
速率限制基于请求来源 (IP) 和频率无效只能缓解,无法根除
KV 索引检查基于请求内容 (文件是否存在)完全有效从逻辑上根除威胁

3. 解决方案:用 KV 筑起一道防火墙

那么,如何阻止这种攻击呢?答案是:在访问 R2 之前,增加一个验证层。

我们不能让所有请求都直接去问 R2。我们应该先查一个“文件清单”,看看请求的文件是否真的存在。这个“文件清单”,就是 Cloudflare Workers KV。

Workers KV 是一个速度极快的全球分布式键值数据库,非常适合用来做索引。

我们的安全流程应该升级为:

  1. 上传时:当一张新图片 dog.jpg 成功上传到 R2 后,我们同时在 KV 里记录下它的名字。

    • KV.put("dog.jpg", "1") // 值是什么不重要,关键是键的存在
  2. 访问时:当有请求访问 dog.jpg 时,Worker 的处理步骤是:

    • 第一步:先问 KVKV.get("dog.jpg") 在我们那个“文件清单”里查一下。
    • 第二步:做判断
      • KV 中存在:证明这是个合法文件。好的,现在可以去 R2 把图片取出来了。
      • KV 中不存在:这一定是个无效或恶意请求!立即返回 404 错误,绝不去打扰 R2!

通过这个简单的改进,所有对随机、不存在路径的恶意请求,都会在第一步就被 KV 防火墙挡住。它们只会触发一次成本极低、速度极快的 KV 读取,而永远无法触及到我们宝贵的 R2 存储,从而完美地保护了我们的钱包。

4. 总结:构建“深度防御”体系

我们的最佳安全策略是“深度防御”,多管齐下:

  1. 核心防线(必须有):采用 “先查 KV,再访问 R2” 的方案。这是保护 R2 资源不被无效请求消耗的根本。
  2. 辅助防线(建议有):在整个网站或关键 API(如上传接口)上额外配置速率限制。它虽然挡不住高级攻击,但可以有效拦截一些低级的脚本小子,并保护你的 Worker 函数本身不被海量请求打垮。

希望这篇文章能帮助你构建一个更安全、更可靠的个人图床。如果你有任何问题,欢迎在评论区留言讨论!

Cloudflare 对象储存 KV cdn