如何在 AWS Elastic Beanstalk 上设置 HTTPS
Posted
技术标签:
【中文标题】如何在 AWS Elastic Beanstalk 上设置 HTTPS【英文标题】:How To Set Up HTTPS on AWS Elastic Beanstalk 【发布时间】:2015-08-07 17:07:57 【问题描述】:我是 AWS、Elastic Beanstalk、Apache 和 Flask 的新手。
我正在尝试完全通过 HTTPS 提供我的网络应用程序。
我提供了我所做的每一个细节,希望有人能找到我遗漏或做错的事情。
AWS 设置
我正在使用 AWS Elastic Beanstalk,使用 Amazon Linux AMI,并在最新的 Python 容器 (Python 3.4) 中使用 Flask 和 Flask-Security(用于处理用户/会话)编写了我的应用程序。
我做了什么
我首先通过 Amazon Route 53 购买了一个域,我们称之为 example.com。最初,我设置了所有必需的 DNS 配置,在适当的地方创建指向 www.example.com 的 A 记录到 example.com,CNAME 记录在适当的地方将 example.com 指向我的 AWS Elastic Load Balancer。
接下来,我更新了弹性负载均衡器上的安全组,以允许 HTTP 和 HTTPS 上的入站和出站流量。
然后,我从一家受欢迎的提供商处购买了 SSL 证书。网上有很多可靠的程序展示了如何做到这一点,所以我从这里省略了它。我在 Elastic Load Balancer 上配置了两个监听器:
一个用于将 HTTP 转发到实例端口 80 一个用于 HTTPS 转发到实例端口 80,指定我的 SSL 证书我编写了我的应用程序的处理程序、配置的端点等,并让它在本地工作。我使用的是 PyCharm 和 AWS Elastic Beanstalk Integration For Web Languages 插件。我将它部署到我的 Elastic Beanstalk 实例,除了在项目根目录的 .ebextensions
目录中的配置文件中指定 option_settings
之外,没有进行任何特殊配置。我用它来配置我的 WSGIPath(我在其中暴露了我的 application
可调用文件)和静态文件:
option_settings:
"aws:elasticbeanstalk:container:python":
WSGIPath: my_app.wsgi
"aws:elasticbeanstalk:container:python:staticfiles":
"/static/": "my_app/static/"
"/favicon.ico": "my_app/static/img/favicon.ico"
我已部署到 Elastic Beanstalk。它起作用了,在访问我的网站 http://www.example.com/ 后,该网站呈现正常。我可以登录,但是显然需要 SSL(因为我通过网络以纯文本形式发送我的用户名/密码)。这验证了我的 option_settings 有效(因为我可以访问所有端点、读取所有静态文件等。
在尝试 https://www.example.com 时它也有效,但仅当我在我的前面手动键入 https:// 时网址。理想情况下,我希望用户键入 www.example.com 并在 https://www.example.com 找到自己。我发现的另一个有趣的行为是,当我点击 https://www.example.com 并登录时,我会被发送到只有 HTTP 而不是 HTTPS 的主页。
最后,我尝试通过 AWS 提供的 .ebextensions
机制添加自定义配置。我为所有未通过 https 进入的流量添加了 RewriteRule
,以通过 https 重定向。我还为端口 443 添加了一个新的 VirtualHost,并添加了我所有的原始映射(从上面,刚刚翻译成 Apache 配置)。我的 SSL 配置文件如下:
files:
"/etc/httpd/conf.d/ssl.conf":
mode: "000644"
owner: root
group: root
content: |
<VirtualHost *:80>
LogLevel debug
RewriteEngine On
RewriteCond %HTTP:X-Forwarded-Proto !https
RewriteRule (.*) https://%HTTP_HOST%REQUEST_URI [L,R]
</VirtualHost>
<VirtualHost *:443>
LogLevel debug
Alias /favicon.ico /opt/python/current/app/my_app/static/img/favicon.ico
<Directory /opt/python/current/app/my_app/static/img/favicon.ico>
Order allow,deny
Allow from all
</Directory>
Alias /static/ /opt/python/current/app/my_app/static/
<Directory /opt/python/current/app/my_app/static/>
Order allow,deny
Allow from all
</Directory>
WSGIScriptAlias / /opt/python/current/app/my_app.wsgi
<Directory /opt/python/current/app/>
Require all granted
</Directory>
</VirtualHost>
container_commands:
restart_apache:
command: /sbin/service httpd restart
现在,在部署该配置文件后,我的网站只会超时 - 无论我访问的是 http 还是 https://www.example.com。奇怪的是,如果我在删除整个 <VirtualHost *:443>
指令的情况下进行部署,我只会得到一个空白的“Index Of /”网页。
我希望我的整个网站都通过 HTTPS 提供服务。许多 SO 文章和其他网站指出如何配置 Elastic Load Balancer 以接受 HTTPS 并转发到 EC2 实例上的端口 80 (HTTP),但是我必须遗漏一些东西 - 好像我的 Apache 服务器没有发送 通过 HTTPS 的出站 流量。
所以我查看了 Apache 配置并注意到 RewriteRule 指令,它将端口 80 的流量重定向到端口 443,但是许多建议使用 RewriteRule 的网站也忘记提到我可能需要为端口 443 设置新的 VirtualHost。
再次,我不确定我是否遗漏了一些关键的东西(显然我的理解存在差距) - 但我似乎无法找到让我的整个网站通过 HTTPS 运行的方法。
提前致谢。
【问题讨论】:
【参考方案1】:我的问题在于我是如何配置端口的。获得证书后,您可以在配置 > 负载均衡器 > 修改中配置端口。
这是我的配置:
这个资源对我非常有用,如果你需要它会提供更多细节:https://colintoh.com/blog/configure-ssl-for-aws-elastic-beanstalk
【讨论】:
【参考方案2】:我认为您收到请求超时的问题是:
您通过弹性负载均衡器 (ELB) 访问了 HTTPS。 ELB 向 EC2 实例 发出 HTTP 请求。 (您提到:一个用于 HTTPS 转发到实例端口 80,指定我的 SSL 证书) 所以,您的 EC2 实例 回复 ELB 并使用 HTTP 重定向 到同一位置但 HTTPS (https://wiki.apache.org/httpd/RewriteHTTPToHTTPS)。 ELB 将回复您的请求 same 作为 EC2,重定向到 HTTPS。 您的浏览器将跟随您的重定向信息。然后回到第一点(永远循环)。要解决此问题,请在您的 ELB 中,将您的 ELB HTTPS 转发到实例 HTTPS(端口 443)。为此,您需要指定额外的 .ebextensions
,因为 AWS Web 控制台中没有 HTTPS 到 HTTPS 配置。
这是我的.ebextensions
文件配置:
Resources:
AWSEBSecurityGroup:
Type: "AWS::EC2::SecurityGroup"
Properties:
GroupDescription: "Allow SSH, HTTP, and HTTPS"
SecurityGroupIngress:
- IpProtocol: "tcp", FromPort: 22, ToPort: 22, CidrIp: "0.0.0.0/0"
- IpProtocol: "tcp", FromPort: 80, ToPort: 80, CidrIp: "0.0.0.0/0"
- IpProtocol: "tcp", FromPort: 443, ToPort: 443, CidrIp: "0.0.0.0/0"
AWSEBLoadBalancerSecurityGroup:
Type: "AWS::EC2::SecurityGroup"
Properties:
GroupDescription: "Allow HTTP and HTTPS"
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: 443, ToPort: 443, CidrIp: "0.0.0.0/0"
AWSEBLoadBalancer:
Type: "AWS::ElasticLoadBalancing::LoadBalancer"
Properties:
Listeners:
- LoadBalancerPort: 80, Protocol: "HTTP", InstancePort: 80, InstanceProtocol: "HTTP"
- LoadBalancerPort: 443, Protocol: "HTTPS", InstancePort: 443, InstanceProtocol: "HTTPS", SSLCertificateId: "arn:aws:iam::123456789012:server-certificate/YourSSLCertificate"
SecurityGroups:
- "Fn::GetAtt" : [AWSEBLoadBalancerSecurityGroup, GroupId]
【讨论】:
【参考方案3】:您需要更新位于 /etc/httpd/conf.d/wsgi.conf 的 wsgi.conf 文件
将 wsgi.conf 文件添加到 .ebextensions将 wsgireplace.config 添加到 .ebextensionsLoadModule wsgi_module modules/mod_wsgi.so WSGIPythonHome /opt/python/run/baselinenv WSGISocketPrefix run/wsgi WSGIRestrictEmbedded On <VirtualHost *:80> RewriteEngine On RewriteCond %HTTP:X-Forwarded-Proto !https RewriteCond %REQUEST_URI !^/status$ RewriteCond %REQUEST_URI !^/version$ RewriteCond %REQUEST_URI !^/_hostmanager/ RewriteRule !/status https://%SERVER_NAME%REQUEST_URI [L,R=301] Alias /static/ /opt/python/current/app/mindbliss/static/ <Directory /opt/python/current/app/mindbliss/static/> Order allow,deny Allow from all </Directory> WSGIScriptAlias / /opt/python/current/app/application.py <Directory /opt/python/current/app/> Require all granted </Directory> WSGIDaemonProcess wsgi processes=3 threads=20 display-name=%GROUP \ python-path=/opt/python/current/app:/opt/python/run/venv/lib64/python2.7/site-packages:/opt/python/run/venv/lib/python2.7/site-packages user=wsgi group=wsgi \ home=/opt/python/current/app WSGIProcessGroup wsgi </VirtualHost> LogFormat "%h (%X-Forwarded-Fori) %l %u %t \"%r\" %>s %b \"%Refereri\" \"%User-Agenti\"" combined
最后是container_commands: 01_wsgireplace: command: 'cp .ebextensions/wsgi.conf /etc/httpd/conf.d/wsgi.conf'
eb deploy
【讨论】:
以上是关于如何在 AWS Elastic Beanstalk 上设置 HTTPS的主要内容,如果未能解决你的问题,请参考以下文章
如何在 AWS Elastic Beanstalk 上修改 Nginx 配置
如何在 AWS Elastic Beanstalk 上设置 HTTPS
如何在 AWS Elastic Beanstalk 上设置 HTTPS
如何在 AWS Elastic Beanstalk 中更改数据库配置