将 Amazon ELB 后面的所有 http 请求重定向到 https 而不使用 if

Jor*_*ter 27 http nginx https redirect amazon-elb

目前我有一个 ELB 服务http://www.example.orghttps://www.example.org

我想设置它以便任何指向http://www.example.org 的请求都重定向到https://www.example.org

ELB 将 https 请求作为 http 请求发送,因此使用:

server {
      listen         80;
       server_name    www.example.org;
       rewrite        ^ https://$server_name$request_uri? permanent;
}
Run Code Online (Sandbox Code Playgroud)

将不起作用,因为对https://www.example.org 的请求仍将被发送到 nginx 上的端口 80。

我知道可以将其重写为

server {
      listen         80;
      server_name    www.example.org;
      if ($http_x_forwarded_proto != "https") {
          rewrite ^(.*)$ https://$server_name$1 permanent;
      }
}
Run Code Online (Sandbox Code Playgroud)

但是我读过的所有内容都if应该在 nginx 配置中不惜一切代价避免,这将适用于每个请求。此外,这意味着我必须为健康检查设置一个特殊的单独配置(如此处所述:“……当您位于 ELB 后面时,ELB 充当 HTTPS 端点并且仅向您的服务器发送 HTTP 流量,您破坏了以 HTTP 200 OK 响应响应 ELB 所需的健康检查的能力”)。

我正在考虑将登录放在 web 应用程序的代码中而不是 nginx 配置中(为了这个问题,我们假设它是一个基于 Django 的应用程序),但我不确定这是否会比在if 配置中。

nu *_*est 15

  1. 设置您的 AWS ELB 映射 ELB:80 到实例:80 和 ELB:443 到实例:1443。
  2. 绑定nginx监听80和1443端口。
  3. 将到达端口 80 的请求转发到端口 443。
  4. 健康检查应该是 HTTP:1443。它拒绝 HTTP:80 因为 301 重定向。

aws elb 设置

NGINX 设置

    server {
       listen         80;
       server_name    www.example.org;
       rewrite        ^ https://$server_name$request_uri? permanent;
    }

    server {
       listen         1443;
       server_name    www.example.org;
   } 
Run Code Online (Sandbox Code Playgroud)

  • 健康检查应该是`HTTP:1443`。它拒绝 `HTTP:80` 因为 301 重定向。 (2认同)

cee*_*yoz 9

如果它像那样正常工作,请不要害怕。http://wiki.nginx.org/IfIsEvil

重要的是要注意 if 的行为不是不一致的,给定两个相同的请求,它不会随机失败一个而在另一个上工作,可以使用适当的测试和理解 ifs。但是,在可用的情况下使用其他指令的建议仍然非常适用。


小智 9

该解决方案使用条件逻辑,但正如公认的答案所暗示的那样,我也认为这没问题。参考:https : //stackoverflow.com/questions/4833238/nginx-conf-redirect-multiple-conditions

此外,这不需要在映像的 aws 安全设置中打开任何其他端口。您可以在 AWS LB 中终止 ssl,并将 https 流量路由到您实例上的 http 端口 80。

在此示例中,LB 运行状况检查在路由到应用程序服务器的端口 80 上命中 /health,因此运行状况检查验证 nginx 和您的应用程序正在呼吸。

server {
  listen 80 default deferred;

  set $redirect_to_https 0;
  if ($http_x_forwarded_proto != 'https') {
    set $redirect_to_https 1;
  }
  if ($request_uri = '/health') {
    set $redirect_to_https 0;
  }
  if ($redirect_to_https = 1) {
    rewrite ^ https://www.example.com$request_uri? permanent;
  }
  ...
}
Run Code Online (Sandbox Code Playgroud)