Let's Encrypt通配符证书申请方法
Let's Encrypt于2018年3月14日在社区宣布支持通配符证书(Wildcard certificates)。
通配符证书可以使同一域名下的所有子域名使用同一个证书,对于拥有大量域名的用户来说,大大减少了证书申请和维护工作。下面简要介绍Let's Encrypt通配符证书的申请方法。
证书申请
Let's Encrypt使用ACME协议验证域名所有权并分配证书,为申请证书首先需要选取实现ACME协议的客户端。
Let's Encrypt证书申请时,需要验证域名的所有权,官方支持三种验证方式:
- http-01: 在域名对应的 Web 服务器下放置一个 HTTP well-known URL 资源文件。
- tls-sni-01: 在域名对应的 Web 服务器下放置一个 HTTPS well-known URL 资源文件。
- dns-01: 给域名添加一个 DNS TXT 记录。
申请Let's Encrypt通配符证书需要注意的事情如下:
- 必须使用dns-01验证方法。
- 必须使用支持ACME v2版本的客户端。
- 需要指定server路径: https://acme-v02.api.letsencrypt.org/directory
- *.example.com不包含example.com,需分别申请。
- *.example.com和www.example.com 不可同时申请,因为前者已包含后者。
官方给出了支持ACME v2的客户端列表,本文选取官方推荐的客户端Certbot,并使用Docker环境申请证书。
假设证书在本地的存放位置为letsencrypt文件夹,日志存放位置为log文件夹,执行如下命令申请证书:
$ docker run -it --rm \
-v path/to/letsencrypt/:/etc/letsencrypt/ \
-v path/to/log/:/var/log/letsencrypt/ \
certbot/certbot:v0.26.1 \
certonly \
--email your@email.com \
--agree-tos \
--manual \
--preferred-challenges dns-01 \
--server https://acme-v02.api.letsencrypt.org/directory \
-d *.yourdomain.com \
-d yourdomain.com
替换其中的邮件和域名,运行后根据提示为域名添加DNS TXT记录,以验证域名所有权。生成的证书存放在本地letsencrypt文件夹中。
证书使用
申请的证书保存在letsencrypt/live/youdomain.com文件夹下,其中四个文件的说明如下:
privkey.pem: 证书私钥。fullchain.pem: 大多数服务器使用的证书文件。chain.pem: 用于OCSP stapling(Nginx >=1.3.7)。cert.pem: 在进一步阅读相关文档前不要使用。
以Nginx服务器为例,在其配置文件中添加如下配置:
ssl on;
ssl_certificate path/to/letsencrypt/live/yourdomain.com/fullchain.pem;
ssl_certificate_key path/to/letsencrypt/live/yourdomain.com/privkey.pem;
证书更新
证书的有效期为90天,在到期前需要手动进行更新,Certbot中可使用renew对申请的证书进行更新,可执行命令如下:
$ docker run -it --rm \
-v path/to/letsencrypt/:/etc/letsencrypt/ \
-v path/to/log/:/var/log/letsencrypt/ \
certbot/certbot:v0.26.1 \
renew
当证书有效期小于30天时,该命令会对证书进行更新。为防止手动更新的麻烦,可创建脚本文件certbotrenew.sh如下:
#!/bin/bash
$ docker run -it --rm \
-v path/to/letsencrypt/:/etc/letsencrypt/ \
-v path/to/log/:/var/log/letsencrypt/ \
certbot/certbot:v0.26.1 \
renew
若使用的服务器为Nginx,在证书更新完成后,服务器不会自动加载证书,需要重启服务器。可创建crontab计划任务,定期执行脚本检查证书,若证书更新后(通过文件修改时间判断)自动重启服务器。脚本文件(checkservice.sh)如下:
#!/bin/bash
timestamp=`date`
echo $timestamp "====renew certbot====" >> path/to/renew.log
path/to/certbotrenew.sh
modifytime=`stat -c %Y path/to/letsencrypt/live/datarepo.cn/fullchain.pem`
nowtime=`date +%s`
if [ $[ $nowtime-$modifytime ] -lt 1800 ]; then
echo $timestamp "====restart nginx====" >> path/to/renew.log
path/to/restartnginx.sh
else
echo $timestamp "====no need to restart====" >> path/to/renew.log
其中restartnginx.sh为重启Nginx服务器的命令。
创建crontab计划任务,每周五0点0分执行checkservice.sh。
0 0 * * 5 path/to/checkservice.sh