Files
Meshray-Manager/docs/DDNS 真实操作功能实现报告.md
T
2026-06-30 15:14:37 +08:00

10 KiB
Raw Blame History

DDNS 真实操作功能实现报告

📋 实现概述

本次实现完成了 DDNS 真实 DNS 记录操作 的核心功能,集成了 libdns 库,支持多个主流 DNS 服务商的 API 调用。


已完成的工作

1. 安装 libdns 库

已安装的库

✅ github.com/libdns/cloudflare v0.2.2
✅ github.com/libdns/tencentcloud v1.4.3
✅ github.com/libdns/libdns v1.1.0

待安装的库(网络问题)

⏳ github.com/libdns/aliyun - 网络超时,暂时使用占位实现

2. 创建 DNS Provider 抽象层

文件结构

internal/dnsprovider/
├── provider.go          # 核心接口和类型定义
├── cloudflare.go        # Cloudflare 实现
├── tencentcloud.go      # 腾讯云实现
└── aliyun.go            # 阿里云实现(占位)

核心接口设计

DNSProvider 接口:

type DNSProvider interface {
    AppendRecords(ctx context.Context, zone string, recs []libdns.Record) ([]libdns.Record, error)
    SetRecords(ctx context.Context, zone string, recs []libdns.Record) ([]libdns.Record, error)
    GetRecords(ctx context.Context, zone string) ([]libdns.Record, error)
    DeleteRecords(ctx context.Context, zone string, recs []libdns.Record) ([]libdns.Record, error)
}

统一工厂方法:

func NewDNSProvider(config ProviderConfig) (DNSProvider, error) {
    switch config.Provider {
    case ProviderCloudflare:
        return NewCloudflareProvider(config)
    case ProviderAliyun:
        return NewAliyunProvider(config)
    case ProviderTencentCloud:
        return NewTencentCloudProvider(config)
    }
}

3. 各服务商实现详情

Cloudflare 实现

文件: internal/dnsprovider/cloudflare.go

配置要求:

  • API Token(必需)
  • 根域名

实现状态:

  • AppendRecords - 添加记录
  • SetRecords - 设置记录(覆盖)
  • GetRecords - 获取记录
  • DeleteRecords - 删除记录

代码示例:

provider := &cloudflare.Provider{
    APIToken: "YOUR_API_TOKEN",
}

腾讯云实现

文件: internal/dnsprovider/tencentcloud.go

配置要求:

  • SecretId(必需)
  • SecretKey(必需)

实现状态:

  • AppendRecords - 添加记录
  • SetRecords - 设置记录(覆盖)
  • GetRecords - 获取记录
  • DeleteRecords - 删除记录

代码示例:

provider := &tencentcloud.Provider{
    SecretId:  "AKIDxxxx",
    SecretKey: "SECRET_KEY",
}

阿里云实现 (占位)

文件: internal/dnsprovider/aliyun.go

配置要求:

  • AccessKey ID(必需)
  • AccessKey Secret(必需)

实现状态:

  • 暂时返回错误提示"暂未支持"
  • 待网络恢复后安装 libdns/aliyun 并实现

TODO 代码:

// TODO: 安装 github.com/libdns/aliyun 后,替换为真实实现
provider := &aliyun.Provider{
    AccessKeyID:     config.AccessKeyID,
    AccessKeySecret: config.AccessKeySecret,
}

4. DDNS 操作服务封装

文件

internal/service/ddns_operation.go

核心功能

CreateDNSRecord - 创建 DNS 记录:

func (s *DDNSOperationService) CreateDNSRecord(
    config *model.Service,     // DDNS 全功能服务配置
    recordType string,         // A/AAAA/TXT/CNAME
    name string,               // 主机记录
    value string,              // 记录值
    ttl int                    // TTL
) error

UpdateDNSRecord - 更新 DNS 记录:

func (s *DDNSOperationService) UpdateDNSRecord(...) error

DeleteDNSRecord - 删除 DNS 记录:

func (s *DDNSOperationService) DeleteDNSRecord(...) error

操作流程

1. 获取关联的 DDNS 配置
   ↓
2. 创建对应的 DNS Provider
   ↓
3. 构建 DNS 记录
   ↓
4. 调用 Provider API
   ↓
5. 记录日志

🎯 使用示例

场景 1: 创建 A 记录(内网穿透)

// 假设用户在前端填写了:
// - 选择 DDNS 配置:Cloudflare (example.com)
// - 记录类型:A
// - 主机记录:nas
// - 目标 IP: 192.168.1.100
// - TTL: 600

service := &model.Service{
    DDNSConfigID: "xxx-xxx-xxx",  // 关联的 DDNS 配置 ID
    RecordType:   "A",
    Subdomain:    "nas",
    TargetIP:     "192.168.1.100",
    TTL:          600,
}

// 创建记录
err := ddnsOpService.CreateDNSRecord(service, "A", "nas", "192.168.1.100", 600)
if err != nil {
    log.Error("创建失败", err)
}

// 结果:创建了 nas.example.com 的 A 记录,指向 192.168.1.100

场景 2: 更新 TXT 记录(MeshSeed 同步)

// 当检测到本地 IP 变化时,自动更新记录
service := &model.Service{
    DDNSConfigID:  "xxx-xxx-xxx",
    RecordType:    "TXT",
    TXTRecordName: "_meshray.abc123",
    TXTValue:      "new_mesh_seed_config",
    TTL:           600,
}

// 更新记录
err := ddnsOpService.UpdateDNSRecord(service, "TXT", "_meshray.abc123", "new_mesh_seed_config", 600)
if err != nil {
    log.Error("更新失败", err)
}

// 结果:更新了 _meshray.abc123.example.com 的 TXT 记录

场景 3: 删除 CNAME 记录

service := &model.Service{
    DDNSConfigID: "xxx-xxx-xxx",
    RecordType:   "CNAME",
    Subdomain:    "www",
}

// 删除记录
err := ddnsOpService.DeleteDNSRecord(service, "CNAME", "www")
if err != nil {
    log.Error("删除失败", err)
}

// 结果:删除了 www.example.com 的 CNAME 记录

📊 技术架构

分层架构

API Handler 层
  ↓
Service 层(业务逻辑)
  ↓
DDNSOperationService
  ↓
DNS Provider 抽象层
  ↓
libdns 库实现
  ↓
DNS 服务商 API

设计模式

工厂模式:

NewDNSProvider(config)  DNSProvider
  ├─ CloudflareProvider
  ├─ TencentCloudProvider
  └─ AliyunProvider待实现

适配器模式:

DNSRecord (内部模型)
   ToLibdnsRecord()
libdns.Record (第三方库模型)

🔧 依赖管理

go.mod 新增依赖

require (
    github.com/libdns/cloudflare v0.2.2
    github.com/libdns/libdns v1.1.0
    github.com/libdns/tencentcloud v1.4.3
)

待添加依赖

// 网络恢复后执行:
go get github.com/libdns/aliyun

验证清单

编译验证

  • 代码编译成功
  • 无语法错误
  • 依赖安装正确
  • 导入路径正确

功能验证(待测试)

  • Cloudflare API 调用成功
  • 腾讯云 API 调用成功
  • 阿里云 API 调用(等待安装)
  • 创建 A 记录成功
  • 更新 TXT 记录成功
  • 删除记录成功

🚀 下一步计划

P0 - 完善阿里云支持

任务: 安装 libdns/aliyun 并完成实现
预计工时: 0.5 天
依赖: 网络环境

步骤:

  1. 执行 go get github.com/libdns/aliyun
  2. 修改 aliyun.go 使用真实实现
  3. 测试 API 调用

P0 - 集成到 Service 创建流程

任务: 在创建 DDNS 全功能服务时自动创建 DNS 记录
预计工时: 0.5 天
依赖: 无

修改文件:

  • internal/service/service.go - CreateService 方法

伪代码:

func (s *ServiceService) CreateService(req *model.Service) (*model.Service, error) {
    // ... 现有校验逻辑 ...
    
    // 如果是 DDNS 全功能模式,创建 DNS 记录
    if req.Type == "DDNS" && req.ConfigMode == "fullservice" {
        ddnsOpService := NewDDNSOperationService(s.logger)
        
        var recordType string
        var name string
        var value string
        
        switch req.RecordType {
        case "A", "AAAA":
            recordType = req.RecordType
            name = req.Subdomain
            value = req.TargetIP
        case "TXT":
            recordType = req.RecordType
            name = req.TXTRecordName
            value = req.TXTValue
        case "CNAME":
            recordType = req.RecordType
            name = req.Subdomain
            value = req.CNAMETarget
        }
        
        err := ddnsOpService.CreateDNSRecord(req, recordType, name, value, req.TTL)
        if err != nil {
            return nil, fmt.Errorf("创建 DNS 记录失败:%w", err)
        }
    }
    
    // ... 保存到数据库 ...
}

P1 - IP 检测与自动更新

任务: 实现本地 IP 检测和自动更新 DNS 记录
预计工时: 1 天
依赖: DDNS 操作服务完成

子任务:

  1. 实现 IPv4 地址检测(调用外部 API)
  2. 实现 IPv6 地址检测(读取本地网络接口)
  3. 实现 IP 变化监控(定时比对)
  4. 实现自动更新 DNS 记录
  5. 实现失败重试机制

P1 - 后台任务调度

任务: 实现定时任务调度器
预计工时: 1 天
依赖: IP 检测完成

子任务:

  1. 实现定时器框架(goroutine + ticker
  2. 批量检测所有启用的 DDNS 服务
  3. 批量更新 DNS 记录
  4. 记录操作日志
  5. 发送告警通知(可选)

P2 - 前后端联调测试

任务: 完整的集成测试
预计工时: 1 天
依赖: 所有功能完成

测试项:

  1. 创建真实的 Cloudflare DNS 记录
  2. 创建真实的腾讯云 DNS 记录
  3. 测试 IP 检测和自动更新
  4. 性能测试(批量创建/更新)
  5. 错误处理和恢复

📝 注意事项

安全性

  • ⚠️ API Token/Secret 需要加密存储
  • ⚠️ 日志中需要脱敏处理
  • ⚠️ 避免在错误信息中泄露敏感数据

性能优化

  • ⚠️ 使用连接池复用 HTTP 客户端
  • ⚠️ 批量操作时使用并发(注意限流)
  • ⚠️ 缓存 DNS Provider 实例

错误处理

  • ⚠️ DNS API 调用失败需要有重试机制
  • ⚠️ 网络异常需要友好提示用户
  • ⚠️ 记录详细的操作日志便于排查

🎉 总结

本次实现完成了 DDNS 真实 DNS 记录操作的核心框架

libdns 库集成 - Cloudflare、腾讯云已支持
Provider 抽象层 - 统一的接口设计
操作服务封装 - Create/Update/Delete 完整功能
编译验证通过 - 无错误

当前状态: 可以开始测试真实的 DNS 服务商 API 调用。

下一步重点:

  1. 集成到 Service 创建流程
  2. 实现 IP 检测和自动更新
  3. 后台任务调度

实现日期: 2026-03-20
实现人员: AI Assistant
实现状态: 核心框架完成,等待集成和测试
文档版本: v1.0