SSL Certbot 使用方法汇总

Certbot 是 Let’s Encrypt SSL 官方推荐的 ACME 协议客户端,它是一个 Python 程序,且包含模块化插件支持。Let’s Encrypt 的根证书浏览器支持广泛,且支持泛域名。但单个证书的有效期为 90 天,以防止滥用。

安装 Certbot

官方安装步骤参考

以下步骤演示在 Python3 环境中安装 Certbot 及其相关依赖

  1. 安装 certbot
    pip install certbot
  2. 申请证书时,要使用 DNS 方式验证域名所有权并且 DNS 使用 Cloudflare 的情况下,可以安装 certbot-dns-cloudflare 插件实现自动验证,参考以下命令安装 certbot-dns-cloudflare,此模块需要 cloudflare 模块的支持
    pip install cloudflare
    pip install certbot-dns-cloudflare
    安装完成后检查相关模块和版本。其中 cloudflare 版本需要最低为 2.3.1 [1]
    # pip list
    certbot 2.10.0
    certbot-dns-cloudflare 2.10.0
    cloudflare 2.19.2
    以上模块安装完成后,即可使用 certbot 申请域名证书,并支持 Cloudflare DNS 的自动验证。

基于 Cloudflare DNS 的自动验证申请域名证书

参考步骤安装 certbot 及 Cloudflare DNS 插件后 即可使用 certbot 自动请求 Cloudflare DNS 创建申请证书时需要的 DNS 记录自动完成域名归属权的验证过程。

certbot 支持的 Cloudflare 相关的参数如下

参数 说明 示例
--dns-cloudflare 使用 Cloudflare 的 DNS 插件自动验证域名归属权
--dns-cloudflare-credentials 请求 Cloudflare 的授权配置文件
--dns-cloudflare-propagation-seconds 请求 Cloudflare DNS 添加相关 DNS 记录后,让 ACME 服务等待多少秒再验证 DNS 记录。主要用来防止 DNS 记录添加后,缓存 DNS 服务器未来得及更新最新记录。
默认为 10

Cloudflare Credentials 说明

假设有 Cloudflare 账号的 Global API Key,则 Credentials 配置文件内容参考如下

cloudflare.ini
# Cloudflare API credentials used by Certbot
dns_cloudflare_email = [email protected]
dns_cloudflare_api_key = 0123456789abcdef0123456789abcdef01234

申请证书的具体命令如下,如果是第一次申请,需要根据提示填写自己的邮箱信息并同意许可协议,邮箱用于接受之后系统发送的错误或者域名证书过期等信息

certbot certonly \
--dns-cloudflare \
--dns-cloudflare-credentials ~/.secrets/certbot/cloudflare.ini \
--dns-cloudflare-propagation-seconds 60 \
-d example.com \
-d www.example.com

如果是非交互式环境,可以使用参数 --email [email protected]--agree-tos 自动绑定邮箱并同意许可

其他常用参数

参数 说明 示例
--cert-path 指定证书存放路径 --cert-path /path/to/certificate.pem
--key-path 密钥存放路径
--fullchain-path full certificate chain 存放路径
--chain-path 证书链存放路径
--non-interactive 使用非交互模式。建议在自动化脚本中使用
--quiet 减少输出,只输出关键信息

certbot 命令常用操作

手动添加 DNS TXT 记录验证申请域名证书

如果需要通过手动添加域名 DNS TXT 记录的方式验证域名归属来申请域名证书,可以参考以下命令:

# certbot certonly --manual --preferred-challenges dns -d test.domain.com
Saving debug log to /var/log/letsencrypt/letsencrypt.log
Requesting a certificate for test.domain.com

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Please deploy a DNS TXT record under the name:

_acme-challenge.test.domain.com.

with the following value:

a1vi7KIPqDvMJtuJRThCD2n1nEnQF2TUc6hqJm-RLLI

Before continuing, verify the TXT record has been deployed. Depending on the DNS
provider, this may take some time, from a few seconds to multiple minutes. You can
check if it has finished deploying with aid of online tools, such as the Google
Admin Toolbox: https://toolbox.googleapps.com/apps/dig/#TXT/_acme-challenge.test.domain.com.
Look for one or more bolded line(s) below the line ';ANSWER'. It should show the
value(s) you've just added.

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Press Enter to Continue

Successfully received certificate.
Certificate is saved at: /etc/letsencrypt/live/test.domain.com/fullchain.pem
Key is saved at: /etc/letsencrypt/live/test.domain.com/privkey.pem
This certificate expires on 2024-08-14.
These files will be updated when the certificate renews.

NEXT STEPS:
- This certificate will not be renewed automatically. Autorenewal of --manual certificates requires the use of an authentication hook script (--manual-auth-hook) but one was not provided. To renew this certificate, repeat this same certbot command before the certificate's expiry date.

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
If you like Certbot, please consider supporting our work by:
* Donating to ISRG / Let's Encrypt: https://letsencrypt.org/donate
* Donating to EFF: https://eff.org/donate-le
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

相关参数使用说明

参数 说明 示例
--manual 使用 manual 插件来验证域名归属权
--preferred-challenges manual 插件支持使用 httpdns 的方式来验证域名归属权。
- http 需要根据提示在所申请域名的网站相关目录下(/.well-known/acme-challenge/)放置特定名称和内容的文件
- dns 需要根据提示为域名添加相应的 TXT 记录

使用 --manual 插件申请的证书不支持到期前自动更新证书,除非使用 --manual-auth-hook 方式绑定了 域名归属权验证脚本(hook)来自动实现 httpdns 的验证过程。

使用 --manual 插件申请的证书在证书到期前要更新的话,将申请证书的过程重新执行一遍即可。

常见错误

DNSSEC: DNSKEY Missing

使用 Cloudflare 插件自动申请证书 ,有些域名可以正常申请,有些域名会申请证书失败,具体错误如下:

Certbot failed to authenticate some domains (authenticator: dns-cloudflare). The Certificate Authority reported these problems:
Domain: qq.test.top
Type: dns
Detail: DNS problem: looking up TXT for _acme-challenge.qq.test.top: DNSSEC: DNSKEY Missing

Domain: qq.cesh.top
Type: dns
Detail: DNS problem: looking up TXT for _acme-challenge.qq.cesh.top: DNSSEC: DNSKEY Missing


Hint: The Certificate Authority failed to verify the DNS TXT records created by --dns-cloudflare. Ensure the above domains are hosted by this DNS provider, or try increasing --dns-cloudflare-propagation-seconds (currently 30 seconds).

Some challenges have failed.
Ask for help or search for solutions at https://community.letsencrypt.org. See the logfile /var/log/letsencrypt/letsencrypt.log or re-run Certbot with -v for more details.

申请证书的过程中,检查 DNS 记录,成功创建了相关的 TXT 记录。

SERVFAIL looking up CAA

使用以下命令申请域名证书失败,本示例 使用 Cloudflare 插件自动进行 DNS 验证

# certbot certonly --debug --manual --preferred-challenges dns -d a.test.com
Saving debug log to /var/log/letsencrypt/letsencrypt.log
Requesting a certificate for a.test.com

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Please deploy a DNS TXT record under the name:

_acme-challenge.a.test.com.

with the following value:

kbLf6l1aKTPdLYwQJruY8-ajROrSinBlB1NDoJXHB1g

Before continuing, verify the TXT record has been deployed. Depending on the DNS
provider, this may take some time, from a few seconds to multiple minutes. You can
check if it has finished deploying with aid of online tools, such as the Google
Admin Toolbox: https://toolbox.googleapps.com/apps/dig/#TXT/_acme-challenge.a.test.com.
Look for one or more bolded line(s) below the line ';ANSWER'. It should show the
value(s) you've just added.

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Press Enter to Continue

Certbot failed to authenticate some domains (authenticator: manual). The Certificate Authority reported these problems:
Domain: a.test.com
Type: dns
Detail: DNS problem: SERVFAIL looking up CAA for a.test.com - the domain's nameservers may be malfunctioning

Hint: The Certificate Authority failed to verify the manually created DNS TXT records. Ensure that you created these in the correct location, or try waiting longer for DNS propagation on the next attempt.

关键报错信息: DNS problem: SERVFAIL looking up CAA for a.test.com - the domain's nameservers may be malfunctioning。测试 TXT 记录已经添加成功

# dig TXT _acme-challenge.a.test

; <<>> DiG 9.11.4-P2-RedHat-9.11.4-26.P2.el7_9.15 <<>> TXT _acme-challenge.a.test
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 24295
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;_acme-challenge.a.test. IN TXT

;; ANSWER SECTION:
_acme-challenge.a.test. 149 IN TXT "kbLf6l1aKTPdLYwQJruY8-ajROrSinBlB1NDoJXHB1g"

;; Query time: 0 msec
;; SERVER: 172.31.0.2#53(172.31.0.2)
;; WHEN: Wed Sep 25 14:26:35 CST 2024
;; MSG SIZE rcvd: 113

参考有关 CAA 的说明: CAA Record and why it is needed (SSL related)

解决方法是需要为每个需要申请证书的域名添加 CAA 记录,用来确保对指定的域名,只有 CAA 中指定的 CA 机构才能为此域名颁发证书

根据此思路,为需要申请的域名(以 a.aabbcc.com 为例)添加 CAA 记录(支持通配符匹配多个值,* 匹配所有),Cloudflare 上为域名添加 CAA 示例如下

配置完成后进行 CAA 解析测试,可以看到已有 CAA 记录 a.aabbcc.com. 300 IN CAA 0 issuewild "*",再次申请证书后,可以正常申请证书

# dig CAA a.aabbcc.com

; <<>> DiG 9.11.4-P2-RedHat-9.11.4-26.P2.el7_9.15 <<>> CAA a.aabbcc.com
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 61363
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;a.aabbcc.com. IN CAA

;; ANSWER SECTION:
a.aabbcc.com. 300 IN CAA 0 issuewild "*"

;; Query time: 3 msec
;; SERVER: 172.31.0.2#53(172.31.0.2)
;; WHEN: Wed Sep 25 14:25:07 CST 2024

CAA 主机部分使用通配符无效,如 *.aabbcc.com. 300 IN CAA 0 issuewild "*"

参考文档

User Guide
CAA Record and why it is needed (SSL related)

脚注