启用 Let's Encrypt 证书
Let's Encrypt 由 ISRG(Internet Security Research Group,互联网安全研究小组)提供了免费、自动化、开放的证书签发服务,虽然证书只有 90 天有效期,但可以通过定时脚本更新,这里参照 imququ 的文章记录了在 CentOS 7 X64 上使用 acme-tiny 申请、配置以及定时更新证书的方法。
安装 openssl
yum install openssl-devel
创建帐号私钥
先创建一个目录 cert
用于存放各种临时文件,然后创建一个 RSA 私钥用于 Let's Encrypt 识别你的身份:
openssl genrsa 4096 > account.key
如果已经有 Let's Encrypt 账号了,那么需要把 JWK 格式的私钥转化为 acme-tiny 使用的 PEM 格式,这里使用了 JonLundy 的脚本 :
wget -O - "https://gist.githubusercontent.com/JonLundy/f25c99ee0770e19dc595/raw/6035c1c8938fae85810de6aad1ecf6e2db663e26/conv.py" > conv.py
cp /etc/letsencrypt/accounts/acme-v01.api.letsencrypt.org/directory/<id>/private_key.json private_key.json
openssl asn1parse -noout -out private_key.der -genconf <(python conv.py private_key.json)
openssl rsa -in private_key.der -inform der > account.key
创建 CSR(Certificate Signing Request,证书签名请求)文件
创建一个域名私钥(一定不要使用上面的账户私钥):
openssl genrsa 4096 > domain.key
如果要签发 ECC 证书,请使用以下任一命令生成 domain.key:
openssl ecparam -genkey -name secp256r1 | openssl ec -out domain.key
openssl ecparam -genkey -name secp384r1 | openssl ec -out domain.key
关于 ECC 证书的介绍请参考 imququ 的文章,然后生成 CSR 文件:
#单个域名
openssl req -new -sha256 -key domain.key -subj "/CN=yoursite.com" > domain.csr
#多个域名,目前一张证书最多可以包含 100 个域名,推荐至少把带 www 和不带 www 的域名加入
openssl req -new -sha256 -key domain.key -subj "/" -reqexts SAN -config <(cat /etc/pki/tls/openssl.cnf <(printf "[SAN]\nsubjectAltName=DNS:airycanon.me,DNS:www.airycanon.me")) > domain.csr
这里需要注意不同 Linux 发行版下 openssl 配置文件的路径,例如我用的 CentOS 是 /etc/pki/tls/openssl.cnf
,而有些发行版是 /etc/ssl/openssl.cnf
。
配置验证服务
Let's Encrypt 在签发证书时,需要验证域名所有权,具体做法是在你的服务器上生成一个随机验证文件,再通过创建 CSR 时指定的域名访问,如果可以访问则表明你对这个域名有控制权。
首先创建用于存放验证文件的目录:
mkdir /usr/share/nginx/html/cert/
然后配置一个 Nginx HTTP 服务:
server {
server_name www.airycanon.me airycanon.me;
location ^~ /.well-known/acme-challenge/ {
alias /usr/share/nginx/html/cert/;
try_files $uri =404;
}
location / {
rewrite ^/(.*)$ https://airycanon.me/$1 permanent;
}
}
这个验证服务以后更新证书还要用到,需要一直保留。
获取网站证书
#下载 acme-tiny 脚本
wget https://raw.githubusercontent.com/diafygi/acme-tiny/master/acme_tiny.py
#用上面的账户私钥、CSR 以及验证目录,执行脚本:
python acme_tiny.py --account-key ./account.key --csr ./domain.csr --acme-dir /usr/share/nginx/html/cert/ > ./signed.crt
如果一切正常,当前目录下就会生成一个 signed.crt,这就是申请好的证书文件。
在配置 HTTPS 证书时,既不要漏掉中间证书,也不要包含根证书,因此在 Nginx 配置中,需要把中间证书和网站证书合在一起:
# 获取中间证书
wget -O - https://letsencrypt.org/certs/lets-encrypt-x1-cross-signed.pem > intermediate.pem
# 合并中间证书和网站证书
cat signed.crt intermediate.pem > chained.pem
在需要启用证书的 Nginx 配置中加入如下两项:
ssl_certificate ~/cert/chained.pem;
ssl_certificate_key ~/cert/domain.key;
最后重新加载 Nginx 配置即可:
systemctl reload nginx
配置自动更新
前面提到 Let’s Encrypt 签发的证书只有 90 天有效期,但可以把上面操作写到脚本中:
#!/bin/bash
cd /usr/share/nginx/cert
python acme_tiny.py --account-key account.key --csr domain.csr --acme-dir /usr/share/nginx/html/cert/ > signed.crt || exit
wget -O - https://letsencrypt.org/certs/lets-encrypt-x1-cross-signed.pem > intermediate.pem
cat signed.crt intermediate.pem > chained.pem
systemctl reload nginx
然后加入 crontab 定时更新:
0 0 1 * * /usr/share/nginx/cert/update.sh >/dev/null 2>&1