- 网络安全
- 密码学
【免费下载链接】lego
Let's Encrypt/ACME client and library written in Go
导读:本文以 lego(Go 编写的 Let's Encrypt/ACME 客户端)官方 DNS 提供商文档为骨架,系统讲解如何配置
yandex360提供商,通过 Yandex 360 的 Domain DNS 服务自动完成 ACME DNS-01 挑战。读完本文,你将掌握YANDEX360_OAUTH_TOKEN、YANDEX360_ORG_ID等核心凭据的获取与使用方式、全部可选调优参数(超时、轮询间隔、TTL)的含义,并能结合 lego 源码理解该提供商在后台调用 Yandex 360 API 的完整流程,从而在实际环境中正确签发和续期通配符证书。
一、Yandex 360 提供商概览
lego 内置了面向 Yandex 360 中,并由生成器自动渲染为官方文档 docs/content/dns/zz_gen_yandex360.md:
- Code:
yandex360(在lego命令行中通过--dns yandex360指定) - Since:v4.14.0(即该提供商自 lego v4.14.0 版本起可用)
- 官方 API:Yandex 360 API 的 DomainDNSService(
https://yandex.ru/dev/api360/doc/ref/DomainDNSService/)
与所有 DNS 提供商一样,它的定位是:在 ACME DNS-01 挑战期间,程序自动向你的 DNS 托管商(这里是 Yandex 360)写入一条_acme-challengeTXT 记录,待 ACME 服务器验证通过后,再自动删除该记录。因此,使用它之前你需要已经将待签发证书的域名解析托管在 Yandex 360 的组织(org)下。
二、快速上手:命令行用法
文档给出的最简用法是设置两个环境变量后直接运行lego run:
YANDEX360_OAUTH_TOKEN=<your OAuth Token> \ YANDEX360_ORG_ID=<your organization ID> \ lego run --dns yandex360 -d '*.example.com' -d example.com其中:
-d '*.example.com'与-d example.com分别签发通配符域名和裸域名,二者都需要 DNS-01 挑战,因此适合使用 DNS 提供商方式;--dns yandex360指定使用 Yandex 360 提供商;- 两个环境变量缺一不可,缺少任何一个都会在初始化阶段直接报错(详见下文"凭据"与"源码解析")。
这种方式的适用前提:你需要一个 Yandex 360 组织的 OAuth Token,且该 Token 具备管理组织下域名 DNS 记录的权限;同时,example.com的 DNS 解析必须托管在 Yandex 360 中。
三、凭据(Credentials)
文档定义的必填凭据共两项:
| 环境变量名 | 描述 |
|---|---|
YANDEX360_OAUTH_TOKEN | OAuth Token |
YANDEX360_ORG_ID | 组织 ID(organization ID) |
凭据的_FILE后缀支持
文档特别说明:所有环境变量名都可以追加_FILE后缀,改为引用一个文件路径,而不是直接写值。例如:
YANDEX360_OAUTH_TOKEN_FILE=/path/to/oauth_token \ YANDEX360_ORG_ID_FILE=/path/to/org_id \ lego run --dns yandex360 -d '*.example.com'/path/to/oauth_token文件内容即为 Token 字符串。这一机制适用于所有 lego 提供商,通用说明见 docs/content/dns/_index.md 中的 "Configuration and Credentials" 一节(以 Cloudflare 为例演示了CLOUDFLARE_EMAIL_FILE、CLOUDFLARE_API_KEY_FILE的用法)。它尤其适合在 CI/CD、容器或密钥管理场景中,避免把 Token 明文写进命令行或环境。
凭据校验逻辑(源码确认)
从源码 providers/dns/yandex360/yandex360.go 可以看到,NewDNSProvider()会调用env.Get(EnvOAuthToken, EnvOrgID)一次性读取两个变量,任何一个缺失都会返回错误;随后OrgID会通过strconv.ParseInt(values[EnvOrgID], 10, 64)解析为int64。对应的测试用例 providers/dns/yandex360/yandex360_test.go 覆盖了三种场景:
- 两个变量都提供:成功创建 provider;
- 缺少
YANDEX360_ORG_ID:报错yandex360: some credentials information are missing: YANDEX360_ORG_ID; - 缺少
YANDEX360_OAUTH_TOKEN:报错yandex360: some credentials information are missing: YANDEX360_OAUTH_TOKEN。
此外,在底层客户端 providers/dns/yandex360/internal/client.go 中,Token 为空或OrgID为 0 也会被拒绝(OAuth token is required/orgID is required)。因此请确保 OAuth Token 非空且组织 ID 是合法的非零数字。
四、附加配置(Additional Configuration)
除了凭据,该提供商还支持四项可选调优参数,文档给出的默认值如下:
| 环境变量名 | 描述 | 默认值 |
|---|---|---|
YANDEX360_HTTP_TIMEOUT | API 请求超时(秒) | 30 |
YANDEX360_POLLING_INTERVAL | DNS 传播检查间隔(秒) | 2 |
YANDEX360_PROPAGATION_TIMEOUT | 等待 DNS 传播的最大时间(秒) | 60 |
YANDEX360_TTL | 挑战 TXT 记录的 TTL(秒) | 21600 |
这些变量同样支持_FILE后缀。
默认值在源码中的体现
从 providers/dns/yandex360/yandex360.go 的NewDefaultConfig()可以看到默认值的真实来源:
TTL:env.GetOrDefaultInt(EnvTTL, 21600),默认 21600 秒(6 小时);PropagationTimeout:env.GetOrDefaultSecond(EnvPropagationTimeout, dns01.DefaultPropagationTimeout),即复用 lego 全局默认的 DNS 传播超时(60 秒);PollingInterval:env.GetOrDefaultSecond(EnvPollingInterval, dns01.DefaultPollingInterval),即全局默认轮询间隔(2 秒);HTTPClient.Timeout:env.GetOrDefaultSecond(EnvHTTPTimeout, 30*time.Second),默认 30 秒。
三个超时/轮询参数通过DNSProvider.Timeout()方法(yandex360.go)暴露给 lego 的挑战调度器,用于决定"写完 TXT 记录后等待多久、以什么频率去检查 DNS 传播是否完成"。如果 Yandex 360 的 DNS 生效较慢,可以适当增大YANDEX360_PROPAGATION_TIMEOUT;若 API 响应较慢,可增大YANDEX360_HTTP_TIMEOUT。
五、挑战流程与 Yandex 360 API 调用(源码级解析)
为了说明"程序到底做了什么",下面结合源码梳理 DNS-01 挑战在 Yandex 360 提供商中的完整链路。
1. Present:添加 TXT 记录
Present(yandex360.go)负责写入挑战记录,步骤如下:
- 由
dns01.GetChallengeInfo计算挑战记录全限定名EffectiveFQDN(通常形如_acme-challenge.example.com.)与校验值; - 调用
dns01.DefaultClient().FindZoneByFqdn通过 DNS 查询找到权威区域(authZone),例如example.com.; - 用
dns01.ExtractSubDomain从全限定名中剥离区域,得到子域名_acme-challenge; - 构造
internal.Record{Name: "_acme-challenge", TTL: config.TTL, Text: 校验值, Type: "TXT"},调用client.AddRecord(ctx, authZone, record)。
底层 HTTP 调用在 providers/dns/yandex360/internal/client.go 中实现:
POST https://api360.yandex.net/directory/v1/org/{orgId}/domains/{domain}/dns请求携带Authorization: OAuth <token>头与 JSON 请求体,成功后返回记录的recordId。Present会把recordId以 token 为键缓存在recordIDsmap 中(用互斥锁保护),供后续清理使用。
2. CleanUp:删除 TXT 记录
挑战验证完成后,CleanUp(yandex360.go)根据缓存的recordId调用:
DELETE https://api360.yandex.net/directory/v1/org/{orgId}/domains/{domain}/dns/{recordId}删除成功后从缓存中移除对应记录。如果找不到缓存的 recordID,会返回yandex360: unknown recordID for %q错误。
3. 数据模型与错误处理
Yandex 360 API 返回的记录结构定义在 providers/dns/yandex360/internal/types.go,Record结构体包含recordId、name、text、ttl、type等字段(还有address、priority、weight等供其他记录类型使用)。非 2xx 响应会被解析为APIError{code, message, details}(types.go),错误信息形如[status code: %d] <code>: <message>: <details>。
4. 测试与模拟验证
该提供商的正确性由两类测试保障:
- 单元/模拟测试:providers/dns/yandex360/internal/client_test.go 用
httptest模拟服务器,断言请求路径为POST/DELETE /directory/v1/org/123456/domains/example.com/dns,请求体为{"name":"_acme-challenge","text":"txtxtxt","ttl":60,"type":"TXT"},并验证请求头包含Authorization: OAuth secret。对应的响应夹具在 add-record.json、delete-record.json、error.json。 - 实况测试(Live Test):yandex360_test.go 中的
TestLivePresent/TestLiveCleanUp需要真实凭据才会运行,默认跳过。
六、作为 Go 库使用(Programmatic Usage)
除了 CLI,你还可以在 Go 程序中直接使用该提供商。核心 API 有两个:
import "github.com/go-acme/lego/v5/providers/dns/yandex360" // 方式一:从环境变量读取凭据 provider, err := yandex360.NewDNSProvider() if err != nil { log.Fatal(err) } // 方式二:通过 Config 结构体手动配置 config := yandex360.NewDefaultConfig() config.OAuthToken = "your-token" config.OrgID = 123456 config.TTL = 300 // 自定义 TTL(秒) provider, err = yandex360.NewDNSProviderConfig(config) if err != nil { log.Fatal(err) }Config结构体(yandex360.go)字段包括OAuthToken、OrgID(int64)、PropagationTimeout、PollingInterval、TTL和可选的HTTPClient。若HTTPClient为 nil,会使用默认 30 秒超时的 client。将provider传给 lego 的certificate.Obtain等流程即可;DNSProvider同时实现了challenge.Provider与challenge.ProviderTimeout接口(见 yandex360.go),因此 lego 能自动获取超时与轮询参数。
七、常见问题与排错建议
根据源码错误路径和测试用例,可以总结以下排查思路:
- 提示
some credentials information are missing: ...:YANDEX360_OAUTH_TOKEN或YANDEX360_ORG_ID未设置。注意_FILE后缀变量与原变量只能二选一,且文件路径必须可读。 - 提示
OAuth token is required/orgID is required:Token 为空字符串,或ORG_ID解析后为 0。 - API 返回 401(如测试中模拟的
status code: 401):OAuth Token 无效或没有该组织域名的 DNS 管理权限,请检查 Token 的作用域。 - 提示
could not find zone for domain ...:FindZoneByFqdn无法通过公共 DNS 找到该域名的权威区域,常见原因是域名并未托管在 Yandex 360,或 NS 记录尚未生效。 - 挑战验证超时:可适当调大
YANDEX360_PROPAGATION_TIMEOUT与YANDEX360_POLLING_INTERVAL,以容忍 Yandex 360 DNS 生效延迟。
八、延伸阅读
- 该提供商的生成文档源文件:docs/content/dns/zz_gen_yandex360.md
- 提供商元数据配置(TOML):providers/dns/yandex360/yandex360.toml
- 提供商实现: providers/dns/yandex360/yandex360.go
- 底层 API 客户端:providers/dns/yandex360/internal/client.go
- DNS 挑战通用配置与
_FILE机制:docs/content/dns/_index.md
注:上述全部环境变量与默认值均以当前仓库 v4.14.0+ 的实现为准;使用前请确认你的 lego 版本不低于 v4.14.0,并遵循 README.md 中的安装与全局配置说明。
- 网络安全
- 密码学
【免费下载链接】lego
Let's Encrypt/ACME client and library written in Go
相关推荐
使用 lego 通过 Fornex DNS Provider 完成 DNS-01 挑战:配置指南与源码解析
使用 lego 通过 Fornex DNS Provider 完成 DNS 01 挑战:配置指南与源码解析 本指南以 lego(Go 编写的 Let's Enc
网络安全密码学使用 lego 通过 DNS.services 完成 DNS-01 挑战:配置、原理与源码解析
使用 lego 通过 DNS.services 完成 DNS 01 挑战:配置、原理与源码解析 本篇技术指南以 lego 项目内置的 DNS.services
网络安全密码学使用 lego 通过 Bunny DNS 完成 DNS-01 挑战:完整配置指南与源码实现解析
使用 lego 通过 Bunny DNS 完成 DNS 01 挑战:完整配置指南与源码实现解析 本篇技术指南以 lego 项目官方文档 docs/content
网络安全密码学
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考