解决 MinIO 反代 403 SignatureDoesNotMatch

解决 MinIO 反代 403 SignatureDoesNotMatch
狂犬主子最近开始折腾自建存储,原计划使用 WebDAV。但发现套了 Cloudflare CDN 只能上传 100MB 的文件,直连服务器上传比较慢,因此考虑使用 MinIO 对象存储 + 分片上传绕过这个限制。不过发现 Cloudflare + MinIO 不是开箱即用的,存在很多坑,比如这个 SignatureDoesNotMatch 问题,没搜到一篇有用的文章,故在此记录一下思路和解决方案。
问题
flowchart LR n1["Rclone"] --> n2["Cloudflare"] n2 --> n3["MinIO"]
如图部署的MinIO对象存储服务器,无法使用客户端链接,报错 SignatureDoesNotMatch
:
1 | ❯ rclone --config rclone.conf lsd minio: |
解决过程
重装 + 升级最新版本:无效。
使用密码直连:无效。
控制台设置 Access Policy 为 Public:无效。
直连服务器没有问题:
flowchart LR n1["Client"] --> n2["MinIO"]
所以问题可能出现在 Cloudflare CDN 上。
查到这两篇文章让关缓存:
但屁用没有,抓到响应头:cf-cache-status: DYNAMIC
。
确认 Cloudflare Dashboard 中已经添加好 Cache Rule。
确认未使用 SAAS 域名。
确认未开启标头转换,这个应该只能改响应头,改不了请求头。
最后尝试使用 NGINX 反代 + 改头,更改架构为:
flowchart LR n1["Client"] --> n2["Cloudflare"] n2 --> n3["Nginx"] n3 --> n4["MinIO"]
MinIO 官方给的配置:https://min.io/docs/minio/linux/integrations/setup-nginx-proxy-with-minio.html
1 | upstream minio_s3 { |
结果还是有问题。
部分文章说需要更改 Host 为 IP:Port:
https://blog.csdn.net/a_123_4/article/details/136448688
结果还是有问题。
最后找到这个 Issue:
https://github.com/minio/minio/issues/15506
说 Cloudflare 存在改头问题导致签名不匹配。
提到还需添加 Accept-Encoding: indentity
,这里添加后就能连上,问题解决。
经过测试,最简配置,少一个都不行:
1 | location / { |
其他的配置不需要都能连上,当然最好都按照官方的添加一下。
解决方案
NGINX 反代 + 改头:
flowchart LR n1["Client"] --> n2["Cloudflare"] n2 --> n3["Nginx"] n3 --> n4["MinIO"]
1 | proxy_set_header Host $http_host; |
复盘
查看客户端的请求,发现 accept-encoding: identity
,估计是传回服务器的时候被改成 gzip
之类的了。响应的 MIME 类型是 application/xml
。
https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Headers/Accept-Encoding
identity
:表示恒等函数(即不作任何修改或压缩)。即使省略,此值始终被视为是可接受的。
由于机器性能不佳,我这里的 NGINX 已经关闭 GZIP 压缩。
1 | gzip off; |
所以 NGINX 也有可能会出现这个问题,具体情况具体分析。
尝试添加压缩规则,发现无法提交规则:exceeded the maximum number of rules in the phase http_response_compression: 1 out of 0
,应该是只对付费用户开放。
在这个页面发现这篇文档:https://developers.cloudflare.com/speed/optimization/content/compression/
从客户端发送请求到 Cloudflare CDN,没有对请求头的 Accept-Encoding
进行修改:
从 Cloudflare CDN 将客户端的请求转发回服务器,发现对请求头的 Accept-Encoding
进行了修改:
反正通篇文章没有提到这个 identity
。
具体验证被改成啥,服务器 NGINX 上加个头试试:
1 | add_header IF-CF-Modify-Accept-Encoding $http_accept_encoding; |
客户端响应到:if-cf-modify-accept-encoding: gzip, br
,看来真的会被改头。另外可以发现头的 Key 被改成了小写。
关于响应内容,客户端没有出现乱码,返回的响应内容应该是能够正常解压的。