- 网络安全
- 密码学
【免费下载链接】lego
Let's Encrypt/ACME client and library written in Go
导读
Core-Networks(code:corenetworks)是 lego 内置的 DNS-01 挑战提供商之一,用于通过 Core-Networks 的 DNS 托管 API 自动添加/删除_acme-challengeTXT 记录,从而为域名(含通配符)签发 Let's Encrypt 证书。本文以官方配置文档为主体,结合仓库源码深入讲解凭据与超时参数的配置方式、_FILE环境变量文件注入机制、DNS-01 挑战的完整调用链,以及如何在 Go 程序中以库的形式集成该提供商。
一、提供商概览
Core-Networks 提供商自v4.20.0起被引入 lego,其注册入口位于 providers/dns/zz_gen_dns_providers.go,通过环境变量加载并调用corenetworks.NewDNSProvider()。提供商元数据定义在 providers/dns/corenetworks/corenetworks.toml,而对应的生成文档即 docs/content/dns/zz_gen_corenetworks.md。
与 HTTP-01 需要 80 端口回源不同,DNS-01 挑战通过在 DNS 中写入 TXT 记录来完成验证,因此特别适合:
- 签发通配符证书(如
*.example.com); - 服务器无法对外开放 80/443 端口的场景;
- 需要为大量子域一次性签发的自动化场景。
使用该提供商前,你需要一个可用的 Core-Networks API 账号(用户名 + 密码),并将待签发域名托管在其 DNS 平台。
二、快速开始:一条命令完成签发
官方文档给出的最小可用示例是通过环境变量注入凭据后直接运行lego run:
CORENETWORKS_LOGIN="xxxx" \ CORENETWORKS_PASSWORD="yyyy" \ lego run --dns corenetworks -d '*.example.com' -d example.com命令说明:
--dns corenetworks:指定使用 Core-Networks 提供商执行 DNS-01 挑战;-d '*.example.com':申请通配符证书;-d example.com:同时申请裸域证书(Let's Encrypt 的通配符证书不覆盖裸域,二者需分别签发)。
签发成功后,证书与私钥默认保存在./.lego/certificates/目录下(可通过 lego 的--path等参数调整存储位置)。该示例同样记录在配置元数据文件 corenetworks.toml 的Example字段中,是官方验证过的可运行形态。
三、凭据配置(Credentials)
3.1 环境变量
Core-Networks 提供商需要两个必填凭据:
| 环境变量名 | 说明 |
|---|---|
CORENETWORKS_LOGIN | API 账号的用户名 |
CORENETWORKS_PASSWORD | API 账号的密码 |
环境变量常量定义在 providers/dns/corenetworks/corenetworks.go:
const ( envNamespace = "CORENETWORKS_" EnvLogin = envNamespace + "LOGIN" EnvPassword = envNamespace + "PASSWORD" // ... )在NewDNSProvider()中通过env.Get(EnvLogin, EnvPassword)统一读取(corenetworks.go),任一凭据缺失都会返回形如corenetworks: some credentials information are missing: CORENETWORKS_LOGIN的错误。这一点在 corenetworks_test.go 的TestNewDNSProvider用例中有完整验证(分别覆盖"缺 login"与"缺 password"两种失败路径)。
3.2 使用 _FILE 后缀注入凭据(Docker/容器场景)
所有环境变量名都可以追加_FILE后缀,改为从文件中读取值,例如CORENETWORKS_PASSWORD_FILE=/run/secrets/cn_password。该机制由 platform/env/env.go 的GetOrFile实现:
- 优先读取
CORENETWORKS_PASSWORD环境变量; - 若为空,则读取
CORENETWORKS_PASSWORD_FILE指向的文件内容; - 读取成功后使用
strings.TrimRight(fileContents, "\r\n")去除末尾换行符。
这一特性特别适合 Docker Secret、Kubernetes Secret 挂载等不允许把密码写进环境变量明文或镜像层的部署场景。所有附加配置项同样支持_FILE后缀,通用说明见文档 docs/content/dns/_index.md 中"Configuration and Credentials"一节。
四、附加配置项详解(Additional Configuration)
Core-Networks 提供商还支持 5 个可选环境变量,用于控制超时、探测频率与记录 TTL:
| 环境变量名 | 说明 | 默认值 |
|---|---|---|
CORENETWORKS_HTTP_TIMEOUT | API 请求超时时间(秒) | 30 |
CORENETWORKS_POLLING_INTERVAL | DNS 传播检查间隔(秒) | 2 |
CORENETWORKS_PROPAGATION_TIMEOUT | DNS 传播最大等待时间(秒) | 60 |
CORENETWORKS_SEQUENCE_INTERVAL | 顺序请求之间的间隔(秒) | 60 |
CORENETWORKS_TTL | 用于挑战的 TXT 记录 TTL(秒) | 3600 |
这些参数的默认值在 NewDefaultConfig 中设定,并与 lego 的dns01包内置常量衔接:
func NewDefaultConfig() *Config { return &Config{ TTL: env.GetOrDefaultInt(EnvTTL, 3600), PropagationTimeout: env.GetOrDefaultSecond(EnvPropagationTimeout, dns01.DefaultPropagationTimeout), PollingInterval: env.GetOrDefaultSecond(EnvPollingInterval, dns01.DefaultPollingInterval), SequenceInterval: env.GetOrDefaultSecond(EnvSequenceInterval, dns01.DefaultPropagationTimeout), HTTPClient: &http.Client{ Timeout: env.GetOrDefaultSecond(EnvHTTPTimeout, 30*time.Second), }, } }源码实现细节值得注意:
- 传播与轮询:
PropagationTimeout和PollingInterval通过Timeout()方法暴露给 lego 的挑战管理器(corenetworks.go),用于等待 TXT 记录在全球 DNS 生效;CORENETWORKS_PROPAGATION_TIMEOUT=60秒是等待上限,CORENETWORKS_POLLING_INTERVAL=2秒是每次探测的间隔。若你的权威 DNS 更新较慢,可适当调大传播超时。 - 顺序模式:
Sequential()返回SequenceInterval(corenetworks.go),当一次签发多个域名(如通配符 + 裸域组合)时,lego 会按此间隔依次发起挑战,避免一次性并发请求过多导致限流。 - TTL:写入 TXT 记录的 TTL,默认 3600 秒。更小的 TTL 可以缩短验证前的等待时间,但会略微增加 DNS 查询量。
- HTTP 超时:所有 API 调用的客户端超时,默认 30 秒,通过
CORENETWORKS_HTTP_TIMEOUT调整。
此外,所有数值型变量都经由env.GetOrDefaultSecond/env.GetOrDefaultInt解析,若变量值无法解析为数字,会静默回退到默认值(见 platform/env/env.go),因此配置错误时不会直接报错,需留意日志。
五、源码级原理:DNS-01 挑战的完整调用链
5.1 Present:添加验证记录
当 lego 发起 DNS-01 挑战时,会调用 provider 的Present方法(corenetworks.go),其流程为:
- 计算挑战信息:通过
dns01.GetChallengeInfo(ctx, domain, keyAuth)得到_acme-challenge的完整域名(EffectiveFQDN)与待写入的 TXT 值(info.Value); - 获取认证令牌:调用内部客户端的
CreateAuthenticatedContext先向 Core-Networks API 换取 Bearer Token(见下节); - 定位 DNS 区域:调用
dns01.DefaultClient().FindZoneByFqdn根据 FQDN 逐级向上查找所属 Zone,例如_acme-challenge.example.com会定位到example.com区域; - 计算子域名:
dns01.ExtractSubDomain从 FQDN 中剥离 Zone 得到记录名(如_acme-challenge); - 构造并提交记录:构造
TXT类型的Record{Name, TTL, Type, Data},先调用AddRecord添加记录,再调用CommitRecords提交变更。
5.2 CleanUp:验证完成后的清理
挑战验证成功后,CleanUp(corenetworks.go)执行逆向操作:同样先定位 Zone、计算子域名,然后调用DeleteRecords删除匹配的 TXT 记录,并再次CommitRecords提交。注意 Core-Networks API 的设计是"增删记录后必须显式 commit 才会真正生效",这也是Present/CleanUp都包含两步写操作的原因。
5.3 底层 API 客户端
内部客户端实现在 providers/dns/corenetworks/internal/client.go,默认 API 基址为https://beta.api.core-networks.de(defaultBaseURL,见 client.go),涉及的关键端点:
| API 端点 | 对应方法 | 作用 |
|---|---|---|
POST /auth/token | CreateAuthenticationToken | 用 login/password 换取令牌 |
GET /dnszones | ListZone | 列出所有 DNS 区域 |
GET /dnszones/{zone} | GetZoneDetails | 查询区域详情(含 DNSSEC、TSIG 等) |
GET /dnszones/{zone}/records | ListRecords | 列出区域记录 |
POST /dnszones/{zone}/records/ | AddRecord | 添加记录 |
POST /dnszones/{zone}/records/delete | DeleteRecords | 删除匹配记录 |
POST /dnszones/{zone}/records/commit | CommitRecords | 提交(生效)变更 |
认证令牌机制见 internal/identity.go:CreateAuthenticationToken以Auth{Login, Password}调用POST /auth/token,返回Token{Token, Expires},随后令牌被放入context.Context,每次请求通过do方法自动附加Authorization: Bearer <token>头(client.go)。请求响应非 2xx 状态码时会通过errutils包装为带状态码的明确错误。
记录与区域的数据结构定义在 internal/types.go:Record{Name, TTL, Type, Data}对应 API 的 TXT 记录;ZoneDetails还包含Active、DNSSec、TSIG等区域元信息。对应接口的请求/响应 JSON 示例可参考测试夹具目录 providers/dns/corenetworks/internal/fixtures 中的auth.json、ListZone.json、ListRecords.json与GetZoneDetails.json。
六、以库的形式集成到 Go 程序
若你并非使用 lego CLI,而是在 Go 项目中以库方式集成,可直接构建 provider 实例。最简方式是通过环境变量:
import "github.com/go-acme/lego/v5/providers/dns/corenetworks" provider, err := corenetworks.NewDNSProvider() if err != nil { log.Fatalf("create provider: %v", err) }需要编程式控制参数时,使用NewDNSProviderConfig(corenetworks.go):
config := corenetworks.NewDefaultConfig() config.Login = "xxxx" config.Password = "yyyy" config.TTL = 300 config.PropagationTimeout = 90 * time.Second provider, err := corenetworks.NewDNSProviderConfig(config) if err != nil { log.Fatalf("create provider: %v", err) }Config结构体(corenetworks.go)包含Login、Password、PropagationTimeout、PollingInterval、SequenceInterval、TTL与可选的HTTPClient字段。校验规则:config为nil或Login/Password任一为空时返回corenetworks: credentials missing。随后将provider交给lego客户端的ChallengeProvider即可参与完整的 ACME 订单流程。
七、测试与验证
仓库为该提供商提供了单元测试与实时测试两套验证手段:
- corenetworks_test.go:
TestNewDNSProvider与TestNewDNSProviderConfig验证凭据缺失时的错误信息是否符合预期; - 同文件的
TestLivePresent/TestLiveCleanUp(corenetworks_test.go)为实时测试:设置CORENETWORKS_LOGIN、CORENETWORKS_PASSWORD以及测试专用的CORENETWORKS_DOMAIN后运行,会真实调用 Core-Networks API 完成一次 TXT 记录的添加与删除,可用于在接入生产前验证账号权限与网络连通性; - 内部客户端层的接口测试与夹具校验位于 internal/client_test.go 与 internal/identity_test.go。
八、注意事项与排障建议
- 通配符证书必须同时申请裸域:Let's Encrypt 签发的
*.example.com不覆盖example.com,这也是官方示例同时传入两个-d参数的原因; - Zone 必须存在于账号下:
Present依赖FindZoneByFqdn找到 Zone,若域名未托管于 Core-Networks 或账号无该 Zone 权限,会返回could not find zone for domain错误; - 别忘记 commit:记录增删后必须提交(
CommitRecords),直接修改 API 或跳过 commit 会导致变更不生效; - 敏感信息优先使用
_FILE:在容器编排场景下,用CORENETWORKS_LOGIN_FILE/CORENETWORKS_PASSWORD_FILE从 Secret 文件注入凭据,避免凭据进入环境变量明文或镜像层; - 传播等待时间:TXT 记录生效需要时间,若频繁出现挑战超时,可适当调大
CORENETWORKS_PROPAGATION_TIMEOUT并调小 TTL; - 多域签发限流:同时签发多个域名时,
CORENETWORKS_SEQUENCE_INTERVAL控制顺序间隔,默认 60 秒,可按需调整以平衡速度与稳定性。
通过以上配置与源码分析,你应当能够独立完成 Core-Networks 托管域名的自动签发配置,并在出现异常时快速定位到具体的参数或调用环节。
- 网络安全
- 密码学
【免费下载链接】lego
Let's Encrypt/ACME client and library written in Go
相关推荐
LinkSwift:九大网盘直链下载助手,告别限速烦恼的智能解决方案
LinkSwift:九大网盘直链下载助手,告别限速烦恼的智能解决方案 还在为网盘下载速度缓慢而烦恼吗?LinkSwift网盘直链下载助手为您带来革命性的下载体验
网络安全密码学Mordecai API完全指南:10个高级用法提升地理数据处理效率
Mordecai API完全指南:10个高级用法提升地理数据处理效率 Mordecai是一个强大的Python地理解析库,专门用于从英文文本中提取地名并将其解析
网络安全密码学Apache Airflow Amazon Provider 之 S3 Tables 操作符全指南:以 Iceberg 表为核心的自动化编排
Apache Airflow Amazon Provider 之 S3 Tables 操作符全指南:以 Iceberg 表为核心的自动化编排 本篇指南基于 Ap
网络安全密码学
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考