目前我有一个 ELB 服务于http://www.example.org和https://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;
}
无法工作,因为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;
}
}
但我读到的所有内容都表明,if
在 nginx 配置中应不惜一切代价避免这种情况,并且这将针对每个请求。此外,这意味着我必须为健康检查设置一个特殊的单独配置(如这里所述:“…当您位于 ELB 后面时,ELB 充当 HTTPS 端点并且仅向您的服务器发送 HTTP 流量,您将无法使用 HTTP 200 OK 响应来响应 ELB 所需的健康检查”。
我正在考虑将登录信息放在 Web 应用程序的代码中,而不是 nginx 配置中(为了解决这个问题,我们假设它是一个基于 Django 的应用程序),但我不确定这是否会比配置if
中的开销更大。
答案1
如果它能正常工作,就不要害怕它。http://wiki.nginx.org/IfIsEvil
值得注意的是, if 的行为并不不一致,给定两个相同的请求,它不会随机地在一个请求上失败而在另一个请求上成功,经过适当的测试和理解,可以使用 ifs。不过,使用其他可用指令的建议仍然适用。
答案2
- 设置您的 AWS ELB 映射 ELB:80 到实例:80,将 ELB:443 映射到实例:1443。
- 绑定nginx监听80和1443端口。
- 将到达端口 80 的请求转发到端口 443。
- 健康检查应该是 HTTP:1443。它拒绝 HTTP:80,因为 301 重定向。
NGINX 设置
server {
listen 80;
server_name www.example.org;
rewrite ^ https://$server_name$request_uri? permanent;
}
server {
listen 1443;
server_name www.example.org;
}
答案3
该解决方案使用条件逻辑,但正如接受的答案所暗示的那样,我也认为这是可以的。参考: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;
}
...
}
答案4
您现在可以在 AWS 负载均衡器设置中创建一个新的监听器,将 HTTP 端口 80 重定向到 HTTPS 端口 443。因此,您不再需要触及 nginx/apache 配置。