☰
lego 使用 Ionos Cloud DNS 提供者签发 Let‘s Encrypt 证书:完整配置与原理剖析
2026/9/25 7:41:51 网站建设 项目流程
  • 网络安全
  • 密码学

【免费下载链接】lego

Let's Encrypt/ACME client and library written in Go

项目地址:https://gitcode.com/gh_mirrors/le/lego
点击查看免费下载

本文是 lego(Let's Encrypt/ACME client,使用 Go 编写)官方文档中 Ionos Cloud DNS 提供者的中文技术指南。文章以 docs/content/dns/zz_gen_ionoscloud.md 为核心骨架,结合 providers/dns/ionoscloud 目录下的源码与测试进行深度展开,帮助读者在 lego 中配置 Ionos Cloud(Ionos 云)DNS 服务,通过 DNS-01 挑战完成通配符证书签发,并理解其底层实现机制。

  • 提供者代码(Code):ionoscloud
  • 引入版本(Since):v4.30.0
  • 官方服务:Ionos Cloud DNS(Cloud DNS 管理界面)
  • API 文档:Ionos Cloud DNS API v1

快速上手:一条命令完成通配符证书签发

在 lego 中使用 Ionos Cloud 作为 DNS 挑战提供者的最小命令如下(原文档示例):

IONOSCLOUD_API_TOKEN="xxxxxxxxxxxxxxxxxxxxx" \ lego run --dns ionoscloud -d '*.example.com' -d example.com

命令语义拆解:

  • IONOSCLOUD_API_TOKEN:Ionos Cloud API 令牌,用于通过Authorization: Bearer <token>头对 DNS API 进行认证(见 providers/dns/ionoscloud/internal/client.go);
  • --dns ionoscloud:指定使用 DNS-01 挑战及 Ionos Cloud 提供者;
  • -d '*.example.com' -d example.com:同时请求通配符域名与裸域证书——由于 ACME 通配符挑战只能通过 DNS-01 完成,这正是此类 DNS 提供者最典型的使用场景。

注意:原文档命令中-d '*.example.com'表示申请的是通配符证书,-d example.com是为了让证书同时覆盖裸域。两个域名共用同一个_acme-challenge验证流程,Ionos Cloud 提供者会分别在所属 DNS zone 中写入对应的 TXT 记录。

使用前准备

  1. 登录 Ionos Cloud 控制台(Cloud DNS 服务),创建并启用托管 DNS zone(如example.com),并将域名的 NS 记录指向 zone 中显示的 nameservers(见 zones.json 测试夹具 中形如ns-ic.ui-dns.com的 NS 列表);
  2. 在 Ionos Cloud 的 API 密钥管理界面生成 API token(需具备 DNS zone 读写权限);
  3. 在 shell 环境中导出IONOSCLOUD_API_TOKEN,即可运行 lego 命令。

凭证配置(Credentials)

Ionos Cloud 提供者需要且仅需要一个凭证环境变量:

环境变量名说明
IONOSCLOUD_API_TOKENAPI token,用于调用 Ionos Cloud DNS API

这一约束在源码中有明确体现:NewDNSProvider()通过env.Get(EnvAPIToken)读取变量,缺失时会返回ionoscloud: some credentials information are missing: IONOSCLOUD_API_TOKEN错误(见 ionoscloud.go),对应的缺失凭证测试用例见 ionoscloud_test.go。而NewDNSProviderConfig()在 API token 为空时会直接返回ionoscloud: credentials missing(见 internal/client.go)。

使用_FILE后缀从文件读取凭证

lego 的 DNS 提供者统一支持"环境变量名 +_FILE"后缀,将变量值替换为指向凭证文件的路径(详见 docs/content/dns/_index.md 的"Configuration and Credentials"章节)。原文档特别提示:所有环境变量(含下文附加配置项)均可追加_FILE后缀引用文件而非直接引用值。

IONOSCLOUD_API_TOKEN_FILE=/path/to/ionoscloud-token \ lego run --dns ionoscloud -d '*.example.com' -d example.com

其中/path/to/ionoscloud-token文件内容应仅包含 token 值本身(不含换行符以外的任何多余内容)。这在需要将敏感信息与命令行历史、CI 日志隔离的场景下尤为实用。

附加配置项(Additional Configuration)

原文档给出了四个可选配置环境变量,均可通过IONOSCLOUD_前缀在 CLI 或程序化配置中设置:

环境变量名说明默认值
IONOSCLOUD_HTTP_TIMEOUTAPI 请求超时时间(秒)30
IONOSCLOUD_POLLING_INTERVALDNS 传播检查的轮询间隔(秒)2
IONOSCLOUD_PROPAGATION_TIMEOUTDNS 传播的最大等待时间(秒)120
IONOSCLOUD_TTLDNS 挑战所用 TXT 记录的 TTL(秒)120

以上默认值在NewDefaultConfig()中通过platform/env包读取并回退到内置默认值(见 ionoscloud.go):

  • IONOSCLOUD_TTL:默认取dns01.DefaultTTL(120 秒);
  • IONOSCLOUD_PROPAGATION_TIMEOUT:默认 120 秒;
  • IONOSCLOUD_POLLING_INTERVAL:默认取dns01.DefaultPollingInterval(2 秒);
  • IONOSCLOUD_HTTP_TIMEOUT:默认 30 秒,作用于底层http.Client的超时。

各配置项的实际影响

  • IONOSCLOUD_TTL:决定Present()阶段写入的 TXT 记录 TTL。该值直接进入 API 请求体(见 ionoscloud.go),测试夹具中对应请求为"ttl": 120(见 create_record-request.json)。TTL 越小,权威 DNS 缓存越早失效,验证速度越快,但会略微增加 DNS 查询压力;
  • IONOSCLOUD_PROPAGATION_TIMEOUT与IONOSCLOUD_POLLING_INTERVAL:通过DNSProvider.Timeout()返回给 lego 的传播等待机制(见 ionoscloud.go),两者共同决定"写入 TXT 后轮询 DNS 解析结果"的总时长与节奏。当实际 DNS 生效较慢时可适当调大PROPAGATION_TIMEOUT;
  • IONOSCLOUD_HTTP_TIMEOUT:限制单次 API 调用的最长耗时,避免网络异常时请求无限挂起。

程序化配置(作为 Go 库使用)

Ionos Cloud 提供者同样支持以库方式集成。NewDNSProvider()从环境变量自动装配配置,而NewDNSProviderConfig()允许显式传入Config结构体:

import ( "github.com/go-acme/lego/v5/challenge/dns01" "github.com/go-acme/lego/v5/providers/dns/ionoscloud" "github.com/go-acme/lego/v5/lego" "github.com/go-acme/lego/v5/registration" ) config := ionoscloud.NewDefaultConfig() config.APIToken = "your-api-token" config.TTL = 120 config.PropagationTimeout = 120 * time.Second config.PollingInterval = 2 * time.Second provider, err := ionoscloud.NewDNSProviderConfig(config) if err != nil { log.Fatal(err) } client := lego.NewClient(lego.NewConfig(account)) client.Challenge.SetDNS01Provider(provider, dns01.CNAMEOption(true))

其中Config结构体字段与上面四类环境变量一一对应(见 ionoscloud.go),便于在代码中直接注入自定义http.Client(例如设置代理或自定义 TLS 配置)。

源码级原理:DNS-01 挑战的完整调用链

从源码结构看,Ionos Cloud 提供者的工作流程可以划分为四个阶段,分别由Present/CleanUp/Timeout三个接口方法与内部 API 客户端完成(见 ionoscloud.go)。

阶段一:定位 DNS zone

Present()首先通过dns01.GetChallengeInfo()计算挑战 FQDN(如_acme-challenge.example.com),随后调用FindZoneByFqdn()找到所属权威 zone,并向 Ionos Cloud DNS API 发起GET /zones?filter.zoneName=<zone>请求精确匹配 zone 名称(见 internal/client.go)。若匹配结果数量不为 1,会返回zone ID not found for domain错误——因此请确保托管 zone 名称与域名完全一致。

对应的测试用例TestDNSProvider_Present严格校验了请求路径GET /zones、查询参数filter.zoneName=example.com以及响应夹具 zones.json(见 ionoscloud_test.go)。

阶段二:创建 TXT 验证记录

定位到 zone 后,Present()计算子域名(_acme-challenge)并构造记录属性:

request := internal.RecordProperties{ Name: subDomain, // 例如 _acme-challenge Type: "TXT", Content: info.Value, // 挑战 token 值 TTL: d.config.TTL, // 默认 120 }

然后调用POST /zones/{zoneID}/records创建记录(见 internal/client.go)。请求体结构由 create_record-request.json 给出,RecordProperties的 JSON 映射定义在 internal/types.go。

创建成功后,Present()会把token → zoneID / recordID的映射缓存到内存中(由sync.Mutex保护,见 ionoscloud.go),供后续清理阶段使用。

阶段三:等待 DNS 传播

lego 的 DNS-01 求解器会反复查询权威/递归 DNS,确认 TXT 记录生效后才向 ACME 服务器发起验证请求。Timeout()返回(PropagationTimeout, PollingInterval)控制这一过程的整体上限与轮询频率(见 ionoscloud.go),对应IONOSCLOUD_PROPAGATION_TIMEOUT(默认 120 秒)与IONOSCLOUD_POLLING_INTERVAL(默认 2 秒)。

阶段四:清理 TXT 记录

证书签发完成后,CleanUp()根据token从缓存中取出 zoneID 与 recordID,调用DELETE /zones/{zoneID}/records/{recordID}删除验证记录(见 internal/client.go),并同步清理内存缓存(见 ionoscloud.go)。对应测试TestDNSProvider_CleanUp通过 mock 服务器验证了DELETE请求路径与 202 响应处理(见 ionoscloud_test.go)。

API 通信细节

  • Base URL:https://dns.de-fra.ionos.com(见 internal/client.go),测试中通过p.client.BaseURL替换为 mock 服务器地址;
  • 认证方式:每个请求携带Authorization: Bearer <apiKey>头(见 internal/client.go),mock 测试也校验了该头(servermock.CheckHeader().WithAuthorization("Bearer secret"),见 ionoscloud_test.go);
  • 错误处理:非 2xx 响应会解析httpStatus与messages[].errorCode/error/message结构并包装为APIError(见 internal/client.go 与 internal/types.go),便于定位 token 失效、zone 不存在等具体原因;
  • 请求头:统一设置Accept: application/json,携带 payload 时设置Content-Type: application/json(见 internal/client.go)。

常见问题排查

现象可能原因与排查方向
ionoscloud: some credentials information are missing: IONOSCLOUD_API_TOKEN未设置IONOSCLOUD_API_TOKEN或_FILE指向的文件为空(见 ionoscloud_test.go)
ionoscloud: zone ID not found for domain ...托管 zone 名称与目标域名不一致,或GET /zones过滤后匹配到 0 个/多个 zone
ionoscloud: could not find zone for domain ...域名在公共 DNS 中尚未解析到 Ionos Cloud 的 NS,请检查域名 NS 记录是否已切换到 zone 的 nameservers
等待验证超时适当调大IONOSCLOUD_PROPAGATION_TIMEOUT,或确认 TXT 记录写入后权威 DNS 的生效速度
API 返回 4xx/5xx检查 token 权限(需 zone 读写)、zone 是否处于enabled状态,以及是否触发了 API 限流

进一步阅读

  • 提供者配置元数据(本文档的生成来源):providers/dns/ionoscloud/ionoscloud.toml
  • 提供者核心实现:providers/dns/ionoscloud/ionoscloud.go
  • API 客户端与类型定义:providers/dns/ionoscloud/internal/client.go、providers/dns/ionoscloud/internal/types.go
  • 单元测试与测试夹具:providers/dns/ionoscloud/ionoscloud_test.go、providers/dns/ionoscloud/internal/fixtures
  • 全局环境变量/_FILE约定:docs/content/dns/_index.md
  • DNS 提供者注册与列表:providers/dns/zz_gen_dns_providers.go

本文所有默认值、环境变量与调用链均以当前仓库代码为准;使用不同 lego 版本时请以对应版本源码及官方文档为准。

  • 网络安全
  • 密码学

【免费下载链接】lego

Let's Encrypt/ACME client and library written in Go

项目地址:https://gitcode.com/gh_mirrors/le/lego
点击查看免费下载

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询