内网服务器无法访问外网如何通过 DNS 验证完成 Let's Encrypt 续签?

文章导读
内网服务器若完全无法访问外网,无法直接运行 ACME 客户端,需通过外部机器配合 DNS 验证完成续签,核心是分离密钥与验证过程。
📋 目录
  1. A 命令与配置准备
  2. B 原理简述
  3. C 分步处理
  4. D 怎么验证是否生效
  5. E 常见坑
  6. F 参考来源
A A

内网服务器若完全无法访问外网,无法直接运行 ACME 客户端,需通过外部机器配合 DNS 验证完成续签,核心是分离密钥与验证过程。

先说结论:DNS-01 验证解决入站限制,但 ACME 协议仍需出站访问 CA,完全隔离时需借用外网机器代理申请。

  • 适合:无法开放 80/443 端口且无出站 HTTPS 权限的严格内网环境
  • 关键安全点:私钥必须在内网生成,外网仅处理 CSR 与验证
  • 先准备:域名 DNS 管理 API 权限,以及内外网文件传输通道
  • 验收:使用 OpenSSL 检查证书有效期及链完整性

命令与配置准备

在外网机器上配置 DNS Provider 的 API Token,以 Cloudflare 为例,建议通过环境变量传递,避免明文留在脚本中:

export CF_Token="your_cloudflare_api_token"
export CF_Account_ID="your_account_id"

安全提示:API Token 仅需授予编辑特定域名 DNS 记录的权限,切勿使用全局 API Key。

若使用 acme.sh 配合 DNS API 申请(需提前配置 DNS Provider 的 Token):

acme.sh `--issue` `--csr` /path/to/csr.csr `--dns` dns_cf

若使用 Certbot 手动模式,需在外网机器运行(不适合自动化):

certbot certonly `--manual` `--preferred-challenges` dns -d example.com

原理简述

默认 HTTP-01 验证要求 Let's Encrypt 服务器能访问你的 80 端口,内网环境通常无法满足。DNS-01 验证改为要求你在域名解析中添加特定 TXT 记录,CA 通过查询 DNS 来确认所有权,不依赖服务器 inbound 连接。但 ACME 协议本身要求客户端与 CA 进行 API 通信,因此客户端仍需出站权限,若内网服务器无出站权限,必须在外网机器执行客户端逻辑。

分步处理

1. 确认网络策略:检查内网服务器是否能访问 acme-v02.api.letsencrypt.org。若不能,准备一台可上网的外部机器。

内网服务器无法访问外网如何通过 DNS 验证完成 Let's Encrypt 续签?

2. 生成私钥与 CSR(推荐内网完成):在内网服务器生成私钥和证书签名请求,确保私钥不出内网。

openssl req -new -newkey rsa:2048 -nodes -keyout private.key -out csr.csr -subj "/CN=example.com"

3. 执行验证

  • 将 csr.csr 复制到外网机器。
  • 在外网机器使用 ACME 客户端加载 CSR 并完成 DNS 验证(推荐配置 DNS API 实现自动化)。
  • 验证通过后,外网机器生成证书文件。

4. 部署证书:仅将公钥证书(fullchain.pem)传回内网,与内网生成的 private.key 配合配置到 Web 服务器。

怎么验证是否生效

使用以下命令检查证书有效期:

openssl x509 -noout -dates -in /path/to/fullchain.pem

检查证书主题是否正确:

openssl x509 -noout -subject -in /path/to/fullchain.pem

检查 Web 服务配置是否正确加载:

nginx -t  # 或 apache2ctl configtest

重启服务后,通过浏览器或 curl 访问域名,查看证书详情。

常见坑

  • DNS 传播延迟:添加 TXT 记录后需等待生效,过早验证会失败,API 模式通常会自动等待。
  • 私钥安全:若在外网机器运行 ACME 客户端,尽量避免私钥离开内网,采用 CSR 模式更安全。
  • API 密钥泄露:外网机器操作完成后,建议清除历史命令中的敏感环境变量。
  • 自动化困难:手动 DNS 模式无法自动化续签,建议使用 DNS API 插件。
  • CAA 记录:检查域名 DNS 是否设置了 CAA 记录限制颁发机构。

参考来源

  • Let's Encrypt Official Documentation, "DNS Challenge", letsencrypt.org
  • Certbot Documentation, "Getting certificates", certbot.eff.org
  • ACME Protocol RFC 8555, IETF