mirror of
https://github.com/tnb-labs/panel.git
synced 2026-08-31 01:12:17 +08:00
fix: 修复裸域名与泛域名共用 ACME TXT 记录时相互覆盖
abc.com 与 *.abc.com 共用 _acme-challenge.abc.com,需同时存在两条 TXT 记录,但 SetRecords 以 (name, type) 为单位覆盖,导致后写入的 challenge 覆盖前者,DNS 验证一直卡死。改为按记录名累积所有 keyAuth 一次性写入。 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
+4
-3
@@ -34,9 +34,10 @@ type DnsOption struct {
|
||||
// UseDns 使用 DNS 接口验证
|
||||
func (c *Client) UseDns(dnsType DnsType, param DNSParam, opt ...DnsOption) {
|
||||
solver := &dnsSolver{
|
||||
dns: dnsType,
|
||||
param: param,
|
||||
records: make(map[string][]libdns.Record),
|
||||
dns: dnsType,
|
||||
param: param,
|
||||
keyAuths: make(map[string][]string),
|
||||
records: make(map[string][]libdns.Record),
|
||||
}
|
||||
if len(opt) > 0 {
|
||||
solver.alias = opt[0].Alias
|
||||
|
||||
+19
-10
@@ -414,7 +414,8 @@ type dnsSolver struct {
|
||||
mu sync.Mutex
|
||||
dns DnsType
|
||||
param DNSParam
|
||||
records map[string][]libdns.Record // dnsName|keyAuth → records
|
||||
keyAuths map[string][]string // dnsName → keyAuth 列表
|
||||
records map[string][]libdns.Record // dnsName → 已设置的记录
|
||||
alias map[string]string // DNS 验证别名映射 (domain → delegated domain)
|
||||
dnsServer string // DNS 验证服务器地址
|
||||
skipVerify bool // 跳过解析验证
|
||||
@@ -434,12 +435,20 @@ func (s *dnsSolver) Present(ctx context.Context, challenge acme.Challenge) error
|
||||
|
||||
s.report(fmt.Sprintf("setting DNS TXT record %s", dnsName))
|
||||
|
||||
rec := libdns.TXT{
|
||||
Name: libdns.RelativeName(dnsName+".", zone+"."),
|
||||
Text: keyAuth,
|
||||
// 同名 TXT 记录可能对应多个 challenge, SetRecords 以 (name, type) 为单位覆盖
|
||||
// 因此需把该记录名下所有 keyAuth 一次性写入,避免后者覆盖前者
|
||||
s.mu.Lock()
|
||||
s.keyAuths[dnsName] = append(s.keyAuths[dnsName], keyAuth)
|
||||
recs := make([]libdns.Record, 0, len(s.keyAuths[dnsName]))
|
||||
for _, ka := range s.keyAuths[dnsName] {
|
||||
recs = append(recs, libdns.TXT{
|
||||
Name: libdns.RelativeName(dnsName+".", zone+"."),
|
||||
Text: ka,
|
||||
})
|
||||
}
|
||||
s.mu.Unlock()
|
||||
|
||||
results, err := provider.SetRecords(ctx, zone+".", []libdns.Record{rec})
|
||||
results, err := provider.SetRecords(ctx, zone+".", recs)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to set DNS record %q for %q: %w", dnsName, zone, err)
|
||||
}
|
||||
@@ -448,8 +457,7 @@ func (s *dnsSolver) Present(ctx context.Context, challenge acme.Challenge) error
|
||||
}
|
||||
|
||||
s.mu.Lock()
|
||||
key := dnsName + "|" + keyAuth
|
||||
s.records[key] = append(s.records[key], results...)
|
||||
s.records[dnsName] = results
|
||||
s.mu.Unlock()
|
||||
|
||||
s.report(fmt.Sprintf("DNS TXT record %s set successfully", dnsName))
|
||||
@@ -538,10 +546,11 @@ func (s *dnsSolver) CleanUp(ctx context.Context, challenge acme.Challenge) error
|
||||
|
||||
s.report("cleaning up DNS TXT records")
|
||||
|
||||
// 同名 TXT 记录下的多条 challenge 记录由首次 CleanUp 一并删除
|
||||
s.mu.Lock()
|
||||
key := dnsName + "|" + challenge.DNS01KeyAuthorization()
|
||||
records := s.records[key]
|
||||
delete(s.records, key)
|
||||
records := s.records[dnsName]
|
||||
delete(s.records, dnsName)
|
||||
delete(s.keyAuths, dnsName)
|
||||
s.mu.Unlock()
|
||||
|
||||
if len(records) > 0 {
|
||||
|
||||
Reference in New Issue
Block a user