【问题标题】:How to get Elastic Beanstalk nginx-backed proxy server to auto-redirect from HTTP to HTTPS?如何让 Elastic Beanstalk 支持 nginx 的代理服务器从 HTTP 自动重定向到 HTTPS?
【发布时间】:2014-08-09 10:43:40
【问题描述】:

我有一个基于 Node.js 的网站,我在 Amazon Elastic Beanstalk 上运行。

我的 Node.js 应用程序在端口 8080 上侦听,我将 nginx 弹性负载平衡器配置与我的 EB 应用程序一起使用,在端口 80 和 443 上侦听 HTTP 和 HTTPS。

但是,我只想在我的应用中接受来自 HTTPS 的流量。

我可以在应用程序中安装一些东西来处理这个问题,但我对让负载均衡器通过 HTTPS 将所有 HTTP 请求重定向到我的站点的方法感兴趣。

【问题讨论】:

    标签: amazon-web-services nginx amazon-ec2 amazon-elastic-beanstalk


    【解决方案1】:

    在亚马逊有偿支持的想法几次错误开始之后,他们最终还是成功了。实现此功能的方法是配置环境以响应端口 80 和 443。然后在 Node.js 主应用程序文件夹中创建一个名为 .ebextensions 的文件夹,并在其中放置一个名为 00_nginx_https_rw.config 的文件,以这段文字为内容:

    files:
      "/tmp/45_nginx_https_rw.sh":
        owner: root
        group: root
        mode: "000644"
        content: |
          #! /bin/bash
    
          CONFIGURED=`grep -c "return 301 https" /etc/nginx/conf.d/00_elastic_beanstalk_proxy.conf`
    
          if [ $CONFIGURED = 0 ]
            then
              sed -i '/listen 8080;/a \    if ($http_x_forwarded_proto = "http") { return 301 https://$host$request_uri; }\n' /etc/nginx/conf.d/00_elastic_beanstalk_proxy.conf
              logger -t nginx_rw "https rewrite rules added"
              exit 0
            else
              logger -t nginx_rw "https rewrite rules already set"
              exit 0
          fi
    
    container_commands:
      00_appdeploy_rewrite_hook:
        command: cp -v /tmp/45_nginx_https_rw.sh /opt/elasticbeanstalk/hooks/appdeploy/enact
      01_configdeploy_rewrite_hook:
        command: cp -v /tmp/45_nginx_https_rw.sh /opt/elasticbeanstalk/hooks/configdeploy/enact
      02_rewrite_hook_perms:
        command: chmod 755 /opt/elasticbeanstalk/hooks/appdeploy/enact/45_nginx_https_rw.sh /opt/elasticbeanstalk/hooks/configdeploy/enact/45_nginx_https_rw.sh
      03_rewrite_hook_ownership:
        command: chown root:users /opt/elasticbeanstalk/hooks/appdeploy/enact/45_nginx_https_rw.sh /opt/elasticbeanstalk/hooks/configdeploy/enact/45_nginx_https_rw.sh
    

    亚马逊的支持团队解释说:这个配置创建了一个部署钩子,它将重写规则添加到 /etc/nginx/conf.d/00_elastic_beanstalk_proxy.conf。

    (以前他们为我提供了将单独文件复制到 /etc/nginx/conf.d 的 .config 文件,但这些文件要么没有效果,要么更糟,似乎覆盖或优先于默认的 nginx 配置,出于某种原因.)

    如果您想撤消此操作,即移除挂钩,则需要移除此 ebextension 并发出命令以移除它创建的文件。您可以手动执行此操作,也可以通过临时放置的 ebextensions 命令执行此操作:

    /opt/elasticbeanstalk/hooks/appdeploy/enact/45_nginx_https_rw.sh
    /opt/elasticbeanstalk/hooks/configdeploy/enact/45_nginx_https_rw.sh
    

    我还没有尝试过,但大概这样的东西可以删除它们并撤消此更改:

    container_commands:
      00_undochange:
        command: rm /opt/elasticbeanstalk/hooks/appdeploy/enact/45_nginx_https_rw.sh
      01_undochange:
        command: rm /opt/elasticbeanstalk/hooks/configdeploy/enact/45_nginx_https_rw.sh
    

    希望这可以在将来对其他人有所帮助。

    【讨论】:

    • AWS 客户支持的后续跟进提示我编辑上述配置。最初,如果请求来自 ELB-HealthChecker,则配置设置为响应 200 OK。这对于开发环境来说可能没问题,但对于生产环境,这些请求应该传递到您的应用程序,以便正确 ping 通。这现在反映在上面的配置中。
    • 我爱你?我想我会的。对这些命令和 ebextensions 的使用没有指导,也很少参考。很高兴你遇到了同样的问题:)
    • 这个解决方案对我有用。配置您的环境以响应 80 和 443 端口,并在创建 Mason G. Zhwiti 建议的文件之后。
    • 使用 Docker,2017 年 6 月。通用解决方案对我有用,但需要进行一些小的调整。我猜是因为 ebextensions 会弄乱那些不是真正稳定的公共 API 的东西。需要进行两项更改:listen 8080; 变为 listen 80;/etc/nginx/conf.d/00_elastic_beanstalk_proxy.conf 变为 /etc/nginx/sites-available/elasticbeanstalk-nginx-docker-proxy.conf
    • 经过数小时的搜索,这是正确的答案。终于有http重定向到https。感谢亚马逊!似乎是一个非常常见的用例。为什么负载均衡器设置中没有“将 http 转发到 https”复选框???
    【解决方案2】:

    接受的答案不再对我有用。默认端口是不同的。配置文件的位置也发生了变化。我正在使用 Puma 设置一个 Ruby On Rails 应用程序。

    我与付费支持人员进行了交谈,我们只是通过在正在运行的实例上手动运行命令来解决这个问题。然后我能够找出以下解决方案。只需登录并重新启动 nginx 即可。

    files:
      "/tmp/45_nginx_https_rw.sh":
        owner: root
        group: root
        mode: "000644"
        content: |
          #! /bin/bash
    
          CONFIGURED=`grep -c "return 301 https" /opt/elasticbeanstalk/support/conf/webapp_healthd.conf`
    
          if [ $CONFIGURED = 0 ]
            then
              sed -i '/listen 80;/a \    if ($http_x_forwarded_proto = "http") { return 301 https://$host$request_uri; }\n' /opt/elasticbeanstalk/support/conf/webapp_healthd.conf
              logger -t nginx_rw "https rewrite rules added"
              exit 0
            else
              logger -t nginx_rw "https rewrite rules already set"
              exit 0
          fi
    
    container_commands:
      00_appdeploy_rewrite_hook:
        command: cp -v /tmp/45_nginx_https_rw.sh /opt/elasticbeanstalk/hooks/appdeploy/enact
      01_configdeploy_rewrite_hook:
        command: cp -v /tmp/45_nginx_https_rw.sh /opt/elasticbeanstalk/hooks/configdeploy/enact
      02_rewrite_hook_perms:
        command: chmod 755 /opt/elasticbeanstalk/hooks/appdeploy/enact/45_nginx_https_rw.sh /opt/elasticbeanstalk/hooks/configdeploy/enact/45_nginx_https_rw.sh
      03_rewrite_hook_ownership:
        command: chown root:users /opt/elasticbeanstalk/hooks/appdeploy/enact/45_nginx_https_rw.sh /opt/elasticbeanstalk/hooks/configdeploy/enact/45_nginx_https_rw.sh
    

    请注意我如何更改端口号和配置文件的位置。

    【讨论】:

    • 对于那些想知道的人来说,这个配置和接受的答案之间的差异是 sed 在它看到“listen 8080”之后附加到/etc/nginx/conf.d/00_elastic_beanstalk_proxy.conf 的行现在在它看到“之后附加到/opt/elasticbeanstalk/support/conf/webapp_healthd.conf”听 80"。 CONFIGURED=grep -c 行上的文件名也有相同的变化。我还不确定为什么这对你和我都有效,但还不确定这是否需要成为公认的答案,或者可能是不同环境的替代答案?
    • 好评论 - 我不知道。支持人员说配置的位置可能已经改变。我也在使用负载平衡版本。
    • 我实现了这个解决方案。有效。我的 http 请求将成功转发到 https。第二天,我试了一下,它又回到了不转发。对此有何想法?
    • 确认这在 2016 年 12 月 9 日在 Ruby on Rails + Puma 2.3 中对我有用。注意到最初的问题与节点和端口 8080 相关 - 而不是端口 80 上的 ruby​​ - 但谢谢!进行此更改后重新启动 nginx 很重要,所以我有一个额外的配置文件:``` container_commands: 01_reload_nginx: command: "service nginx reload" ```
    • @j10io 我认为除了额外的配置文件来重新启动 nginx,您还可以在 elasticbeanstalk Web 控制台中单击“Restart App Server(s)”。
    【解决方案3】:

    您可以通过 Node.js 应用程序处理重定向。

    当客户端连接不安全时,Amazon 会发送等于 httpX-Forwarded-Proto 标头。

    以下中间件应在初始化Express 之后并在定义路由以自动将客户端重定向到相应的 HTTPS 端点之前插入:

    // Redirect to HTTPS
    app.use(function (req, res, next) {
        // Insecure request?
        if (req.get('x-forwarded-proto') == 'http') {
            // Redirect to https://
            return res.redirect('https://' + req.get('host') + req.url);
        }
    
        next();
    });
    

    【讨论】:

    • 在 node.js 层执行此操作的权衡是值得为您的应用程序层提供额外的 CPU 工作和更慢的重定向时间。
    • @tom 感谢您的意见!
    • 对我们不起作用,因为我们有一个没有 ELB 的 EB 实例 - Nginx 未配置为设置 x-forwarded-proto
    • @liridayn 如果您的实例不在 ELB 之后,那么您可以通过检查 req.secure 来检查 req 对象上的协议:stackoverflow.com/a/16405622/1123355
    【解决方案4】:

    我能够通过一个稍微简单的解决方案来解决这个问题。

    请注意,这是一个弹性 beanstalk 部署的 SINGLE 实例,没有负载平衡。

    这是我添加的 ebextension。

    files:
      "/etc/nginx/conf.d/000_my_config.conf":
        mode: "000755"
        owner: root
        owner: root
        content: |
          server {
              listen 8080;
              return 301 https://$host$request_uri;
          }
    

    【讨论】:

    • 为什么端口是 8080 而不是 80?
    • 我希望我知道...这需要大量调试。我的猜测是 Elastic Beanstalk 实际上使用端口 8080 而不是 80。
    • 你的环境是负载均衡的还是单实例的?
    • 单个实例,编辑答案以包含该事实。
    • @WindUpToy 您需要检查接受的答案中指定的$http_x_forwarded_proto 参数。 ELB 将所有请求转发到端口 80 上的实例,然后将其视为 HTTP。 AWS 添加了 $http_x_forwarded_proto 值和 X-Forwarded-Proto 标头来进行此项检查。
    【解决方案5】:

    我在 AWS Elastic Beanstalk 上运行“Ruby2 Puma”环境,该环境的配置可能与上述略有不同。 在我的环境中,我需要使用“listen 80”而不是“listen 8080”。

    sslredirect.config 基于elloworld111's answer:

    files:
      "/etc/nginx/conf.d/000_my_config.conf":
        mode: "000755"
        owner: root
        owner: root
        content: |
          server {
              listen 80;
              return 301 https://$host$request_uri;
          }
    

    【讨论】:

      【解决方案6】:

      我正在使用 Elastic Beanstalk 和 Docker,因此我采取了稍微不同的方式来让事情运行起来,但非常受接受的答案的启发。此脚本将所需的配置注入 /etc/nginx/sites-available/elasticbeanstalk-nginx-docker-proxy.conf。 (如果有人有更优雅的解决方案希望看到它)

      此脚本还使 Beanstalk 健康检查能够访问我的健康检查端点(在我的情况下是 api/healthcheck)更好地允许 LoadBalancer 访问应用程序,而不是在 Nginx 处终止。

      files:
        "/tmp/45_nginx_https_rw.sh":
          owner: root
          group: root
          mode: "000755"
          content: |
            #! /bin/bash
      
            CONFIGURED=`grep -c "return 301 https" /etc/nginx/sites-available/elasticbeanstalk-nginx-docker-proxy.conf`
      
            if [ $CONFIGURED = 0 ]
              then
                sed -i "/access.log;/a \ \ \ \ \ \ \ \ location /api/health-check { proxy_pass http://docker; }" /etc/nginx/sites-available/elasticbeanstalk-nginx-docker-proxy.conf
                sed -i "/proxy_add_x_forwarded_for;/a \ \ \ \ \ \ \ \ \ \ \ \ if (\$http_x_forwarded_proto != 'https') { return 301 https://\$host\$request_uri; }" /etc/nginx/sites-available/elasticbeanstalk-nginx-docker-proxy.conf
                logger -t nginx_rw "https rewrite rules added"
                exit 0
              else
                logger -t nginx_rw "https rewrite rules already set"
                exit 0
            fi
      
      container_commands:
        00_run_script:
          command: /tmp/45_nginx_https_rw.sh
      

      【讨论】:

        【解决方案7】:

        我能够让它以不同的方式工作。我更改了负载均衡器以将端口 80 流量转发到端口 8082,并更改了防火墙规则(实例上的入站,防火墙上的出站)以允许这样做。然后在 .ebextensions 中添加这个文件:

        files:
          "/etc/nginx/conf.d/50-atd-hotel-http-redirect.conf":
            mode: "000644"
            owner: root
            group: root
            content: |
              server {
                listen   8082;
        
                return 301 --WHATEVER DESTINATION YOU WANT--;
              }
        

        【讨论】:

          【解决方案8】:

          接受的答案对我不起作用。经过多次尝试(以及数小时的谷歌搜索),我找到了一些对我有用的东西。我也有一个基于 Node.js 的站点,我在 Elastic Beanstalk 上运行。

          我使用了这里的脚本:https://adamjstevenson.com/tutorials/2017/02/02/configuring-and-forcing-https-for-aws-elastic-beanstalk.html

          我做的唯一修改是关闭了

          /opt/elasticbeanstalk/support/conf/webapp_healthd.conf
          

          通过

          /etc/nginx/sites-available/elasticbeanstalk-nginx-docker-proxy.conf
          

          所以它给出了这个:

          files:
            "/tmp/45_nginx_https_rw.sh":
              owner: root
              group: root
              mode: "000644"
              content: |
                #! /bin/bash
          
                CONFIGURED=`grep -c "return 301 https" /etc/nginx/sites-available/elasticbeanstalk-nginx-docker-proxy.conf`
          
                if [ $CONFIGURED = 0 ]
                  then
                    sed -i '/listen 80;/a \    if ($http_x_forwarded_proto = "http") { return 301 https://$host$request_uri; }\n' /etc/nginx/sites-available/elasticbeanstalk-nginx-docker-proxy.conf
                    logger -t nginx_rw "https rewrite rules added"
                    exit 0
                  else
                    logger -t nginx_rw "https rewrite rules already set"
                    exit 0
                fi
          
          container_commands:
            00_appdeploy_rewrite_hook:
              command: cp -v /tmp/45_nginx_https_rw.sh /opt/elasticbeanstalk/hooks/appdeploy/enact
            01_configdeploy_rewrite_hook:
              command: cp -v /tmp/45_nginx_https_rw.sh /opt/elasticbeanstalk/hooks/configdeploy/enact
            02_rewrite_hook_perms:
              command: chmod 755 /opt/elasticbeanstalk/hooks/appdeploy/enact/45_nginx_https_rw.sh /opt/elasticbeanstalk/hooks/configdeploy/enact/45_nginx_https_rw.sh
            03_rewrite_hook_ownership:
              command: chown root:users /opt/elasticbeanstalk/hooks/appdeploy/enact/45_nginx_https_rw.sh /opt/elasticbeanstalk/hooks/configdeploy/enact/45_nginx_https_rw.sh
          

          eb deploy 之后,只需重启你的 nginx sudo service nginx restart 就可以了。

          【讨论】:

            猜你喜欢
            • 2018-01-07
            • 2016-06-19
            • 2018-01-01
            • 2017-02-04
            • 2019-01-24
            • 2015-07-09
            • 2021-02-23
            • 2018-09-30
            • 2013-12-08
            相关资源
            最近更新 更多