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 里的吗?)