【问题标题】:Installing SSL cert on Amazon EC2 ELB在 Amazon EC2 ELB 上安装 SSL 证书
【发布时间】:2016-05-29 21:11:27
【问题描述】:

我是 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

和公钥证书:

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 网址 (https://www.example.org/) 时,它不起作用。 http://www.example.org/ 但确实有效。

由于安装 SSL 证书的步骤非常多,我怀疑我在此过程中犯了一个错误。问题是,我不知道在哪里。有没有人指点?

另外,安装 SSL 证书有没有更简单的方法?对于如此常见的事情,这似乎是可笑的复杂。我愿意花钱请专家为我做这件事(我是一名软件开发人员,几乎对 SSL 相关的任何知识一无所知),但是很难找到任何人来完成这样的任务(而且存在必须交出登录详细信息等)。非常感谢任何帮助。

编辑

下面的建议是我应该使用AWS Certificate Manager。我看过了,这似乎是一个更轻松的选择。但是,我确实花了 86 欧元购买了 Go Daddy 的 SSL 证书,所以我宁愿不要浪费。我的任何工作都可以挽救吗?是否有转售 SSL 证书的意思?

编辑

我还没有找到真正的解决方案。澄清一下,我有一个非常小众的网站,访问者很少。我有一个 EC2 实例上的站点。我按照上面的网站建议使用负载均衡器和 Cloudfront 以使用 SSL 进行加密。但是,它不起作用,无论如何它可能是矫枉过正的。谁能帮我这个?我想使用我支付的 SSL 证书,但如果没有,我应该使用 Lets Encrypt 之类的东西吗?

【问题讨论】:

  • 您将证书安装在 CloudFront 上,而不是您的 EC2 实例上。您是否在 EC2 实例前使用 CloudFront 作为 CDN?您可以使用新的 AWS Certificate Manager 轻松获得免费证书:aws.amazon.com/certificate-manager
  • 我没有打算使用 Cloudfront,我只是因为我遵循指南才使用它。我可以将我的 go daddy 证书与 AWS 证书管理器一起使用吗?
  • 我查看了证书管理器,它看起来非常简单。但是我已经从 Go Daddy 购买了 SSL 证书:(
  • 见:sunk costs
  • @MarkB 实际上看起来这仅在美国东部地区可用

标签: ssl amazon-ec2 https ssl-certificate amazon-elb


【解决方案1】:

您提到指南说需要 3 个文件,包括“DigiCertCA.crt”文件;听起来它是用 DigiCert 作为您的证书提供者而不是 GoDaddy 编写的。

证书

首先,确保“f6f65901b1708ae5.crt”包含您请求的证书(并消除任何疑问)。为此,您可以将“server.csr”文件(即证书签名请求)中的数据(例如通用名称 (CN)、DNS 主题备用名称 (SAN) 等)与“f6f65901b1708ae5.crt”文件中有什么:

$ openssl req -noout -text < server.csr

这应该会在 CSR 文件中显示有关您的域详细信息的人类可读文本。比较一下:

$ openssl x509 -noout -text < f6f65901b1708ae5.crt

这应该会显示类似的人类可读文本,并填写更多详细信息/字段。但它们应该大致符合您的预期。 注意,如果您看到类似这样的错误:

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,看看你提到的“gd_bundle-g2-g1.crt”文件是否存在,确实存在。 (这些文件可以公开使用,因为它们包含供任何人/所有人使用的公共证书。)查看 gd_bundle-g2-g1.crt 文件,我发现它包含 多个 证书.这很重要。

请参阅,“证书链”是提供信任路径(或“链”)的文件列表,从您拥有的“f6f65901b1708ae5.crt”证书到受信任的根 GoDaddy CA证书。每个证书都有一个主题(它的颁发者)和一个颁发者(颁发者)。这意味着您可以“向后”走,从您的证书到颁发者的证书,再到该证书的颁发者的证书,等等。这种倒退就是“证书链”。

“gd_bundle-g2-g1.crt”文件包含多个证书这一事实意味着该文件包含您需要的证书链。这也意味着您确实不想这样做:

$ openssl x509 -inform PEM -in gd_bundle-g2-g1.crt > aws_public.pem

因为openssl x509只读取指定文件中的first证书,而你需要all

鉴于以上所有情况,您可能只需要以下内容(以确保您的私钥是 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,只是为了确保它不会覆盖/与您现有的配置冲突。作为建议,您可以在名称中包含所上传证书的创建日期(或者,更好的是过期)作为名称的一部分,以提示您未来的自我何时该证书已添加,例如“redmatterapp_com-2016-02-18”。

另外注意,如果您使用 CloudFront,那么您应该使用--path 选项。如果您之前使用 CloudFront 然后将其删除,我强烈建议您再次执行上述 aws iam upload-server-certificate 命令,仅使用不同的 --server-certificate-name 并且没有 --path 选项(并删除以前的名称)。这可能意味着重新配置任何现有的 ELB HTTPS 侦听器以使用新的证书名称,但这可能是必要的,因为 --path 会影响 SSL 处理。

完成上述操作后,使用例如 AWS 控制台,您应该能够配置您的 AWS ELB,然后在“Listeners”选项卡下,单击“Edit”。为“https”添加一个监听器例如。添加任何支持 SSL 的侦听器时,您会在“SSL 证书”列/选项卡下看到“更改”链接。单击“更改”,然后选择“现有证书”按钮。然后,在“证书名称”下拉列表下,您应该会看到上面使用的 --server-certificate-name 字符串/标签的条目。选择该条目,然后单击“保存”。现在,应针对浏览器信任的 SSL/TLS 连接正确配置与 AWS ELB 上该侦听器的连接。

因此 HTTPS 侦听器配置如下所示:

  • 负载平衡器协议:HTTPS
  • 负载均衡器端口:443
  • 实例协议:HTTP
  • 实例端口:80
  • 密码:(默认策略)
  • SSL 证书:(--server-certificate-name 名称)

请注意,您确实希望将端口 443 也用于实例端口;如果这样做,则表示您希望从 ELB 到您的实例的 HTTPS ,这通常不需要。 (一些安全站点想要这个,但这是一个不同的主题/存储。)因此,上面配置了 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 requestX-Forwarded-For(和其他请求标头)。

现在,一旦您配置了 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 忽略任何证书不匹配/问题,以便我们可以看到有关事物的详细信息。

这是需要更多配置的地方。 如果您在 curl 命令(或浏览器)中使用自动生成的 ELB DNS 名称,那么您很可能会看到安全警告/问题。为什么?因为 HTTPS 的一部分是验证您在 URL 中使用的 DNS 名称​​匹配服务器证书中的域/主机名,或者作为证书中的公用名 (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 请求标头的内容。一些 HTTP 服务器(在您的后端实例上运行的服务器)对那里的价值非常挑剔;他们希望Host 标头与他们的配置中的某些内容相匹配,如果不匹配,他们可能会拒绝该请求。

另一个常见的问题是:

  • HTTP 503 服务不可用:后端服务器已满

如果您从 ELB 收到此响应,通常意味着您的后端服务器没有响应或未能响应 ELB 健康检查。仔细检查用于 ELB 健康检查的端口和路径/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,您可能会收到客户/用户的负面反应。

对您网站的所有流量使用 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" 文件) 包含一个通用名称 (CN) 或 DNS 主题备用名称 (SAN),它与客户端在其 URL 中使用的域名匹配。显然,您的证书包含“www.evilco.com”的 CN 或 DNS SAN,因此验证过程会失败——最终用户会看到某些东西有问题。但是,如果您的网站也允许 HTTP 流量,则可能会发生这种现象 - 而您查看您网站的日志,永远不会知道!

后记

我自己没有使用过 AWS Certificate Manager 或 CloudFront(所以我无法评论它们),但我已经多次使用上述过程来进行各种证书预置多个领域,多个工作。

希望这会有所帮助!

【讨论】:

  • 感谢您非常彻底的回答。我尝试了所有这些,但仍然 https 无法正常工作。我还删除了云端分发,因为看起来我不需要它。 f6f65901b1708ae5.crt 是 PEM 格式,当我运行上面的命令时,我看到它是针对我的域的。我的节点应用程序正在侦听端口 8080。我已经有一个 iptables 规则将流量从端口 80 转发到端口 8080。这适用于 http 流量。我添加了另一个规则,将流量转发到 443 到 8080。但是,https 仍然无法正常工作...
  • “不工作”到底是什么意思?您的 ELB HTTPS 侦听器使用哪些端口(前端、后端/实例)?是否有我可以自己测试的 ELB 帽子的 DNS 名称/IP 地址,以便我可以提供更多帮助?
  • 我已经用调试/测试步骤更新了我的帖子,并添加了一些关于一些必要的 DNS CNAME 配置的部分。
  • 当前“www.redmatterapp.com”解析为 IP 地址 (52.36.104.235),即“ec2-52-36-104-235.us-west-2.compute.amazonaws” .com";我应该等待您的 DNS 记录更新多长时间才能获取 CNAME 更改?
猜你喜欢
  • 2017-12-18
  • 1970-01-01
  • 2017-12-11
  • 1970-01-01
  • 2012-10-10
  • 1970-01-01
  • 2020-07-28
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多