DockerHub 反向代理 Missing x-amz-content-sha256
使用 CF Workers 做反向代理时,一般直接把原请求直接 passthrough 到 dockerhub 服务器,类似:
// ...
const newUrl = new URL(upstream + url.pathname);
const req = new Request(newUrl, {
method: request.method,
headers: request.headers,
redirect: 'follow',
});
return await fetch(req);
// ...
假如我们请求的 url 是 https://registry-1.docker.io/v2/library/[image_name]/blobs/sha256:[sha256_value]
,那么在验证完 Authorization
请求头后,会 307 到对象存储的地址,比如 R2 的地址 https://docker-images-prod.[...].r2.cloudflarestorage.com/registry-v2/[...]/data?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=[...]&X-Amz-Date=[...]&X-Amz-Expires=1200&X-Amz-SignedHeaders=host&X-Amz-Signature=[...]
请求到 R2 的时候,这个 Authorization
头如果带上了,就会报 Missing x-amz-content-sha256
。 CF Workers 的 fetch 直接把请求头带到了第二个请求里,这个 bug 导致了报错。
那么到底 fetch 遇到跳转是否应该带原来的请求头呢?当跳转时 origin 改变了,某些 header 就应该被去掉。见 Fetch Standard - 4.4 HTTP-redirect fetch:
Note: I.e., the moment another origin is seen after the initial request, the
Authorization
header is removed.
这个 bug 理论上会对安全性造成影响,把另一个站点的凭据泄漏给另外一个站点。
Node.js 无此 bug 。( fetch 是写在 v8 里的吗?)