Cloudfront 自定义源分发返回 502“错误无法满足请求。”对于某些 URL

Posted

技术标签:

【中文标题】Cloudfront 自定义源分发返回 502“错误无法满足请求。”对于某些 URL【英文标题】:Cloudfront custom-origin distribution returns 502 "ERROR The request could not be satisfied." for some URLs 【发布时间】:2014-01-06 23:28:20 【问题描述】:

我们有一个自定义来源的 Cloudfront 发行版,该发行版在很长一段时间内都运行良好,为我们的一个站点提供静态资产。就在今天早上,我们注意到我们的徽标显示为断开的链接。

经过进一步调查,Cloudfront 正在返回一条我以前从未见过的 URL in question 的奇怪错误消息:

错误

无法满足请求。



由云端(CloudFront)生成

此发行版中的其他几个 Cloudfront URL 返回相同的错误,但其他(同样来自同一发行版)的工作正常。我没有看到什么有效,什么无效的模式。

其他一些数据点:

origin URLs 工作正常。据我所知,最近服务没有中断。 我已专门使徽标 URL 无效,但没有效果。 我已使分发的根 URL 无效,但没有任何效果。

知道这里发生了什么吗?我以前从未见过 Cloudfront 这样做。

更新:

这是来自 Cloudfront 的逐字 HTTP 响应:

$ http GET https://d2yu7foswg1yra.cloudfront.net/static/img/crossway_logo.png
HTTP/1.1 502 Bad Gateway
Age: 213
Connection: keep-alive
Content-Length: 472
Content-Type: text/html
Date: Wed, 18 Dec 2013 17:57:46 GMT
Server: CloudFront
Via: 1.1 f319e8962c0268d31d3828d4b9d41f98.cloudfront.net (CloudFront)
X-Amz-Cf-Id: H_HGBG3sTOqEomHzHubi8ruLbGXe2MRyVhGBn4apM0y_LjQa_9W2Jg==
X-Cache: Error from cloudfront

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<HTML><HEAD><META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1">
<TITLE>ERROR: The request could not be satisfied</TITLE>
</HEAD><BODY>
<H1>ERROR</H1>
<H2>The request could not be satisfied.</H2>
<HR noshade size="1px">
</BODY></HTML>

<BR clear="all">
<HR noshade size="1px">
<ADDRESS>
Generated by cloudfront (CloudFront)
</ADDRESS>
</BODY></HTML>

【问题讨论】:

有趣....我刚刚创建了我的第一个发行版(没有自定义 CNAME)并且得到了同样的结果。从基本的一切开始,但还没有运气。 是的,我创建了一个新的发行版来测试,同样的事情。 :\ 我遇到了类似的问题,尽管 CloudFront 分配中的一些静态文件出现 504 网关超时。我意识到我启用了pglcmd,它通过 iptables 阻止了 IP 范围。我仍然不知道为什么 CloudFront 会检查这些文件,这些文件的过期标头设置为一年。 【参考方案1】:

我今天在使用 Amazon Cloudfront 时遇到了这个错误。这是因为我使用的 cname(例如 cdn.example.com)没有添加到“备用 cnames”下的分发设置中,我只在我的站点/主机控制面板中将 cdn.example.com 转发到了云端域,但是您还需要将其添加到 Amazon CloudFront 面板。

【讨论】:

就我而言,这是 CNAME 中的拼写错误。呵呵! 谢谢,解决了! 添加备用 CNAME 后,CloudFront 分发状态(在“常规”选项卡下)需要一段时间才能从“进行中”变为“已部署”。在此期间,您仍会收到类似的 CloudFront 错误消息。在我的情况下花了大约半个小时。 对于一些查找更改 cname 的人:转到 CloudFront 部分 => 选择您的云端 => 选择 General => Edit => 在 Alternate Domain Names (CNAMEs) 中添加您的 CNAME url(它在第三行)【参考方案2】:

我最近遇到了类似的问题,结果证明是由于我使用的 ssl_ciphers 造成的。

来自http://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/RequestAndResponseBehaviorCustomOrigin.html,

"CloudFront 使用 SSLv3 或 TLSv1 协议以及 AES128-SHA1 或 RC4-MD5 密码将 HTTPS 请求转发到源服务器。如果您的源服务器不支持 AES128-SHA1 或 RC4-MD5 密码,则 CloudFront 无法建立与您的来源的 SSL 连接。 "

我不得不更改我的 nginx 配置以将 AES128-SHA(不推荐使用的 RC4:HIGH)添加到 ssl_ciphers 以修复 302 错误。我希望这有帮助。我已经粘贴了我的 ssl.conf 中的行

ssl_ciphers ECDH+AESGCM:ECDH+AES256:ECDH+AES128:DH+3DES:RSA+3DES:AES128-SHA:!ADH:!AECDH:!MD5;

【讨论】:

这似乎是我的特定问题的正确解决方案,尽管似乎有多种方法可以获取该错误消息,这反映在此处的其他答案中。 您可能希望使用AES128-SHA 而不是RC4:HIGH。使用RC4:HIGH 将我的Qualsys SSL Labs 测试成绩从A 降为C。 这也解决了我的问题。但是,我必须使用带有“1”的AES128-SHA1。没有 1 它对我不起作用。此外,AWS 建议使用 TLSv1 而不是 SSLv3,这不太安全。【参考方案3】:

找到我的答案并将其添加到此处,以防对 David(和其他人)有所帮助。

原来我的源服务器(比如 www.example.com)上有一个 301 重定向设置来将 HTTP 更改为 HTTPS:

HTTP/1.1 301 Moved Permanently
Location: https://www.example.com/images/Foo_01.jpg

但是,我的源协议策略设置为仅 HTTP。这导致 CloudFront 找不到我的文件并引发 502 错误。此外,我认为它会将 502 错误缓存 5 分钟左右,因为在删除 301 重定向后它没有立即工作。

希望有帮助!

【讨论】:

嗯!不完全是我的情况,但我敢打赌那真的很接近。 你确定?我将您的网址作为 http 运行并得到:HTTP/1.1 301 永久移动服务器:nginx/0.7.65 日期:2013 年 12 月 19 日星期四 05:00:15 GMT 内容类型:文本/html 内容长度:185 连接:保持-alive 位置:my.crossway.org/static/img/crossway_logo.png 301 永久移动

301 永久移动

中心>
nginx/0.7.65
但我没有在我的原始策略中使用HTTP Only,我使用的是Match Viewer。奇怪的是,直到最近它还运行良好。 我认为即使您使用“匹配查看器”,它也会导致问题,即使它不应该。我在主页上有一个 301 时遇到了同样的问题,它在 5 分钟的缓存长度内破坏了该页面。【参考方案4】:

在我们的例子中,一切看起来都还不错,但花了大部分时间才弄明白:

TLDR:检查您的证书路径以确保根证书正确。对于 COMODO 证书,它应该是“USERTrust”并由“AddTrust External CA Root”颁发。不是“COMODO RSA 证书颁发机构”颁发的“COMODO”。

来自 CloudFront 文档: http://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/SecureConnections.html

如果源服务器返回无效证书或自签名证书,或者源服务器以错误顺序返回证书链,CloudFront 会断开 TCP 连接,返回 HTTP 错误代码 502,并设置 X-Cache从云端到错误的标头。

我们启用了正确的密码:http://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/RequestAndResponseBehaviorCustomOrigin.html#RequestCustomEncryption

根据 Google、Firefox 和 ssl-checker,我们的证书是有效的: https://www.sslshopper.com/ssl-checker.html

但是 ssl 检查器链中的最后一个证书是“COMODO RSA 域验证安全服务器 CA”,由“COMODO RSA 证书颁发机构”颁发

CloudFront 似乎不持有“COMODO RSA 证书颁发机构”的证书,因此认为源服务器提供的证书是自签名的。

这工作了很长时间,然后显然突然停止了。发生的事情是我刚刚更新了当年的证书,但在导入过程中,所有以前的证书的证书路径发生了一些变化。他们都开始引用“COMODO RSA 证书颁发机构”,而之前链更长,根是“AddTrust External CA Root”。

因此,切换回旧证书并不能解决云端问题。

我不得不删除名为“COMODO RSA 证书颁发机构”的额外证书,该证书没有引用 AddTrust。完成此操作后,我的所有网站证书路径都更新为再次指向 AddTrust/USERTrust。注意也可以从路径中打开坏根证书,点击“详细信息”->“编辑属性”,然后这样禁用它。这立即更新了路径。您可能还需要删除证书的多个副本,这些副本位于“个人”和“受信任的根证书颁发机构”下

最后我不得不在 IIS 中重新选择证书,让它为新的证书链服务。

在这一切之后,ssl-checker 开始显示链中的第三个证书,它指向“AddTrust External CA Root”

最后,CloudFront 接受了原始服务器的证书和提供的链作为受信任的。我们的 CDN 又开始正常工作了!

为了防止以后发生这种情况,我们需要从具有正确证书链的机器中导出我们新生成的证书,即不信任或删除由“COMODO RSA Certification Authroity”颁发的证书“COMODO RSA Certification Authroity”( 2038 年到期)。这似乎只影响默认安装此证书的 Windows 机器。

【讨论】:

【参考方案5】:

另一种可能的解决方案:我有一个登台服务器,通过 HTTP 为站点和 Cloudfront 资产提供服务。我将来源设置为“匹配查看器”而不是“仅 HTTP”。我还使用 HTTPS Everywhere 扩展,它将所有 http://*.cloudfront.net URL 重定向到 https://* 版本。由于暂存服务器无法通过 SSL 使用,而且 Cloudfront 与查看器匹配,因此它无法在 https://example.com 找到资产,而是缓存了一堆 502。

【讨论】:

【参考方案6】:

我刚刚解决了这个问题,就我而言,它确实与重定向有关,但与我的 CloudFront 来源或行为中的错误设置无关。如果您的源服务器仍重定向到源 URL,而不是您为云端 URL 设置的内容,则会发生这种情况。如果您忘记更改配置,这似乎很常见。例如,假设您有 www.yoursite.com CNAME 到您的云端发行版,来源为 www.yoursiteorigin.com。显然人们会来到 www.yoursite.com。但是,如果您的代码尝试重定向到 www.yoursiteorigin.com 上的任何页面,您将收到此错误。

对我来说,我的源仍在执行 http->https 重定向到我的源 URL,而不是我的 Cloudfront URL。

【讨论】:

【参考方案7】:

就我而言,这是因为我们的 ssl 证书无效。问题出在我们的暂存箱上,我们也使用我们的产品证书。在过去的几年里,它一直在使用这种配置,但突然之间我们开始收到这个错误。奇怪。

如果其他人收到此错误,请检查 ssl 证书是否有效。您可以通过 AWS CloudFront 分发接口启用对 s3 的日志记录以帮助调试。

另外,你可以在这里参考亚马逊的文档:http://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/SecureConnections.html

【讨论】:

【参考方案8】:

我遇到了这个问题,在我停止使用代理后它自行解决了。也许 CloudFront 将某些 IP 列入黑名单。

【讨论】:

【参考方案9】:

通过连接我的证书以生成有效的证书链(使用 GoDaddy 标准 SSL + Nginx)解决了这个问题。

http://nginx.org/en/docs/http/configuring_https_servers.html#chains

要生成链:

cat 123456789.crt gd_bundle-g2-g1.crt > my.domain.com.chained.crt

然后:

ssl_certificate /etc/nginx/ssl/my.domain.com.chained.crt;
ssl_certificate_key /etc/nginx/ssl/my.domain.com.key;

希望对你有帮助!

【讨论】:

【参考方案10】:

就我而言,问题在于我同时使用 Amazon 的 Cloudflare 和 Cloudfront 的 Cloudfront,而 Cloudfront 不喜欢我提供的 Cloudflare 设置。

更具体地说,在 Cloudflare 的 Crypto 设置中,我将“最低 TLS 设置”设置为 1.2,而没有为 Cloudfront 中的分发启用 TLS 1.2 通信设置。这足以让 Cloudfront 在尝试连接到受 Cloudflare 保护的服务器时声明 502 Bad Gateway 错误。

要解决此问题,我必须在该 Cloudfront 分发的源设置中禁用 SSLv3 支持,并启用 TLS 1.2 作为该源服务器支持的协议。

为了调试这个问题,我使用了 curl 的命令行版本,以查看当您从其 CDN 请求图像时 Cloudfront 实际返回的内容,并且我还使用了 openssl 的命令行版本来确定究竟是哪个Cloudflare 提供的协议(它不提供 TLS 1.0)。

tl:博士;确保一切都接受并要求使用 TLS 1.2,或者在您阅读本文时每个人都在使用的任何最新和最棒的 TLS。

【讨论】:

【参考方案11】:

对于我的特殊情况,这是因为我的 CloudFront 行为背后的 Origin ALB 具有指向不同域名的 DEFAULT ACM 证书。

要解决这个问题,我必须:

    转到 ALB 在 Listeners 选项卡下,选择我的 Listener,然后选择 Edit 在默认 SSL 证书下,选择正确的源证书。

【讨论】:

【参考方案12】:

当心Origin Protocol Policy:

对于 CloudFront 转发到此源的 HTTPS 查看器请求,您的源服务器上 SSL 证书中的一个域名必须与您为源域名指定的域名匹配。否则,CloudFront 会使用 HTTP 状态代码 502(错误网关)响应查看器请求,而不是返回请求的对象。

在大多数情况下,您可能希望 CloudFront 使用“仅 HTTP”,因为它也从可能由 Amazon 托管的服务器获取对象。在这一步不需要额外的 HTTPS 复杂性。

请注意,这与Viewer Protocol Policy 不同。你可以阅读更多关于这两个here的区别。

【讨论】:

此解决方案适用于我的情况。是不是更不安全?有什么风险吗?【参考方案13】:

就我而言,我使用 nginx 作为 API 网关 URL 的反向代理。我遇到了同样的错误。

当我在 Nginx 配置中添加以下两行时,我解决了这个问题:

proxy_set_header Host "XXXXXX.execute-api.REGION.amazonaws.com";
proxy_ssl_server_name on;

来源在这里:Setting up proxy_pass on nginx to make API calls to API Gateway

【讨论】:

【参考方案14】:

在我们的案例中,我们放弃了对 SSL3、TLS1.0 和 TLS1.1 的支持,以便在我们的源服务器上实现 PCI-DSS 合规性。但是,您必须在 CloudFront 源服务器配置中手动添加对 TLS 1.1+ 的支持。 AWS 控制台会显示客户端到 CF 的 SSL 设置,但在您向下钻取之前不会轻易地向您显示 CF 到源的设置。要修复,在 CloudFront 下的 AWS 控制台中:

    点击分发。 选择您的发行版。 单击“起源”选项卡。 选择您的源服务器。 点击编辑。 在“Origin SSL Protocols”下选择您的源支持的所有协议

【讨论】:

【参考方案15】:

确保您已正确配置 SSL/TLS/密码设置。如果您的源服务器未与适当的 TLS 密码握手,CloudFront 将断开 HTTPS 连接。

我推荐以下设置:

# Apache
SSLCipherSuite 'ECDHE+AES:@STRENGTH:+AES256'
SSLCipherSuite 'ECDHE+AES:DHE+AES:@STRENGTH:+AES256:kRSA+3DES'
SSLProtocol all -SSLv3 -TLSv1 -TLSv1.1
SSLProtocol all -SSLv3
SSLHonorCipherOrder on

# Nginx
ssl_ciphers 'ECDHE+AES:@STRENGTH:+AES256';
ssl_ciphers 'ECDHE+AES:DHE+AES:@STRENGTH:+AES256:kRSA+3DES';
ssl_protocols all -SSLv3 -TLSv1 -TLSv1.1;
ssl_protocols all -SSLv3;
ssl_prefer_server_ciphers on;

@STRENGTH 指令将按照强度对密码进行排序。

SSLHonorCipherOrder on (apache) 和 ssl_prefer_server_ciphers on (Nginx) 将确保遵守顺序。

您可以通过在 shell 上运行命令来查看您的 openssl 版本支持的可用密码的完整列表:

$ openssl ciphers -v 'ALL'

您还可以以类似的方式按强度顺序列出上述建议指令的可用密码:

$ openssl ciphers -v 'ECDHE+AES:@STRENGTH:+AES256'

如果您遇到此类问题,我强烈建议您增加 Web 服务器日志的详细程度,尤其是与 SSL 有关的日志。

在 Apache 中,您必须在 conf 文件中使用以下指令来执行此操作

LogLevel debug

以下是可能的 Apache LogLevel 指令列表:

emerg (emergencies - system is unusable)
alert (action must be taken immediately)
crit (critical conditions)
error (error conditions)
warn (warning conditions)
notice (normal but significant condition)
info (informational)
debug (debug-level messages)
trace1 (trace messages)
trace2 (trace messages)
trace3 (trace messages)
trace4 (trace messages)
trace5 (trace messages)
trace6 (trace messages)
trace7 (trace messages, dumping large amounts of data)
trace8 (trace messages, dumping large amounts of data)

一般来说,调试足以让您识别协商问题(可能是密码问题,也可能是证书问题)

CloudFront 无法与您的源服务器成功协商 SSL 的典型反应如下所示:

[ssl:info] [pid 25091] [client xxx.xxx.xxx.xxx:15078] AH01964: Connection to child 1 established (server example.com:443)
[ssl:debug] [pid 25091] ssl_engine_kernel.c(2372): [client xxx.xxx.xxx.xx:15078] AH02043: SSL virtual host for servername example.com found
[ssl:debug] [pid 25091] ssl_engine_io.c(1368): (104)Connection reset by peer: [client xxx.xxx.xxx.xxx:15078] AH02007: SSL handshake interrupted by system [Hint: Stop button pressed in browser?!]
[ssl:info] [pid 25091] [client xxx.xxx.xxx.xxx.15078] AH01998: Connection closed to child 1 with abortive shutdown (server example.com:443)

在这种情况下,Apache 通过“提示:在浏览器中按下停止按钮?!”来解释 CloudFront 断开连接。是的,有点滑稽。

另一方面,CloudFront 可能是一个棘手的野兽。如果您在分配中强制使用 HTTPS 或将 HTTP 定向到 HTTPS,则必须确保 CloudFront 和源服务器之间的通信通过具有有效 SSL 证书的有效 SSL 连接运行。这可能意味着通过 Elastic Load Balancer (ELB) 链接 Amazon ACM 来获取证书。

...或者您也可以通过将 ACM 证书链接到您的发行版来获得所需的结果(确保您列出了***域和子域,例如:example.com 和 *.example.com)。这会将 ACM 证书传播到分发中的源/目标,但是,源服务器中的 Apache/Nginx 服务器必须具有有效且有效的 SSL 证书,即使它是由 Letsencrypt/Certbot(我们的其他一些有效的非自签名证书)。确保您在 apache *.conf 设置中配置了完整的链。

您可以阅读有关 502 Bad Gateway 或 502 无法满足请求 from AWS 以及 requiring HTTPS for communication between CloudFront and your custom origin (this may also help) 的更多信息。 This information about ciphers 和 list of supported ciphers on AWS 非常有帮助

其中一些命令也可能有助于调试您的 SSL 情况:

openssl s_client -connect test.example.com:443 -tls1_1

(您可以尝试使用 -tls1_2 、 -tls1_3 或其他协议)

您可能还想尝试使用 http 命令行工具(您可能需要安装它),它会为您提供如下输出:

$ http https://example.com --head

HTTP/1.1 301 Moved Permanently
Connection: keep-alive
Content-Length: 251
Content-Type: text/html; charset=iso-8859-1
Date: Mon, 20 Dec 2021 19:20:15 GMT
Location: https://example.com
Server: Apache
Strict-Transport-Security: max-age=63072000; includeSubdomains; preload
Via: 1.1 xxxxxxxxxxxxxxxxxxxxxxxxxxxxx.cloudfront.net (CloudFront)
X-Amz-Cf-Id: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx==
X-Amz-Cf-Pop: GIG51-C2
X-Cache: Miss from cloudfront
X-Content-Type-Options: nosniff
X-Frame-Options: SAMEORIGIN

祝调试好运,记住:继续深入挖掘,不要放弃,增加日志的详细程度!

【讨论】:

以上是关于Cloudfront 自定义源分发返回 502“错误无法满足请求。”对于某些 URL的主要内容,如果未能解决你的问题,请参考以下文章

CloudFront 到 EC2 源返回 502 错误。我该如何调查?

CloudFront 无法与 ELB 502 错误网关通信

CLOUDFRONT EC2 源错误 CloudFront 试图建立与源的连接 [重复]

Cloudfront 为备用域名返回 502

具有私有 EC2 源的 Cloudfront

如何从自定义源的请求中获取 Cloudfront 子域?