Let's Encrypt 证书

之前在《Nginx 配置 HTTPS 服务器》有提到过,配置 HTTPS 可以在一些提供免费 SSL 证书的 CA 申请证明,此前本站正是用 StarCom 提供的 DV 证书。

然而,就在2016年10月底和11月底,Google 和 Mozilla 以及 Apple 相继宣布,不再信任所有 StarCom 根证书!于是乎,使用 StarCom SSL 证书的 https 站点页面在 Chrome 上就变成各种『红X』页面:

Chrome不信任 StarCom证书

StarCom 站点看了下,也有了正式公告:

Mozilla and Google decided to distrust all StartCom root certificates as of 21st of October, 2016, meaning that since January all the SSL certificates issued from that date will no longer be trusted in Firefox and Chrome newest releases.
Besides, Google has gone further and as explained here:
https://security.googleblog.com/2016/10/distrusting-wosign-and-startcom.html will not trust even those SSL certificates issued before that date until the final disruption.

Apple’s decision announced on Nov 30th, 2016 was to distrust all StartCom root certificates as of 1st of December, meaning that SSL cert issued after December 1st, 2016 will no longer be trusted in Apple’s systems.

如此看来,StarCom 的 DV 免费证书是不能用了,虽说 StarCom 承诺在未来的 6 个月里会忍受着巨损去按照 Mozilla 的要求对所有系统做优化更新,但细想一下,抛弃StarCom 会稳一点。

于是发现了不少大神推荐的Let's Encrypt, 一个免费、自动化、开放的 CA,由非盈利性小组 Internet Security Research Group(ISRG,互联网安全研究小组)提供服务,详细介绍可以参考 About Let’s Encrypt

使用 acme-tiny 安装 Let’s Encrypt 证书

申请 Let's Encrypt 证书可有 90 天的有效期,之后需要重新申请,但可以通过脚本自动更新有效期。官网推荐通过 Certbot ACME 客户端 完成安装,过程较繁琐,本博使用了 acme-tiny 这个简便的开源工具完成了证书申请,该工具还提供了自动续期的方法。

1、创建 Let’s Encrypt 帐号私钥

创建一个目录,如 domain_ssl,用于存放证书相关各种文件,然后创建一个用于 Let’s Encrypt 验证身份的 RSA 私钥:

1
openssl genrsa 4096 > account.key

2、创建 CSR 文件

Let's Encrypt 使用的 ACME 协议,需要使用 CSR 文件,为此要专门为申请的域名创建一个 RSA 私钥(注意,这里不能使用 account.key 作为域名私钥

1
openssl genrsa 4096 > domain.key

创建了私钥后,就可以创建 CSR 文件了

1
openssl req -new -sha256 -key /domain_ssl/domain.key -subj "/" -reqexts SAN -config <(cat /domain_ssl/openssl.cnf <(printf "[SAN]\nsubjectAltName=DNS:domain.com,DNS:sub.domain.com"))
  • -key /domain_ssl/domain.key 域名私钥
  • [SAN]\nsubjectAltName=DNS:domain.com,DNS:sub.domain.com" 需要配置的域名,目前一张 Let's Encrypt 证书最多可包含 100 个

如果没有 openssl.cnf 配置文件,会报错,需要自己配置一个 openssl.cnf 文件

[ req ]
distinguished_name = req_distinguished_name

[ req_distinguished_name ]
commonName_default = domain.com
commonName_max = 64
organizationName_default =
organizationalUnitName_default =
localityName_default = ShenZhen
stateOrProvinceName_default = GuangDong
countryName_default = CN 

完成后会在当前目录生成 domain.csr 文件

3、生成 Let’s Encrypt 证书 signed.crt 文件

首先要下载 acme_tiny.py 脚本

1
wget https://raw.githubusercontent.com/diafygi/acme-tiny/master/acme_tiny.py

执行 acme_tiny.py 脚本前需要创建一个用于验证服务器所有权的路径,如 /home/www/challenges,创建完 challenges 后,执行脚本:

1
python acme_tiny.py --account-key /domain_ssl/account.key --csr /domain_ssl/domain.csr --acme-dir /home/www/challenges/ > /domain_ssl/signed.crt

执行完后,会在当前目录生成 signed.crt 证书文件

4、下载 Let’s Encrypt 中间证书

nginx 系统需要将 Let’s Encrypt 中间证书合并到 signed.crt 证书文件

1
2
wget -O - https://letsencrypt.org/certs/lets-encrypt-x3-cross-signed.pem > /domain_ssl/intermediate.pem
cat /domain_ssl/signed.crt /domain_ssl/intermediate.pem > /domain_ssl/chained.pem

之后再到配置文件进行相关配置,再 reload nginx 服务就可以了

1
2
ssl_certificate /domain_ssl/chained.pem;
ssl_certificate_key /domain_ssl/domain.key;

自动更新证书有效期

首先要到 /usr/bin 创建 renew_cert.sh,记得赋于相关执行权限

1
chmod a+x renew_cert.sh

编辑 renew_cert.sh 文件

1
2
3
4
#/usr/bin
python /domain_ssl/acme_tiny.py --account-key /domain_ssl/account.key --csr /domain_ssl/domain.csr --acme-dir /home/www/challenges/ > /domain_ssl/signed.crt || exit
wget -O - https://letsencrypt.org/certs/lets-encrypt-x3-cross-signed.pem > /domain_ssl/intermediate.pem
cat /domain_ssl/signed.crt /domain_ssl/intermediate.pem > /domain_ssl/chained.pem

重启 nginx 服务后,用 crontab -e 在 crontab 写入

1
2
# 每月运行一次
0 0 1 * * /domain_ssl/renew_cert.sh 2>> /var/log/acme_tiny.log

OK,到此大功告成。