使用 DNS 验证获取 Let's Encrypt 的 SSL 证书

2024-09-22#SSL证书#Lego

Let's Encrypt 是一个非盈利的证书颁发机构,为互联网站点提供免费的 SSL 证书。通常,可以通过 HTTP 认证(HTTP Validation)获取 Let's Encrypt 的证书。比如 Caddy 服务器就内置了自动获取 Let's Encrypt 或者 ZeroSSL 证书的特性。但这种 HTTP 认证的方式,需要域名指向一个可以被互联网公网访问的 HTTP 服务器,并开放 HTTP端口(80) 和 HTTPS 端口(443)。这在某些情况下可能并不适用。幸运的是,还可以通过 DNS 认证(DNS Validation)获取 SSL 证书。当然在获取(以及续期)的过程中,需要修改域名的 DNS 的记录,以便证明对域名的所有权。

开源工具 lego 介绍 🔗

开源工具 lego 是一个用Go语言编写的 Let's Encrypt/ACME 客户端和库。它提供了只包含一个二进制文件的命令行工具,用于获取 SSL 证书,既支持 HTTP 认证,也支持 DNS 认证。对于 DNS 认证,它支持上百个DNS提供商,比如 Name.com阿里云DNS 等。

使用方法 🔗

安装 🔗

参考 lego 的安装文档,可以使用包管理工具安装,也可以从 Github Releases 页面下载所需平台的命令行二进制文件。当然,也可以下载源码自行编译

使用方法 🔗

获取域名服务的 API 凭证 🔗

由于使用 DNS 验证时,为了验证 DNS 的所有权,需要修改 DNS 记录。因此,首先在 DNS 提供商处获取能够修改域名记录的 API 凭证。

获取证书 🔗

lego的DNS提供商 的文档中,找到域名提供商对应的文档页。设置对应的环境变量,然后运行 lego 程序即可。

比如 Name.com 的文档页为 https://go-acme.github.io/lego/dns/namedotcom/。参考其说明,在命令行中执行:

NAMECOM_USERNAME=foo.bar \
NAMECOM_API_TOKEN=a379a6f6eeafb9a55e378c118034e2751e682fab \
lego --email you@example.com --dns namedotcom --domains my.example.org run

成功执行后,获取到的证书文件位于当前目录下的 .lego/certificates 目录中。

注意事项 🔗

Let's Encrypt 颁发的证书的有效期通常为 90 天,到期之前应该续期(renew),否则在访问依赖此证书的网站等服务会出现安全问题。

补记 🔗

通过 Cloudflare 获取超过4层域名的证书 🔗

参考 Lego 的文档针对 Cloudflare 的文档 《Cloudflare》,当使用如下命令获取证书时:

CLOUDFLARE_DNS_API_TOKEN=1234567890abcdefghijklmnopqrstuvwxyz \
lego --email you@example.com --dns cloudflare -d '4th.subdomain.example.com' run

可能会遇到如下错误:

2024/11/10 15:53:54 [WARN] [4th.subdomain.example.com] acme: cleaning up failed: cloudflare: could not find zone for domain "4th.subdomain.example.com": [fqdn=_acme-challenge.4th.subdomain.example.com.] unexpected response for '4th.subdomain.example.com.' [question='4th.subdomain.example.com. IN  SOA', code=NOTIMP] 
2024/11/10 15:53:54 [INFO] Deactivating auth: https://acme-v02.api.letsencrypt.org/acme/authz-v3/428089070127
2024/11/10 15:53:55 Could not obtain certificates:
        error: one or more domains had a problem:
[4th.subdomain.example.com] [4th.subdomain.example.com] acme: error presenting token: cloudflare: could not find zone for domain "4th.subdomain.example.com": [fqdn=_acme-challenge.4th.subdomain.example.com.] unexpected response for '4th.subdomain.example.com.' [question='4th.subdomain.example.com. IN  SOA', code=NOTIMP]

Lego 项目的 Github 项目中已经有过这个议题,比如《Cloudflare can't find zone for sub-domain #1303》。幸运的是,有人在《[cloudns] unable to request certificate for fourth level domain #884》 提到了解决方法,那就是使用 --dns.resolvers 选项。因此可将获取证书的命令修改为:

CLOUDFLARE_DNS_API_TOKEN=1234567890abcdefghijklmnopqrstuvwxyz \
lego --email you@example.com --dns cloudflare -d '4th.subdomain.example.com' --dns.resolvers "8.8.8.8" run

加载中...