众所周知,现代网站和 web 服务,都需要 TLS 证书。
获取证书的一种便捷方法是使用支持 ACME 协议的证书颁发机构(例如 Let's Encrypt)。在本文,我将把它称为 ACME 服务器。
ACME 服务器并不知道您的真实身份。但他们可以验证您是否与相关域名存在关联。在订购过程中,他们会发出质询,以便您证明您在技术上拥有申请证书的域名的控制权。
如果您的服务在互联网上,并且使用 HTTP 协议,那么这个过程就非常简单直接。
该服务可通过公共 IP 地址访问。ACME 客户端会在 80 端口响应符合特定模式的 URL 请求,当 ACME 服务器验证 URL 包含正确的响应数据后,就会生成您的证书。
这是 HTTP-01 挑战,是RFC 8555中定义的两种挑战之一。Let's Encrypt 在其网站上提供了对其支持的挑战类型的清晰描述,这些描述比 RFC 本身更容易理解。
您也可以使用 TLS-ALPN-01 挑战,但在大多数情况下,HTTP-01 就足够了。
等等,如果这项服务不在互联网上呢?
您的服务可能位于私有网络中,其 IP 地址例如 10.2.3.5,该地址无法通过公共互联网路由。在验证阶段,ACME 服务器将无法连接到此服务。
或者,您的服务可能位于互联网上,但您无法或不想开放 80 端口。例如,您的服务可能是 IRC 服务器或 SFTP 服务器。
别担心,你仍然可以获得证书。有一种标准化的验证方法非常适合这种情况,叫做 DNS-01。DNS-01 的优点在于它允许带外验证。
使用 DNS 进行 ACME 验证非常灵活。让我们来看看如何设置它。
本文不会详细介绍如何配置任何特定的 ACME 客户端,而是着重探讨一些基本概念以及如何避免一些常见的陷阱。
当您使用 DNS-01 请求证书时,ACME 服务器将查找包含质询响应的特殊 DNS 记录。
假设您想申请一个证书 intranet.myentwebapp.com
ACME 服务器随后将查找 TXT 记录。 _acme-challenge.intranet.myentwebapp.com
在标准情况下,您的 ACME 客户端(或相关脚本)会连接到 DNS 服务器,并指示它创建一个新的 TXT 记录,其中包含名称 _acme-challenge.intranet.myentwebapp.com 和某个“神奇”值。
来自 RFC 8555:
客户端通过根据挑战中提供的“令牌”值和客户端的账户密钥构建密钥授权来完成此挑战。然后,客户端计算密钥授权的 SHA-256 摘要 [FIPS180-4]。
由于每次申请或续订证书时都需要创建此类记录,我强烈建议您使用提供 API 的 DNS 服务。您可以选择 Google Cloud、AWS 或 Cloudflare。当然,这些只是几个例子,还有很多其他选择。
DNS-01 的另一个优点是它允许您申请通配符证书。在 Let's Encrypt 中,它是唯一可用于此目的的质询类型。
但如果 myentwebapp.com 的 DNS 控制者不是你/你的团队呢?
或许它由另一个团队甚至另一个部门控制。他们可能不愿意把整个域的 DNS 控制权交给你。
幸运的是,有办法解决这个问题。CNAME 记录就派上用场了。如果您还不熟悉 CNAME 记录,我建议您查阅维基百科上关于CNAME 记录的文章。简单来说,CNAME 记录是指向其他记录的记录,类似于Unix 系统中的符号链接。
因此,您可以设置如下所示的结构,而 不是直接创建 TXT 记录:_acme-challenge.intranet.myentwebapp.com
您创建了一个专门用于响应 ACME 挑战的专用域名。我们称之为 myentwebapp-acme-responses.com
管理 myentwebapp.com 的部门设置了 CNAME 记录:
_acme-challenge.intranet.myentwebapp.com→intranet.myentwebapp.com.myentwebapp-acme-responses.com
现在,当您的客户响应挑战时,您不会要求它在某个位置创建 TXT 记录,_acme-challenge.intranet.myentwebappcom 而是在某个位置 创建 TXT 记录。intranet.myentwebapp.com.myentwebapp-acme-responses.com
使用 API 完善的 DNS 服务时,创建新记录轻而易举。删除记录也是如此。在客户端的清理阶段,无论请求是否成功,都应该删除 TXT 记录。
如果你不想这样做,你不必为此注册一个单独的域名。你也可以创建一个新的区域。例如acme-challenges.myentwebapp.com
如果您选择此解决方案,则控制 myentwebapp.com 的部门需要通过创建 NS 记录将此区域委托给您。
在此示例中,您将创建的 TXT 记录将是: intranet.myentwebapp.com.acme-challenges.myentwebapp.com
acme-challenges.myentwebapp.com 作为参考,以下示例展示了如果将 DNS 请求委托给 Google Cloud 的 DNS 服务,其外观会是什么样子 :
; <<>> DiG 9.10.6 <<>> acme-challenges.myentwebapp.com NS
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 47111
;; flags: qr rd ra; QUERY: 1, ANSWER: 4, AUTHORITY: 0, ADDITIONAL: 1
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 512
;; QUESTION SECTION:
;acme-challenges.myentwebapp.com. IN NS
;; ANSWER SECTION:
acme-challenges.myentwebapp.com. 21600 IN NS ns-cloud-a4.googledomains.com.
acme-challenges.myentwebapp.com. 21600 IN NS ns-cloud-a1.googledomains.com.
acme-challenges.myentwebapp.com. 21600 IN NS ns-cloud-a3.googledomains.com.
acme-challenges.myentwebapp.com. 21600 IN NS ns-cloud-a2.googledomains.com.
;; Query time: 64 msec
;; SERVER: 8.8.8.8#53(8.8.8.8)
;; WHEN: Fri Sep 19 18:59:19 CEST 2025
;; MSG SIZE rcvd: 166权限记录的开头部分大致如下所示:
; <<>> DiG 9.10.6 <<>> acme-challenges.myentwebapp.com SOA
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 10796
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 512
;; QUESTION SECTION:
;acme-challenges.myentwebapp.com. IN SOA
;; ANSWER SECTION:
acme-challenges.myentwebapp.com. 21600 IN SOA ns-cloud-a1.googledomains.com. cloud-dns-hostmaster.google.com. 127 21600 3600 259200 300
;; Query time: 90 msec
;; SERVER: 8.8.8.8#53(8.8.8.8)
;; WHEN: Fri Sep 19 12:46:05 CEST 2025
;; MSG SIZE rcvd: 138使用基于 CNAME 的方法的缺点是,对于每个要使用的域名,管理员都需要先创建相应的 CNAME 记录,然后才能申请证书。如果您经常创建新的主机名,这可能不太方便。在这种情况下,您可以考虑使用通配符证书。
本文探讨了如何使用 DNS-01 挑战来验证您是否有权为特定域名或子域名申请证书。即使您的服务运行在私有网络上,不使用 HTTP 协议,并且您无法完全控制该域名的 DNS,您仍然可以获取证书。是不是很巧妙?关于 SSL 证书验证,请参考 SSL 证书验证工具。
全文完,感谢阅读。
