加载AWS CloudFront文件时获取403(禁止)

Shi*_*ina 15 amazon-s3 amazon-web-services amazon-cloudfront

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

使用CF,我一直在403 (Forbidden)使用这个URL https://***.cloudfront.net/***.我错过了什么吗?

在我决定从CloudFront加载指向我的存储桶的内容之前,一切正常.

有解决方案吗?

Mic*_*bot 13

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

了解CloudFront旨在成为行为良好的缓存非常重要."表现良好",我的意思是CloudFront的设计永远不会返回与原始服务器返回的响应不同的响应.我相信你可以看到这是一个重要因素.

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

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

"但是等等,"你反对."我的网站取决于某个标题的值,以确定如何回应." 是的,这是有道理的......所以我们必须告诉CloudFront:

相反,基于刚才所请求的路径上缓存我的网页,我需要你也转发Referer:User-Agent:或浏览器发送的,其他几个头一个和缓存上不仅包括同一路径的其他请求使用的响应,但您转发给我的额外标题也是相同的值.

但是,当原始服务器是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:(命中/未命中)和Age:(多久以前缓存此特定页面)响应.这些在故障排除中也很有用.


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

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

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


Pat*_*Chu 5

同样,这可能很简单。首次将文件上传到S3存储桶时,即使该存储桶中的其他文件是公共的,也即使存储桶本身是公共的,它也不是公共的。

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

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

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

aws s3 cp index.html s3://your.remote.bucket --acl public-read
Run Code Online (Sandbox Code Playgroud)

  • 使用Cloudfront访问S3时,您应该使用原始访问ID,而不是将S3存储桶公开。然后,存储桶可以授予对存储桶策略的权限(如果使用控制台设置Cloudfront,则实际上可以自动完成此操作)。 (2认同)

小智 5

我确定了CloudFront可以返回的另一个原因403 (Bad request)。也许那是一个极好的案例,但我想与您分享。

CloudFront实施了前向环路检测机制,以防止转发环路攻击。
根据AWS支持,您不能将两个以上的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)