繁体   English   中英

加载 AWS CloudFront 文件时出现 403(禁止)

[英]Getting 403 (Forbidden) when loading AWS CloudFront file

我正在开发一个视频应用程序并将文件存储在 AWS S3 上,使用默认的 URL 像https://***.amazonaws.com/***工作正常,但我决定使用 CloudFront,它对内容来说更快送货。

使用 CF,我使用这个 URL https://***.cloudfront.net/***不断得到403 (Forbidden) 我错过了什么吗?

一切正常,直到我决定从指向我的存储桶的 CloudFront 加载内容。

请问有什么解决办法吗?

当使用检查传入Referer:标头的存储桶策略限制对 S3 内容的访问时,您需要进行一些自定义配置以“智胜”CloudFront。

了解 CloudFront 旨在成为性能良好的缓存很重要。 “行为良好”是指 CloudFront 设计为从不返回与源服务器返回的响应不同的响应。 我相信你可以看到这是一个重要的因素。

假设我在 CloudFront 后面有一个 Web 服务器(不是 S3),并且我的网站被设计为根据对Referer:标头...或任何其他 http 请求标头(如User-Agent:的检查返回不同的内容User-Agent:例如。 根据您的浏览器,我可能会返回不同的内容。 CloudFront 如何知道这一点,从而避免为用户提供某个页面的错误版本?

答案是,它无法分辨——它无法知道这一点。 因此,CloudFront 的解决方案根本不是将大多数请求标头转发到我的服务器。 我的 Web 服务器看不到的内容,它无法做出反应,因此我返回的内容不能根据我未收到的标头而变化,这可以防止 CloudFront 缓存并根据这些标头返回错误的响应。 Web 缓存有义务避免为给定页面返回错误的缓存内容。

“但是等等,”你反对。 “我的网站依赖于某个标头的值来确定如何响应。” 是的,这是有道理的……所以我们必须告诉 CloudFront:

除了根据请求的路径缓存我的页面之外,我还需要您转发Referer:User-Agent:或浏览器发送的其他几个标头之一,并缓存响应以用于其他请求,包括 not只有相同的路径,而且您转发给我的额外标题的值也相同

但是,当源服务器是 S3 时,CloudFront 不支持转发大多数请求标头,假设由于静态内容不太可能变化,这些标头只会导致它不必要地缓存多个相同的响应。

您的解决方案不是告诉 CloudFront 您正在使用 S3 作为源。 相反,将您的分配配置为使用“自定义”源,并为其提供存储桶的主机名以用作源服务器主机名。

然后,您可以将 CloudFront 配置为将Referer:标头转发到源,并且基于该标头拒绝/允许请求的 S3 存储桶策略将按预期工作。

嗯,几乎和预期的一样。 这将在一定程度上降低您的缓存命中率,因为现在缓存页面将根据路径 + 引用页面进行缓存。 如果您站点的多个页面引用了一个 S3 对象,CloudFront 将为每个唯一请求缓存一份副本。 这听起来像是一个限制,但实际上,它只是正确缓存行为的产物——无论转发到后端的任何内容,几乎所有内容,都必须用于确定该特定响应是否可用于为未来的请求提供服务。

请参阅http://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/distribution-web-values-specify.html#DownloadDistValuesForwardHeaders以将 CloudFront 配置为将要发送到源服务器的特定标头列入白名单。

重要提示:不要转发您不需要的任何标头,因为每个变体请求都会进一步降低您的命中率。 特别是在使用 S3 作为自定义源的后端时,不要转发Host:标头,因为这可能不会达到您的预期。 在此处选择Referer:标题,然后进行测试。 S3 应该开始看到标题并做出相应的反应。

请注意,当您删除存储桶策略进行测试时,CloudFront 将继续提供缓存的错误页面,除非您通过发送失效请求来刷新缓存,这会导致 CloudFront 在整个过程中清除与您指定的路径模式匹配的所有缓存页面约 15 分钟。 试验时最简单的做法是使用新配置创建一个新的 CloudFront 分配,因为分配本身是免费的。

查看来自 CloudFront 的响应标头时,请注意X-Cache: (hit/miss) 和Age:此特定页面在多长时间前被缓存)响应。 这些在故障排除中也很有用。


更新: @alexjs做出了一个重要的观察:而不是使用存储桶策略执行此操作并将Referer:标头转发到 S3 进行分析——这会在一定程度上损害您的缓存比率,这会随着资源在引用页面上的分布而变化—— - 您可以使用新的 AWS Web 应用程序防火墙服务,该服务允许您对传入 CloudFront 的请求施加过滤规则,以根据请求标头中的字符串匹配来允许或阻止请求。

为此,您需要将分发连接到 S3 作为 S3 源(正常配置,与我提出的相反,在上面的解决方案中,使用“自定义”源)并使用 CloudFront 的内置功能来验证对 S3 的后端请求(因此,如果恶意行为者直接从 S3 请求,则无法直接访问存储桶内容)。

有关此选项的更多信息,请参阅https://www.alexjs.eu/preventing-hotlinking-using-cloudfront-waf-and-referer-checking/

此外,它可能很简单。 当您第一次将文件上传到 S3 存储桶时,它是非公开的,即使该存储桶中的其他文件是公开的,甚至该存储桶本身也是公开的。

要在 AWS 控制台中更改此设置,请选中要公开的文件夹(您刚刚上传的文件夹)旁边的框,然后从菜单中选择“公开”。

该文件夹(和任何子文件夹)中的文件将公开,您将能够从 S3 提供文件。

对于 AWS CLI,在您的命令中添加“--acl public-read”选项,如下所示:

aws s3 cp index.html s3://your.remote.bucket --acl public-read

我确定了 CloudFront 可以返回403 (Bad request)另一个原因。 也许那是一个边缘情况,但我想与你分享。

CloudFront 实施了前向循环检测机制以防止转发循环攻击。
根据 AWS 支持,您不能级联超过 2 个 CloudFront 分配作为源。

假设您已将 CloudFront A 配置为 CloudFront B 作为源,并且在 CloudFront B 中您已将 CloudFront C 配置为源,而在 CloudFront C 中您有一个 S3 存储桶作为源。

A --> B --> C --> S3 bucket (can return a 403 error)

如果您在级联结束时从位于 S3 存储桶中的 CloudFront A 请求文件,CloudFront C 将返回 403(错误请求)。

如果您的级联最后只包含 2 个 CloudFront 分配和一个 S3 存储桶,则来自 S3 源的文件请求有效。

A --> B --> S3 bucket (works)

对我来说,我必须让 CodePipeline 访问我的 S3 存储桶策略。 例如这样的事情:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "PublicReadGetObject",
            "Effect": "Allow",
            "Principal": "*",
            "Action": "s3:GetObject",
            "Resource": "arn:aws:s3:::mys3bucket/*"
        }
    ]
}

我的要求是将存储桶设为私有,所以我使用了 OAI,我面临的主要问题是我在创建发行版之前创建了 OAI 并在源部分下拉列表中选择了它,而 cloudfront 开始向我抛出 403。我通过让 cloudfront 在创建 cloudfront 源时创建 OAI 来解决这个问题(我从下拉列表中选择了原始域名并选择了存储桶,然后它提供了限制 s3 存储桶的选项,然后您将获得创建源访问身份的选项和一个名为在存储桶上授予读取权限的选项,让 aws/cloudfront 处理它)

有时 aws 可能无法在 s3 存储桶中添加 OAI 的权限,请使用此文档手动添加权限

https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/private-content-restricting-access-to-s3.html#private-content-granting-permissions-to-oai

还要确保您在 s3 和 cloudfront 中都提供了入口点(在我的情况下为 index.html)

我没有在 cloudfront 中创建任何错误页面,希望它能节省别人的时间

编辑:重新加载页面抛出 403 错误,所以我在 cloudfront 中添加了 403 和 404 的错误页面和页面为“/index.html”

对于POST请求,我从 cloudfront 收到 403 错误,其中我的来源是域名而不是 s3 存储桶。

原因是 cloudfront 默认不允许POST 我从控制台的“ Behaviors选项卡启用了POST ,然后它就起作用了。

在此处输入图片说明

一个问题可能是您没有指定 CNAME(特定的或通配符),当您尝试使用域名时,它不起作用,但可以使用 CF Distro url

我遇到了类似的问题,但在我的存储桶策略中,我在资源部分只提到了存储桶 ARN。 而不是我需要提及 bucketname/* 以允许访问该存储桶中的所有对象。 认为这可能对一些面临类似问题的人有所帮助。

我通过更新我的 cloudfront 发行版下的原始域来解决

在源选项卡下编辑源名称不要直接从列表中选择存储桶名称,而是从您的 s3 存储桶复制静态网站托管(在属性选项卡下检查)

test.uk.s3-website.eu-west-2.amazonaws.com

在我的情况下,我使用同一个 s3 存储桶中的子文件夹来部署多个反应应用程序。 这就是我所做的。

  1. 确保 s3 策略具有“资源”:“arn:aws:s3:::s3bucketname/ ”,“ ”很重要。
  2. 在 CloudFront 分发版的“源”选项卡下,确保您没有从下拉列表中选择 select,而只需从没有 http:// 的 S3 属性选项卡中复制网站托管端点。
  3. 必要时用“/*”使无效。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM