- 网络安全
- 密码学
【免费下载链接】lego
Let's Encrypt/ACME client and library written in Go
导读
Domeneshop(也写作 "Domainnameshop")是挪威的一家域名与托管服务商。lego 项目从 v4.3.0 起内置了domeneshop这个 DNS 提供商,用于在自动签发 Let's Encrypt 证书时解决 DNS-01 挑战:通过 Domeneshop 公开 API 自动创建 / 删除_acme-challengeTXT 记录。本文将基于官方文档 docs/content/dns/zz_gen_domeneshop.md(该文档由 providers/dns/domeneshop/domeneshop.toml 自动生成)与仓库源码,完整介绍凭证获取、环境变量配置、超时参数调优,并深入解读其底层实现与测试用例,帮助你真正把该提供商跑起来并理解其工作原理。
一、Provider 基本信息
| 项目 | 值 |
|---|---|
| Code(命令行使用名) | domeneshop |
| 别名 | domainnameshop |
| 引入版本 | v4.3.0 |
| 支持挑战类型 | DNS-01(TXT 记录) |
| 实现源码 | providers/dns/domeneshop/domeneshop.go |
从源码结构看,该提供商由两层组成:对外暴露的 DNSProvider 负责与 lego 的挑战框架对接(实现Present、CleanUp、Timeout等接口),内部则封装了一个精简的 Domeneshop API 客户端 internal/client.go,仅处理 ACME 场景所需的 TXT 记录增删操作。
二、前置条件
在使用该提供商前需要确认:
- 待签发证书的域名(或其权威 DNS 区域)托管在 Domeneshop,且该域名在 Domeneshop 侧已启用 DNS 服务。
- 这一点在源码中有明确校验:
internal.Client.GetDomainByName遍历域名列表时,会跳过Services.DNS == false的域名(internal/client.go),因为未启用 DNS 服务的域名无法添加记录。
- 这一点在源码中有明确校验:
- 已拥有 Domeneshop API 凭证(API token + API secret)。创建方法见 Domeneshop API 文档的 "Authentication" 章节,凭证本质是一对用于 HTTP Basic Auth 的 token/secret 组合(见下文源码解析)。
三、快速上手:签发证书
官方文档给出的典型用法如下,通过环境变量注入凭证,然后使用--dns domeneshop指定提供商:
DOMENESHOP_API_TOKEN=<token> \ DOMENESHOP_API_SECRET=<secret> \ lego run --dns domeneshop -d '*.example.com' -d example.com要点说明:
-d '*.example.com'签发通配符证书时必须走 DNS-01 挑战,这是dns domeneshop的核心场景;- 同时传入根域名
example.com可以在一张证书里同时覆盖根域与所有子域; - 命令执行过程中,lego 会调用
Present自动在 Domeneshop 创建 TXT 记录,等待 DNS 传播验证通过后,再调用CleanUp删除记录(详见第五节)。
四、凭证与环境变量配置
4.1 必填凭证
| 环境变量名 | 说明 |
|---|---|
DOMENESHOP_API_SECRET | API secret |
DOMENESHOP_API_TOKEN | API token |
两个变量缺一不可。源码中 NewDNSProvider 通过env.Get(EnvAPIToken, EnvAPISecret)一次性读取并校验,缺失时会直接报错;对应的测试用例 domeneshop_test.go 覆盖了四种情况:
- 两者齐全 → 创建成功;
- 两者都缺失 → 报错
domeneshop: some credentials information are missing: DOMENESHOP_API_TOKEN,DOMENESHOP_API_SECRET; - 仅缺 token → 报错并指明缺失项;
- 仅缺 secret → 同上。
因此排查问题时,先确认终端里两个变量都已正确 export(或使用_FILE变体,见 4.3)。
4.2 可选调优参数
| 环境变量名 | 说明 | 默认值 |
|---|---|---|
DOMENESHOP_HTTP_TIMEOUT | API 请求超时时间(秒) | 30 |
DOMENESHOP_POLLING_INTERVAL | 两次 DNS 传播检测之间的间隔(秒) | 20 |
DOMENESHOP_PROPAGATION_TIMEOUT | 等待 DNS 传播的最长时间(秒) | 300 |
这些默认值在 NewDefaultConfig 中均有对应实现,且与Timeout()接口直接挂钩:Timeout()返回的(timeout, interval)就是PropagationTimeout与PollingInterval(domeneshop.go),lego 将依据这两个值决定轮询_acme-challengeTXT 记录何时在全球 DNS 中生效。
调优建议(依据源码默认行为推断):
- 若你的 DNS 服务商传播较慢,可调大
DOMENESHOP_PROPAGATION_TIMEOUT,避免在 300 秒内未生效时签发失败; - 若想加快签发速度,可适当调小
DOMENESHOP_POLLING_INTERVAL(20 秒是相对保守的轮询间隔); DOMENESHOP_HTTP_TIMEOUT只影响与 API 的单次请求时长,一般无需修改。
4.3_FILE后缀:用文件代替值
文档明确说明:"环境变量名可通过_FILE后缀改为引用文件而不是直接写值"。例如:
DOMENESHOP_API_TOKEN_FILE=/run/secrets/domeneshop_token \ DOMENESHOP_API_SECRET_FILE=/run/secrets/domeneshop_secret \ lego run --dns domeneshop -d '*.example.com' -d example.com这在 Docker/Kubernetes Secret 挂载等场景下非常实用。该机制由 lego 统一的 platform/env/env.go 实现:优先读取KEY本身,为空时再尝试读取KEY_FILE指向的文件内容,并自动去除结尾的换行符(strings.TrimRight(..., "\r\n"))。注意:当KEY与KEY_FILE同时存在时,直接的环境变量值优先。
4.4 使用配置文件(File Configuration)
除环境变量外,lego 还支持基于 YAML 的 文件配置模式(lego run --config config.yml)。在文件配置中同样使用DOMENESHOP_*命名空间下的键来提供凭证与调优参数,适合需要把证书签发参数化、版本化的团队。更完整的通用凭证与配置约定可参见 DNS 提供商总览文档。
五、工作原理:Present / CleanUp 与 API 交互
5.1 挑战记录的生命周期
DNSProvider实现了 lego 挑战框架要求的两个核心方法(domeneshop.go):
Present(ctx, domain, _, keyAuth):签发前调用。流程为——- 用
dns01.GetChallengeInfo根据域名与keyAuth计算出挑战记录内容; splitDomain把完整挑战 FQDN 拆成「权威区域 zone」与「主机名 host」两部分(基于 DNS 查询FindZoneByFqdn,splitDomain);client.GetDomainByName找到对应的域名对象;client.CreateTXTRecord在host上写入 TXT 记录。
- 用
CleanUp(ctx, domain, _, keyAuth):验证完成后调用,按相同的 zone/host 拆解逻辑定位域名,再按「host + 记录内容」双重匹配删除对应记录。
5.2 底层 API 客户端
internal/client.go 是对 Domeneshop API(https://api.domeneshop.no/v0)的轻量封装,关键实现细节:
- 认证方式:每个请求通过
req.SetBasicAuth(c.apiToken, c.apiSecret)设置 HTTP Basic Auth(client.go),即 token 作为用户名、secret 作为密码; - 创建记录:
POST /domains/{domainId}/dns,写入的记录固定为Type: "TXT"、TTL: 300(CreateTXTRecord),请求体结构可见测试夹具 create_record-request.json; - 查询域名:
GET /domains,返回结构见 getDomains.json,其中services.dns用于过滤未启用 DNS 服务的域名; - 删除记录:先
GET /domains/{domainId}/dns找到Host与Data都匹配的记录,再DELETE /domains/{domainId}/dns/{recordId}(DeleteTXTRecord),匹配逻辑见 getDNSRecordByHostData; - 数据结构:
Domain/Service/DNSRecord的 JSON 字段定义在 internal/types.go。
5.3 验证与测试
仓库为 providers/dns/domeneshop/domeneshop_test.go 提供了两类测试:
- 单元测试:
TestNewDNSProvider/TestNewDNSProviderConfig校验凭证缺失时的报错行为与默认配置的生成; - 在线测试(live test):
TestLivePresent/TestLiveCleanUp会真实调用 API 写入123d==这条挑战记录再删除,需要设置真实凭证与DOMENESHOP_DOMAIN环境变量才会执行(envTest.IsLiveTest()判定)。如果你想在接入前做一次真实链路冒烟验证,可以仿照这两个用例进行。
六、以库的形式接入(进阶用法)
除了 CLI,lego 还提供 Go 库接口。若你在自己的程序里调用该提供商,可以使用NewDNSProviderConfig传入一个 Config 结构体:
import "github.com/go-acme/lego/v4/providers/dns/domeneshop" config := domeneshop.NewDefaultConfig() config.APIToken = "your-token" config.APISecret = "your-secret" // 可选:覆盖超时 // config.PropagationTimeout = 10 * time.Minute // config.PollingInterval = 10 * time.Second provider, err := domeneshop.NewDNSProviderConfig(config) if err != nil { log.Fatal(err) }NewDNSProviderConfig会做两道校验(domeneshop.go):config 不能为 nil;APIToken与APISecret不能为空。同时,注入的HTTPClient会被包上一层clientdebug.Wrap,用于在LEGO_DEBUG开启时输出调试信息,便于排查 API 交互问题。
七、注意事项与常见问题
- 凭证必填:
DOMENESHOP_API_TOKEN/DOMENESHOP_API_SECRET缺一不可,缺失时报错信息会明确点名缺失的变量,可按提示逐个核对。 - 域名必须启用 DNS 服务:
GetDomainByName会跳过services.dns == false的域名,若报 "failed to find matching domain name",请先到 Domeneshop 控制台确认该域名的 DNS 服务状态。 - 删除记录依赖内容匹配:
CleanUp按 host + data 双重匹配删除,如果挑战记录已被第三方手动修改,可能匹配失败,此时需人工清理残留 TXT 记录。 - 通配符证书只能走 DNS-01:
-d '*.example.com'无法使用 HTTP-01,必须搭配--dns,这正是本提供商的使用场景。 - 传播等待可调:默认最多等 300 秒、每 20 秒检查一次;遇到 "timeout waiting for record" 类错误时,优先考虑调大
DOMENESHOP_PROPAGATION_TIMEOUT。 - 敏感信息保护:生产环境推荐使用
_FILE后缀从 Secret 文件注入凭证,避免 token 出现在进程列表或 shell 历史中。
- 网络安全
- 密码学
【免费下载链接】lego
Let's Encrypt/ACME client and library written in Go
相关推荐
Jekyll Gitbook 主题 LaTeX 数学公式指南:MathJax 渲染公式一步到位
Jekyll Gitbook 主题 LaTeX 数学公式指南:MathJax 渲染公式一步到位 jekyll gitbook 是一款把 Jekyll 静态站点打
网络安全密码学GetQzonehistory:你的QQ空间时光机,一键备份十年青春回忆
GetQzonehistory:你的QQ空间时光机,一键备份十年青春回忆 你是否曾翻看QQ空间,发现那些承载着青春记忆的说说和照片正在慢慢消失?超过70%的QQ
网络安全密码学marimo-pair 技能深度解析:AI 如何在 marimo 实时内核中安全地操作笔记本
marimo pair 技能深度解析:AI 如何在 marimo 实时内核中安全地操作笔记本 marimo pair 是 marimo 内置给 AI 代理 编辑
网络安全密码学
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考