在Amazon EC2 ELB上安装SSL证书

时间:2016-02-17 22:25:07

标签: ssl amazon-ec2 https ssl-certificate amazon-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

和公钥认证:

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。我看了一眼,这似乎是一个更加轻松的选择。但是,我确实在Go Daddy的SSL证书上花了86欧元,所以我更愿意,如果这不浪费。我的任何工作都可以挽救吗?是否有意转售SSL证书?

修改

我还没有找到真正的解决方案。为了澄清,我有一个非常小众的网站,访客很少。我在EC2实例上有该站点。我按照上面的网站建议使用Load Balancer和Cloudfront来加密SSL。然而,它不起作用,无论如何它可能是矫枉过正的。谁能帮我这个?我想使用我支付的SSL证书,但如果没有,我应该使用像Lets Encrypt这样的东西吗?

1 个答案:

答案 0 :(得分:5)

你提到指南要说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

然后它表明你的&#34; f6f65901b1708ae5.crt&#34;文件是DER格式,而不是PEM格式。如果没有,那么您已经有了一个PEM文件,这是AWS ELB所期望的。如果您有DER格式的证书,则可以使用以下方法轻松转换为PEM格式:

$ openssl x509 -in f6f65901b1708ae5.crt -inform DER -out f6f65901b1708ae5.pem -outform PEM

我只是希望通过提及这部分来彻底。

现在假设我们知道那&#34; f6f65901b1708ae5.crt&#34;包含您域名的PEM格式证书,我们已准备好处理&#34;证书链&#34;一部分。

我看了GoDaddy的online certificate repository,看看&#34; gd_bundle-g2-g1.crt&#34;你提到的文件就在那里,它就是。 (这些文件可以公开获取,因为它们包含供任何人/每个人使用的公共证书。)查看该gd_bundle-g2-g1.crt文件,我发现它包含多个证书。这很重要。

参见&#34;证书链&#34;是一个提供信任路径(或&#34;链&#34;)的文件列表,来自&#34; f6f65901b1708ae5.crt&#34;证书您必须拥有受信任的根GoDaddy CA证书。每个证书都有一个主题(它是发给的人)和一个发行者(发布它的人)。这意味着您可以从证书到发行人的证书,向后走&#34;到该证书的发行人证书。向后走是证书链&#34;。

&#34; gd_bundle-g2-g1.crt&#34;文件包含多个证书意味着该文件包含您需要的证书链。这也意味着你想要这样做:

$ 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

然后,因为我们假设&#34; f6f65901b1708ae5.crt&#34;已经是PEM格式(如果没有,你知道如何在上面进行转换),我们知道那&#34; gd_bundle-g2-g1.crt&#34;已经进行了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,只是为了确保它不会覆盖/与您现有的配置冲突。作为建议,您可以包括创建上载证书的日期(或者,更好的是,当它将到期时),作为名称的一部分,作为您未来自我的暗示该证书已添加,例如&#34; redmatterapp_com-2016-02-18&#34;。

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

完成上述操作后,使用例如 AWS控制台,您应该能够配置您的AWS ELB,并在&#34; Listeners&#34;选项卡,单击&#34;编辑&#34;。为&#34; https&#34;添加一个监听器例如。添加任何支持SSL的侦听器时,您将看到&#34;更改&#34;链接显示在&#34; SSL证书&#34;列/选项卡。单击&#34;更改&#34;,然后选择&#34;现有证书&#34;按钮。在&#34;证书名称&#34;然后,您应该看到上面使用的--server-certificate-name字符串/标签的条目。选择该条目,然后单击&#34;保存&#34;。现在,应在AWS ELB上为该侦听器建立连接,以便为浏览器信任的SSL / TLS连接进行正确配置。

因此,HTTPS Listener配置看起来像:

  • 负载均衡协议: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名称的证书链; &#34;服务器证书&#34;部分应匹配&#34; f6f65901b1708ae5.crt&#34;你加载的PEM文件。

HTTPS和DNS

现在测试 HTTPS 部分;为此,我喜欢使用curl,就像这样:

$ curl -kv https://example.com/

-v选项显示更多信息,特别是证书是否与DNS名称匹配; -k告诉curl忽略任何证书不匹配/问题,以便我们可以看到有关事情的详细信息。

这是需要更多配置的地方。 如果您在curl命令(或浏览器)中使用自动生成的ELB DNS名称,那么您很可能会看到安全警告/问题。为什么?由于HTTPS的一部分正在验证您在URL 中使用的DNS名称与服务器证书中的域/主机名匹配,因此要么作为证书中的公用名(CN),或< / em>作为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 healtcheck。仔细检查用于ELB healtcheck的端口和路径/ URL是否正确,,任何防火墙或AWS安全组都允许从ELB连接到您的实例。

所以,现在你应该有一个ELB,它将端口80(HTTP)和端口443(HTTPS)转发到你的后端实例。并且您有&#34; www.example.com&#34;的CNAME记录。在DNS中指向该ELB名称。剩下的是什么?

HTTP重定向

高度建议您将HTTP服务器配置为始终重定向到相同网址的HTTPS等效项。为什么呢?

为了确保客户端与服务器之间的数据安全,现在需要使用SSL / TLS。以至于越来越多的浏览器首先自动尝试HTTPS,并且只是不情愿地使用HTTP作为后备。像Chrome(和其他人)这样的浏览器希望避免这种HTTP回退,以至于他们引入了HTTP Strict Transport Security这样的机制:您的网站告诉浏览器只能使用HTTPS的方式网站,永远不会HTTP 。此外,它总是一个更好的营销故事;事实上,如果您使用HTTPS,您可能会受到客户/用户的负面反应。

使用HTTPS为您的所有网站流量提供的另一件事是保护您免受:其他人使用其DNS名称和您的ELB。您有&#34; www.example.com&#34;的CNAME记录指向&#34; aws-elb-1.elb.amazonaws.com&#34;。但是,如果我为&#34; www.evilco.com&#34;创建我自己的CNAME,它指向相同的&#34; aws-elb-1.elb.amazonaws.com& #34 ;?人们前往&#34; www.evilco.com&#34;会看到您的网站,并认为它是我的网站!

通过强制您网站的所有流量为HTTPS,您强制所有HTTPS客户端验证服务器提供的证书您的&#34 ; f6f65901b1708ae5.crt&#34; file)包含公共名称(CN)或DNS主题备用名称(SAN),匹配客户端在其URL中使用的域名。显然,您的证书包含CN或DNS SAN,因为验证过程会失败 - 最终用户会看到有些东西是可疑的。但是,如果你的网站也允许HTTP流量,这种现象可能会发生 - 你看着你网站的日志,就永远不会知道!

后记

我自己没有使用过AWS证书管理器或CloudFront(因此我无法对它们发表评论),但我 多次使用上述过程,适用于多个域的多种证书配置。

希望这有帮助!