我在通过 AWS Elastic Beanstalk 部署的站点强制使用 HTTPS 时遇到了问题。
这是一个使用 EmberJS 的前端应用程序。我花了很多天试图弄清楚如何将 http 流量重定向到 https。我在 EC2 机器上使用 Amazon Linux AMI。
我得出的结论是(仍然不确定这是否正确),我强制使用 HTTPS 的不是 Elastic Beanstalk。我允许 HTTP 和 HTTPS 通过我的 Elastic Beanstalk 负载均衡器,并尝试在服务器上进行重定向。
这是我遇到问题的地方。我找到了很多关于重写规则的答案,mod_rewrite
这些答案都是基于X-Forwarded-Proto
Header 的,但根据 find 搜索,该文件在我的 EC2 机器上不存在。
我也尝试在.ebextensions
目录中创建一个配置文件,但是也不起作用。
我主要想做的是让用户在尝试访问 http 地址时直接转到 https。任何指示或建议都非常感谢,谢谢!
编辑:我正在使用运行 Python 3.4 的 64 位 Debian jessie v1.4.1(预配置 - Docker)
答案1
我认为您需要指定您使用的 Elastic Beanstalk 环境(请参阅:支持的平台),因为不同的环境有不同的配置。
基本上,您需要自定义:
- 弹性负载均衡器:
- 监听端口 80 并将其代理到 EC2 实例端口 80。
- 监听端口 443 并将其代理到 EC2 实例端口 443。
- EC2 Web 服务器/代理:
- 监听端口 80 并重定向到 HTTPS 进行响应。
- 监听端口 443 并处理请求。
要定制它,您可以使用 CLI 或.ebextensions
。
您可以查看在 AWS Elastic Beanstalk 上启用 HTTPS 和 HTTP 重定向。它告诉您如何配置 Elastic Beanstalk Single Docker Container 服务 HTTPS 和 HTTP(重定向到 HTTPS)。您可以根据需要调整配置。
答案2
通过使用 ELB 设置的标头,也可以更轻松地完成此操作,而无需触及负载均衡器X-Forwarded-Proto
。以下是我最终做的事情:
files:
"/etc/nginx/sites-available/elasticbeanstalk-nginx-docker-proxy.conf":
mode: "00644"
owner: root
group: root
content: |
map $http_upgrade $connection_upgrade {
default "upgrade";
"" "";
}
server {
listen 80;
gzip on;
gzip_comp_level 4;
gzip_types text/html text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript;
access_log /var/log/nginx/access.log;
location / {
proxy_pass http://docker;
proxy_http_version 1.1;
proxy_set_header Connection $connection_upgrade;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
if ($http_x_forwarded_proto = 'http') {
return 301 https://$host$request_uri;
}
}
答案3
Elastic Beanstalk 不支持单个 Docker 容器的多个端口,因此您需要按照建议在代理级别处理此问题。但是,您的 EC2 实例不需要知道您的证书,因为您可以在负载均衡器上终止 SSL 连接。
在您的.ebextensions
目录中,为包含两个服务器配置的 nginx 代理创建一个配置;一个代理http://docker
(默认配置,端口 80),另一个重定向到 https(我选择端口 8080)。
.ebextensions/01-nginx-proxy.config
:
files:
"/etc/nginx/sites-available/000-default.conf":
mode: "000644"
owner: root
group: root
content: |
map $http_upgrade $connection_upgrade {
default "upgrade";
"" "";
}
server {
listen 80;
gzip on;
gzip_comp_level 4;
gzip_types text/html text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript;
access_log /var/log/nginx/access.log;
location / {
proxy_pass http://docker;
proxy_http_version 1.1;
proxy_set_header Connection $connection_upgrade;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
server {
listen 8080;
location / {
return 301 https://$host$request_uri;
}
}
commands:
00_enable_site:
command: 'rm -f /etc/nginx/sites-enabled/* && ln -s /etc/nginx/sites-available/000-default.conf /etc/nginx/sites-enabled/000-default.conf'
为 EB 负载均衡器和安全组创建第二个配置,并按如下方式设置它们:
- EC2 实例:
- 允许来自负载均衡器的 80/8080 端口上的流量
- 允许来自任何地方的端口 22 上的流量(用于 ssh 访问,可选)
- 负载均衡器:
- 将端口 443 HTTPS 转发到端口 80 HTTP
- 将端口 80 HTTP 转发到端口 8080 HTTP
.ebextensions/02-load-balancer.config
:
"Resources" : {
"AWSEBSecurityGroup": {
"Type" : "AWS::EC2::SecurityGroup",
"Properties" : {
"GroupDescription" : "Instance security group (22/80/8080 in)",
"SecurityGroupIngress" : [ {
"IpProtocol" : "tcp",
"FromPort" : "80",
"ToPort" : "80",
"SourceSecurityGroupId" : { "Ref" : "AWSEBLoadBalancerSecurityGroup" }
}, {
"IpProtocol" : "tcp",
"FromPort" : "8080",
"ToPort" : "8080",
"SourceSecurityGroupId" : { "Ref" : "AWSEBLoadBalancerSecurityGroup" }
}, {
"IpProtocol" : "tcp",
"FromPort" : "22",
"ToPort" : "22",
"CidrIp" : "0.0.0.0/0"
} ]
}
},
"AWSEBLoadBalancerSecurityGroup": {
"Type" : "AWS::EC2::SecurityGroup",
"Properties" : {
"GroupDescription" : "Load balancer security group (80/443 in, 80/8080 out)",
"VpcId" : "<vpc_id>",
"SecurityGroupIngress" : [ {
"IpProtocol" : "tcp",
"FromPort" : "80",
"ToPort" : "80",
"CidrIp" : "0.0.0.0/0"
}, {
"IpProtocol" : "tcp",
"FromPort" : "443",
"ToPort" : "443",
"CidrIp" : "0.0.0.0/0"
} ],
"SecurityGroupEgress": [ {
"IpProtocol" : "tcp",
"FromPort" : "80",
"ToPort" : "80",
"CidrIp" : "0.0.0.0/0"
}, {
"IpProtocol" : "tcp",
"FromPort" : "8080",
"ToPort" : "8080",
"CidrIp" : "0.0.0.0/0"
} ]
}
},
"AWSEBLoadBalancer" : {
"Type" : "AWS::ElasticLoadBalancing::LoadBalancer",
"Properties" : {
"Listeners" : [ {
"LoadBalancerPort" : "80",
"InstancePort" : "8080",
"Protocol" : "HTTP"
}, {
"LoadBalancerPort" : "443",
"InstancePort" : "80",
"Protocol" : "HTTPS",
"SSLCertificateId" : "arn:aws:iam::<certificate_id>:<certificate_path>"
} ]
}
}
}
(注意:不要忘记用您的值替换 SSLCertificateId 和 VpcId)。
负载均衡器 (HTTP) 端口 80 上的任何流量都将到达 EC2 实例上的端口 8080,该端口将重定向到 HTTPS。负载均衡器 (HTTPS) 端口 443 上的流量最终将由 EC2 实例上的端口 80(即 docker 代理)提供服务。
答案4
我正在使用 Terraform 在 ElasticBeanstalk 上启用 HTTP 到 HTTPS 重定向,
我刚刚添加了额外的监听器规则
data "aws_alb_listener" "http" { //Get ARN of Listener on Port-80
load_balancer_arn = aws_elastic_beanstalk_environment.myapp.load_balancers[0]
port = 80
}
resource "aws_alb_listener_rule" "redirect_http_to_https" {
listener_arn = data.aws_alb_listener.http.arn
action {
type = "redirect"
redirect {
port = "443"
protocol = "HTTPS"
status_code = "HTTP_301"
}
}
condition {
host_header {
values = ["*.*"]
}
}
}