0%

Lets Encrypted 免费Https证书 通配符/泛域名

https://letsencrypt.org 支持免费的https证书。但是有效期只有三个月,因此要定时更新。

现在也支持 泛域名证书(如*.example.com),无需为每个域名单独签发证书。

生成证书和更新证书要使用客户端工具,官方推荐是 cerbot-auto 但是感觉 acme.sh 更好用。因此本文只介绍后者。

这两个客户端工具都是通过ACME协议与证书颁发机构通信来管理https证书。

CA 即 Certificate Authority 证书签发机构

ACME protocol 即 Automatic Certificate Management Environment 自动证书管理环境。是证书颁发机构和用户服务器之间的自主交互的通信协议。

acme 的使用

https证书使用大致分如下几步

  1. 获取客户端工具
  2. 签发证书
  3. 配置nginx的https
  4. 配置自动更新

Step1. 获取客户端工具

1.直接安装(推荐)

默认安装到 /root/.acme.sh/

1
curl https://get.acme.sh | sh

2.使用docker

参考:https://github.com/Neilpang/acme.sh/wiki/Run-acme.sh-in-docker

1
docker run --rm neilpang/acme.sh

两种方式都是为了获取acme.sh脚本。因此直接安装的使用方式是

1
/path/to/acme.sh --arg1 --arg2

dcoker的使用方式是

1
2
docker run --rm -it -v "$(pwd)/out":/acme.sh --net=host neilpang/acme.sh \
--arg1 --arg2

我觉得也可以将对docker的操作封指定别名操作更方便,但是没有试过。 如:

1
2
alias acme-docker='docker run --rm -it -v "$(pwd)/out":/acme.sh --net=host neilpang/acme.sh'
acme-docker --arg1 --arg2

Step2. 签发证书(issue操作)

签发证书有多种方式,其目的是为了证明对域名的拥有权。仅介绍两种最方便的:

  1. 通过添加一条 txt 类型的域名解析
  2. 通过在网站根目录放置文件

方法1.txt类型域名解析(支持泛域名的唯一方式)

该方法分自动(推荐)和手动。自动方式需要域名商提供API,配置Key和Secret即可支持自动签发和更新证书。

以阿里云域名解析为示例,自动操作如下:

1
2
3
4
5
#在shell中设置变量
export Ali_Key="sdfsdfsdfljlbjkljlkjsdfoiwje"
export Ali_Secret="jlsdflanljkljlfdsaklkjflsa"
#签发证书
acme.sh --issue --dns dns_ali -d example.com -d *.example.com

所有支持的DNS服务商:https://github.com/Neilpang/acme.sh/wiki/dnsapi

注意事项:通配符/泛域名解析,需要同时指定根域名和泛域名,如:-d 'example.com' -d '*.example.com'

手动操作流程如下:

  1. 先执行一下签发(issue)操作。这一步会失败,但只是为了获取需要做解析的txt文本
  2. txt类型的域名解析,需要解析的子域名和值都会在执行上个操作后高亮显示出来
  3. 等解析成功后,重新生成证书(renew)
1
2
3
4
5
6
7
#1.先执行签发 获取需要做解析的txt文本
/root/.acme.sh/acme.sh --issue --dns -d 'example.com' -d '*.example.com' \
--yes-I-know-dns-manual-mode-enough-go-ahead-please
#2.到阿里云做域名解析
#3.等域名解析成功后,做renew操作
/root/.acme.sh/acme.sh --renew --dns -d 'example.com' -d '*.example.com' \
--yes-I-know-dns-manual-mode-enough-go-ahead-please

注意事项:手动签发便于测试,但不建议用在生产环境。因为每次证书更新都必须手动重新签发(issue) 更新txt域名解析,生成(renew)

手动配置的txt类型解析,在证书生成后可以手动删掉

方法2.指定网站根目录(不支持泛域名)

该方法不支持泛域名,但是支持自动更新。其更新原理也是在 root 账户的 crontab 脚本添加定时任务。

颁发证书(issue操作)

1
2
/root/.acme.sh/acme.sh --issue -d 'example.com' -d 'www.example.com' \
--webroot /path/to/web-root/

Step3. 配置nginx

证书签发后会告诉我们生成证书的路径

1
2
3
4
[Sat May 15 18:22:40 CST 2021] Your cert is in  /root/.acme.sh/example.com/example.com.cer
[Sat May 15 18:22:40 CST 2021] Your cert key is in /root/.acme.sh/example.com/example.com.key
[Sat May 15 18:22:40 CST 2021] The intermediate CA cert is in /root/.acme.sh/example.com/ca.cer
[Sat May 15 18:22:40 CST 2021] And the full chain certs is there: /root/.acme.sh/example.com/fullchain.cer

但是这个非常不建议直接用,因为这是acme自己内部用的。而且它提供了一个用于安装到指定路径的命令,该命令还要指定用于 Reload 的命令,用于证书自动更新的时候重新加载证书。

所以我们先确定路径,并配置到nginx中

  • 证书文件:/data/https-cert/example.com/fullchain.cer
  • 私钥文件:/data/https-cert/example.com/example.key
  • 证书颁发机构的证书 /data/https-cert/example.com/ca.cer,如果不启用 OCSP,可以不配(nginx 默认关闭)。
1
2
3
4
5
6
7
8
# domain自行替换成自己的域名
server {
server_name example.com www.example.com;
listen 443 http2 ssl;
ssl_certificate /data/https-cert/example.com/fullchain.cer;
ssl_certificate_key /data/https-cert/example.com/example.key;
ssl_trusted_certificate /data/https-cert/example.com/ca.cer; #本行可不配
}

如果既要https又要http

1
2
3
4
5
6
7
8
server {
listen 80;
listen 443 ssl;
#ssl on; #这一行要注释掉

ssl_certificate /data/https-cert/example.com/fullchain.cer;
ssl_certificate_key /data/https-cert/example.com/example.key;
}

如果要http跳转到https

1
2
3
4
5
server{
listen 80;
server_name example.com www.example.com;
rewrite ^(.*)$ https://$host$1 permanent;
}

然后可以将证书复制到指定位置并 reload 服务器

1
2
3
4
5
6
acme.sh --installcert -d 'example.com' -d 'www.example.com' \
--fullchain-file /data/https-cert/example.com/fullchain.cer \
--key-file /data/https-cert/example.com/example.key \
--ca-file /data/https-cert/example.com/ca.cer \
--reloadcmd '/usr/local/nginx/sbin/nginx -s reload'
# 最后一行用于更新证书后重启服务器

Step4. 自动更新证书

对于通过自动DNS解析和网站根目录放置文件的方式,acme.sh支持自动更新,无需任何操作。首次执行的时候其会记录相关配置,如域名、 App_key、App_Secret等。然后在root账户下生成一个定时任务。

1
2
[root@localhost /]# crontab -l
4 0 * * * "/root/.acme.sh"/acme.sh --cron --home "/root/.acme.sh" > /dev/null

可以看出每天0点4分执行一次。

此外,当证书更新后要重启nginx,reload的指令在 /root/.acme.sh/example.com/example.com.conf

1
Le_ReloadCmd='__ACME_BASE64__START_L3Vzci9sb2NhbC9uZ2lueC9zYmluL25naW54IC1zIHJlbG9hZA==__ACME_BASE64__END_'

这个行命令是经过 base64转码的,比如我这里转码后是 L3Vzci9sb2NhbC9uZ2lueC9zYmluL25naW54IC1zIHJlbG9hZA==

解码后是:/usr/local/nginx/sbin/nginx -s reload

手动DNS解析的方式,临近到期前需要手动重新走一遍签发、更新TXT解析、更新证书的流程

参考