- 网络安全
- 密码学
【免费下载链接】lego
Let's Encrypt/ACME client and library written in Go
本文是 lego(Let's Encrypt/ACME 客户端)中 Virtualname DNS 提供者的完整使用指南。Virtualname 是一家西班牙 DNS 托管服务,从 lego v4.30.0 起支持通过其 API 完成 DNS-01 挑战,从而为通配符域名自动签发证书。读完本文,你将掌握 Virtualname 提供者的环境变量配置、命令行签发流程、调优参数含义,以及其基于 Tecnocrática 共享客户端的底层实现原理。
Virtualname 提供者是什么
Virtualname 是 lego 内置的 DNS 提供者(Provider)之一,代码名为virtualname,自v4.30.0版本起可用。它通过 Virtualname 的 DNS API 自动创建、验证并删除用于 ACME DNS-01 挑战的 TXT 记录,使 lego 能够在无需人工干预的情况下完成域名所有权验证并签发证书(包括*.example.com这类通配符证书)。
该提供者的官方说明文档位于 docs/content/dns/zz_gen_virtualname.md,其元数据定义在 providers/dns/virtualname/virtualname.toml 中。在 lego 的提供者注册表中,virtualname已被映射到对应的构造函数(见 providers/dns/zz_gen_dns_providers.go 中的case "virtualname"),因此 CLI 可直接按名称启用。
快速开始:签发通配符证书
使用 Virtualname 提供者签发证书的最小命令如下(摘自官方文档):
VIRTUALNAME_TOKEN=xxxxxx \ lego run --dns virtualname -d '*.example.com' -d example.com命令要点:
VIRTUALNAME_TOKEN为你的 Virtualname API 令牌,通过环境变量传入;--dns virtualname指定使用 Virtualname 提供者完成 DNS-01 挑战;- 同时传入
-d '*.example.com'与-d example.com,可在一张证书中同时包含通配符域名与裸域名(ACME 要求裸域与通配符域同时验证,因此不能省略裸域)。
命令执行后,lego 会经历以下流程:向 ACME 服务器注册订单 → 计算 DNS-01 挑战所需的 TXT 记录值 → 调用 Virtualname API 创建 TXT 记录 → 等待 DNS 传播 → 通知 ACME 服务器验证 → 验证通过后下载证书。
凭证配置:VIRTUALNAME_TOKEN
提供者仅需要一个凭证环境变量:
| 环境变量名 | 说明 |
|---|---|
VIRTUALNAME_TOKEN | API 令牌(API token) |
从源码 providers/dns/virtualname/virtualname.go 可以看到,环境变量命名空间统一为VIRTUALNAME_:
const ( envNamespace = "VIRTUALNAME_" EnvToken = envNamespace + "TOKEN" // ... )在NewDNSProvider()中,如果VIRTUALNAME_TOKEN缺失或为空,会直接返回错误:
values, err := env.Get(EnvToken) if err != nil { return nil, fmt.Errorf("virtualname: %w", err) }对应的单元测试 providers/dns/virtualname/virtualname_test.go 也验证了这一行为:缺失令牌时返回virtualname: some credentials information are missing: VIRTUALNAME_TOKEN。
使用_FILE后缀从文件读取凭证
所有环境变量都可以追加_FILE后缀,改为从文件读取值。例如将令牌写入文件后:
echo -n 'xxxxxx' > /path/to/token.txt VIRTUALNAME_TOKEN_FILE=/path/to/token.txt \ lego run --dns virtualname -d '*.example.com' -d example.com这一机制对 CI/CD 场景非常实用——避免把令牌直接暴露在命令行或环境变量中。有关 lego 环境变量与文件配置的完整约定,参见 docs/content/dns/_index.md 中的 "Configuration and Credentials" 一节,以及 docs/content/advanced/file-configuration.md。
附加配置参数与调优
除了令牌之外,Virtualname 提供者还支持以下可选参数:
| 环境变量名 | 说明 | 默认值 |
|---|---|---|
VIRTUALNAME_HTTP_TIMEOUT | API 请求超时时间(秒) | 30 |
VIRTUALNAME_POLLING_INTERVAL | DNS 传播检查间隔(秒) | 10 |
VIRTUALNAME_PROPAGATION_TIMEOUT | DNS 传播最大等待时间(秒) | 300 |
VIRTUALNAME_TTL | DNS 挑战所用 TXT 记录的 TTL(秒) | 120 |
这些默认值并非文档凭空而来,而是直接编码在 providers/dns/virtualname/virtualname.go 的NewDefaultConfig()中:
func NewDefaultConfig() *Config { return &Config{ TTL: env.GetOrDefaultInt(EnvTTL, dns01.DefaultTTL), PropagationTimeout: env.GetOrDefaultSecond(EnvPropagationTimeout, 5*time.Minute), PollingInterval: env.GetOrDefaultSecond(EnvPollingInterval, 10*time.Second), HTTPClient: &http.Client{ Timeout: env.GetOrDefaultSecond(EnvHTTPTimeout, 30*time.Second), }, } }几点源码级补充说明:
dns01.DefaultTTL在 challenge/dns01/dns_challenge.go 中定义为120,即 TTL 默认值 120 秒的来源;PROPAGATION_TIMEOUT默认 300 秒(5 分钟)、POLLING_INTERVAL默认 10 秒,二者共同决定 lego 轮询 DNS 传播的节奏;HTTP_TIMEOUT控制与 Virtualname API 交互的 HTTP 客户端超时。
调优建议
- TTL:如果 Virtualname 后台刷新速度较慢,可适当调大
VIRTUALNAME_TTL;反之希望挑战尽快完成、TXT 记录尽快消失时,可调小 TTL; - 传播等待:DNS 记录在权威服务器间同步耗时较长时,可调大
VIRTUALNAME_PROPAGATION_TIMEOUT,避免 lego 因等待不足而误报失败; - 所有参数同样支持
_FILE后缀从文件读取。
工作原理:源码级解析
Virtualname 提供者本身是一个薄封装,其核心逻辑委托给共享的 Tecnocrática 客户端实现(providers/dns/internal/tecnocratica/provider.go),API 端点为https://api.virtualname.net/v1(见 providers/dns/virtualname/virtualname.go 中的defaultBaseURL)。
创建 TXT 记录(Present)
Present是 ACME 挑战生命周期中的"置备"阶段。其流程为:
- 由
dns01.GetChallengeInfo计算挑战记录值与有效 FQDN; - 通过
FindZoneByFqdn查找域名所属的权威 DNS zone; - 调用
GetZones在 Virtualname 侧匹配 zone(按name或human_name比对); - 用
ExtractSubDomain提取子域前缀; - 构造
TXT类型记录并调用CreateRecord创建; - 将
zoneID与recordID以挑战 token 为键存入内存 map,供后续清理使用。
record := internal.Record{ Name: subDomain, Type: "TXT", Content: info.Value, TTL: d.config.TTL, } newRecord, err := d.client.CreateRecord(ctx, zone.ID, record)删除 TXT 记录(CleanUp)
证书签发完成后,lego 会调用CleanUp删除挑战 TXT 记录,避免留下无用的 DNS 数据。它通过之前保存的zoneID/recordID调用DeleteRecord,成功后从内存 map 中清除对应条目。
传播等待(Timeout)
DNSProvider实现了challenge.ProviderTimeout接口:
func (d *DNSProvider) Timeout() (timeout, interval time.Duration) { return d.config.PropagationTimeout, d.config.PollingInterval }这正是VIRTUALNAME_PROPAGATION_TIMEOUT与VIRTUALNAME_POLLING_INTERVAL两个环境变量在运行时被消费的位置。
底层 HTTP 客户端
Tecnocrática 客户端(providers/dns/internal/tecnocratica/internal/client.go)使用X-TCpanel-Token请求头携带 API 令牌,请求路径为:
GET /dns/zones—— 列出全部 zone;POST /dns/zones/{zoneID}/records—— 创建记录(请求体为{"record": {...}});DELETE /dns/zones/{zoneID}/records/{recordID}—— 删除记录。
所有请求还会附加Accept: application/json头、lego 的 User-Agent 头,并在响应状态码非 2xx 时返回带状态码与响应体的错误信息。
在 Go 代码中集成使用
除了 CLI,你也可以在 Go 程序中将 Virtualname 提供者作为库使用。以下示例展示两种构造方式:
package main import ( "log" "github.com/go-acme/lego/v5/providers/dns/virtualname" ) func main() { // 方式一:从环境变量 VIRTUALNAME_TOKEN 读取凭证 provider, err := virtualname.NewDNSProvider() if err != nil { log.Fatal(err) } // 方式二:显式传入配置(可覆盖默认 TTL、超时等) config := virtualname.NewDefaultConfig() config.Token = "xxxxxx" config.TTL = 60 provider, err = virtualname.NewDNSProviderConfig(config) if err != nil { log.Fatal(err) } _ = provider }Config类型直接复用了 Tecnocrática 的配置结构(providers/dns/internal/tecnocratica/provider.go),包含Token、PropagationTimeout、PollingInterval、TTL、HTTPClient五个字段,与上文的四个环境变量一一对应。
之后将provider传入 lego 的Certificate.Obtain流程即可。若config为 nil,构造会返回virtualname: the configuration of the DNS provider is nil错误;若Token为空,则返回virtualname: missing credentials——这两条错误信息同样由单元测试覆盖。
验证与测试
providers/dns/virtualname/virtualname_test.go 提供了三类测试:
TestNewDNSProvider:验证环境变量正常/缺失两种情况;TestNewDNSProviderConfig:验证显式配置的正常/缺失令牌两种情况;TestLivePresent/TestLiveCleanUp:真实调用 Virtualname API 的现场测试(需要设置VIRTUALNAME_DOMAIN环境变量,并仅在开启 live 测试标记时运行),分别验证 TXT 记录的创建与清理。
这些测试是排查"为什么我的配置不生效"时的最佳参照——它们精确列出了每种失败场景下的错误文案。
注意事项
- Virtualname 提供者自v4.30.0起才可用,请确认你的 lego 版本不低于该版本;
- 通配符证书(
-d '*.example.com')必须同时包含裸域名,否则 ACME 校验会失败; - API 令牌应妥善保管,优先通过
VIRTUALNAME_TOKEN_FILE或安全的密钥管理服务注入,避免提交到版本库; - 本文所有默认值与行为均以当前仓库源码为准(v5 版本线),若升级 lego 版本请以对应版本的文档与源码为准。
参考资料
- 提供者官方文档:docs/content/dns/zz_gen_virtualname.md
- 提供者实现:providers/dns/virtualname/virtualname.go
- 共享客户端实现:providers/dns/internal/tecnocratica/provider.go 与 providers/dns/internal/tecnocratica/internal/client.go
- 单元测试:providers/dns/virtualname/virtualname_test.go
- 环境变量与文件配置约定:docs/content/dns/_index.md、docs/content/advanced/file-configuration.md
- 网络安全
- 密码学
【免费下载链接】lego
Let's Encrypt/ACME client and library written in Go
相关推荐
GenericAgent 桌面宠物系统:皮肤包格式、Sprite 动画管线与 Hub 远程控制全解析
GenericAgent 桌面宠物系统:皮肤包格式、Sprite 动画管线与 Hub 远程控制全解析 GenericAgent 的 frontends/desk
网络安全密码学使用 lego 的 ScanNet DNS 提供器签发通配符证书:环境变量配置与源码原理解析
使用 lego 的 ScanNet DNS 提供器签发通配符证书:环境变量配置与源码原理解析 ScanNet 是 lego 内置的 DNS 01 挑战提供器之一
网络安全密码学使用 lego 与 Core-Networks DNS 提供商签发通配符证书:环境变量配置与源码级原理解析
使用 lego 与 Core Networks DNS 提供商签发通配符证书:环境变量配置与源码级原理解析 导读 Core Networks(code: cor
网络安全密码学
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考