如何在亚马逊弹性豆茎上强制 https 而不会失败健康检查 [重复]

Posted

技术标签:

【中文标题】如何在亚马逊弹性豆茎上强制 https 而不会失败健康检查 [重复]【英文标题】:How to force https on amazon elastic beanstalk without failing the health check [duplicate] 【发布时间】:2011-10-15 01:38:37 【问题描述】:

我已将我的 Elastic Beanstalk 环境配置为将所有页面重定向到 https,重定向工作,但是,实例未通过运行状况检查并被终止,任何想法如何配置重写规则?

我的配置:

NameVirtualHost *:80

<VirtualHost *:80>
.
.
.

RewriteEngine On
RewriteCond %HTTP:X-Forwarded-Proto !https
RewriteRule !/_hostmanager/healthcheck https://%SERVER_NAME%REQUEST_URI [L,R] 
</VirtualHost>

【问题讨论】:

互联网似乎无法就这个问题的单一、完整和有效的解决方案达成一致。希望你能得到一些帮助here in my post。最后,我不得不费尽心思才想出这个。 【参考方案1】:

除了运行状况检查之外,Elastic Beanstalk 还需要访问多个 hostmananger URL。 Grepping /var/log/httpd/elasticbeanstalk-access_log,我看到对 /_hostmanager/tasks/_hostmanager/healthcheck 的请求。

以下是我在 EC2 实例上添加到 /etc/httpd/sites/elasticbeanstalk 的规则:

RewriteEngine On
RewriteCond %HTTP:X-Forwarded-Proto !https
RewriteCond %REQUEST_URI !^/status$ 
RewriteCond %REQUEST_URI !^/version$ 
RewriteCond %REQUEST_URI !^/_hostmanager/ 
RewriteRule . https://%SERVER_NAME%REQUEST_URI [L,R]

请注意,我还允许非 https 流量访问我的 /status/version 页面。我实际上使用/status 作为实际的健康检查查找 URL,因此让该流量跳过重写将避免重定向并使状态查找更快(我假设)。

【讨论】:

这仍然会导致我的运行状况检查失败。【参考方案2】:

我认为这里的其他一些答案可能不是基于任意User-Agent AWS 当前设置的。当我查看 Apache 日志时,我看到了这个用户代理:

ELB-HealthChecker/1.0

在撰写本文时,以下mod_rewrite 规则对我有效:

RewriteEngine On
RewriteCond %HTTP:X-Forwarded-Proto !https
RewriteCond %HTTP_USER_AGENT !^ELB-HealthChecker.* 
RewriteRule . https://%SERVER_NAME%REQUEST_URI [L,R]

【讨论】:

【参考方案3】:

截至 2016 年,这些答案都不适合我,但这有效:

1 检索/etc/httpd/conf.d/wsgi.conf

2 将以下内容添加到虚拟主机:(请注意,第三行可防止设置脚本 /opt/elasticbeanstalk/hooks/config.py 等待 5 分钟无法加载路径 / 的问题。)

RewriteEngine On
RewriteCond %HTTP:X-Forwarded-Proto !https
RewriteCond %HTTP_HOST !localhost
RewriteCond %HTTP_USER_AGENT !^ELB-HealthChecker.* 
RewriteRule . https://%SERVER_NAME%REQUEST_URI [L,R=301]

3 将文件放入您的存储库,并添加以下容器命令:

06_https:
  command: "cp wsgi.conf /opt/python/ondeck/wsgi.conf"

安装脚本会自动将该文件复制到/etc/httpd/conf.d

【讨论】:

【参考方案4】:

AWS Health Checker 似乎使用了用户代理“AWSHealthCheck”。

如果请求来自健康检查器用户代理,我通过避免重定向来解决这个问题。

类似:

RewriteEngine On
RewriteCond %HTTP:X-Forwarded-Proto !https
RewriteCond %USER_AGENT !^AWSHealthCheck$ 
RewriteRule . https://%SERVER_NAME%REQUEST_URI [L,R]

【讨论】:

这很接近,但似乎并不适合我。健康检查仍然失败。 %USER_AGENT 似乎不是有效的 mod_rewrite 变量。根据httpd.apache.org/docs/2.2/mod/mod_rewrite.html 的文档,正确的变量是HTTP_USER_AGENT【参考方案5】:

您可以将 ELB 配置为使用特定路径进行健康检查,例如 /ping。然后,您可以明确告诉 apache 不要重定向该 URL,而不是依赖 UserAgent 字符串。

您还可以告诉 ELB 使用 HTTPS 进行健康检查,然后将所有 HTTP URL 重定向到 HTTPS,包括健康检查。

这两项设置都可以在 EC2 控制台的负载均衡器部分进行更改。

【讨论】:

【参考方案6】:

如果您尝试在 Wordpress 或 php 中执行此操作,您可以按如下方式设置您的 .htaccess,而无需通过 .ebextensions 进行任何修改:

<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %HTTP:X-Forwarded-Proto !https
RewriteCond %REQUEST_URI !^/status\.html$
RewriteCond %REQUEST_URI !^/_hostmanager/
RewriteRule ^.*$ https://%SERVER_NAME%REQUEST_URI [R=301,L]
</IfModule>

# BEGIN WordPress
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteRule ^index\.php$ - [L]
RewriteCond %REQUEST_FILENAME !-f
RewriteCond %REQUEST_FILENAME !-d
RewriteRule . /index.php [L]
</IfModule>
# END WordPress

记得将 status.html 更改为您用于执行 Elastic Beanstalk 运行状况检查的任何路径

欲了解更多信息,请参阅我的回复here。

【讨论】:

这非常适合我的 Wordpress/Woocommerce Docker 部署。【参考方案7】:

此答案假设您已经在负载均衡器安全组中启用了 https,将 SSL 证书添加到负载均衡器,将 443 添加到负载均衡器转发的端口,并使用 Route 将您的域名指向 Elastic Beanstalk 环境53(或等效的 DNS 服务)。

您只需将以下内容添加到您的.config files in the .ebextensions directory of your project 之一:

files:
  "/etc/httpd/conf.d/ssl_rewrite.conf":
    mode: "000644"
    owner: root
    group: root
    content: |
      RewriteEngine On
      <If "-n '%HTTP:X-Forwarded-Proto' && %HTTP:X-Forwarded-Proto != 'https'">
      RewriteRule (.*) https://%HTTP_HOST%REQUEST_URI [R,L]
      </If>

说明

这在 Elastic Beanstalk 之外是相当直接的。通常会添加一个 Apache 重写规则,如下所示:

RewriteCond %HTTPS off
RewriteRule (.*) https://%HTTP_HOST%REQUEST_URI

或者,如果在负载均衡器后面,就像我们在这种情况下一样:

RewriteCond %HTTP:X-Forwarded-Proto !https
RewriteRule (.*) https://%HTTP_HOST%REQUEST_URI [R,L]

但是,这些配置仅适用于 &lt;VirtualHost&gt; 块。将RewriteCond 更改为&lt;If&gt; 块允许它在&lt;VirtualHost&gt; 块之外正常工作,允许我们放入独立的Apache 配置文件。请注意,CentOS 上的标准 Apache 设置(包括 ElasticBeanstalk 上的设置)包含与 /etc/httpd/conf.d/*.conf 匹配的所有文件,这与我们存储此文件的文件路径匹配。

条件的-n '%HTTP:X-Forwarded-Proto' 部分会阻止它在您不在负载均衡器之后进行重定向,从而允许您在具有负载均衡器和 https 的生产环境与单实例和暂存环境之间共享配置没有https。如果您在所有环境中都使用负载平衡器和 https,则这不是必需的,但拥有它并没有什么坏处。

我见过的糟糕解决方案

我已经看到了很多关于这个问题的糟糕解决方案,值得通过它们来理解为什么这个解决方案是必要的。

    使用 Cloudfront: 有人建议在 Elastic Beanstalk 前面使用非缓存 Cloudfront 设置来执行 HTTP 到 HTTPS 的重定向。这增加了一个不完全合适的全新服务(从而增加了复杂性)(Cloudfront 是一个 CDN;它不是在固有动态内容上强制使用 HTTPS 的正确工具)。 Apache config 是这个问题的常规解决方案,而 Elastic Beanstalk 使用 Apache,所以我们应该这样做。

    SSH 进入服务器并...: 这与 Elastic Beanstalk 的观点完全相反,并且存在很多问题。通过自动缩放创建的任何新实例都不会具有修改后的配置。任何克隆的环境都没有配置。任何数量的合理环境更改都将清除配置。这真是个坏主意。

    用新文件覆盖 Apache 配置: 这进入了正确的解决方案领域,但如果 Elastic Beanstalk 更改服务器设置的各个方面(他们很可能做)。另请参阅下一项中的问题。

    动态编辑 Apache 配置文件以添加几行: 这是一个不错的想法。这样做的问题是,如果 Elastic Beanstalk 更改其默认 Apache 配置文件的名称,它将无法正常工作,并且此文件可能会在您最意想不到的时候被覆盖:https://forums.aws.amazon.com/thread.jspa?threadID=163369

【讨论】:

【参考方案8】:

创建一个静态 health.html。如果可能,作为配置模板。

【讨论】:

【参考方案9】:

这是一个简单的解决方案

    SSH 到您的 EC2 实例 将 /etc/httpd/conf.d/wsgi.conf 的内容复制到名为 wsgi.conf 的本地文件中,该文件将放置在应用程序的基本文件夹中

    编辑 wsgi.conf 的本地版本并在 标签中添加以下重定向规则

    RewriteEngine On
    RewriteCond %HTTP:X-Forwarded-Proto !https
    RewriteRule !/status https://%SERVER_NAME%REQUEST_URI [L,R=301]
    

    “/status”更改为您用作健康检查页面的任何页面。

    保存文件

    在您的 .ebextensions 目录中编辑您的 .conf 文件,以添加一个容器命令,将这个版本的 wsgi.conf 复制到亚马逊的版本上

    container_commands:
    01_syncdb:
      command: "django-admin.py syncdb --noinput" leader_only: true
    02_collectstatic:
      command: "django-admin.py collectstatic --noinput"
    03_wsgireplace:
      command: 'cp wsgi.conf ../wsgi.conf'
    ...
    

    部署代码。

    /etc/httd/conf.d/wsgi.conf 中部署的 wsg.conf 版本现在将包含必要的重定向规则。

它应该可以工作,并且每次部署都会正确更新文件。唯一需要注意的是,如果 Amazon 将来更改其基本 wsgi.conf 文件内容,那么您的副本可能不再有效。

作者rickchristianson

【讨论】:

【参考方案10】:

对我来说,将wsgi.conf 复制到适当的位置从未奏效。 EB 将无法部署,或者文件将被覆盖。

我发现唯一有效的答案是here。本质上,他使用sed 将必要的重写规则插入到wsgi.conf 中。他说要添加的容器命令是

container_commands:
  01_http_to_https_redirect:
    command: 
      sed -i '/\<VirtualHost \*:80\>/a RewriteEngine On\nRewriteCond %HTTP:X-Forwarded-Proto !https\nRewriteRule \!/robots.txt https://%SERVER_NAME%REQUEST_URI [L,R=301]' /opt/python/ondeck/wsgi.conf

不要忘记将您的健康检查端点从 robots.txt 更改。

【讨论】:

【参考方案11】:

作为一个通用策略,对于我们来说,Apache 和 nginx EC2 实例都位于 AWS 安全负载均衡器之后:

    在负载均衡器上,将端口 80 转发到实例上的端口 80 在实例上将端口 443 转发到端口 8080(例如) 在 Web 服务器中,监听两个端口(80 和 8080) 将端口 80 重定向到端口 443 将环境变量“HTTPS”,值为“on”添加到 EC2,例如使用 Elastic Beanstalk 软件配置

第 1 步确保 AWS 内部流量得到“自然”处理。

第 2 步只允许安全的外部流量到达我们的代码

第 5 步告诉 Web 服务器和它背后的东西(在我们的例子中是 Laravel)生成的 URL 应该被赋予 https: 方案。其他框架可能需要设置其他一些环境变量才能触发该行为。

【讨论】:

以上是关于如何在亚马逊弹性豆茎上强制 https 而不会失败健康检查 [重复]的主要内容,如果未能解决你的问题,请参考以下文章

如何在亚马逊弹性豆茎上强制 https 而不会失败健康检查 [重复]

如何在亚马逊弹性豆茎上强制 https 而不会失败健康检查 [重复]

如何在亚马逊弹性豆茎上强制 https 而不会失败健康检查 [重复]

如何在弹性豆茎上强制 https?

在弹性豆茎上设置 https 代理

如何在弹性豆茎上安装 ng