第04章 - DNS验证方式申请证书
DNS-01 验证通过在域名的 DNS 记录中添加特定 TXT 记录来证明域名控制权。与 HTTP-01 相比,DNS-01 验证不需要服务器开放任何端口,且支持通配符证书,是企业和专业用户的首选验证方式。
4.1 DNS-01 验证原理
DNS-01 验证流程:
- acme.sh 向 CA 发起证书申请
- CA 返回一个挑战令牌
- acme.sh(通过 DNS API 或手动)在
_acme-challenge.<域名>添加 TXT 记录 - CA 查询该 TXT 记录是否包含正确的值
- 验证通过后颁发证书
DNS-01 验证的优势:
- ✅ 不需要服务器开放 80/443 端口
- ✅ 支持通配符证书(
*.example.com) - ✅ 服务器不需要直接暴露在公网
- ✅ 内网服务器也可以申请证书
- ✅ 适合 CDN、负载均衡、多服务器场景
DNS-01 验证的局限:
- DNS API 凭据存储在服务器上,有一定安全风险(建议使用最小权限 API Key)
- 手动 DNS 模式无法自动续期
4.2 手动 DNS 模式
4.2.1 适用场景
当 DNS 服务商没有提供 API,或者不方便使用 API 时,可以使用手动 DNS 模式。
# 申请单域名
acme.sh --issue -d example.com --dns
# 申请通配符证书(需要两条 TXT 记录)
acme.sh --issue -d example.com -d *.example.com --dns
4.2.2 操作步骤
执行命令后,acme.sh 会暂停并显示需要添加的 TXT 记录信息:
[Mon 15 Jan 2024 10:00:00] Add the following TXT record:
[Mon 15 Jan 2024 10:00:00] Domain: '_acme-challenge.example.com'
[Mon 15 Jan 2024 10:00:00] TXT value: 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'
[Mon 15 Jan 2024 10:00:00] Please be aware that you prepend _acme-challenge. before your domain
[Mon 15 Jan 2024 10:00:00] so the resulting subdomain will be: _acme-challenge.example.com
[Mon 15 Jan 2024 10:00:00] Please add the TXT record and re-run with --renew.
申请通配符时会有两条 TXT 记录需要添加(针对 example.com 和 *.example.com 各一条)。
按照提示:
- 登录你的 DNS 控制台
- 添加
_acme-challenge.example.comTXT 记录,值为提示中的字符串 - 等待 DNS 记录生效(通常 1-5 分钟,也可能需要更长时间)
- 验证 DNS 记录已生效:
# 检查 DNS 记录是否生效
dig _acme-challenge.example.com TXT
# 或
nslookup -type=TXT _acme-challenge.example.com
- 确认生效后,执行续期命令完成验证:
acme.sh --renew -d example.com
4.2.3 手动 DNS 模式的缺点
手动 DNS 模式无法自动续期——每次续期都需要手动操作。如果域名的 DNS 服务商提供了 API,强烈建议改用 DNS API 自动模式。
4.3 DNS API 自动模式
DNS API 自动模式是 acme.sh 最强大的功能之一。acme.sh 调用 DNS 服务商的 API 自动添加/删除 TXT 记录,整个过程无需人工干预,且自动续期完全免维护。
4.3.1 DNS API 凭据管理
首次使用:通过环境变量传递凭据,acme.sh 会自动将其保存到 ~/.acme.sh/account.conf:
export Ali_Key="your_key"
export Ali_Secret="your_secret"
acme.sh --issue --dns dns_ali -d example.com
# 第一次执行后,凭据会被保存,后续无需再 export
查看已保存的凭据:
cat ~/.acme.sh/account.conf
修改凭据(如 API Key 更换后):
# 方式一:直接编辑 account.conf
vim ~/.acme.sh/account.conf
# 方式二:重新 export 并执行一次带 --force 的续期
export Ali_Key="new_key"
export Ali_Secret="new_secret"
acme.sh --renew -d example.com --force
4.3.2 通用参数
# DNS 传播等待时间(秒),当 DNS 更新较慢时需要增加
--dnssleep 120 # 等待 120 秒再让 CA 验证 TXT 记录
# 示例:申请通配符证书,等待 120 秒 DNS 传播
acme.sh --issue --dns dns_ali -d example.com -d *.example.com --dnssleep 120
4.4 常用 DNS API 提供商(中国)
4.4.1 阿里云 DNS(dns_ali)
获取 API 凭据:
- 登录阿里云 RAM 控制台
- 创建 RAM 子用户(建议不要使用主账号 AccessKey)
- 为该用户授予
AliyunDNSFullAccess权限策略 - 创建并保存 AccessKey ID 和 AccessKey Secret
export Ali_Key="your_access_key_id"
export Ali_Secret="your_access_key_secret"
# 申请单域名
acme.sh --issue --dns dns_ali -d example.com
# 申请通配符证书
acme.sh --issue --dns dns_ali -d example.com -d *.example.com
# 申请多域名
acme.sh --issue --dns dns_ali \
-d example.com \
-d *.example.com \
-d www.example.com \
-d api.example.com
最小权限配置(建议):
在 RAM 控制台创建自定义权限策略,仅允许 DNS 相关操作:
{
"Version": "1",
"Statement": [
{
"Action": [
"alidns:AddDomainRecord",
"alidns:DeleteDomainRecord",
"alidns:DescribeDomainRecords",
"alidns:DescribeDomains"
],
"Resource": "*",
"Effect": "Allow"
}
]
}
4.4.2 腾讯云 DNS/DNSPod(dns_tencent)
腾讯云有两个 DNS API:
新版腾讯云 API(推荐,dns_tencent):
- 登录腾讯云 API 密钥控制台
- 新建密钥,获取 SecretId 和 SecretKey
export Tencent_SecretId="your_secret_id"
export Tencent_SecretKey="your_secret_key"
acme.sh --issue --dns dns_tencent -d example.com -d *.example.com
旧版 DNSPod.cn API(dns_dp):
- 登录 DNSPod 控制台
- 创建 DNSPod API Token(注意:是 Token,不是密钥对)
export DP_Id="your_dnspod_id"
export DP_Key="your_dnspod_token"
acme.sh --issue --dns dns_dp -d example.com -d *.example.com
选择建议:如果域名在腾讯云 DNS 上管理,使用
dns_tencent;如果通过 DNSPod.cn 独立账户管理,使用dns_dp。
4.4.3 华为云 DNS(dns_huaweicloud)
- 登录华为云 IAM 控制台
- 创建 IAM 用户,授予
DNS FullAccess权限 - 获取账户域名(DomainName,即账号名)
export HUAWEICLOUD_Username="your_iam_username"
export HUAWEICLOUD_Password="your_iam_password"
export HUAWEICLOUD_DomainName="your_account_domain_name"
acme.sh --issue --dns dns_huaweicloud -d example.com -d *.example.com
注意:华为云的 DomainName 是登录账号的”账号名”,不是邮箱,在华为云控制台右上角可以查看。
4.4.4 百度云 DNS(dns_baidu)
- 登录百度云 API 密钥管理
- 创建 AccessKey
export BAIDU_Cloud_ID="your_access_key_id"
export BAIDU_Cloud_Key="your_access_key_secret"
acme.sh --issue --dns dns_baidu -d example.com -d *.example.com
4.4.5 京东云 DNS(dns_jd)
- 登录京东云 API 密钥控制台
- 创建 AccessKey
export JD_ACCESS_KEY_ID="your_access_key_id"
export JD_ACCESS_KEY_SECRET="your_access_key_secret"
# 可选:指定区域(默认 cn-north-1)
export JD_REGION="cn-north-1"
acme.sh --issue --dns dns_jd -d example.com -d *.example.com
4.4.6 西部数码(dns_west_cn)
- 登录西部数码 API 配置页面
- 获取 API 密钥(需要取 MD5 加密后的密钥)
export WEST_Username="your_username"
export WEST_Key="md5_encrypted_api_key"
acme.sh --issue --dns dns_west_cn -d example.com -d *.example.com
4.4.7 DNS.LA(dns_la)
- 登录 dns.la 控制台
- 获取 AppID 和 API Secret
export LA_Id="your_appid"
export LA_Sk="your_api_secret"
acme.sh --issue --dns dns_la -d example.com -d *.example.com
4.4.8 名字.com(dns_namecom)
export Namecom_Username="your_username"
export Namecom_Token="your_api_token"
acme.sh --issue --dns dns_namecom -d example.com -d *.example.com
4.4.9 CloudDNS(dns_clouddns)
部分国内用户使用 CloudDNS:
export CLOUDDNS_EMAIL="your@email.com"
export CLOUDDNS_PASSWORD="your_password"
acme.sh --issue --dns dns_clouddns -d example.com -d *.example.com
4.5 DNS Persist 模式(新特性)
4.5.1 概述
DNS Persist 模式(基于 draft-ietf-acme-dns-persist-01)是 acme.sh 最新支持的特性,专为无 DNS API、但希望实现自动续期的场景设计。
传统手动 DNS 模式的问题:每次续期都需要手动更新 TXT 记录。
DNS Persist 模式的解决方案:只需手动添加一次特殊 TXT 记录,之后 acme.sh 可以永久自动续期,无需再次手动操作。
4.5.2 使用步骤
第一步:生成持久化验证值
acme.sh --make-dns-persist-value -d example.com
输出示例:
[Mon 15 Jan 2024 10:00:00] Add the following TXT record:
[Mon 15 Jan 2024 10:00:00] Domain: '_validation-persist.example.com'
[Mon 15 Jan 2024 10:00:00] TXT value: 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'
[Mon 15 Jan 2024 10:00:00] Once the record is added, you can use --dns-persist to issue/renew.
第二步:手动在 DNS 控制台添加 TXT 记录
- 记录名:
_validation-persist.example.com - 记录类型:
TXT - 记录值:命令输出的字符串
第三步:申请证书(含通配符)
acme.sh --issue -d example.com -d *.example.com --dns-persist
之后所有续期都会自动进行,无需任何手动操作。
注意:DNS Persist 模式需要 CA 支持,目前主要在 Let’s Encrypt 测试环境和部分 CA 上可用。
4.6 DNS 别名模式(DNS Alias Mode)
4.6.1 概述
DNS 别名模式适用于以下场景:
- 主域名的 DNS 服务商没有提供 API
- 出于安全考虑,不想把主域名的 DNS API Key 存放在服务器上
- 多服务器共用一个 DNS API Key 进行验证
原理:将 ACME 挑战的 TXT 记录 CNAME 到另一个域名(该域名支持 API 操作),acme.sh 通过操作该别名域名的 DNS 来完成验证。
4.6.2 配置步骤
第一步:在主域名 DNS 控制台添加 CNAME 记录(一次性手动操作):
_acme-challenge.example.com CNAME _acme-challenge.challenge.anotherdomain.com
第二步:确保 challenge.anotherdomain.com 的 DNS 支持 API 操作(如使用 Cloudflare):
export CF_Token="your_cloudflare_token"
export CF_Account_ID="your_account_id"
# 使用 DNS 别名模式申请证书
acme.sh --issue --dns dns_cf \
-d example.com \
-d *.example.com \
--challenge-alias challenge.anotherdomain.com
acme.sh 会将 TXT 记录写入 challenge.anotherdomain.com 域,而主域名通过 CNAME 解析到该域,CA 可以验证成功。
4.7 DNS 传播等待时间调整
不同 DNS 服务商的 TTL 和记录传播时间不同,有时需要调整等待时间:
# 为当次申请设置等待时间(秒)
acme.sh --issue --dns dns_ali -d example.com --dnssleep 120
# 为特定域名设置持久等待时间(保存到配置)
acme.sh --issue --dns dns_ali -d example.com
# 编辑 ~/.acme.sh/example.com/example.com.conf,添加:
# Le_DNSSleep=120
各 DNS 服务商推荐等待时间参考:
| DNS 服务商 | 推荐等待时间 |
|---|---|
| 阿里云 DNS | 60-120 秒 |
| 腾讯云 DNS | 60-120 秒 |
| Cloudflare | 默认(极快) |
| GoDaddy | 600 秒 |
| Linode | 900 秒 |
| AWS Route53 | 60-120 秒 |
4.8 小结
本章介绍了 DNS-01 验证的所有模式:
- 手动 DNS 模式:适合一次性申请,无法自动续期
- DNS API 自动模式:推荐生产环境使用,支持通配符,自动续期
- DNS Persist 模式:新特性,一次手动操作,永久自动续期
- DNS 别名模式:适合主域名 DNS 无 API 的场景
下一章将专门介绍 acme.sh 与中国各大主流云服务商的集成使用。