Loading... # ACME DNS 验证与自定义递归服务器作用分析 # 一、问题背景 ## 1. 核心疑问 在使用 acme.sh 的 DNS 验证方式申请域名证书时,用户可以指定自定义的递归 DNS 服务器。这引发了一个疑问:ACME 服务器是通过互联网的公共 DNS 进行域名验证的,用户指定的 DNS 服务器能起到什么作用? ## 2. 涉及组件 - ACME 协议:自动化证书管理环境协议 - acme.sh:Shell 脚本实现的 ACME 客户端 - DNS 验证:ACME 挑战-响应验证方式之一 - 递归 DNS 服务器:负责递归查询域名解析的服务器 # 二、ACME DNS 验证机制 ## 1. 验证流程概述 ```mermaid sequenceDiagram participant Client as acme.sh 客户端 participant DNS as DNS 服务商 participant Propagation as DNS 传播 participant ACME as ACME 服务器<br/>(Let's Encrypt) participant PublicDNS as 公共 DNS Client->>DNS: 1. 申请证书 Client->>DNS: 2. 添加 TXT 记录<br/>_acme-challenge.example.com DNS-->>Client: 确认添加成功 Note over Client,ACME: 等待 DNS 传播完成 Client->>PublicDNS: 3. 轮询检测 TXT 记录<br/>(使用指定 DNS 服务器) PublicDNS-->>Client: 仍不可见 Client->>PublicDNS: 继续轮询... PublicDNS-->>Client: 记录已可见 Client->>ACME: 4. 通知 ACME 服务器验证 ACME->>PublicDNS: 5. 从多个位置查询 TXT 记录 PublicDNS-->>ACME: 返回 TXT 记录值 ACME-->>Client: 6. 验证通过,颁发证书 Client->>DNS: 7. 清理 TXT 记录 ```  ## 2. ACME 服务器的验证行为 ### A. 多位置验证 ACME 服务器(如 Let's Encrypt)从全球多个位置验证 DNS 记录: - 验证源分布:美国、欧洲、亚太等地 - 使用的 DNS:公共递归服务器(如 Google 8.8.8.8、Cloudflare 1.1.1.1) - 验证逻辑:必须从多个位置都能查询到正确的 TXT 记录 ### B. 权威性验证路径 ``` ACME 服务器 → 公共递归 DNS → 权威 DNS → DNS 记录验证 ``` **关键点**:ACME 服务器不使用用户指定的 DNS 服务器进行验证。 # 三、自定义 DNS 服务器的作用 ## 1. 本地预检测机制 用户指定的 DNS 服务器仅用于 **acme.sh 本地的预检测**,不影响 ACME 服务器的验证过程。 ### A. 问题场景 ``` 时间轴: T0: 用户添加 TXT 记录到 DNS 服务商 T1: DNS 服务商更新权威记录 T2: 记录传播到部分 DNS 服务器 T3: 记录全球可见 acme.sh 在 T2 时刻触发验证 → ACME 服务器可能看不到记录 → 验证失败 ``` ### B. 解决方案 ```bash # 方式 1:固定等待时间(粗暴) acme.sh --issue --dns dns_cf -d example.com --dnssleep 120 # 方式 2:指定 DNS 服务器进行智能检测 export ACME_DNS_SERVER="8.8.8.8" acme.sh --issue --dns dns_cf -d example.com ``` ## 2. 工作原理对比 ```mermaid graph TB subgraph "方式 1:固定等待" A1[添加 TXT 记录] -->|等待 120 秒| B1[触发 ACME 验证] B1 --> C1{ACME 服务器查询} C1 -->|成功| D1[颁发证书] C1 -->|失败| E1[重试] end subgraph "方式 2:智能检测" A2[添加 TXT 记录] -->|轮询检测| B2[使用指定 DNS 查询] B2 -->|未检测到| B2 B2 -->|检测到| C2[触发 ACME 验证] C2 --> D2[颁发证书] end ```  ## 3. 具体配置示例 ### A. 使用公共递归 DNS ```bash # 使用 Google DNS 进行预检测 export ACME_DNS_SERVER="8.8.8.8:53" # 使用 Cloudflare DNS export ACME_DNS_SERVER="1.1.1.1:53" # 使用国内 DNS(加速检测) export ACME_DNS_SERVER="223.5.5.5:53" ``` ### B. 使用权威 DNS ```bash # 直接查询权威 DNS 服务器,传播延迟最小 export ACME_DNS_SERVER="ns1.example.com:53" ``` ### C. acme.sh 源码逻辑 ```bash # acme.sh 中的检测逻辑(简化) _Dns_lookup() { domain="$1" dns_server="$ACME_DNS_SERVER" # 使用用户指定的 DNS # 如果未指定,使用系统默认 DNS if [ -z "$dns_server" ]; then dns_server=$(cat /etc/resolv.conf | grep nameserver | head -1 | awk '{print $2}') fi # 查询 TXT 记录 dig @$dns_server _acme-challenge.$domain TXT +short } # 轮询检测 _check_dns_propagation() { max_wait=300 # 最多等待 5 分钟 interval=10 # 每 10 秒检测一次 for i in $(seq 1 $((max_wait / interval))); do result=$(_Dns_lookup "$domain") if [ -n "$result" ]; then echo "DNS 记录已传播" return 0 fi echo "等待 DNS 传播... ($i/$((max_wait / interval)))" sleep $interval done return 1 } ``` # 四、应用场景分析 ## 1. 有用的场景 ### A. 加速 DNS 传播检测 使用权威 DNS 或就近的递归 DNS 可以更快检测到记录更新: ```bash # 场景:DNS 服务商在国内,权威 DNS 在阿里云 export ACME_DNS_SERVER="ns1.aliyun.com:53" acme.sh --issue --dns dns_ali -d example.com ``` **效果**:无需等待 120 秒固定时间,记录可见后立即触发验证。 ### B. 绕过有问题的本地 DNS 某些本地 DNS 可能缓存时间过长或响应异常: ```bash # 绕过本地 DNS,直接使用公共 DNS export ACME_DNS_SERVER="8.8.8.8:53" ``` ### C. 多 DNS 服务器环境 在内网有自定义 DNS 服务器时,明确指定使用公共 DNS: ```bash # 避免查询到内网的错误结果 export ACME_DNS_SERVER="114.114.114.114:53" ``` ## 2. 无效的场景 ### A. 内网 DNS 验证 ``` 错误认知:指定内网 DNS 服务器可以让 ACME 服务器验证内网域名 实际情况: - ACME 服务器从互联网查询公共 DNS - 内网 DNS 对 ACME 服务器不可见 - 公网域名无法通过内网 DNS 验证 ``` ### B. 强制 ACME 服务器使用指定 DNS ``` 错误认知:用户指定的 DNS 会影响 ACME 服务器的验证行为 实际情况: - ACME 服务器忽略客户端的 DNS 配置 - 使用自己的验证基础设施 - 用户 DNS 仅用于客户端预检测 ``` # 五、技术细节 ## 1. DNS 传播时间 | DNS 服务器类型 | 典型传播时间 | 适用场景 | |--------------|------------|---------| | 权威 DNS | 0-5 秒 | 最快检测,推荐 | | 公共递归 DNS | 10-60 秒 | 通用场景 | | 本地 ISP DNS | 60-300 秒 | 不推荐,可能缓存旧数据 | ## 2. 配置参数说明 ```bash # --dnssleep:固定等待时间(秒) acme.sh --dnssleep 300 # 等待 5 分钟 # ACME_DNS_SERVER:指定 DNS 服务器用于预检测 export ACME_DNS_SERVER="8.8.8.8:53" # 两者关系: # - 设置 ACME_DNS_SERVER 后,--dnssleep 会变成超时时间 # - 未设置 ACME_DNS_SERVER 时,--dnssleep 是固定等待时间 ``` ## 3. 最佳实践 ### A. 推荐配置 ```bash #!/bin/bash # 最佳实践示例 # 1. 使用权威 DNS(如果知道) export ACME_DNS_SERVER="ns1.cloudflare.com:53" # 2. 或使用就近的公共 DNS export ACME_DNS_SERVER="223.5.5.5:53" # 阿里 DNS # 3. 设置合理的超时时间 acme.sh --issue --dns dns_cf \ -d example.com \ -d www.example.com \ --dnssleep 300 # 最多等待 5 分钟 ``` ### B. 生产环境建议 - 对于生产环境,建议等待足够时间(DNS TTL + 缓冲时间) - 监控 DNS 传播状态,记录实际传播时间 - 使用 DNS 监控服务验证全球可见性 # 六、总结 ## 1. 核心要点 ### A. 验证路径分离 ``` 用户指定 DNS → acme.sh 本地预检测(优化等待时间) ACME 服务器 → 公共 DNS → 权威 DNS(实际验证) ``` ### B. 作用范围 - ✅ 可以优化:本地检测等待时间 - ❌ 不能改变:ACME 服务器的验证行为 - ❌ 不能实现:内网域名的公网验证 ### C. 推荐使用 - 权威 DNS 服务器:最快检测 - 就近公共 DNS:平衡速度和可靠性 - 避免使用:有缓存问题的本地 ISP DNS ## 2. 常见误解澄清 | 误解 | 实际情况 | |------|---------| | 用户 DNS 影响 ACME 验证 | 仅影响本地预检测 | | 可以指定内网 DNS 验证 | ACME 服务器无法访问内网 DNS | | 固定等待时间更可靠 | 智能检测更高效,减少不必要的等待 | | DNS 传播需要很长时间 | 权威 DNS 可立即检测到 | ## 3. 技术价值 自定义 DNS 服务器功能的价值在于: - 减少证书申请的总时间 - 提高自动化脚本的效率 - 适应不同的网络环境和 DNS 基础设施 这是一个典型的 **客户端优化** 功能,通过本地智能检测减少等待时间,但不改变服务端的验证逻辑。 *** ## 参考资料 1. [ACME 协议规范 (RFC 8555)](https://datatracker.ietf.org/doc/html/rfc8555) 2. [Let's Encrypt 验证方式说明](https://letsencrypt.org/docs/challenge-types/) 3. [acme.sh 官方文档 - DNS 手动模式](https://github.com/acmesh-official/acme.sh/wiki/dns-manual-mode) 4. [DNS 传播机制原理](https://www.dns-oarc.net/oarc/articles/dns-propagation) 最后修改:2026 年 01 月 29 日 © 允许规范转载 赞 如果觉得我的文章对你有用,请随意赞赏