尧图网络科技YAOTU DIGITAL 获取报价
获取报价
首页 / 资讯中心 / 文章详情

使用 lego 与 Joohoi‘s ACME-DNS 完成 DNS-01 挑战:配置指南与源码原理

发布时间:2026/9/24 16:58:48

资讯中心
01
ARTICLE

使用 lego 与 Joohoi‘s ACME-DNS 完成 DNS-01 挑战:配置指南与源码原理

使用 lego 与 Joohoi‘s ACME-DNS 完成 DNS-01 挑战:配置指南与源码原理
网络安全密码学【免费下载链接】legoLets Encrypt/ACME client and library written in Go项目地址https://gitcode.com/gh_mirrors/le/lego点击查看免费下载本篇技术指南讲解如何在 Go 语言编写的 Lets Encrypt/ACME 客户端 lego 中将Joohois ACME-DNSprovider Code 为acme-dns自 lego v1.1.0 起支持配置为 DNS-01 挑战的解决方案。你将掌握 ACME-DNS 的全部环境变量含_FILE后缀与 dotenv 用法、账户文件/HTTP 两种存储模式、首次使用时的一次性 CNAME 手工接入流程以及该 provider 在源码层面的工作机理从而在自建/私有 DNS 场景下稳定地自动化签发通配符证书。适用场景为什么选择 ACME-DNSACME-DNS 是一套轻量级、自托管的 DNS 服务由 Joohoi 维护它通过在权威 DNS 区域中为待验证域名添加一条指向 ACME-DNS 服务的 CNAME 记录的方式把_acme-challenge的 TXT 解析权委托给 ACME-DNS 实例再由 lego 通过 HTTP API 直接写入 TXT 记录。这样无需为每个域名提供商的 DNS API 维护独立凭证只需操作一次 CNAME 委托适合那些不提供便捷 API 的域名注册商、内网自建 DNS、或希望把挑战响应集中管理到自有服务的场景。在 lego 中该 provider 的元数据定义在 providers/dns/acmedns/acmedns.toml其 Code 为acmedns并保留了别名acme-dns为兼容 lego v4 的旧命令写法未来版本计划移除该别名。快速开始两条可直接运行的命令原文档给出了两种启动方式二者的核心区别在于账户数据的存放位置本地 JSON 文件或远端 HTTP 存储下文会逐一剖析。方式一账户数据保存在本地 JSON 文件ACME_DNS_API_BASEhttp://10.0.0.8:4443 \ ACME_DNS_STORAGE_PATH/root/.lego-acme-dns-accounts.json \ lego run --dns acme-dns -d *.example.com -d example.com方式二账户数据由远端 HTTP 服务托管ACME_DNS_API_BASEhttp://10.0.0.8:4443 \ ACME_DNS_STORAGE_BASE_URLhttp://10.10.10.10:80 \ lego run --dns acme-dns -d *.example.com -d example.com两条命令都同时签发*.example.com与example.com覆盖裸域与通配符域这是 ACME 通配符证书的典型组合写法。lego run会完成注册账户、申请订单、执行 DNS-01 挑战、下载证书的完整流程。环境变量详解凭证类变量Credentials环境变量说明ACME_DNS_API_BASEACME-DNS 服务的 API 地址例如http://10.0.0.8:4443即你的 acme-dns 实例监听地址。必填ACME_DNS_STORAGE_PATHACME-DNS 账户数据的本地 JSON 文件路径。lego 会按域名注册/持久化独立账户到该文件并在后续 TXT 更新时复用。与ACME_DNS_STORAGE_BASE_URL二选一ACME_DNS_STORAGE_BASE_URLACME-DNS 账户数据的远端存储服务地址HTTP 存储用于跨机器共享账户映射二选一约束ACME_DNS_STORAGE_PATH与ACME_DNS_STORAGE_BASE_URL必须且只能配置其一。在 acmedns.go 的getStorage函数中可以看到两者都为空会报错storagePath or storageBaseURL is not set两者同时设置会报错storagePath and storageBaseURL cannot be used at the same time从源码层面强制了模式互斥。附加配置变量Additional Configuration环境变量说明ACME_DNS_ALLOWLIST允许访问的源网络使用 CIDR 表示法多个值用英文逗号分隔例如192.168.100.1/24,1.2.3.4/32,2002:c0a8:2a00::0/40该示例同时含 IPv4 与 IPv6 网段见 acmedns.go 中常量注释。该列表会随新账户注册请求一并发送给 ACME-DNS 服务端用于限制该账户的 TXT 写入来源_FILE后缀从文件读取配置值原文档特别指出上述所有环境变量名都可以追加_FILE后缀改为从文件读取值。这是 lego 各 DNS provider 的通用能力细节定义在 docs/content/dns/_index.md 的 Configuration and Credentials 一节ACME_DNS_API_BASE_FILE/the/path/to/api-base \ ACME_DNS_STORAGE_PATH_FILE/the/path/to/storage-path \ lego run --dns acme-dns --domains *.example.com --domains example.com使用_FILE时文件内容必须只包含该变量的值本身不含换行、注释或KEYvalue形式。该能力非常适合在 systemd 单元、容器 secrets 或 CI 流水线中避免把敏感地址/路径直接写进命令行。在源码中对应 acmedns.go 的env.GetOrFile调用——EnvStoragePath、EnvStorageBaseURL、EnvAllowList均支持文件回退读取。使用 dotenv 文件lego run还支持通过--env-file标志加载 dotenv 文件适合把多个 provider 的变量集中管理lego run --dns acme-dns --domains example.com --domains *.example.com --env-file .env.acmedns.env.acmedns内容示例ACME_DNS_API_BASEhttp://10.0.0.8:4443 ACME_DNS_STORAGE_PATH/root/.lego-acme-dns-accounts.json ACME_DNS_ALLOWLIST192.168.100.1/24,2002:c0a8:2a00::0/40使用配置文件.lego.yml时则可在对应 challenges 条目下通过envFile: .env.acmedns指定详见 docs/content/dns/_index.md。账户存储本地文件模式与 HTTP 模式ACME-DNS 的账户Account本质上是域名 → 该域在 acme-dns 服务上注册的子域凭证的映射lego 必须持久化这份映射才能在下一次续期时直接更新 TXT而不必重新注册。两种存储模式分别对应ACME_DNS_STORAGE_PATH与ACME_DNS_STORAGE_BASE_URL。本地文件存储File Storage当配置ACME_DNS_STORAGE_PATH时lego 调用storage.NewFile(config.StoragePath, 0o600)创建文件存储见 acmedns.go即账户 JSON 文件的权限被收紧为仅属主可读写0o600。文件内容为域名 → 账户的 JSON 映射例如{ example.com: { fulldomain: acme-dns.your-domain.com, subdomain: random-looking-junk, username: spooky.mulder, password: trustno1, server_url: http://10.0.0.8:4443 } }其中fulldomain即 ACME-DNS 为该域分配的随机子域也是之后 CNAME 委托的目标地址Target。HTTP 存储HTTP Storage当配置ACME_DNS_STORAGE_BASE_URL时lego 使用内置的HTTPStorage实现见 providers/dns/acmedns/internal/http_storage.go把账户映射持久化到远端 HTTP 服务便于多台签发机共享同一份账户数据。其 HTTP 接口契约详见 providers/dns/acmedns/internal/readme.md为GET BaseURL/domain拉取指定域名的账户返回 200 与账户 JSON返回 404 表示该域尚无账户映射为storage.ErrDomainNotFoundGET BaseURL拉取全部域名 → 账户映射POST BaseURL/domain写入账户。响应状态码有特殊语义200存储端未代为创建 CNAMElego 将中止签发等待用户手工在 DNS 区域中添加 CNAME201存储端已代为创建好 CNAMElego 将继续签发流程而不报错。该200 停止 / 201 继续的语义在 http_storage.go 中以ErrCNAMEAlreadyCreated区分并有专门的单元测试覆盖见 internal/http_storage_test.go 的TestHTTPStorage_Put_CNAME_created验证 POST 返回 201 时返回该哨兵错误。HTTP 客户端超时被设置为 2 分钟http_storage.goSave在 HTTP 模式下是空操作无专门端点。工作流程与源码原理Present 的完整调用链在 acmedns.go 的Present方法中DNS-01 挑战的写入按以下步骤进行计算挑战信息调用dns01.GetChallengeInfo(ctx, domain, keyAuth)得到待写入的_acme-challenge.domainFQDN 与 TXT 值查询既有账户从存储文件或 HTTP中Fetch(domain)该域名对应的账户若已存在 → 直接进入第 4 步用既有账户调用client.UpdateTXTRecord更新 TXT若返回storage.ErrDomainNotFound该域还没有账户→ 进入第 3 步注册新账户并中断签发调用 ACME-DNS 的RegisterAccount(ctx, config.AllowList)注册新账户同时把ACME_DNS_ALLOWLIST作为 allowFrom 限制一并提交然后将账户Put进存储并Save持久化。之后故意返回ErrCNAMERequired错误终止本次签发——这是设计使然该错误会向用户打印需要手工创建的 CNAME 记录更新 TXT 记录调用UpdateTXTRecord(ctx, account, info.Value)完成挑战写入。上述流程在 acmedns_test.go 中由TestPresent、TestRegister以及基于 httptest 的TestPresent_httpStorage/TestRegister_httpStorage全面覆盖测试点包括存储返回意外错误、域名不存在时注册新账户并返回ErrCNAMERequired、TXT 更新失败、以及 HTTP 存储返回 200/201 两种分支201 时UpdateTXTRecord会被调用200 时不会。首次使用必须完成的一次性 CNAME 接入由于 ACME-DNS 的核心机制是CNAME 委托每个新域名在第一次签发时都会触发上述第 3 步的注册账户 中止签发。lego 会打印如下形式的错误由 acmedns.go 的ErrCNAMERequired.Error()生成acme-dns: new account created for example.com. To complete setup for example.com you must provision the following CNAME in your DNS zone and re-run this provider when it is in place: _acme-challenge.example.com. CNAME acme-dns.your-domain.com.你需要登录域名的权威 DNS 管理面板添加如下记录ErrCNAMERequired结构体的三个字段分别对应 Domain、FQDN 别名、Target 规范名见 acmedns.go类型主机记录name值value/targetCNAME_acme-challenge.example.comacme-dns.your-domain.com即新建账户的fulldomainCNAME 生效后重新运行同样的lego run命令即可此时存储中已存在该域账户流程会跳过注册、直接更新 TXT 并完成签发。该 CNAME 只需设置一次后续同一域名的续期与重新签发都会自动复用该委托关系。CleanUp 语义为什么记录不会被删除与原文档中多数 provider 不同ACME-DNS 的CleanUp是一个空实现acmedns.go// ACME-DNS doesnt support the notion of removing a record. // For users of ACME-DNS it is expected the stale records remain in-place. func (d *DNSProvider) CleanUp(_ context.Context, _, _, _ string) error { return nil }这是因为 ACME-DNS 服务端不提供删除 TXT 记录的能力旧记录残留是其预期行为不会影响下一次挑战下一次写入会覆盖同名 TXT 值。这也是使用 ACME-DNS 时需要注意的一个运维细节TXT 记录会持续保留在 ACME-DNS 实例中。以库方式集成可选除 CLI 之外该 provider 也可作为 Go 库使用。核心入口为acmedns.NewDNSProvider()读取环境变量构造与acmedns.NewDNSProviderConfig(config *Config)直接传入结构体构造其中Config定义在 acmedns.goAPIBase、AllowList[]string、StoragePath、StorageBaseURL。provider 实现了challenge.Provider接口Present/CleanUp可与其他 lego 组件组合使用其底层通过 nrdcg/goacmedns 客户端与 ACME-DNS 服务交互并针对测试将客户端抽象为acmeDNSClient接口UpdateTXTRecord与RegisterAccount两个方法见 acmedns.go。常见问题与注意事项ACME_DNS_API_BASE未设置NewDNSProvider会通过env.Get强制校验并返回acme-dns: erroracmedns.go因此该变量是唯一必填项存储模式不能混用文件模式与 HTTP 模式互斥同时设置会直接报错见上文二选一约束allowlist 分隔符ACME_DNS_ALLOWLIST支持 IPv4/IPv6 CIDR多个网段以逗号分隔acmedns.go 使用strings.Split(allowList, ,)解析权限安全文件模式下账户 JSON 以0o600权限落盘请勿将含密码的账户文件提交到版本库或暴露给其他用户CLI 兼容写法--dns acme-dns与--dns acmedns在当前版本均可使用别名acme-dns为兼容 v4 保留新项目建议直接使用acmedns。至此你已经掌握了从环境变量配置、两种账户存储模式到一次性 CNAME 接入与源码级调用链的完整知识可以在自己的 ACME-DNS 实例上落地通配符证书的自动化签发。赞分享网络安全密码学【免费下载链接】legoLets Encrypt/ACME client and library written in Go项目地址https://gitcode.com/gh_mirrors/le/lego点击查看免费下载相关推荐使用 lego 与 Gandi DNS 完成 ACME DNS-01 挑战配置指南与源码原理剖析使用 lego 与 Gandi DNS 完成 ACME DNS 01 挑战配置指南与源码原理剖析 导读 本文围绕 legoLets Encrypt/AC网络安全密码学使用 lego 的 ConoHa v2 DNS Provider 完成 ACME DNS-01 挑战配置指南与实现原理使用 lego 的 ConoHa v2 DNS Provider 完成 ACME DNS 01 挑战配置指南与实现原理 导读 本篇文章聚焦于 Go 语言编写的网络安全密码学使用 lego 与 Abion DNS 提供方完成 ACME DNS-01 挑战配置指南与源码解析使用 lego 与 Abion DNS 提供方完成 ACME DNS 01 挑战配置指南与源码解析 Abion 是 legoLets Encrypt/AC网络安全密码学上一篇KMS_VL_ALL_AIO 完整激活指南一个脚本搞定 Windows 与 Office 永久激活下一篇植物大战僵尸修改器神器 PVZ Toolkit零基础 5 分钟解锁无限阳光阵型与无尽模式效率翻倍创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
02
RELATED NEWS

相关资讯

更多网站建设与数字化升级内容

03
WHY YAOTU

想打造同款高转化官网?

懂行业、懂生意,从建站到增长一站式陪跑

场景化定制

不做模板站,围绕你的业务场景量身设计,小众不撞款。

营销型架构

以转化目标组织内容与路径,让官网真正带来询盘。

全周期服务

设计、开发、运营、运维一体,上线只是开始。

免费获取你的建站方案

留下需求,专属顾问 24 小时内为你输出方案建议。