You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Nginx正则匹配代理S3存储桶SignatureDoesNotMatch报错排查

问题根因

出现SignatureDoesNotMatch报错的核心原因是正则匹配+变量构造proxy_pass地址的场景下,Nginx的默认行为和固定前缀匹配场景完全不一致,导致转发给S3的Host头、请求路径和签名计算时使用的参数不匹配,触发S3的签名校验拦截。

你之前前缀匹配配置能正常运行,是因为两个默认行为刚好符合S3的签名要求:

  • 固定字符串写法的proxy_pass(不带变量),Nginx会自动将请求Host头设置为proxy_pass指向的域名bucketname.s3.amazonaws.com,和签名时使用的Host一致
  • 固定字符串proxy_pass带结尾斜杠时,Nginx会自动截断匹配到的location前缀(也就是/bucketname/),将后续路径拼接给上游,转发给S3的请求路径和签名计算的路径完全一致。

而你写的正则location配置,踩了三个Nginx的默认行为坑:

  1. 当proxy_pass中包含变量(你这里用了$1)时,Nginx不会自动设置上游Host头,会直接透传客户端请求的Host值(也就是localhost:801),和S3要求的{bucket}.s3.amazonaws.comHost头不匹配,直接导致签名校验失败
  2. 当proxy_pass中包含变量时,Nginx不会自动做URI截断替换,会将客户端的完整原始URI直接转发给上游,你之前写的结尾斜杠不会起到截断前缀的作用,最终S3收到的请求路径带了多余的桶名前缀,和签名时的路径不一致
  3. 你写的正则~ ([^/]+)没有锚定URI开头,存在捕获错误字符串的风险,虽然你验证过$1取值正确,但属于不规范写法。
修复方案

直接替换为以下配置即可,逻辑和你正常运行的前缀匹配完全对齐:

# 锚定URI开头,同时捕获桶名和后续请求路径
location ~ ^/([^/]+)/(.*)$ {
    resolver 8.8.8.8;
    # 手动设置S3要求的Host头,和签名时的域名保持一致
    proxy_set_header Host $1.s3.amazonaws.com;
    # 透传所有原始请求头,避免Nginx修改签名相关的自定义头
    proxy_pass_request_headers on;
    # 截断URI开头的桶名前缀,和前缀匹配的路径转发逻辑对齐
    rewrite ^/[^/]+/(.*)$ /$1 break;
    # 转发到对应S3桶地址,不要带结尾斜杠避免路径拼接异常
    proxy_pass https://$1.s3.amazonaws.com;
}
额外排查点

如果替换配置后还是报错,按以下顺序检查:

  • 确认签名时使用的请求方法、URI路径、query参数和Nginx实际转发的完全一致,不要漏签query参数
  • 如果请求带请求体,加proxy_set_header Content-Length $http_content_length;配置,避免Nginx重算Content-Length导致头值和签名时不一致
  • 确认使用的S3域名和桶所在区域匹配,跨区域访问会触发域名跳转,导致签名校验失败

内容的提问来源于stack exchange,提问作者Wwww24115

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.28 11:06:24