用户服务器在没有 80 端口的情况下,DNS-01 挑战正是解决SSL证书申请问题的标准答案。它通过证明你对域名的 DNS 管理权来获取证书,完全不依赖于任何端口的开放状态。
以下是基于你“纯内网”或“端口转发”环境的解决方案和具体操作步骤。
一、为什么 DNS-01 挑战能解决你的问题?
与需要公网 Web 服务的 HTTP-01 不同,DNS-01 的工作机制绕过了网络层的限制:
无需开放端口:CA 机构不会连接你的服务器,而是通过查询全球 DNS 系统来验证。这意味着你的服务器可以深藏在内网,没有公网 IP,或者 80/443 端口被运营商封锁(如家庭宽带),都无法阻止证书颁发。
适用性广:它不仅适用于内网,还支持申请通配符证书(`*.example.com`),这是 HTTP-01 无法做到的。
二、如何操作:两种实现路径
根据你的环境是否允许自动化,有两种主流的实现方式。
方案一:手动模式(适合偶尔申请或 DNS 服务商无 API)
这种方式不依赖任何自动化工具,只需在命令行和 DNS 管理后台之间切换即可。
1. 安装客户端并执行命令:在任意一台能联网的机器上(不一定是目标服务器),运行 Certbot 并指定手动模式和 DNS 挑战。
bash
certbot certonly --manual --preferred-challenges dns -d your-internal-domain.com
2. 获取验证信息:命令执行后,会暂停并显示一条需要添加的 TXT 记录信息。例如:
> Please deploy a DNS TXT record under the name:
> `_acme-challenge.your-internal-domain.com`
> with the following value:
> `cOVnVQwdMEAXpTjjZHnPL7AMQ0gDf78T3W7_exfO4W4`
3. 配置 DNS 记录:登录你的域名 DNS 服务商后台(如阿里云、DNSPod、Cloudflare 等),添加上述主机记录和 TXT 值。
4. 等待并验证:添加后,可以使用 `dig` 命令检查记录是否全球生效(通常几分钟内):
bash
dig +short txt _acme-challenge.your-internal-domain.com @8.8.8.8
5. 完成签发:返回命令行按回车,CA 验证通过后,证书文件就会生成在当前机器的指定目录下(通常是 `/etc/letsencrypt/live/`)。之后,你可以手动将这些证书文件传输到你的内网服务器上进行配置。
方案二:自动模式(适合长期、自动化续期)
如果你的 DNS 服务商提供 API 密钥,可以实现“一次配置,自动续期”,彻底摆脱手动操作的繁琐。
1. 准备 API 凭证:登录你的 DNS 服务商控制台,申请并获取 API 密钥(通常需要具备 DNS 记录增删权限)。
2. 使用支持 API 的客户端:推荐使用 `acme.sh`,它内置了大量 DNS 服务商的 API 集成。
bash
# 以阿里云为例,导出环境变量
export Ali_Key="你的AccessKey ID"
export Ali_Secret="你的AccessKey Secret"
# 签发证书
acme.sh --issue --dns dns_ali -d your-internal-domain.com
```
3. 部署证书:签发成功后,将证书安装到你的内网服务指定路径,并设置重启服务的命令。
bash
acme.sh --install-cert -d your-internal-domain.com \
--key-file /data/ssl/your-domain.key \
--fullchain-file /data/ssl/your-domain.crt \
--reloadcmd "systemctl restart nginx" # 根据你的服务调整命令
4. 自动续期:`acme.sh` 会自动添加定时任务,后续在证书到期前会自动通过 API 添加 TXT 记录完成续期。
三、注意事项
传播时间:DNS 记录添加后,全球生效可能需要几十秒到几分钟。在手动模式中,建议添加记录后等待 30-60 秒再按回车,避免 CA 查询不到记录导致验证失败。
记录清理:验证完成后,建议手动删除刚添加的 TXT 记录(自动模式客户端会自行处理),保持 DNS 解析整洁。
续期命令:如果使用手动模式,SSL证书到期(如 Let's Encrypt 的 90 天有效期)后,需要重复上述手动流程,无法自动化。
你可以根据自己的网络环境和维护频率,选择最适合的方案。如果想了解特定 DNS 服务商(如阿里云、Cloudflare)的 API 配置细节,也可以随时问我。