使用acme.sh签发Wildcard ECC+RSA双证书

Posted by EtaoinWu on 周六 19 一月 2019

前两天收到 Let's Encrypt 发来的邮件 , 说现在的证书的验证方式是 TLS-SNI-01 , 即将结束支持 。 趁着这个机会 , 顺便把之前一直攒着的想换外卡和想换 ECC 的两个小坑填了 。

第一个要解决的问题是 Nginx。Nginx 在 Ubuntu 16.04 源里的最近版本是 v1.10.4, 并不支持写多个 tls_certificate 命令 , 这样就没法配置双证书 。 因此解决方案是

sudo apt-add-repository ppa:nginx/stable
sudo apt update
sudo apt remove nginx nginx-core nginx-common
sudo apt install nginx

最后一步会询问你是否覆盖配置文件 , 默认填 N 就好了 。

第二步是安装 acme.sh 。 这里我先吐槽一下 , Certbot 是真的难用 。

# Root shell
curl https://get.acme.sh | sh
# or you can use wget if you prefer
# wget -O -  https://get.acme.sh | sh
source .bashrc

然后就可以签发证书了 。

讲一下证书验证 ( ACME challenge ) 吧 。 签发一个证书之前需要验证该域名属于你 。Let's Encrypt 目前支持这么几种验证方式 : 在 DNS 里加入 TXT 记录 ; 通过 http(s) 访问某子目录进行验证 ; 通过 SNI 进行验证 ( 即将废弃 ); 通过 ALPN 进行验证 ; 等 。 我个人使用的是 Aliyun 来进行 DNS 管理的 , 恰好 acme.sh 提供了阿里云的 dns api, 可以方便很多操作 。 需要现在阿里的控制台里面签一个 AccessKey 出来 ; 如果使用 RAM 权限控制 , 需要给出 DNS 的读写权限 。

export Ali_Key="sdfsdfsdfljlbjkljlkjsdfoiwje"
export Ali_Secret="jlsdflanljkljlfdsaklkjflsa"

acme.sh --issue --dns dns_ali -d example.com -d *.example.com
# You need to wait 120s for the TXT record to take effect

注意 , 只签 *.example.com 是不行的 , 会导致根域名无法访问 。

这里签发了一张 RSA 的证书 。 如果要签 ECC 的 , 需要额外执行一步

acme.sh --issue --dns dns_ali -d example.com -d *.example.com --keylength ec-384
# OR:
acme.sh --issue --dns dns_ali -d example.com -d *.example.com --keylength ec-256

签发完了之后 , 证书会存在 ~/.acme.sh/ 中 , 这是一个临时目录 , 可能会随着 acme.sh 的更新而变化 , 不应该用来直接引用 , 所以要安装证书到特定位置 。

acme.sh --install-cert -d example.com \
--key-file       /etc/letsencrypt/keys/rsa.key.pem  \
--fullchain-file /etc/letsencrypt/keys/rsa.cert.pem \
--reloadcmd     "service nginx force-reload"
acme.sh --install-cert -d example.com --ecc \
--key-file       /etc/letsencrypt/keys/ecc.key.pem  \
--fullchain-file /etc/letsencrypt/keys/ecc.cert.pem \
--reloadcmd     "service nginx force-reload"

之后将以下代码加入到 nginx 配置文件即可 。

ssl_certificate /etc/letsencrypt/keys/ecc.cert.pem;
ssl_certificate_key /etc/letsencrypt/keys/ecc.key.pem;

ssl_certificate /etc/letsencrypt/keys/rsa.cert.pem;
ssl_certificate_key /etc/letsencrypt/keys/rsa.key.pem;

另外 , 为了拿到 A+ , 还有一个加密算法优先级的问题 ; 本站自用的 :

ssl_ciphers "ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES256-SHA:ECDHE-ECDSA-DES-CBC3-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:DES-CBC3-SHA:!DSS";