Improve: Delete the corresponding DNS record if the IPv4/IPv6 address is empty.

This commit is contained in:
77-QiQi authored and GitHub committed 2026-09-08 12:07:23 +08:00
1 parent eb48a178f8
commit c684388153
1 file changed
+82 -4
+82 -4
View File
@@ -5,6 +5,7 @@ import (
"fmt"
"log"
"net/netip"
"strings"
"time"
"github.com/libdns/libdns"
@@ -54,10 +55,13 @@ func (provider *Provider) updateDomain(ctx context.Context, domain string) error
return err
}
// 独立处理 IPv4 更新
// 独立处理 IPv4 更新或删除
if *provider.DDNSProfile.EnableIPv4 {
if provider.IPAddrs.IPv4Addr == "" {
log.Printf("NEZHA>> Skip IPv4 update for domain %s: IPv4 address is empty", domain)
log.Printf("NEZHA>> IPv4 address is empty for domain %s, deleting A record...", domain)
if err = provider.deleteDomainRecord(ctx, "A"); err != nil {
return fmt.Errorf("failed to delete IPv4 record: %w", err)
}
} else {
if err = provider.addDomainRecord(ctx, "A", provider.IPAddrs.IPv4Addr); err != nil {
return err
@@ -65,10 +69,13 @@ func (provider *Provider) updateDomain(ctx context.Context, domain string) error
}
}
// 独立处理 IPv6 更新
// 独立处理 IPv6 更新或删除
if *provider.DDNSProfile.EnableIPv6 {
if provider.IPAddrs.IPv6Addr == "" {
log.Printf("NEZHA>> Skip IPv6 update for domain %s: IPv6 address is empty", domain)
log.Printf("NEZHA>> IPv6 address is empty for domain %s, deleting AAAA record...", domain)
if err = provider.deleteDomainRecord(ctx, "AAAA"); err != nil {
return fmt.Errorf("failed to delete IPv6 record: %w", err)
}
} else {
if err = provider.addDomainRecord(ctx, "AAAA", provider.IPAddrs.IPv6Addr); err != nil {
return err
@@ -96,6 +103,77 @@ func (provider *Provider) addDomainRecord(ctx context.Context, recType, addr str
return err
}
// deleteDomainRecord 用于删除指定类型的解析记录
func (provider *Provider) deleteDomainRecord(ctx context.Context, recType string) error {
// 检查 libdns.RecordGetter 和 libdns.RecordDeleter
getter, ok := provider.Setter.(libdns.RecordGetter)
if !ok {
return fmt.Errorf("dns provider does not support record getting")
}
deleter, ok := provider.Setter.(libdns.RecordDeleter)
if !ok {
return fmt.Errorf("dns provider does not support record deletion")
}
// 获取 DNS 记录
allRecords, err := getter.GetRecords(ctx, provider.zone)
if err != nil {
return fmt.Errorf("failed to get DNS records: %w", err)
}
cleanName := func(name string) string {
return strings.ToLower(strings.TrimSuffix(name, "."))
}
cleanPrefix := cleanName(provider.prefix)
cleanZone := cleanName(provider.zone)
targetRecType := strings.ToUpper(recType)
// 筛选和匹配
var targetRecords []libdns.Record
for _, rec := range allRecords {
rr := rec.RR()
recName := rr.Name
currentType := strings.ToUpper(rr.Type)
if currentType != targetRecType {
continue
}
relName := libdns.RelativeName(recName, provider.zone)
cleanRel := cleanName(relName)
cleanRRName := cleanName(recName)
var matchedName bool
if cleanPrefix == "" {
matchedName = cleanRel == "" || cleanRel == "@" || cleanRRName == cleanZone
} else {
matchedName = cleanRel == cleanPrefix || cleanRRName == cleanPrefix
}
// 保留原始的 rec 接口(包含 Cloudflare 所需的 ProviderData 元数据),用于精准删除
if matchedName {
targetRecords = append(targetRecords, rec)
}
}
// 若未找到对应记录,则直接返回成功(视为已删除或不存在)
if len(targetRecords) == 0 {
log.Printf("NEZHA>> No matching %s record found for deletion under zone %s", recType, provider.zone)
return nil
}
// 执行删除操作
_, err = deleter.DeleteRecords(ctx, provider.zone, targetRecords)
if err != nil {
return fmt.Errorf("deleter.DeleteRecords failed: %w", err)
}
log.Printf("NEZHA>> Successfully deleted %d matching %s record(s) for %s.%s", len(targetRecords), recType, provider.prefix, provider.zone)
return nil
}
func (provider *Provider) splitDomainSOA(ctx context.Context, domain string) (prefix string, zone string, err error) {
c := &dns.Client{Timeout: dnsTimeOut}