无法使用 nginx 连接到 S3

无法使用 nginx 连接到 S3

我正在尝试从 Amazon S3 存储桶提供静态文件和媒体文件,但 Nginx 无法连接到它

这是我得到的错误

<Error>
<Code>AccessDenied</Code>
<Message>
AWS authentication requires a valid Date or x-amz-date header
</Message>
<RequestId></RequestId>
<HostId></HostId>
</Error>

和我的 Nginx 配置

server {
listen          80;
server_name     my_elastic_ip;

location = /favicon.ico { access_log off; log_not_found off; }

location / {
    try_files $uri @s3;
}

location @s3 {
    set $s3_bucket          'my_bucket.s3.amazonaws.com';
    set $url_full           '$1';
    set $aws_access_key     'my_access_key';
    set $aws_secret_key     'my_secret_key';

    proxy_http_version      1.1;
    proxy_set_header        Host $s3_bucket;
    proxy_set_header        x-amz-date $date_gmt;
    proxy_set_header        Authorization 'AWS $aws_access_key:$aws_secret_key';
    proxy_hide_header       x-amz-id-2;
    proxy_hide_header       x-amz-request-id;
    proxy_hide_header       Set-Cookie;
    proxy_ignore_headers    "Set-Cookie";
    proxy_buffering         off;
    proxy_intercept_errors  on;

    resolver                8.8.4.4 8.8.8.8 valid=300s;
    resolver_timeout        10s;
    proxy_pass              http://$s3_bucket/$url_full;
}
}

编辑1:

我已通过将 x-amz-date 替换为以下内容解决了该问题:

set_by_lua $now         "return ngx.cookie_time(ngx.time())";
proxy_set_header        x-amz-date $now;

如果你需要额外的 Nginx 包,请使用以下命令安装它们:

sudo apt-get install nginx-extras

现在我收到此错误:

<Error>
<Code>SignatureDoesNotMatch</Code>
<Message>
The request signature we calculated does not match the signature you provided. Check your key and signing method.
</Message>

编辑2:

为了创建签名,我添加了 set-misc-nginx-module (https://github.com/openresty/set-misc-nginx-module#installation)到 nginx(安装 nginx 可选模块

然后将我的 Nginx 配置更新为:

server {
listen          80;
server_name     my_ip;

location = /favicon.ico { access_log off; log_not_found off; }

location / {
    try_files $uri @s3;
}

location @s3 {
    set $s3_bucket          'my_bucket';
    set $key                'my_file';
    set $aws_access_key     'my_access_key';
    set $aws_secret_key     'my_secret_key';

    set_by_lua $now         "return ngx.cookie_time(ngx.time())";
    set $aws_signature      '';
    set $string_to_sign     "$request_method\n\n\n\nx-amz-date:$now\n/$s3_bucket/$key";
    set_hmac_sha1           $aws_signature $aws_secret_key $string_to_sign;
    set_encode_base64       $aws_signature $aws_signature;

    proxy_http_version      1.1;
    proxy_set_header        x-amz-date $now;
    proxy_set_header        Authorization 'AWS $aws_access_key:$aws_signature';
    proxy_set_header        Host $s3_bucket.s3.amazonaws.com;
    proxy_hide_header       x-amz-id-2;
    proxy_hide_header       x-amz-request-id;
    proxy_hide_header       Set-Cookie;
    proxy_ignore_headers    "Set-Cookie";
    proxy_buffering         off;
    proxy_intercept_errors  on;

    resolver                8.8.4.4 8.8.8.8 valid=300s;
    resolver_timeout        10s;
    proxy_pass              http://s3.amazonaws.com;
}
}

收到此错误:

状态:HTTP/1.1 403 禁止

<Code>AccessDenied</Code>
<Message>Access Denied</Message>

答案1

考虑暂时将proxy_pass后端服务设置为本地服务或 HTTP echo 服务,以便您可以查看发送到 Amazon 的完整 HTTP 请求。(如果您使用 HTTP echo Web 服务,请先从请求中删除敏感位!)。

然后直接调试 Amazon 请求中存在的问题。找出问题所在后,您可以对 Nginx 进行适当的更改,以便它为您发送有效的请求标头。

答案2

NGINX S3 网关

我在 NGINX 的团队发布了一个功能齐全的(在 Docker 中)示例,介绍如何代理 S3 API 后端。它支持 v2 和 v4 身份验证签名。实现的核心部分是在新泽西并且应该具有合理的性能。使用该项目作为参考,您可能会找到更全面的实现,从而避免您遇到的一些问题。

相关内容