我想在序言中指出,网络不是我的强项,但我必须在我的用例中使用它。
我正在尝试与在 Apache Tomcat 上运行的 Web 应用程序建立 HTTPS 连接。我在 AWS elastic beanstalk 中启动了容器,当我只使用单个实例时,它运行得很好。当我放入负载均衡器时,它也工作得很好,保留默认端口侦听器并按原样处理。但是,当我尝试将传入连接重定向到 HTTPS 时,我收到 502 错误。我检查了控制台,看起来端口 443 或 8443 上都没有运行侦听器(我已确认在 tomcat 配置文件夹下的 server.xml 文件中启用了后者),当我检查 Catalina 时我注意到,似乎正在运行的唯一协议处理程序是为端口 8080 设置的协议处理程序,尽管配置文件明确指出了其他情况。日志中没有错误,这表明我的应用程序启动正确。此外,502 bad gateway 错误页面没有显示其他信息 - 没有 nginx 版本来指示错误与代理有关,并且 Amazon 的任何日志记录中都没有有用的信息。
我完全被难住了,因为亚马逊的文档中没有真正的迹象表明,使用 HTTPS 需要对其 tomcat 环境进行任何进一步的特殊配置——其范围意味着发生在 EBS 设置配置中,其中负载均衡器和这样配置的。您是否有可能无法重新配置环境以追溯使用 HTTPS,而我必须重建整个环境才能实现此目的?在过去的一天半里,我只是觉得我在用头撞墙。
我尝试重新启动实例,修改负载均衡器重定向配置,并将代理服务器从 nginx 切换到 apache httpd。显然,我希望应用程序能够加载,而不是继续这种令人讨厌的拒绝合作(AWS 就像一头愤怒的公牛,过去几周我一直在与它争论)。根据日志,tomcat 似乎正在尝试将请求解释为未加密的 HTTP 请求,所以显然缺少某些内容...帮助!
对于将来遇到这种头痛的其他人,这就是我所做的(最终)有效的。
AWS 文档中隐藏着有关使用 YAML 和/或 JSON 文件手动配置 beanstalk 环境的信息(据我所知,您可以在文件中混合语法)。 .ebextensions 文件夹包含这些文件,然后 .platform 文件夹包含特定于您的服务器的配置(在本例中为 Apache)。我还获得了用于端到端加密的自签名证书,因为浏览器只能看到负载均衡器正在使用的证书,而不必担心后端是自签名的。 (为此,我必须大量阅读有关 SSL 和安全性的内容,几年后它将过时......叹息)
您的应用程序根目录中需要两个文件夹(也就是说,如果您解压 WAR,如果您使用的是 Java EE 或 Spring,这些文件夹将与 WEB-INF 文件夹处于同一级别)。 在 .ebextensions 下,您必须配置负载均衡器(我还借此机会在此文件夹中指定了我的环境变量)。
配置应该如下所示(您可以拆分文件,只要将它们命名为相对容易记住的名称即可):
packages:
yum:
mod_ssl : []
Resources:
AWSEBAutoScalingGroup:
Type: "AWS::AutoScaling::AutoScalingGroup"
Metadata:
AWS::CloudFormation::Authentication:
S3Auth:
type: "S3"
buckets: ["elasticbeanstalk-us-east-1-705738864590"]
roleName:
"Fn::GetOptionSetting":
Namespace: "aws:autoscaling:launchconfiguration"
OptionName: "IamInstanceProfile"
DefaultValue: (your instance profile name)
option_settings:
aws:elbv2:listener:443:
Protocol: HTTPS
SSLCertificateArns: (put the ARN for your certificate here)
aws:elasticbeanstalk:environment:process:default:
Port: '443'
Protocol: HTTPS
StickinessEnabled: 'true'
StickinessLBCookieDuration: '43200'
aws:elasticbeanstalk:environment:proxy:
ProxyServer: apache
files:
/etc/pki/tls/certs/server.crt:
mode: "000400"
owner: root
group: root
content: |
-----BEGIN CERTIFICATE-----
(paste your self-signed certificate's public key here)
-----END CERTIFICATE-----
/etc/pki/tls/certs/server.key:
mode: "000400"
owner: root
group: root
authentication: "S3Auth"
source: (link your certificate's private key from the S3 bucket here)
/opt/elasticbeanstalk/hooks/appdeploy/post/99_start_httpd.sh:
mode: "000755"
owner: root
group: root
content: |
#!/usr/bin/env bash
sudo service httpd restart
然后你需要有一个配置文件来将侦听器放在端口 443 和 80 上 - 这位于 .platform 下(这在文档中并不明显,我花了相当多的时间才找到答案 - - 如果您尝试将它们放在 .ebextensions 下,它将不起作用)。事实证明,我遇到的很多麻烦是因为我的端口重定向导致运行状况检查失败——我需要为重定向规则设置一个重写条件,这样它就不会扰乱运行状况检查.
.platform/httpd/conf.d/redirect.conf:
RewriteEngine On
RewriteCond %{HTTP_HOST} !localhost
RewriteCond %{HTTP_USER_AGENT} !^ELB-HealthChecker.*
<If "-n '%{HTTP:X-Forwarded-Proto}' && %{HTTP:X-Forwarded-Proto} != 'https'">
RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI} [R,L]
</If>
.platform/httpd/conf.d/https.conf:
Listen 443
LoadModule ssl_module modules/mod_ssl.so
<VirtualHost *:443>
<Proxy *>
Order deny,allow
Allow from all
</Proxy>
ServerName (your domain)
SSLEngine on
SSLCertificateFile "/etc/pki/tls/certs/server.crt"
SSLCertificateKeyFile "/etc/pki/tls/certs/server.key"
SSLCipherSuite EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH
SSLProtocol All -SSLv2 -SSLv3
SSLHonorCipherOrder On
Header always set Strict-Transport-Security "max-age=63072000; includeSubdomains; preload"
Header always set X-Frame-Options DENY
Header always set X-Content-Type-Options nosniff
ProxyPass / http://localhost:8080/ retry=0
ProxyPassReverse / http://localhost:8080/
ProxyPreserveHost on
</VirtualHost>
请注意,证书和密钥文件名只需与您在 .ebextensions 下的文件系统配置中输入的内容相匹配。
无论如何,足以说明 AWS 不遗余力地让这对我来说是一大堆看似不必要的工作,我现在更有理由鄙视 Jeff Bezos。