您提到指南说需要 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 request 的 X-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 标头与他们的配置中的某些内容相匹配,如果不匹配,他们可能会拒绝该请求。
另一个常见的问题是:
如果您从 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(所以我无法评论它们),但我已经多次使用上述过程来进行各种证书预置多个领域,多个工作。
希望这会有所帮助!