在 Amazon EC2 ELB 上安装 SSL 证书
Installing SSL cert on Amazon EC2 ELB
我是 Amazon Web Services 的新手,一直在尝试在 EC2 实例上安装 SSL 证书。我尝试按照 AWS 文档进行操作,但发现它令人费解。然后我按照 http://www.robertbrewitz.com/2014/09/aws-and-setting-up-a-custom-ssl-certificate/.
的指南进行操作
我用 Go Daddy 购买了我的 SSL 证书,并使用 openssl 生成了 2 个文件:
server.key
server.csr
向导说我应该有 3 个证书:
DigiCertCA.crt
TrustedRoot.crt
star_yourdomain_com.crt
相反,我莫名其妙地收到了 2 个名为:
的文件
f6f65901b1708ae5.crt
gd_bundle-g2-g1.crt
我假设 f6f65901b1708ae5.crt
是我的域证书(但我不确定)。不管怎样,指南说我需要一个 Elastic Load Balancer 才能安装 SSL 证书,所以我创建了一个。
我生成了私钥:
openssl rsa -in server.key -text
和 public 密钥证书:
openssl x509 -inform PEM -in f6f65901b1708ae5.crt
我还需要输入证书链。我不确定这是什么以及如何获得它,所以我猜到了命令:
openssl x509 -inform PEM -in gd_bundle-g2-g1.crt
并输入以“-----BEGIN CERTIFICATE-----”开头的生成的证书密钥
指南继续说我需要设置 Cloudfront。我安装了 aws 命令行工具,为了生成 PEM,我 运行:
openssl rsa -in server.key -text > aws_private.pem
openssl x509 -inform PEM -in f6f65901b1708ae5.crt > aws_public.pem
openssl x509 -inform PEM -in gd_bundle-g2-g1.crt > aws_public.pem
我上传了 SSL 证书:
aws iam upload-server-certificate --server-certificate-name mydomain_com \
--certificate-body file://aws_public.pem --private-key file://aws_private.pem \
--certificate-chain file://aws_chain.pem --path /cloudfront/mydomain_com/
这是成功的。
然后我不得不创建一个 Cloudfront 分发,我这样做了,选择了 SSL 证书。
然而,当我访问我的 https url(https://www.example.org/), it's not working. http://www.example.org/ 但是确实有效。
由于仅安装 SSL 证书就需要大量步骤,我怀疑我在安装过程中犯了一个错误。问题是,我不知道在哪里。有人指点一下吗?
另外,有没有更简单的安装SSL证书的方法?对于如此普通的东西来说,它似乎复杂得可笑。我愿意花钱聘请专家为我做这件事(我是一名软件开发人员,几乎不了解任何与 SSL 相关的知识),但是很难找到任何人来完成这样的任务(而且有一个问题是必须交出登录详细信息等)。非常感谢任何帮助。
编辑
下面的建议是我应该使用AWS Certificate Manager。我看了一下,这似乎是一个更轻松的选择。但是,我确实花了 86 欧元从 Go Daddy 购买了 SSL 证书,所以我希望这不会浪费。我的任何工作都可以挽救吗?是否有转售 SSL 证书的意思?
编辑
我还没有找到真正的解决办法。澄清一下,我有一个非常小众的网站,访问者很少。我在 EC2 实例上拥有该站点。我遵循了上面的网站,该网站建议使用负载均衡器和 Cloudfront 以便使用 SSL 进行加密。但是,它不起作用,而且无论如何都可能矫枉过正。谁能帮我这个?我想使用我支付的 SSL 证书,但如果没有,我应该使用像 Lets Encrypt 这样的东西吗?
您提到指南说需要 3 个文件,包括一个“DigiCertCA.crt”文件;听起来它是用 DigiCert 作为您的证书提供商编写的,而不是 GoDaddy。
证书
首先,确保“f6f65901b1708ae5.crt”包含您请求的证书(并消除任何疑虑)。为此,您可以比较“server.csr”文件(即证书签名请求)以及“f6f65901b1708ae5.crt”文件中的内容:
$ openssl req -noout -text < server.csr
这应该会在 CSR 文件中显示有关您的域的详细信息的 human-readable 文本。比较:
$ openssl x509 -noout -text < f6f65901b1708ae5.crt
这应该显示类似 human-readable 的文本,并填充了更多 details/fields。但它们应该大致符合您的预期。 注意 如果您看到类似这样的错误:
51299:error:0906D06C:PEM routines:PEM_read_bio:no start line:/SourceCache/OpenSSL098/OpenSSL098-52.40.1/src/crypto/pem/pem_lib.c:648:Expecting: TRUSTED CERTIFICATE
然后提示你的“f6f65901b1708ae5.crt”文件是DER格式,不是PEM格式。如果没有,那么您已经有一个 PEM 文件,这正是 AWS ELB 所期望的。如果您有 DER 格式的证书,可以很容易地转换为 PEM 格式,使用:
$ openssl x509 -in f6f65901b1708ae5.crt -inform DER -out f6f65901b1708ae5.pem -outform PEM
我只是想通过提及这部分来彻底。
现在假设我们知道“f6f65901b1708ae5.crt”包含您域的 PEM 格式证书,我们已准备好处理“证书链" 部分.
我查看了 GoDaddy 的 online certificate repository, to see if the "gd_bundle-g2-g1.crt" file you mentioned was there, and it was. (It's OK for these files to be publicly available, as they contain the public certificates which are meant for anyone/everyone to use.) Looking at that gd_bundle-g2-g1.crt 文件,我发现它包含 多个 证书。这很重要。
看,“证书链”是提供信任路径(或“链”)的文件列表,从那个“f6f65901b1708ae5.crt”证书你必须具有受信任的根 GoDaddy CA 证书。每个证书都有一个 subject(谁颁发给 to)和一个 issuer(谁颁发的).这意味着您可以“倒退”,从您的证书到颁发者的证书,再到该证书的颁发者的证书,等。这个倒着走就是“证书链”。
“gd_bundle-g2-g1.crt”文件包含多个证书这一事实意味着该文件包含您需要的证书链。这也意味着您不想这样做:
$ openssl x509 -inform PEM -in gd_bundle-g2-g1.crt > aws_public.pem
因为openssl x509
只读取指定文件中的第一个个证书,而你需要全部个
考虑到以上所有情况,您可能只需要以下内容(以确保您的私钥是 PEM 格式的):
$ openssl rsa -in server.key -text > aws_private.pem
然后,因为我们假设“f6f65901b1708ae5.crt”已经是 PEM 格式(如果不是,您知道如何在上面转换它),并且我们知道 “gd_bundle-g2-g1.crt” 已经是 PEM 格式,我们现在准备将它们上传到 AWS ELB。
AWS ELB
要上传供 ELB 使用的证书和密钥,请使用如下内容:
$ aws iam upload-server-certificate \
--server-certificate-name redmatterapp_com2 \
--certificate-body file://f6f65901b1708ae5.crt \
--private-key file://aws_private.pem \
--certificate-chain file://gd_bundle-g2-g1.crt \
--path /cloudfront/redmatterapp_com/
注意 我使用了不同的 --server-certificate-name
,只是为了确保它不 override/conflict 与您现有的配置。作为建议,您可以将上传的证书的创建日期(或者,更好的是,它何时 expire)作为名称的一部分,作为对您未来的暗示添加该证书时的自我,例如“redmatterapp_com-2016-02-18”。
另外 注意 如果您不 使用 CloudFront,那么您应该不 使用--path
选项。如果您 曾 使用 CloudFront 然后将其删除,我强烈建议再次执行上述 aws iam upload-server-certificate
命令,只是使用不同的 --server-certificate-name
而没有 --path
选项(并删除以前的名称)。这可能意味着 re-configuring 任何现有的 ELB HTTPS 侦听器都可以使用新的证书名称,但这可能是必要的,因为 --path
会影响 SSL 处理。
完成上述操作后,使用 例如 AWS 控制台,您应该能够配置您的 AWS ELB,并在“侦听器”选项卡下单击“编辑”。为“https”添加一个监听器 ,例如 。添加任何 SSL-capable 侦听器时,您会在“SSL 证书”column/tab 下看到“更改”link。单击“更改”,然后选择“现有证书”按钮。然后,在“证书名称”下拉列表下,您应该会看到上面使用的 --server-certificate-name
string/label 的条目。选择该条目,然后单击“保存”。现在,应该为浏览器信任的 SSL/TLS 连接正确配置与您的 AWS ELB 上的该侦听器的连接。
因此 HTTPS 侦听器配置类似于:
- 负载平衡器协议:HTTPS
- 负载均衡器端口:443
- 实例协议:HTTP
- 实例端口:80
- 密码:(默认策略)
- SSL Crtificate: (
--server-certificate-name
名称)
请注意,您不也想使用端口 443 作为实例端口;如果你这样做,那就意味着你想要 HTTPS 从 ELB 到你的实例,这通常 不需要。 (一些安全站点需要这个,但那是不同的 topic/store。)因此上面配置了 ELB 来处理 SSL 终止;到实例上的 Node.js 服务器,它只会在端口 80:
上接收纯 HTTP 请求
client ---> HTTP ---> ELB port 80 ---> HTTP ---> server port 80
client ---> HTTPS --> ELB port 443 --> HTTP ---> server port 80
如果您的服务器需要知道原始请求是 HTTP 还是 HTTPS,请查找 AWS ELB 将 automatically add to the request 的 X-Forwarded-For
(和其他请求 header)。
现在,一旦您配置了 ELB,这是验证它是否正常工作的好步骤。首先,您可以使用 openssl s_client
来验证 SSL 握手是否有效:
$ openssl s_client -connect example.com:443
CONNECTED(00000003)
depth=3 /C=US/O=The Go Daddy Group, Inc./OU=Go Daddy Class 2 Certification Authority
verify error:num=19:self signed certificate in certificate chain
verify return:0
---
Certificate chain
0 s:/OU=Domain Control Validated/CN=redmatterapp.com
i:/C=US/ST=Arizona/L=Scottsdale/O=GoDaddy.com, Inc./OU=http://certs.godaddy.com/repository//CN=Go Daddy Secure Certificate Authority - G2
1 s:/C=US/ST=Arizona/L=Scottsdale/O=GoDaddy.com, Inc./OU=http://certs.godaddy.com/repository//CN=Go Daddy Secure Certificate Authority - G2
i:/C=US/ST=Arizona/L=Scottsdale/O=GoDaddy.com, Inc./CN=Go Daddy Root Certificate Authority - G2
2 s:/C=US/ST=Arizona/L=Scottsdale/O=GoDaddy.com, Inc./CN=Go Daddy Root Certificate Authority - G2
i:/C=US/O=The Go Daddy Group, Inc./OU=Go Daddy Class 2 Certification Authority
3 s:/C=US/O=The Go Daddy Group, Inc./OU=Go Daddy Class 2 Certification Authority
i:/C=US/O=The Go Daddy Group, Inc./OU=Go Daddy Class 2 Certification Authority
---
Server certificate
-----BEGIN CERTIFICATE-----
...
-----END CERTIFICATE-----
subject=/OU=Domain Control Validated/CN=example.com
issuer=/C=US/ST=Arizona/L=Scottsdale/O=GoDaddy.com, Inc./OU=http://certs.godaddy.com/repository//CN=Go Daddy Secure Certificate Authority - G2
---
No client certificate CA names sent
---
SSL handshake has read 4929 bytes and written 456 bytes
---
New, TLSv1/SSLv3, Cipher is AES128-SHA
Server public key is 2048 bit
Secure Renegotiation IS supported
Compression: NONE
Expansion: NONE
SSL-Session:
Protocol : TLSv1
Cipher : AES128-SHA
...
Timeout : 300 (sec)
Verify return code: 0 (ok)
---
以上显示我们成功完成了SSL握手,您可以看到它显示了带有GoDaddy名称的证书链; “服务器证书”部分应与您加载的“f6f65901b1708ae5.crt”PEM 文件匹配。
HTTPS 和 DNS
现在测试 HTTPS 部分;为此,我喜欢使用 curl
,像这样:
$ curl -kv https://example.com/
-v
选项显示更多信息,特别是证书是否与 DNS 名称匹配; -k
告诉 curl
忽略任何证书 mismatches/issues,这样我们就可以看到有关事物的详细信息。
这是需要多一点配置的地方。 如果您在 curl
命令(或浏览器)中使用 auto-generated ELB DNS 名称,那么您很可能会看到安全性 warnings/issues。为什么?因为 HTTPS 的一部分正在验证您在 URL 中使用的 DNS 名称是否匹配 服务器证书中的 domain/host 名称,或者作为通用名称 (CN)在您的证书中, 或 作为 DNS 主题备用名称 (SAN) 之一。您可能没有在发给 GoDaddy 的证书签名请求 (CSR) 中包含 ELB DNS 名称。
这意味着下一步是配置指向 AWS ELB 名称的 DNS CNAME 记录,例如:
www.example.com CNAME to aws-elb-1.elb.amazonaws.com
如果您将 AWS 用于 DNS,那么您可以使用 例如 Route 53 执行此操作。然后您重试 curl
命令(或浏览器):
curl -kv https://www.example.com/
另一个需要注意的重要事项(您可以在 curl -v
输出中看到这一点)是 Host
请求 header 的内容。某些 HTTP 服务器( 即 后端实例上的一个 运行)对那里的值非常挑剔;他们希望 Host
header 与他们的配置相匹配,如果不匹配,他们可能会拒绝请求。
另一个常见问题是:
- HTTP 503 服务不可用:Back-end 服务器已满
如果您从 ELB 收到此响应,通常 意味着您的后端服务器没有响应或无法响应 ELB 健康检查。 Double-check 用于 ELB 健康检查的端口和 path/URL 是正确的, 和 任何防火墙或 AWS 安全组都允许从 ELB 连接到您的实例。
所以,现在您应该有一个 ELB,它将端口 80 (HTTP) 和端口 443 (HTTPS) 转发到您的后端实例。并且您在 DNS 中有一个指向该 ELB 名称的“www.example.com”的 CNAME 记录。还剩什么?
HTTP 重定向
我高度建议将您的 HTTP 服务器配置为始终 重定向到相同 URL 的 HTTPS 等价物。为什么?
为了您的客户端和服务器之间的数据安全,现在需要使用 SSL/TLS。以至于越来越多的浏览器自动首先尝试 HTTPS,并且只是不情愿地使用 HTTP 作为后备。像 Chrome(和其他)这样的浏览器非常希望避免这种 HTTP 回退,以至于他们引入了像 HTTP Strict Transport Security 这样的机制:一种让您的网站告诉浏览器永远只 的方法为站点使用 HTTPS,从不使用 HTTP。另外,它总是一个更好的营销故事;事实上,如果您 不 使用 HTTPS,您可能会从 clients/users 那里得到负面反应。
对您网站的所有流量使用 HTTPS 还可以保护您免受另一件事:其他人使用他们的 DNS 名称和您的 ELB。您有一个指向“aws-elb-1.elb.amazonaws.com”的“www.example.com”的 CNAME 记录。但是如果我也为“www.evilco.com”创建我自己的 CNAME,它指向相同的“aws-elb-1.elb.amazonaws.com”怎么办?去“www.evilco.com”的人会看到你的网站,并认为它是我的!
通过强制您站点的所有流量为 HTTPS,您强制所有 HTTPS 客户端验证服务器提供的证书(即 您的“f6f65901b1708ae5.crt”文件)包含 与 客户端在其 URL 中使用的域名。显然,您的证书不 包含“www.evilco.com”的 CN 或 DNS SAN,因此验证过程会失败——最终用户会发现有问题。但是,如果您的网站也允许 HTTP 流量,则可能会发生这种现象——而您查看您网站的日志,永远不会知道!
后记
我自己没有使用过 AWS Certificate Manager 或 CloudFront(因此我无法对它们发表评论),但我已经多次使用上述过程,用于多个域的各种证书配置,在多个作业中。
希望对您有所帮助!
我是 Amazon Web Services 的新手,一直在尝试在 EC2 实例上安装 SSL 证书。我尝试按照 AWS 文档进行操作,但发现它令人费解。然后我按照 http://www.robertbrewitz.com/2014/09/aws-and-setting-up-a-custom-ssl-certificate/.
的指南进行操作我用 Go Daddy 购买了我的 SSL 证书,并使用 openssl 生成了 2 个文件:
server.key
server.csr
向导说我应该有 3 个证书:
DigiCertCA.crt
TrustedRoot.crt
star_yourdomain_com.crt
相反,我莫名其妙地收到了 2 个名为:
的文件f6f65901b1708ae5.crt
gd_bundle-g2-g1.crt
我假设 f6f65901b1708ae5.crt
是我的域证书(但我不确定)。不管怎样,指南说我需要一个 Elastic Load Balancer 才能安装 SSL 证书,所以我创建了一个。
我生成了私钥:
openssl rsa -in server.key -text
和 public 密钥证书:
openssl x509 -inform PEM -in f6f65901b1708ae5.crt
我还需要输入证书链。我不确定这是什么以及如何获得它,所以我猜到了命令:
openssl x509 -inform PEM -in gd_bundle-g2-g1.crt
并输入以“-----BEGIN CERTIFICATE-----”开头的生成的证书密钥
指南继续说我需要设置 Cloudfront。我安装了 aws 命令行工具,为了生成 PEM,我 运行:
openssl rsa -in server.key -text > aws_private.pem
openssl x509 -inform PEM -in f6f65901b1708ae5.crt > aws_public.pem
openssl x509 -inform PEM -in gd_bundle-g2-g1.crt > aws_public.pem
我上传了 SSL 证书:
aws iam upload-server-certificate --server-certificate-name mydomain_com \
--certificate-body file://aws_public.pem --private-key file://aws_private.pem \
--certificate-chain file://aws_chain.pem --path /cloudfront/mydomain_com/
这是成功的。
然后我不得不创建一个 Cloudfront 分发,我这样做了,选择了 SSL 证书。
然而,当我访问我的 https url(https://www.example.org/), it's not working. http://www.example.org/ 但是确实有效。
由于仅安装 SSL 证书就需要大量步骤,我怀疑我在安装过程中犯了一个错误。问题是,我不知道在哪里。有人指点一下吗?
另外,有没有更简单的安装SSL证书的方法?对于如此普通的东西来说,它似乎复杂得可笑。我愿意花钱聘请专家为我做这件事(我是一名软件开发人员,几乎不了解任何与 SSL 相关的知识),但是很难找到任何人来完成这样的任务(而且有一个问题是必须交出登录详细信息等)。非常感谢任何帮助。
编辑
下面的建议是我应该使用AWS Certificate Manager。我看了一下,这似乎是一个更轻松的选择。但是,我确实花了 86 欧元从 Go Daddy 购买了 SSL 证书,所以我希望这不会浪费。我的任何工作都可以挽救吗?是否有转售 SSL 证书的意思?
编辑
我还没有找到真正的解决办法。澄清一下,我有一个非常小众的网站,访问者很少。我在 EC2 实例上拥有该站点。我遵循了上面的网站,该网站建议使用负载均衡器和 Cloudfront 以便使用 SSL 进行加密。但是,它不起作用,而且无论如何都可能矫枉过正。谁能帮我这个?我想使用我支付的 SSL 证书,但如果没有,我应该使用像 Lets Encrypt 这样的东西吗?
您提到指南说需要 3 个文件,包括一个“DigiCertCA.crt”文件;听起来它是用 DigiCert 作为您的证书提供商编写的,而不是 GoDaddy。
证书
首先,确保“f6f65901b1708ae5.crt”包含您请求的证书(并消除任何疑虑)。为此,您可以比较“server.csr”文件(即证书签名请求)以及“f6f65901b1708ae5.crt”文件中的内容:
$ openssl req -noout -text < server.csr
这应该会在 CSR 文件中显示有关您的域的详细信息的 human-readable 文本。比较:
$ openssl x509 -noout -text < f6f65901b1708ae5.crt
这应该显示类似 human-readable 的文本,并填充了更多 details/fields。但它们应该大致符合您的预期。 注意 如果您看到类似这样的错误:
51299:error:0906D06C:PEM routines:PEM_read_bio:no start line:/SourceCache/OpenSSL098/OpenSSL098-52.40.1/src/crypto/pem/pem_lib.c:648:Expecting: TRUSTED CERTIFICATE
然后提示你的“f6f65901b1708ae5.crt”文件是DER格式,不是PEM格式。如果没有,那么您已经有一个 PEM 文件,这正是 AWS ELB 所期望的。如果您有 DER 格式的证书,可以很容易地转换为 PEM 格式,使用:
$ openssl x509 -in f6f65901b1708ae5.crt -inform DER -out f6f65901b1708ae5.pem -outform PEM
我只是想通过提及这部分来彻底。
现在假设我们知道“f6f65901b1708ae5.crt”包含您域的 PEM 格式证书,我们已准备好处理“证书链" 部分.
我查看了 GoDaddy 的 online certificate repository, to see if the "gd_bundle-g2-g1.crt" file you mentioned was there, and it was. (It's OK for these files to be publicly available, as they contain the public certificates which are meant for anyone/everyone to use.) Looking at that gd_bundle-g2-g1.crt 文件,我发现它包含 多个 证书。这很重要。
看,“证书链”是提供信任路径(或“链”)的文件列表,从那个“f6f65901b1708ae5.crt”证书你必须具有受信任的根 GoDaddy CA 证书。每个证书都有一个 subject(谁颁发给 to)和一个 issuer(谁颁发的).这意味着您可以“倒退”,从您的证书到颁发者的证书,再到该证书的颁发者的证书,等。这个倒着走就是“证书链”。
“gd_bundle-g2-g1.crt”文件包含多个证书这一事实意味着该文件包含您需要的证书链。这也意味着您不想这样做:
$ openssl x509 -inform PEM -in gd_bundle-g2-g1.crt > aws_public.pem
因为openssl x509
只读取指定文件中的第一个个证书,而你需要全部个
考虑到以上所有情况,您可能只需要以下内容(以确保您的私钥是 PEM 格式的):
$ openssl rsa -in server.key -text > aws_private.pem
然后,因为我们假设“f6f65901b1708ae5.crt”已经是 PEM 格式(如果不是,您知道如何在上面转换它),并且我们知道 “gd_bundle-g2-g1.crt” 已经是 PEM 格式,我们现在准备将它们上传到 AWS ELB。
AWS ELB
要上传供 ELB 使用的证书和密钥,请使用如下内容:
$ aws iam upload-server-certificate \
--server-certificate-name redmatterapp_com2 \
--certificate-body file://f6f65901b1708ae5.crt \
--private-key file://aws_private.pem \
--certificate-chain file://gd_bundle-g2-g1.crt \
--path /cloudfront/redmatterapp_com/
注意 我使用了不同的 --server-certificate-name
,只是为了确保它不 override/conflict 与您现有的配置。作为建议,您可以将上传的证书的创建日期(或者,更好的是,它何时 expire)作为名称的一部分,作为对您未来的暗示添加该证书时的自我,例如“redmatterapp_com-2016-02-18”。
另外 注意 如果您不 使用 CloudFront,那么您应该不 使用--path
选项。如果您 曾 使用 CloudFront 然后将其删除,我强烈建议再次执行上述 aws iam upload-server-certificate
命令,只是使用不同的 --server-certificate-name
而没有 --path
选项(并删除以前的名称)。这可能意味着 re-configuring 任何现有的 ELB HTTPS 侦听器都可以使用新的证书名称,但这可能是必要的,因为 --path
会影响 SSL 处理。
完成上述操作后,使用 例如 AWS 控制台,您应该能够配置您的 AWS ELB,并在“侦听器”选项卡下单击“编辑”。为“https”添加一个监听器 ,例如 。添加任何 SSL-capable 侦听器时,您会在“SSL 证书”column/tab 下看到“更改”link。单击“更改”,然后选择“现有证书”按钮。然后,在“证书名称”下拉列表下,您应该会看到上面使用的 --server-certificate-name
string/label 的条目。选择该条目,然后单击“保存”。现在,应该为浏览器信任的 SSL/TLS 连接正确配置与您的 AWS ELB 上的该侦听器的连接。
因此 HTTPS 侦听器配置类似于:
- 负载平衡器协议:HTTPS
- 负载均衡器端口:443
- 实例协议:HTTP
- 实例端口:80
- 密码:(默认策略)
- SSL Crtificate: (
--server-certificate-name
名称)
请注意,您不也想使用端口 443 作为实例端口;如果你这样做,那就意味着你想要 HTTPS 从 ELB 到你的实例,这通常 不需要。 (一些安全站点需要这个,但那是不同的 topic/store。)因此上面配置了 ELB 来处理 SSL 终止;到实例上的 Node.js 服务器,它只会在端口 80:
上接收纯 HTTP 请求client ---> HTTP ---> ELB port 80 ---> HTTP ---> server port 80
client ---> HTTPS --> ELB port 443 --> HTTP ---> server port 80
如果您的服务器需要知道原始请求是 HTTP 还是 HTTPS,请查找 AWS ELB 将 automatically add to the request 的 X-Forwarded-For
(和其他请求 header)。
现在,一旦您配置了 ELB,这是验证它是否正常工作的好步骤。首先,您可以使用 openssl s_client
来验证 SSL 握手是否有效:
$ openssl s_client -connect example.com:443
CONNECTED(00000003)
depth=3 /C=US/O=The Go Daddy Group, Inc./OU=Go Daddy Class 2 Certification Authority
verify error:num=19:self signed certificate in certificate chain
verify return:0
---
Certificate chain
0 s:/OU=Domain Control Validated/CN=redmatterapp.com
i:/C=US/ST=Arizona/L=Scottsdale/O=GoDaddy.com, Inc./OU=http://certs.godaddy.com/repository//CN=Go Daddy Secure Certificate Authority - G2
1 s:/C=US/ST=Arizona/L=Scottsdale/O=GoDaddy.com, Inc./OU=http://certs.godaddy.com/repository//CN=Go Daddy Secure Certificate Authority - G2
i:/C=US/ST=Arizona/L=Scottsdale/O=GoDaddy.com, Inc./CN=Go Daddy Root Certificate Authority - G2
2 s:/C=US/ST=Arizona/L=Scottsdale/O=GoDaddy.com, Inc./CN=Go Daddy Root Certificate Authority - G2
i:/C=US/O=The Go Daddy Group, Inc./OU=Go Daddy Class 2 Certification Authority
3 s:/C=US/O=The Go Daddy Group, Inc./OU=Go Daddy Class 2 Certification Authority
i:/C=US/O=The Go Daddy Group, Inc./OU=Go Daddy Class 2 Certification Authority
---
Server certificate
-----BEGIN CERTIFICATE-----
...
-----END CERTIFICATE-----
subject=/OU=Domain Control Validated/CN=example.com
issuer=/C=US/ST=Arizona/L=Scottsdale/O=GoDaddy.com, Inc./OU=http://certs.godaddy.com/repository//CN=Go Daddy Secure Certificate Authority - G2
---
No client certificate CA names sent
---
SSL handshake has read 4929 bytes and written 456 bytes
---
New, TLSv1/SSLv3, Cipher is AES128-SHA
Server public key is 2048 bit
Secure Renegotiation IS supported
Compression: NONE
Expansion: NONE
SSL-Session:
Protocol : TLSv1
Cipher : AES128-SHA
...
Timeout : 300 (sec)
Verify return code: 0 (ok)
---
以上显示我们成功完成了SSL握手,您可以看到它显示了带有GoDaddy名称的证书链; “服务器证书”部分应与您加载的“f6f65901b1708ae5.crt”PEM 文件匹配。
HTTPS 和 DNS
现在测试 HTTPS 部分;为此,我喜欢使用 curl
,像这样:
$ curl -kv https://example.com/
-v
选项显示更多信息,特别是证书是否与 DNS 名称匹配; -k
告诉 curl
忽略任何证书 mismatches/issues,这样我们就可以看到有关事物的详细信息。
这是需要多一点配置的地方。 如果您在 curl
命令(或浏览器)中使用 auto-generated ELB DNS 名称,那么您很可能会看到安全性 warnings/issues。为什么?因为 HTTPS 的一部分正在验证您在 URL 中使用的 DNS 名称是否匹配 服务器证书中的 domain/host 名称,或者作为通用名称 (CN)在您的证书中, 或 作为 DNS 主题备用名称 (SAN) 之一。您可能没有在发给 GoDaddy 的证书签名请求 (CSR) 中包含 ELB DNS 名称。
这意味着下一步是配置指向 AWS ELB 名称的 DNS CNAME 记录,例如:
www.example.com CNAME to aws-elb-1.elb.amazonaws.com
如果您将 AWS 用于 DNS,那么您可以使用 例如 Route 53 执行此操作。然后您重试 curl
命令(或浏览器):
curl -kv https://www.example.com/
另一个需要注意的重要事项(您可以在 curl -v
输出中看到这一点)是 Host
请求 header 的内容。某些 HTTP 服务器( 即 后端实例上的一个 运行)对那里的值非常挑剔;他们希望 Host
header 与他们的配置相匹配,如果不匹配,他们可能会拒绝请求。
另一个常见问题是:
- HTTP 503 服务不可用:Back-end 服务器已满
如果您从 ELB 收到此响应,通常 意味着您的后端服务器没有响应或无法响应 ELB 健康检查。 Double-check 用于 ELB 健康检查的端口和 path/URL 是正确的, 和 任何防火墙或 AWS 安全组都允许从 ELB 连接到您的实例。
所以,现在您应该有一个 ELB,它将端口 80 (HTTP) 和端口 443 (HTTPS) 转发到您的后端实例。并且您在 DNS 中有一个指向该 ELB 名称的“www.example.com”的 CNAME 记录。还剩什么?
HTTP 重定向
我高度建议将您的 HTTP 服务器配置为始终 重定向到相同 URL 的 HTTPS 等价物。为什么?
为了您的客户端和服务器之间的数据安全,现在需要使用 SSL/TLS。以至于越来越多的浏览器自动首先尝试 HTTPS,并且只是不情愿地使用 HTTP 作为后备。像 Chrome(和其他)这样的浏览器非常希望避免这种 HTTP 回退,以至于他们引入了像 HTTP Strict Transport Security 这样的机制:一种让您的网站告诉浏览器永远只 的方法为站点使用 HTTPS,从不使用 HTTP。另外,它总是一个更好的营销故事;事实上,如果您 不 使用 HTTPS,您可能会从 clients/users 那里得到负面反应。
对您网站的所有流量使用 HTTPS 还可以保护您免受另一件事:其他人使用他们的 DNS 名称和您的 ELB。您有一个指向“aws-elb-1.elb.amazonaws.com”的“www.example.com”的 CNAME 记录。但是如果我也为“www.evilco.com”创建我自己的 CNAME,它指向相同的“aws-elb-1.elb.amazonaws.com”怎么办?去“www.evilco.com”的人会看到你的网站,并认为它是我的!
通过强制您站点的所有流量为 HTTPS,您强制所有 HTTPS 客户端验证服务器提供的证书(即 您的“f6f65901b1708ae5.crt”文件)包含 与 客户端在其 URL 中使用的域名。显然,您的证书不 包含“www.evilco.com”的 CN 或 DNS SAN,因此验证过程会失败——最终用户会发现有问题。但是,如果您的网站也允许 HTTP 流量,则可能会发生这种现象——而您查看您网站的日志,永远不会知道!
后记
我自己没有使用过 AWS Certificate Manager 或 CloudFront(因此我无法对它们发表评论),但我已经多次使用上述过程,用于多个域的各种证书配置,在多个作业中。
希望对您有所帮助!