将EC2弹性负载均衡器从HTTP重定向到HTTPS

123

我希望将所有的HTTP请求重定向到ELB上的HTTPS请求。我有两个EC2实例,使用nginx作为服务器。我已经尝试在没有成功的情况下重新编写nginx配置文件。我希望得到一些关于此问题的建议。


1
似乎互联网上无法就这个问题达成单一、完整且可行的解决方案。希望您能在我的帖子中得到一些帮助。我必须经历重重困难才最终想出了这个方案。 - ADTC
1
这个答案有最新的解决方案,而不是被接受的答案。 - AsifM
12个回答

126

AWS应用程序负载均衡器现在支持本地HTTP到HTTPS重定向。

要在控制台中启用此功能,请执行以下操作:

  1. 进入您的EC2负载均衡器并选中“侦听器”选项卡
  2. 在HTTP侦听器上选择“查看/编辑规则”
  3. 删除除默认规则(最后一个)以外的所有规则
  4. 编辑默认规则:将“重定向到”选择为动作,将所有内容保留为默认设置,并输入端口“443”。

Native redirect listener rule

也可以使用CLI实现相同功能,具体说明请参见此处

在Cloudformation中也可以完成此操作,需要设置类似于以下内容的Listener对象:

  HttpListener:
    Type: AWS::ElasticLoadBalancingV2::Listener
    Properties:
      LoadBalancerArn: !Ref LoadBalancer
      Port: 80
      Protocol: HTTP
      DefaultActions:
      - Type: redirect 
        RedirectConfig:
          Protocol: HTTPS
          StatusCode: HTTP_301
          Port: 443

如果您仍在使用经典负载均衡器,请选择其他人描述的NGINX配置之一。


1
现在知道这一点非常有用。但是,如果提供更多关于配置什么的信息而不仅仅是一个链接,那将是更好的答案。 - John Rees
1
@JohnRees相应地编辑了答案,希望这有所帮助。 - Ulli
3
你似乎在使用经典负载均衡器。切换到应用程序负载均衡器以获取该选项。 - Ulli
如何将应用负载均衡器分配给我的实例?(因为没有instances选项卡) - Florian Ludewig
只想补充一点,如果您已经有了一个 Https 的监听器,请不要删除它。相反,添加一个 Http 监听器,并使用单个规则将其重定向到 Https。 - Wiz
显示剩余4条评论

110

ELB设置X-Forwarded-Proto头,您可以使用它来检测原始请求是否为HTTP并重定向到HTTPS。

您可以在server配置中尝试此操作:

if ($http_x_forwarded_proto = 'http') {
    return 301 https://yourdomain.com$request_uri;
}

请查看ELB文档


3
这个配置应该在哪里进行? - ericpeters0n
2
@ericpeters0n 答案中的代码片段是针对 nginx 配置的,但原则适用于任何 Web 服务器。 - Dmitry Mukhin
1
如果您正在使用beanstalk和passenger-standalone,请参考此链接以了解如何更改nginx配置。http://qiita.com/tak_nishida/items/cf30a2d373744943b943 - Yeonho
3
请确保负载均衡器上同时具有HTTP和HTTPS监听器。 - Gavin Palmer
1
@Ronald,通过响应中的服务器配置,我指的是运行在 ELB 后面的 EC2 实例上的 Nginx 服务器。 - Dmitry Mukhin
显示剩余12条评论

37

我有同样的问题,在我的情况下,HTTPS是完全由ELB处理的,而且我事先不知道我的源域,所以最终我做了这样的操作:

server {
  listen 81;
  return 301 https://$host$request_uri;
}

server {
  listen 80;
  # regular server rules ...
}

当然,接下来需要将 ELB 的 'https' 指向实例端口 80,将 'http' 路由指向实例端口 81。


5
这太聪明了。 - Andy Hayden
2
@CodyBugstein 这是nginx配置,如果你有一个的话。 - timurso
@timurso 如果你有一个什么? - CodyBugstein
如果你的应用程序前面有nginx(例如,我没有 - 它直接路由到运行ExpressJS的容器),@CodyBugstein - timurso
nginx应该放在哪里?放在ELB内还是EC2内?这个配置是在Elastic Beanstalk中进行的吗? - CodyBugstein
所以在我的原始情况下,这是一个在EC2上运行的nginx服务器。ELB只是指向一组EC2实例。 - TylerFowler

16
亚马逊弹性负载均衡器(ELB)支持一个名为X-FORWARDED-PROTO的HTTP头。通过ELB传输的所有HTTPS请求都将具有X-FORWARDED-PROTO的值等于“HTTPS”。对于HTTP请求,您可以通过添加以下简单的重写规则来强制使用HTTPS。对我来说,这很有效!在您的.htaccess文件中添加以下行:(译者注:此处省略了具体的代码内容)
RewriteEngine On
RewriteCond %{HTTP:X-Forwarded-Proto} !https
RewriteRule ^.*$ https://%{SERVER_NAME}%{REQUEST_URI}

如果您在同一EC2 Web服务器上管理多个域名时使用vhost.conf,则可以将以下内容添加到vhost.conf中(将其添加到要使用https的域中):

<VirtualHost *:80>
...
RewriteEngine On
RewriteCond %{HTTP:X-Forwarded-Proto} !https
RewriteRule ^.*$ https://%{SERVER_NAME}%{REQUEST_URI}
...
</VirtualHost>

IIS

安装 IIS Url-Rewrite 模块,使用配置界面添加以下设置:

<rewrite xdt:Transform="Insert">
<rules>
<rule name="HTTPS rewrite behind ELB rule" stopProcessing="true">
<match url="^(.*)$" ignoreCase="false" />
<conditions>
<add input="{HTTP_X_FORWARDED_PROTO}" pattern="^http$" ignoreCase="false" />
</conditions>
<action type="Redirect" redirectType="Found" url="https://{SERVER_NAME}{URL}" />
</rule>
</rules>
</rewrite>

这里阅读更多。


我们遇到了一个问题,即实例重定向正常的http流量,因为头部甚至不存在。我通过设置条件来解决它: RewriteCond %{HTTP:X-Forwarded-Proto} !(https|^$) - natronite
这会导致无限重定向。我正在使用带有Windows服务器的IIS。 - It's a trap
@It'satrap:对于IIS,如果它没有起作用,那么请尝试在此URL中使用脚本:http://stephen.genoprime.com/2012/01/01/aws-elb-ssl-with-iis.html - Iman Sedighi

5

以上的.htaccess解决方案导致了ELB健康检查失败。我曾经遇到了一些麻烦,直到我在网上发现了一篇文章,其中有人遇到了和我一样的问题。他的解决方案是在.htaccess文件的开头添加以下内容:

RewriteEngine on 
RewriteCond %{HTTP:X-Forwarded-Proto} ^http$
RewriteRule .* https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]

为了允许本地和其他HTTP请求,同时通过ELB将外部请求重定向到HTTPS,在rewrite条件中调整匹配http而不是在https上进行负面匹配。
来源:AWS和ELB的HTTP重定向到HTTPS

将重写条件调整为匹配http而不是在https上进行负匹配,这就是我试图修复的部分。谢谢! - Merricat

4

基于 @Ulli 的回答,如果您想使用Terraform进行配置,这里提供一个示例>

resource "aws_alb_listener" "web" {
  load_balancer_arn = "${aws_alb.web.arn}"

  port              = "80"
  protocol          = "HTTP"

  default_action {
    type = "redirect"

    redirect {
      port        = "443"
      protocol    = "HTTPS"
      status_code = "HTTP_301"
    }
  }
}

Source


4

也许这不是你想要的解决方案,但另一种选择是在使用ELB的同时使用AWS CloudFront。CloudFront允许将所有传入的HTTP流量重定向到HTTPS。



3
我在Nginx和ELB配置中遇到了奇怪的问题。我的设置包括一个Nginx内三个不同的服务,放置在ELB后面。我遇到了混合内容问题:当您使用https向ELB发出请求,但在ELB内部仅使用http时,服务器会使用http创建静态资源的相对路径,因此浏览器会出现“混合内容”问题。 我必须创建解决方案,使http和https都能正常工作,而无需任何重定向。
以下是位于nginx/conf.d/文件夹中的配置:
# Required for http/https switching
map $http_x_forwarded_port $switch {
  default   off;
  "80"    off;
  "443"   on;
}

这意味着我们将了解真实客户端协议的知识。正如您所见,我们将在$switch变量中拥有它。 并且此时您可以在需要的所有位置使用它:
location ~ /softwareapi/index.php {
  fastcgi_param HTTPS $switch;
  .. other settings here ..
}

通过设置HTTPS,PHP应用程序将自动检测正确的协议,并谨慎构建相对路径,以防止混合内容问题。

此致敬礼。


3

我刚刚通过以下命令在EC2实例终端中进行了重定向测试:

curl -Iv [your url]

例如:curl -Iv http://example.com

要求

  1. AWS Route 53中设置DNS和名称服务器的托管区域

  2. 使用AWS证书管理器获取证书

  3. 在负载均衡器上添加侦听器,用于端口443选择2.中的证书和SSL

    • Elastic Beanstalk --> 点击环境 --> 配置 --> 查找负载均衡器,然后单击编辑 --> 添加侦听器;使用2016-08的SSL策略(其他可能会出现错误)

我所做的是:

  1. 重定向 http://yourwebsite.com --> https://www.yourwebsite.com (步骤 2)
  2. 重定向 http://www.yourwebsite.com --> https://www.yourwebsite.com (步骤 2)
  3. 重定向 https://yourwebsite.com --> https://www.yourwebsite.com (步骤 3)

步骤

1. 进入 EC2 负载均衡器

2. 进入监听器 ID HTTP:80(在规则列下面点击查看/编辑规则)

编辑默认操作:(在顶部点击铅笔图标,使用“切换到完整 URL”,直到输入 #{port} 才会变灰)

  1. THEN块更改为重定向到https://#{host}:443/#{path}?#{query}
  2. 状态码:HTTP_301

添加一个操作(点击顶部的加号符号)

  1. 选择IF块, 主机头是yourwebsite.com
  2. THEN块更改为重定向到https://www.#{host}:443/#{path}?#{query}
  3. 状态码:HTTP_301

enter image description here

3. 返回并进入侦听器ID HTTPS: 443(单击“查看/编辑规则”)

添加一个动作(在顶部单击加号符号)

  1. 选择IF块,主机标头为yourwebsite.com
  2. THEN块更改为重定向到https://www.#{host}:443/#{path}?#{query}
  3. 状态码:HTTP_301

不要编辑HTTPS上的默认操作

enter image description here


0

这里是精确答案: 使用以下名称创建此文件,并将以下内容放入其中。

redirect-to-https.json

[
  {
      "Type": "redirect",
      "RedirectConfig": {
          "Protocol": "HTTPS",
          "Port": "443",
          "Host": "#{host}",
          "Path": "/#{path}",
          "Query": "#{query}",
          "StatusCode": "HTTP_301"
      }
  }
]

使用此awscli命令在端口80上创建一个侦听器规则,使用HTTP协议将所有流量重定向到HTTPS端口。

aws elbv2 create-listener --load-balancer-arn arn:aws:elasticloadbalancing:us-east-1:12345678910:loadbalancer/app/demo1-alb/b4d5fbc78965417f --port 80 --protocol HTTP --default-actions file://redirect-to-https.json


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接