Cloudflare CDN小黄云导致 MinIO 403以及解决办法

Cloudflare CDN小黄云导致 MinIO 403以及解决办法

前两天给搭了个 MinIO 对象存储,由于我域名解析在CF上使用的通配符*,流量自然而然的走 Cloudflare 的CDN小黄云代理。结果使用minio SDK测试上传文件的时候,报 403 错误。

报错信息是这样的:

1
An error occurred (403) when calling the HeadObject operation: Forbidden

一开始我还以为是我权限配错了,翻来覆去检查了半天 Access Key、Secret Key、Bucket Policy,都没问题。本地直连 MinIO 一切正常,一走 Cloudflare 就挂。

问题出在哪

后来查了半天才发现,原来是 Cloudflare 的缓存机制搞的鬼。

MinIO 的 S3 API 用 HEAD 请求来检查对象是否存在,还要获取对象的元数据做签名验证。但 Cloudflare 的默认行为是:遇到 HEAD 请求,它会把缓存的 GET 请求返回给你,但是把 body 给清空。

这就尴尬了。MinIO 期待 HEAD 响应里要有完整的元数据信息,结果 Cloudflare 给它一个空 body,签名验证就失败了,直接 403。

MinIO 本来会在响应头里返回 x-minio-error-descx-minio-error-code 这些调试信息,但被 Cloudflare 一缓存,这些头信息可能也跟着丢了。

怎么解决

折腾了一圈,找到了两个办法。

方法一:关掉小黄云

最直接的就是给 MinIO 的域名关掉 Cloudflare 代理,变成灰色的云。这样 HEAD 请求就直接打到 MinIO 上了,问题解决。

但这个方法有个问题:如果你依赖 Cloudflare 的 SSL 证书或者防护功能,这就不可行了。

方法二:配置缓存规则绕过

这个方法更实用一点。在 Cloudflare 里配置一个缓存规则,让 MinIO 的 URL 不走缓存。

具体步骤:

  1. 登录 Cloudflare,选你的域名
  2. 进入左边菜单 缓存 > Cache Rules
  3. 点击 创建规则
  4. 规则名称随意
  5. 在 “如果传入请求匹配…” 里选 “自定义筛选表达式”
  6. 设置匹配规则:
    • Field: 主机名
    • Operator: 等于
    • Value: 你的minioapi域名(即反向代理9000端口的域名)
  7. 在 缓存资格 部分选 绕过缓存
  8. 点 保存

这样配置之后,MinIO 的请求就会绕过 Cloudflare 缓存,直接打到后端,HEAD 请求也能正常返回元数据了。

cf配置缓存规则

还有个坑

查资料的时候看到有人说,用 Cloudflare 当对象存储的 CDN 可能违反他们的服务条款。这个我没仔细确认,如果你打算长期这么用,最好去看看 Cloudflare 的官方文档。

总结

这个问题折腾了我一下午,一开始完全没想到是缓存的问题。以后遇到这种本地正常、走代理就挂的情况,第一反应该想想是不是缓存层搞的鬼。

希望这篇文章能帮到遇到同样问题的你。如果还有其他坑,欢迎交流。