通过 Certbot 工具申请 Let's Encrypt SSL 证书

一、简要概述

Certbot 是一个免费、开源、自动化的 ACME 客户端工具,可用于申请 Let’s Encrypt SSL 证书。它可以帮助网站管理员轻松地实现 HTTPS 等功能,提高网站的安全性和可靠性。

  • ACME 协议:定义了客户端(通常是证书申请者或服务器管理员)和证书颁发机构之间的交互过程。ACME 客户端使用 ACME 协议与证书颁发机构的 ACME 服务端进行通信,实现自动申请证书、证明域名所有权、获取证书、以及在证书到期前续订证书等功能。
  • Let’s Encrypt:一个免费的证书颁发机构,支持 ACME 协议进行证书申请和维护。
  • Let’s Encrypt SSL 证书:由 Let’s Encrypt 颁发机构颁发的 SSL 证书,使用了 SHA-256 签名算法,并支持最新版本的 TLS 协议,因此可以提供强大的加密和认证保护,保障网站和用户数据的安全。同时,Let’s Encrypt 证书的根证书已被所有主流浏览器信任,这意味着用户不需要手动添加任何信任条目或 CA 证书到浏览器中。

提示:Certbot 是使用 Python 编写的,因此在使用之前需要确保系统上已经安装了 Python 解释器和相关依赖库(一般 Linux 服务器都默认安装有 Python)。

官方文档:https://certbot.eff.org/docs

二、安装 certbot

1. 通过系统默认包管理器安装旧版 certbot

通过系统默认包管理器安装的版本通常是 certbot v1 的旧版,虽然不同使用没有什么问题,但是在使用一些高级功能(如:DNS 插件)等可能会出现版本不支持的问题。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#apt安装certbot
apt install -y certbot

#yum安装certbot
yum install -y epel-release
yum install -y certbot

#通过查看certbot版本验证安装是否成功
certbot --version

##卸载certbot(如需要)
yum remove -y certbot #yum卸载
apt remove -y certbot #apt卸载
#删除残余目录或文件(包括证书)
rm -rf /var/lib/letsencrypt /etc/letsencrypt

💁‍♂ 提示:certbot-auto 是较旧的版本,官方已不再支持。

2. 通过 pip 包管理器安装最新版 certbot

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
#通过 pip 安装最新版 certbot,要求 python 3.6+,故需要在系统中安装版本高于 3.6 的 python 版本。可以借助 pyenv 来安装任意版本的 python。

#(1)安装依赖
yum install -y gcc make patch zlib-devel bzip2 bzip2-devel readline-devel sqlite sqlite-devel openssl-devel tk-devel libffi-devel xz-devel

#(2)安装pyenv
wget -O pyenv-2.3.17.tar.gz https://github.com/pyenv/pyenv/archive/refs/tags/v2.3.17.tar.gz
tar -zxvf pyenv-2.3.17.tar.gz
mv pyenv-2.3.17 ~/.pyenv

#(3)配置环境变量
#添加环境变量。cat后的>>表示追加,>则表示覆盖。<< 后的EOF用引号可以避免$赋值,如果希望赋值则不加引号
cat >> ~/.bashrc << 'EOF'

export PYENV_ROOT="$HOME/.pyenv"
export PATH="$PYENV_ROOT/bin:$PATH"
if command -v pyenv 1>/dev/null 2>&1; then
eval "$(pyenv init -)"
fi
EOF

#(4)使环境变量生效
source ~/.bashrc

#(5)安装python版本
pyenv install 3.7.0

#(6)设置全局python版本(系统全局环境使用的版本)
pyenv global 3.7.0

#(6)升级指定python版本的pip版本
pip install --upgrade pip

#(7)通过指定python版本的pip安装certbot
pip install certbot

#(8)安装指定版本的urllib,防止certbot运行报错
pip install 'urllib3<2.0'

#(9)链接certbot到系统/usr/bin目录里
ln -s /root/.pyenv/versions/3.7.0/bin/certbot /usr/bin/certbot

#(10)查看certbot版本
certbot --version

#(11)升级certbot版本(如需要)
pip install --upgrade certbot

#(12)改回系统原本自带的python版本(如需要)
pyenv global system

参考:https://certbot.eff.org/instructions?ws=nginx&os=pip

3. 通过 snap 包管理器安装最新版 certbot

提示:通过 snap 包管理器可以安装最新版的 certbot,这也是 certbot 官方推荐的安装方式,但相对于系统默认包管理器的安装方式, snap 的安装包文件占用更大,如果服务器磁盘空间不够的话并不建议使用,另外snap 的管理命令也需要有一定的学习成本,其实目前系统默认包管理器安装的旧版 certbot 已经足够日常使用了,不一定非要使用 snap。

卸载旧版 certbot(如有)

1
2
3
4
#apt卸载
apt remove -y certbot
#yum卸载
yum remove -y certbot

安装 snap

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
##(1)安装snapd
# apt安装(提示:ubuntu16.04之后的版本已经内置了snap,在debian系统上则需要手动安装)
apt update
apt install -y snapd

# yum安装(操作命令相对会多一些)
yum install -y epel-release
yum install -y snapd

##(2)启动snad的套接字单元
# 启动snapd套接字单元(注意套接字单元是snapd.socket,而不是snapd.service,其中snapd.service可简写为snapd)
systemctl enable --now snapd.socket #等同于 sudo systemctl enable snapd.socket && sudo systemctl start snapd.socket
# 查看是否成功启动snapd
systemctl status snapd.socket

##(3)需要注销并重新登录(重新打开终端即可)或重新启动系统以确保正确更新snap的路径
exit

##(4)安装snap核心包
# 安装snap核心包
snap install core
snap refresh core

##(5)配置支持snap经典模式安装(仅yum安装snap时需要)
# 说明:由于snap经典模式安装需要操作/snap目录。通过yum安装snapd时,snap所安装的经典包存放在/var/lib/snapd/snap目录中而非/snap目录,所以需要创建一个符号链接/snap指向到/var/lib/snapd/snap,否则snap只能安装标准包而无法安装经典包。而使用apt安装snapd时,snap所安装的经典包就存放在/snap目录中,故而不需要创建符号链接。
ln -s /var/lib/snapd/snap /snap

snap 安装参考:https://snapcraft.io/docs/installing-snapd

报错解决:

  • (1)snap install core 时如果报错提示:error: system does not fully support snapd: open /tmp/syscheck-squashfs-1411954570: no such file or directory,只需重启系统重试即可解决。

安装 certbot

1
2
3
4
5
6
#通过snap安装certbot
snap install --classic certbot
ln -s /snap/bin/certbot /usr/bin/certbot

#通过查看certbot版本验证安装是否成功
certbot --version

certbot 安装参考:https://certbot.eff.org

卸载 certbot(如需要)

1
2
3
4
#卸载certbot
snap remove certbot
#删除残余目录或文件(包括证书)
rm -rf /var/lib/letsencrypt /etc/letsencrypt /usr/bin/certbot

卸载 snap

1
2
3
4
5
6
7
8
9
10
11
12
13
#关闭snapd套接字单元(卸载前先停掉snapd套接字单元,否则卸载失败)
systemctl stop snapd.socket

##卸载snap
#1、yum卸载
yum remove -y snapd
#删除残余目录或文件
rm -rf /var/lib/snapd /snap ~/snap

#2、apt卸载
apt remove --purge -y snapd #如果不加--purge则需要手动删除/var/lib/snapd和/snap
#删除残余目录或文件
rm -rf ~/snap

三、申请签发证书

1. 简要概述

需要说明的是:在 Certbot 申请证书时,证书是由 Let’s Encrypt 官方 ACME 服务器生成的,而不是由本地服务器生成的。Certbot 将向 Let’s Encrypt CA(证书颁发机构)发出签发请求,并将验证域名的控制权。一旦验证通过,Let’s Encrypt 将向 Certbot 返回 SSL 证书,以便在您的 Web 服务器上部署和使用。

2. certbot 常用的选项和参数

  • --webroot:使用自动 HTTP 验证方式方式(默认模式)。在 .well-known/acme-challenge/ 路径下创建一个临时文件,并通过 HTTP 获取该文件来验证域名所有权。

  • --manual:手动模式,该模式需要您手动执行一些步骤,例如在 DNS 记录中添加 TXT 记录以验证域名所有权。

  • --nginx:使用 Nginx Web 服务器插件。该模式允许 Certbot 自动配置 Nginx Web 服务器,以便验证域名所有权并部署证书。

  • --apache:使用 Apache Web 服务器插件。该模式允许 Certbot 自动配置 Apache Web 服务器,以便验证域名所有权并部署证书。

  • --standalone:使用独立 Web 服务器插件。该模式允许 Certbot 在自己的 Web 服务器(standalone)上运行,以验证域名所有权和颁发证书

  • --server: ACME 服务器地址。默认为 Let’s Encrypt 官方 ACME 服务器地址,即:https://acme-v02.api.letsencrypt.org/directory

  • --domains DOMAIN(简写:-d DOMAIN):要签发证书的域名。如:-d example.com

  • --staging:签发测试环境证书。

  • --cert-name CERTNAME:为证书命名。

  • --expand:更新现有证书以包括新的子域名。

  • --duplicate:复制现有证书。

  • --reinstall:重新安装现有证书。

  • --force-renewal:在有效期内强制更新证书。

  • --email EMAIL(简写:-m EMAIL):账号邮箱地址。可用于自动注册 ACME 账号,还可用于证书到期前 20 天、10 天和 1 天时接收到到期通知邮件。如:--email [email protected]

  • --agree-tos:同意 Let’s Encrypt 的服务条款,并接受由 Let’s Encrypt 颁发的 SSL/TLS 证书。如果您不同意服务条款,则无法使用 Let’s Encrypt 颁发的证书。

  • --preferred-challenges PREF_CHALLENGES:首选的域名所有权验证类型。如:--preferred-challenges dns-01

    支持的验证类型如下:

    (1)http-01:默认验证方法,将向公开在 HTTP 上运行的 Web 服务器发送请求,在 .well-known/acme-challenge/ 路径下创建一个临时文件,并通过 HTTP 获取该文件来验证您拥有该域名。

    (2)dns-01:使用 DNS 记录验证域名所有权。此方法需要您手动更新相应的 DNS 记录。在 DNS 记录更新后,Let’s Encrypt 将使用 DNS 查找该记录以验证您拥有该域名。

    (3)tls-sni-01:已弃用,不再使用。原本是在 HTTPS 连接的 SNI 扩展中发送验证信息,但由于安全问题而被弃用。

    (4)tls-alpn-01:一种基于 TLS 的验证方法,它使用新的 ALPN 协议扩展来发送验证信息。与 tls-sni-01 不同,它不会公开任何信息,因此更加安全。

  • --non-interactive:禁用交互式模式。(默认certonly 命令是交互式的)

  • --no-eff-email:禁止发生统计信息邮件给EFF。(默认情况下,Certbot 在生成 SSL/TLS 证书时会向 EFF 发送电子邮件,以便收集有关证书使用情况的统计信息)

  • --dry-run:测试证书颁发流程,但不实际签发证书。

  • -h:获取帮助信息。

  • --version:查看 Certbot 版本号。

  • --config-dir CONFIG_DIR:指定配置文件目录。

  • --work-dir WORK_DIR:指定工作目录。

  • --logs-dir LOGS_DIR:指定日志目录。

💁‍♂ 说明:如果不指定选项和参数,则一些必要的选项参数将会在交互式命令中要求指定。

3. Let’s Encrypt 证书申请请求限制

  • 生产环境限制

    • 每个域名/证书每周最多只能签发 5 次

    • 每个 IP 地址每小时最多能提交 300 个证书申请请求

  • 测试环境限制(certbot 使用 --staging 选项时)

    • 测试环境下颁发的证书无法被浏览器或操作系统信任
    • 测试环境下每个域名/证书每周最多可签发 50 次
    • 测试环境下每个 IP 地址每小时最多能提交 300 个请求
    • 测试环境下没有通过 HSTS 预载的域名(生产环境支持通过 HSTS 预载的域名)

4. 申请证书方式

Let’s Encrypt CA(ACME 服务器)判断是否允许用户申请域名对应的证书,需要验证用户是否为域名的拥有者,只有确定用户为域名拥有者才能签发证书。

方式1:自动 HTTP 验证方式申请证书

简要概述:

(1)certbot(ACME 客户端)会在 Web 服务器的根目录下自动创建一个特定的临时文件(即:.well-known/acme-challenge/<random_token> ),然后 Let’s Encrypt CA(ACME 服务器)通过 HTTP 协议请求访问此文件(访问地址:http://example.com/.well-known/acme-challenge/<random_token>),访问到该文件则说明用户对域名具有控制权,通过用户的控制权情况间接确定用户是否是域名的拥有者。

(2)如果验证确定用户是域名的拥有者,则允许为其签发生成 SSL 证书,否则申请失败。

(3)验证完成并签发生成证书后,certbot 会自动删除 Web 服务器根目录下的.well-known临时目录文件。

1)单域名证书

准备工作:

(1)需要有一个需要申请证书的域名。如:example.com

(2)需要有一台拥有公网 IP 的服务器,并且公网服务器里运行有 Web 服务(如:nginx,tomcat等)

(3)需要提前在 DNS 服务提供商的管理后台里把需要申请证书的域名解析到服务器的公网 IP 上

1
2
3
4
5
6
#自动 HTTP 验证方式申请签发单域名证书(模板)(可加 --staging 选项来申请签发测试环境的证书)
certbot certonly \
--agree-tos --no-eff-email \
--webroot -w /opt/nginx/html \
-m [email protected] \
-d example.com

💁‍♂ 说明:

  • --webroot:指定 certbot 创建临时文件所在的 Web 服务器根目录路径。

除了通过指定--webroot选项使用自动 HTTP 验证方式外,还可以仅使用 --preferred-challenges http-01 (或都不指定,因为 http-01 是默认值),但这种方式需要手动创建.well-known/acme-challenge/<random_token> 临时文件,并根据提示给文件写入内容,明显会比较麻烦,故不推荐。

2)多域名证书(推荐)

准备工作:

(1)需要有多个需要申请证书的域名。如下:

  • example.com
  • www.example.com

(2)需要有一台拥有公网 IP 的服务器,并且公网服务器里运行有 Web 服务(如:nginx,tomcat等)。

(3)需要提前在 DNS 服务提供商的管理后台里把所有需要申请证书的域名解析到到服务器的公网 IP上。

多域名证书可以通过类似 -d example.com -d www.example.com 的指定方式申请签发。

1
2
3
4
5
6
7
#自动 HTTP 验证方式申请签发多域名证书(模板)(可加 --staging 选项来申请签发测试环境的证书)
certbot certonly \
--agree-tos --no-eff-email \
--webroot -w /opt/nginx/html \
-m [email protected] \
-d example.com \
-d www.example.com

说明:

  • 多域名证书如果不指定名称,将会以第一个域名作为证书名称。
  • Let’s Encrypt CA(ACME 服务器)会根据指定的多个域名依次发起 HTTP 请求访问 Web 服务器根目录下的临时文件以确定申请用户对每个域名的所有权。

注意:多域名证书是一个 SSL 证书,该证书可以包含多个域名的信息,故一个证书可以同时用于多个域名的 SSL 验证。

3)通配符域名证书(不支持)

使用自动 HTTP 验证方式不支持通配符域名证书申请,Let’s Encrypt 只允许使用 DNS-01 验证模式来获取通配符域名证书。

💁‍♂ 关于“使用自动 HTTP 验证方式不支持申请通配符域名证书”的说明:

申请通配符域名(如:*.example.com)证书时,Let’s Encrypt CA(ACME 服务器)需要验证用户是否为通配符域名的父级域名(如:example.com)的拥有者,只有确定用户为域名拥有者才能签发证书。

使用自动 HTTP 验证方式验证用户是否为域名的拥有者时,ACME 客户端会在 Web 服务器上放置一个特定的临时文件,ACME 服务器通过 HTTP 协议请求访问此文件是否存在来证明用户对该域名的控制权,再通过域名控制权验证结果来间接确定用户是否是域名的拥有者,由于其验证是间接的,不能直接确定用户就是域名的拥有者,所以使用自动 HTTP 验证方式不支持申请通配符域名证书。

而使用 DNS 验证模式验证用户是否是域名的拥有者是可以直接确定的,因为拥有 DNS 域名解析权限的用户那肯定可以理解为域名的拥有者。所以使用 DNS 验证模式支持申请通配符域名证书。

如下测试在自动 HTTP 验证方式下申请通配符域名证书会提示不支持。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
$ certbot certonly \
--staging \
--agree-tos --no-eff-email \
--webroot -w /opt/nginx/html \
-m [email protected] \
-d example.com \
-d *.example.com

#如下是申请失败提示内容:
Saving debug log to /var/log/letsencrypt/letsencrypt.log
Plugins selected: Authenticator webroot, Installer None
Starting new HTTPS connection (1): acme-staging-v02.api.letsencrypt.org
Requesting a certificate for example.com and *.example.com
Performing the following challenges:
Client with the currently selected authenticator does not support any combination of challenges that will satisfy the CA. You may need to use an authenticator plugin that can do challenges over DNS.
Client with the currently selected authenticator does not support any combination of challenges that will satisfy the CA. You may need to use an authenticator plugin that can do challenges over DNS.

4)Web 服务器配置注意事项

对于自动 HTTP 验证方式进行证书申请的情况下,如果这个域名对应 80 端口做了重定向、反向代理等配置导致 Let’s Encrypt CA(ACME 服务器)无法获取.well-known/acme-challenge目录下的临时文件,那么会导致自动续期失败。所以需要注意对于 /.well-known/acme-challenge/ 这个访问路径(访问地址:http://example.com/.well-known/acme-challenge/<random_token>)需要确保一定能够访问到临时文件,在域名的 80 端口配置里添加如下配置(以 Nginx 为例):

1
2
3
4
# certbot 自动 HTTP 验证方式申请证书,临时文件访问验证配置
location /.well-known/acme-challenge {
root /opt/nginx/html; # 该路径应该为certbot certonly命令申请证书时 --webroot -w 指定的路径参数。
}

示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
server {
listen 80 default_server;
listen [::]:80 default_server;

# certbot 自动 HTTP 验证方式申请证书,临时文件访问验证配置
location /.well-known/acme-challenge {
root /opt/nginx/html; # 该路径应该为certbot certonly命令申请证书时 --webroot -w 指定的路径参数。
}

location / {
return 301 https://$host$request_uri;
}
}

提示:只有在自动 HTTP 验证方式申请域名证书才需要该配置。

一般安装了 SSL 以后很多用户选择将 http 跳转到 https,可以通过配置default_server,表示作为默认服务器配置,即当 Nginx 接收到请求时,如果请求的域名与服务器块的监听地址(listen)中的域名都不匹配时,Nginx 将会选择配置了 default_server 的服务器块作为默认的服务器块进行处理。比如进行重定向到 https 地址处理,这样做就可以让一处配置就能同时支持多个域名访问 http 请求时都自动跳转到 https。

方式2:手动 DNS 验证方式申请证书

简要概述:

(1)certbot(ACME 客户端)会生成一串随机字符串,并要求用户将这个字符串作为域名的 TXT 记录值设置到DNS域名托管平台的对应域名解析设置里。等用户设置完成后,certbot 将会请求域名地址,通过判断是否能获取有效且与生成字符串相等的记录值来确定用户是否是域名的拥有者。这个过程中添加 TXT 记录情况如下:

  • 记录类型:TXT
  • 主机记录:_acme-challenge.example.com
  • 记录值: certbot 工具生成的随机字符串(如:vrZwcxxxxxx5k42XUr025UWRNl4

(2)如果验证确定用户是域名的拥有者,则允许为其签发生成 SSL 证书,否则申请失败。

说明:手动 DNS 域名验证即需要通过在 DNS 服务器手动添加 TXT 记录来使让 certbot 确定用户对域名的持有权。

1)单域名证书

准备工作:

(1)需要有一台能访问互联网的主机(可为内网主机)。

(2)需要有一个需要申请证书的域名。如:example.com

(3)需要在 DNS 服务提供商的管理后台里添加域名的 TXT 记录。如下:

  • _acme-challenge.example.com - > vrZwcxxxxxx5k42XUr025UWRNl4

提示:TXT 记录值由下方执行certbot命令获得。

1
2
3
4
5
6
#DNS 验证模式申请签发单域名证书(模板)(可加 --staging 选项来申请签发测试环境的证书)
certbot certonly \
--manual --preferred-challenges dns-01 \
--agree-tos --no-eff-email \
-m [email protected] \
-d example.com

当申请完成后即在 DNS 服务提供商的管理后台删除掉这个临时的 TXT 记录。

2)多域名证书

准备工作:

(1)需要有一台能访问互联网的主机(可为内网主机)。

(2)需要准备多个需要申请证书的域名。如下:

  • example.com
  • www.example.com

(3)需要在 DNS 服务提供商的管理后台里为每个域名添加 TXT 记录。如下:

  • _acme-challenge.example.com - > vrZwcxxxxxx5k42XUr025UWRNl4

  • _acme-challenge.www.example.com - > fr5wcxxxxxx7ko2PUr025UWRGo5

提示:TXT 记录值由下方执行certbot命令获得。

1
2
3
4
5
6
7
#DNS 验证模式申请签发多域名证书(模板)(可加 --staging 选项来申请签发测试环境的证书)
certbot certonly \
--manual --preferred-challenges dns-01 \
--agree-tos --no-eff-email \
-m [email protected] \
-d example.com \
-d www.example.com
  • 多域名证书可以通过类似 -d example.com -d www.example.com 的指定方式申请签发。
  • 多域名证书申请过程中,需要给每个域名添加 TXT 记录,Let’s Encrypt CA(ACME 服务器)会依次校验每个域名的 TXT 记录以确定每个域名的所有权。

3)通配符域名证书

准备工作:

(1)需要有一台能访问互联网的主机(可为内网主机)。

(2)需要有一个需要申请证书的域名。如:example.com

(3)需要在 DNS 服务提供商的管理后台里添加域名的 TXT 记录。如下:

  • _acme-challenge.example.com - > vrZwcxxxxxx5k42XUr025UWRNl4

提示:TXT 记录值由下方执行certbot命令获得。

1
2
3
4
5
6
7
#DNS 验证模式申请签发通配符证书(模板)(可加 --staging 选项来申请签发测试环境的证书)
certbot certonly \
--manual --preferred-challenges dns-01 \
--agree-tos --no-eff-email \
-m [email protected] \
-d example.com \
-d *.example.com
  • DNS-01 验证模式是支持通配符域名证书申请的。
  • 通配符域名证书可以通过类似-d *.example.com的指定方式来申请签发。
  • 通配符域名证书申请过程中,对于通配符域名,只需要给除去通配符后剩下的域名添加一条 TXT 记录即可完成验证。这种验证方式不需要为通配符中的每个子域名添加记录,这也是 DNS-01 验证模式比 HTTP-01 更加灵活和安全的重要原因。
  • 通常做三级通配符域名证书时,为了支持其父级域名,申请证书时都会加上其父级域名(即二级域名),如:-d example.com
  • *.example.com表示的通配符域名证书表示只支持三级域名证书(如:www.example.comblog.example.commail.example.com 等),但这个通配符不支持其父级域名(如:example.com),也不支持四级域名(如:dev.www.example.com

四、列出拥有的证书信息

1
2
3
4
5
#列出拥有的证书及其有效期等信息
certbot certificates

#查看证书有效期
openssl x509 -noout -dates -in cert.pem

五、配置使用证书

certbot 申请签发的证书默认存储在 /etc/letsencrypt/live/example.com/etc/letsencrypt/archive/example.com 目录下。

  • /etc/letsencrypt/live/example.com 目录:包含当前使用的 SSL/TLS 证书的符号链接,指向 /etc/letsencrypt/archive 目录中相应的证书文件。
  • /etc/letsencrypt/archive/example.com 目录:包含按域名和时间戳命名的 SSL/TLS 证书文件。

使用 certbot 申请签发证书时,会得到以下几个文件:

  • 服务端证书 (cert.pem):该文件主要包含有域名和公钥,由证书颁发机构(CA)签发,用于客户端验证服务器上域名的身份。
  • 中间证书 (chain.pem):该文件包含 CA 的证书链,其中可能包含一个或多个中间证书和根证书。中间证书由 CA 签发,用于将 CA 根证书和服务端证书连接起来,以能够使客户端验证服务端证书的真实性。
  • 全链证书 (fullchain.pem):也称证书链文件,该文件包含了服务端证书以及所有中间证书和根证书,包含了完整的 SSL 证书链。用于客户端验证服务端证书的真实性。
  • 私钥文件 (privkey.pem):该文件包含私钥内容。用于解密请求的数据以及加密响应的数据。

证书的定义:证书是一种用于验证身份和加密通信的电子文件。通常包含了身份信息、公钥、有效期限、颁发机构信息等内容。(注意:一般证书都是不包含私钥内容的)

常见的 Web 服务器软件有 nginx、apache、tomcat等。在这些 Web 服务器软件中配置 SSL 证书的方式不经相同,但它们都是支持使用 Let’s Encrypt SSL 证书的。

六、吊销证书

吊销证书是一种在证书到期之前废止其有效性的方法。如果您认为您的 SSL/TLS 证书已经被盗用或不再需要使用,则应该立即将其吊销。通过吊销证书,您可以确保不会有人再使用该证书来进行恶意活动。

1
2
3
4
5
6
7
8
#吊销指定域名的证书
certbot revoke --cert-name example.com

#吊销指定文件路径的证书(此命令将吊销存储在 /etc/letsencrypt/live/example.com/cert.pem 中的证书)
certbot revoke --cert-path /etc/letsencrypt/live/example.com/cert.pem

#吊销指定域名相关的所有证书(此命令将吊销 /etc/letsencrypt/archive/ 目录中与 example.com 域名相关的所有证书)
certbot revoke --cert-path /etc/letsencrypt/archive/ -d example.com

提示:使用 Certbot 或其他工具吊销了 Let’s Encrypt 发放的 SSL/TLS 证书,Let’s Encrypt 在证书到期之前仍然会发送到期提醒邮件。吊销证书并不会阻止 Let’s Encrypt 发送到期提醒。(感觉有点坑啊~)

七、删除证书

1
2
3
4
5
6
#删除指定域名的证书
certbot delete --cert-name example.com

#或者:(certbot delete操作同下)
rm -rf /etc/letsencrypt/live/example.com
rm -rf /etc/letsencrypt/archive/example.com

💁‍♂ 如果仅仅删除证书,但原本证书没有注销或过期,那么再次申请签发生成新的证书时,默认生成的新证书与旧证书的一些基本信息(如私钥、公钥和有效期等)会保持相同,仅到期日期和其他元数据(例如序列号、版本号和指纹)不同。

八、证书续期申请

1. 简要概述

Let’s Encrypt 证书的有效期是 90 天,证书到期前 20 天、10 天和 1 天时将会接收到到期通知邮件,提醒用户进行证书续期申请操作。用户可以通过 certbot renew 命令来给即将过期的证书续期,续期会生成新的证书并自动替换掉原来的证书。

💁‍♂ 说明:

  • certbot renew 命令会默认根据申请各证书时的参数对所有证书进行续期。申请各证书时的参数会被用作续订参数记录在 /etc/letsencrypt/renewal/example.com.conf 配置文件里(该文件是用户在申请证书完成后根据申请的参数自动生成的)。用户可以修改续期配置文件以调整默认的续订策略(如:修改验证插件、修改手动验证的 hook 脚本等)。如果不修改续期配置文件,也可以在执行 certbot renew 命令时指定参数来自定义续订策略。
  • 如果证书已经过期或者被吊销,则 certbot 将无法对其进行续期,对于这种情况只能重新申请签发新的证书。
  • 证书到期前 30 天内才可以续订,多于30天则不允许续订。
  • 通过 certbot renew 命令来续订,默认生成的新证书与旧证书的一些基本信息(如私钥、公钥和有效期等)会保持相同,仅到期日期和其他元数据(例如序列号、版本号和指纹)不同。
  • 如果希望通过旧的证书信息强制重新申请签发新的证书并替换则需要加选项 --force-renewal
  • 如果续期的是测试环境的证书则需要加选项:--break-my-certs

2. 自动 HTTP 验证方式续期证书

1)手动续期

1
2
3
4
5
6
#证书续期(使用续期配置文件的参数作为续订策略)
#可以指定 -v(--verbose)选项查看更详细的日志信息
certbot renew

#重新加载nginx配置
nginx -s reload

💁‍♂ 注意:自动 HTTP 验证方式下只支持单域名证书和多域名证书的续期,不支持通配符域名证书。

2)自动续期

可以通过Linux的定时任务来完成自动续期的需求,操作如下:

1
2
3
4
5
6
7
8
9
10
#创建日志保存目录
mkdir -p /opt/certbot/logs

#设置系统的定时任务
crontab -e
#在最后添加如下定时规则(在每个月的第一天凌晨3点0分0秒时执行定时任务)
0 3 1 * * certbot renew --deploy-hook "nginx -s reload" >> /opt/certbot/logs/renew.log

#列出系统的定时任务
crontab -l

定时任务规则中 certbot renew--deploy-hook 选项用于指定证书续期更新完成后自动触发执行某自定义脚本或命令,这里填写的是命令是重新加载 nginx 配置以使得新的 SSL 证书生效。

3. 自动 DNS 域名验证续期证书

参考下文:自动 DNS 验证方式申请和续期证书

九. 自动 DNS 验证方式申请和续期证书

实现原理:通过使用 DNS 插件或者自定义 hook 脚本来调用 DNS 服务器的 API 更新 DNS TXT 记录以实现自动 DNS 验证方式申请和续期证书。

1. 简要概述

对于手动dns验证方式申请证书的情况,通过 certbot renew 命令进行证书续期时默认是会失败的。原因是 certbot 默认无法自动更新 DNS 服务器的 TXT 记录,从而无法通过 DNS 验证。如果需要在这种模式下通过 DNS 验证,则需要安装 DNS 插件或者自定义 hook 脚本并且配置 DNS 服务器访问令牌等来调用 DNS 服务器的 API 来自动更新 DNS 的 TXT 记录,另外使用 DNS 插件或者自定义 hook 脚本后,申请申请证书也不需要再手动添加 DNS TXT 记录了,维护上会更加便利。

💁‍♂ 对于 DNS 验证模式申请的域名证书,执行certbot renew命令续期,不指定 DNS 插件或者 hook 脚本选项时会提示如下报错信息:

Failed to renew certificate example.com with error: The manual plugin is not working; there may be problems with your existing configuration. The error was: PluginError('An authentication script must be provided with --manual-auth-hook when using the manual plugin non-interactively.

注意:不论是单域名证书、多域名证书、还是通配符证书,都是需要指定自动更新 DNS 记录的方式,否则无法成功续期。

💁‍♂ 关于域名注册商和 DNS 服务提供商的说明:

通常情况下,域名注册商和 DNS 服务提供商可以是同一个公司,也可以是不同的公司。一些常见的域名注册商和 DNS 服务提供商包括:

2. DNS 插件自动更新 DNS 记录方式

1)安装并配置 DNS 插件

默认支持的 DNS 插件:

非默认支持的 DNS 插件:

具体使用可参考:官方文档 DNS-Plugins

💁‍♂ 说明:

  • 这些插件不包含在默认的 Certbot 安装中,必须单独安装。
  • certbot 默认只支持常见的 DNS 服务提供商相关 DNS 插件进行自动验证,但如果用户的 DNS 服务器不在支持列表中,则需要编写插件(可在 Github 上查找)或者使用自定义 hook 脚本来进行手动验证(更新 DNS TXT 记录)。

(1)安装 Certbot DNS 插件

说明:以 Cloudflare 的 DNS 插件为例

(1.1)通过系统包管理器安装 Certbot DNS 插件
1
2
3
4
5
6
7
#yum 安装 Certbot DNS 插件
yum install -y epel-release
yum install -y python2-certbot-dns-cloudflare

#apt 安装 Certbot DNS 插件
apt update
apt install -y python3-certbot-dns-cloudflare
(1.2)通过 snap 包管理器安装 Certbot DNS 插件
1
2
3
4
5
6
#通过 snap 安装 DNS 插件
snap set certbot trust-plugin-with-root=ok
snap install certbot-dns-cloudflare
#snap connect certbot:plugin certbot-dns-cloudflare
#查看插件是否成功安装到certbot(看有没有多出dns-aliyun的一条记录)
certbot plugins
(1.3)通过 pip 包管理器安装 Certbot DNS 插件
1
pip install certbot-dns-cloudflare

(2)配置 Certbot DNS 插件

1
2
3
4
5
6
7
8
#配置DNS服务提供商认证凭证
mkdir -p /opt/certbot/dns-plugins
cat > /opt/certbot/dns-plugins/cloudflare-credentials.ini << 'EOF'
dns_cloudflare_api_token = 0123xxxxxx4567
EOF

#设置配置文件权限
chmod 600 /opt/certbot/dns-plugins/cloudflare-credentials.ini

创建并获得 Cloudflare 的 API 令牌的访问链接:https://dash.cloudflare.com/profile/api-tokens

2)申请证书

1
2
3
4
5
6
certbot certonly \
--dns-cloudflare \
--dns-cloudflare-credentials /opt/certbot/dns-plugins/cloudflare-credentials.ini \
-m [email protected] \
-d example.com \
-d *.example.com

3)手动续期

1
2
3
4
5
6
7
8
9
10
11
#证书续期(使用续期配置文件的参数作为续订策略)
#可以指定 -v(--verbose)选项查看更详细的日志信息
certbot renew

#证书续期(指定参数以自定义续订策略,可选)
certbot renew \
--dns-cloudflare \
--dns-cloudflare-credentials /opt/certbot/dns-plugins/cloudflare-credentials.ini

#重新加载nginx配置
nginx -s reload

4)自动续期

可以配置 Linux 的定时任务来完成自动续期的需求,操作如下:

1
2
3
4
5
6
7
8
9
10
#创建日志保存目录
mkdir -p /opt/certbot/logs

#设置系统的定时任务
crontab -e
#在最后添加如下定时规则(在每个月的第一天凌晨3点0分0秒时执行定时任务)
0 3 1 * * certbot renew --deploy-hook "nginx -s reload" >> /opt/certbot/logs/renew.log

#列出系统的定时任务
crontab -l

3. 自定义 hook 脚本手动更新 DNS 记录方式

certbot 申请证书或者续期可通过指定 hook 选项来执行一些命令或者脚本从而实现更新 DNS 记录等,涉及的 hook 选项包括:--manual-auth-hook--manual-cleanup-hook

hook 选项说明:

--manual-auth-hook 在 certbot 进行 TXT 验证前执行,验证完成后还可以通过指定--manual-cleanup-hook来删除已经验证完的 TXT 临时记录。

通过 hook 脚本更新 DNS TXT 记录一般是调用对应域名托管服务商的 API 来实现。对于不同的域名托管服务商 API 的具体调用方式也不一样。下面主要以更新阿里云 DNS 的域名解析记录为例:

1)编写 hook 脚本

脚本1(支持多家 DNS 服务提供商,推荐)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
##(1)下载并安装脚本(该脚本同时支持阿里云、腾讯云、华为云、GoDaddy 的 DNS 解析记录更新)
mkdir -p /opt/certbot/dns-hooks
git clone https://github.com/yangrongzhou/certbot-letencrypt-wildcardcertificates-alydns-au /opt/certbot/dns-hooks/au
chmod 0777 /opt/certbot/dns-hooks/au/au.sh

##(2)配置根域名
#查看是否有对应的根域名(如要测试的域名为:example.site,则根域名为:site)
cat /opt/certbot/dns-hooks/au/domain.ini | grep "site"
#如果以上cat命令没有查到,则可以通过如下命令进行添加(如果已经有则不需要添加)
echo "site" >> /opt/certbot/dns-hooks/au/domain.ini

##(3)配置阿里云DNS的 API key 和 Secrec
vim /opt/certbot/dns-hooks/au/au.sh #通过vim命令编辑脚本文件,然后修改对应域名托管服务商的KEY和TOKEN变量值,(如阿里云为:ALY_KEY 和 ALY_TOKEN,而腾讯云为:TXY_KEY 和 TXY_TOKEN)


#创建certbot手动添加dns txt记录的hook脚本
cat > /opt/certbot/dns-hooks/manual-auth-hook.sh << 'EOF'
#阿里云
/opt/certbot/dns-hooks/au/au.sh python aly add
#腾讯云
#/opt/certbot/dns-hooks/au/au.sh python txy add
EOF

#创建certbot手动删除dns txt记录的hook脚本
cat > /opt/certbot/dns-hooks/manual-cleanup-hook.sh << 'EOF'
#阿里云
/opt/certbot/dns-hooks/au/au.sh python aly clean
#腾讯云
#/opt/certbot/dns-hooks/au/au.sh python txy clean
EOF

#给脚本赋予执行权限
chmod +x /opt/certbot/dns-hooks/manual-auth-hook.sh
chmod +x /opt/certbot/dns-hooks/manual-cleanup-hook.sh

原项目脚本说明参考:https://github.com/ywdblog/certbot-letencrypt-wildcardcertificates-alydns-au

腾讯云解析升级至 API 3.0,脚本更新参考:https://github.com/yangrongzhou/certbot-letencrypt-wildcardcertificates-alydns-au

脚本2(仅支持阿里云 DNS)

实现方式:编写 shell 脚本调用阿里云 CLI 工具来更新的阿里云域名云解析

(1)需要先安装并配置阿里云 CLI 工具

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#安装阿里云 CLI 工具
#pip install aliyuncli
wget https://aliyuncli.alicdn.com/aliyun-cli-linux-3.0.16-amd64.tgz
tar xzvf aliyun-cli-linux-3.0.16-amd64.tgz
mv aliyun /usr/local/bin
chown root:root /usr/local/bin/aliyun

#配置(配置调用阿里云资源所需的凭证信息、地域、语言等),配置保存在~/.aliyun/config.json文件里
aliyun configure set \
--profile akProfile \
--mode AK \
--region cn-hangzhou \
--access-key-id LTAxxxxxxxx9x7a \
--access-key-secret oNYXxxxxxxxxvFcz8F


#查看配置
aliyun configure get


#测试 CLI 工具是否能成功更新记录
#aliyun alidns AddDomainRecord --DomainName example.com --Type Txt --RR _txt-test --Line default --Value txt000 --TTL 600

#卸载(如果需要)
rm -rf /usr/local/bin/aliyun
rm -rf ~/.aliyun

阿里云 CLI 工具使用说明可参考:阿里云CLICLI 工具 DNS 解析CLI工具项目

阿里云 API key 和 Secrec 可在阿里云管理后台 AccessKey 管理 页面创建获取。

阿里云 API key 和 Secrec 官方申请文档

(2)创建 shell 脚本文件

1
2
mkdir -p /opt/certbot/dns-hooks
vim /opt/certbot/dns-hooks/alidns.sh

内容如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
#!/bin/bash

if ! command -v aliyun >/dev/null; then
echo "错误: 你需要先安装 aliyun 命令行工具 https://help.aliyun.com/document_detail/121541.html。" 1>&2
exit 1
fi

DOMAIN=$(expr match "$CERTBOT_DOMAIN" '.*\.\(.*\..*\)')
SUB_DOMAIN=$(expr match "$CERTBOT_DOMAIN" '\(.*\)\..*\..*')
if [ -z $DOMAIN ]; then
DOMAIN=$CERTBOT_DOMAIN
fi
if [ ! -z $SUB_DOMAIN ]; then
SUB_DOMAIN=.$SUB_DOMAIN
fi

if [ $# -eq 0 ]; then
aliyun alidns AddDomainRecord \
--DomainName $DOMAIN \
--RR "_acme-challenge"$SUB_DOMAIN \
--Type "TXT" \
--Value $CERTBOT_VALIDATION
/bin/sleep 20
else
RecordId=$(aliyun alidns DescribeDomainRecords \
--DomainName $DOMAIN \
--RRKeyWord "_acme-challenge"$SUB_DOMAIN \
--Type "TXT" \
--ValueKeyWord $CERTBOT_VALIDATION \
| grep "RecordId" \
| grep -Eo "[0-9]+")

aliyun alidns DeleteDomainRecord \
--RecordId $RecordId
fi

脚本来源:https://github.com/justjavac/certbot-dns-aliyun

1
2
3
4
5
6
7
8
9
10
11
12
13
#创建certbot手动添加dns txt记录的hook脚本
cat > /opt/certbot/dns-hooks/manual-auth-hook.sh << 'EOF'
/opt/certbot/dns-hooks/alidns.sh
EOF
#创建certbot手动删除dns txt记录的hook脚本
cat > /opt/certbot/dns-hooks/manual-cleanup-hook.sh << 'EOF'
/opt/certbot/dns-hooks/alidns.sh clean
EOF

#给脚本赋予执行权限
chmod +x /opt/certbot/dns-hooks/alidns.sh
chmod +x /opt/certbot/dns-hooks/manual-auth-hook.sh
chmod +x /opt/certbot/dns-hooks/manual-cleanup-hook.sh

2)申请证书

1
2
3
4
5
6
7
8
certbot certonly \
--manual --preferred-challenges dns-01 \
--agree-tos --no-eff-email \
--manual-auth-hook "/opt/certbot/dns-hooks/manual-auth-hook.sh" \
--manual-cleanup-hook "/opt/certbot/dns-hooks/manual-cleanup-hook.sh" \
-m [email protected] \
-d example.site \
-d *.example.site

3)手动续期

1
2
3
4
5
6
7
8
9
10
11
12
#证书续期(使用续期配置文件的参数作为续订策略)
#可以指定 -v(--verbose)选项查看更详细的日志信息
certbot renew

#证书续期(指定参数以自定义续订策略,可选)
certbot renew \
--manual --preferred-challenges dns-01 \
--manual-auth-hook "/opt/certbot/dns-hooks/manual-auth-hook.sh" \
--manual-cleanup-hook "/opt/certbot/dns-hooks/manual-cleanup-hook.sh"

#重新加载nginx配置
nginx -s reload

4)自动续期

可以配置 Linux 的定时任务来完成自动续期的需求,操作如下:

1
2
3
4
5
6
7
8
9
10
#创建日志保存目录
mkdir -p /opt/certbot/logs

#设置系统的定时任务
crontab -e
#在最后添加如下定时规则(在每个月的第一天凌晨3点0分0秒时执行定时任务)
0 3 1 * * certbot renew --deploy-hook "nginx -s reload" >> /opt/certbot/logs/renew.log

#列出系统的定时任务
crontab -l


----------- 本文结束 -----------




如果你觉得我的文章对你有帮助,你可以打赏我哦~
0%