首页 文章

在Amazon EC2 ELB上安装SSL证书

提问于
浏览
2

我是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相关的知识),但是很难找到任何人做这样的任务(并且有必要的问题)交出登录详细信息等) . 任何帮助非常感谢 .

EDIT

以下建议是我应该使用AWS Certificate Manager . 如果那不浪费,我更愿意 . 我的任何工作都可以挽救吗?是否有意转售SSL证书?

EDIT

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

1 回答

  • 5

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

    证书

    首先,要确保"f6f65901b1708ae5.crt"包含您所请求的证书(并在那里放置任何疑问) . 为此,您可以比较"server.csr"文件中的数据(例如,公共名称(CN),DNS主题备用名称(SAN)等)(该"f6f65901b1708ae5.crt"文件中的's the Certificate Signing Request) with what':

    $ openssl req -noout -text < server.csr
    

    这应该在CSR文件中显示有关域的详细信息的人类可读文本 . 与之相比:

    $ openssl x509 -noout -text < f6f65901b1708ae5.crt
    

    这应该显示类似的人类可读文本,填写更多的细节/字段 . 但它们应该大致有你期望的 . Note 如果您看到类似于此的错误:

    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
    

    我只想提一下这一部分 .

    现在,假设我们 know 包含您域名的PEM格式证书,我们已准备好处理"certificate chain"部分 .

    我查看了GoDaddy的online certificate repository,看看你提到的"gd_bundle-g2-g1.crt"文件是否存在,而且确实如此 . (这些文件可以公开获取,因为它们包含供任何人/每个人使用的公共证书 . )查看gd_bundle-g2-g1.crt文件,我发现它包含多个证书 . 这个很重要 .

    请参阅"certificate chain"是提供信任路径(或"chain")的文件列表,从您拥有的证书到受信任的根GoDaddy CA证书 . 每个证书都有一个主题(发给它的人)和一个发行者(发行者) . 这意味着你可以步行"backward",从您的证书到发行人's certificate, to that certificate'发行人的证书等 . 这个向后走的是"certificate chain" .

    "gd_bundle-g2-g1.crt"文件包含多个证书的事实意味着该文件包含您需要的证书链 . 这也意味着你要做 not 想要这样做:

    $ 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格式化(如果不是,你知道如何在上面进行转换),并且 know "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" .

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

    完成上述操作后,使用例如在AWS Console中,您应该能够配置AWS ELB,并在"Listeners"选项卡下单击"Edit" . 添加一个监听器,例如为"https" . 添加任何支持SSL的侦听器时,您会在"SSL Certificate"列/选项卡下看到"Change"链接 . 单击"Change",然后选择"existing certificate"按钮 . 在"Certificate Name"下拉列表中,您应该看到上面使用的 --server-certificate-name 字符串/标签的条目 . 选择该条目,然后单击"Save" . 现在,应在AWS ELB上为该侦听器 Build 连接,以便为浏览器信任的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名称的证书链; “服务器证书”部分应与您加载的“f6f65901b1708ae5.crt”PEM文件匹配 .

    HTTPS和DNS

    现在来测试HTTPS部分;为此,我喜欢使用 curl ,如下所示:

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

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

    这是需要更多配置的地方 . If 您在 curl 命令(或浏览器)中使用自动生成的ELB DNS名称,那么您很可能会看到安全警告/问题 . 为什么?因为HTTPS的一部分正在验证您在URL中使用的DNS名称是否与服务器证书中的域/主机名匹配,可以是证书中的公用名(CN),也可以是DNS主题备用名称(SAN)之一 . 您可能没有在证书中包含ELB DNS名称向GoDaddy签署请求(CSR) .

    这意味着,下一步是配置指向AWS ELB名称的DNS CNAME记录,例如:

    www.example.com CNAME to aws-elb-1.elb.amazonaws.com
    

    如果您使用AWS进行DNS,那么您可以使用例如路由53.然后您重试 curl 命令(或浏览器):

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

    要注意的另一个重要事项(您可以在 curl -v 输出中看到这一点)是 Host 请求标头的内容 . 一些HTTP服务器(即在后端实例上运行的服务器)对那里的值非常挑剔;他们希望 Host 标头匹配其配置中的内容,如果不匹配,他们可能会拒绝该请求 .

    另一个常见的问题是:

    • HTTP 503服务不可用:后端服务器处于容量状态

    如果您从ELB获得此响应,通常意味着您的后端服务器没有响应或未能响应ELB healtcheck . 仔细检查用于ELB healtcheck的端口和路径/ URL是否正确, and 任何防火墙或AWS安全组都允许从ELB连接到您的实例 .

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

    HTTP重定向

    我建议将您的HTTP服务器配置为 always 重定向到相同URL的HTTPS等效项 . 为什么?

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

    有's another thing that using HTTPS for all your site'的流量保护您免受:其他人使用他们的DNS名称和您的ELB . 您有"www.example.com"的CNAME记录,指向"aws-elb-1.elb.amazonaws.com" . 但是如果我也为"www.evilco.com"创建自己的CNAME,它指向相同的"aws-elb-1.elb.amazonaws.com"怎么办?去"www.evilco.com"的人会看到 your 网站,并认为这是我的!

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

    后记

    我对它们发表了评论,但我已经多次使用上述过程,在多个作业中为多个域提供各种证书 .

    希望这可以帮助!

相关问题