C#调用阿里云接口实现动态域名解析,支持IPv6(Windows系统下载可用)

电信宽带一般能申请到公网IP,但是是动态的,基本上每天都要变,所以想到做一个定时任务,随系统启动,网上看了不少博文很多都支持IPv4,自己动手写了一个。

(私信可全程指导)

部署步骤:

1、下载软件包,修改配置文件

下载地址:私信获取

下载压缩包,解压后修改配置文件AliDDNS.exe.config中的阿里云帐号和自己的域名。

2、修改脚本,并运行脚本

将"安装服务.bat"和"卸载服务.bat"脚本中的可执行文件路径,改为自己的软件包所在路径,然后右键"安装服务.bat"进行安装服务。

执行脚本后会将定时服务添加到系统服务中。

3、启动服务

右键"此电脑",点击"管理"进入计算机管理窗口,在服务列表中找到上一步新增的服务,然后启动。即可定时更新阿里云解析记录,实现动态IP的DDNS。

源代码:

cs 复制代码
/// <summary>
/// 刷新阿里云域名解析记录
/// </summary>
private void RefreshAliRecord()
{
    string recordTypes = ConfigurationManager.AppSettings["RecordTypes"];
    if (string.IsNullOrWhiteSpace(recordTypes))
    {
        NLogHelper.WriteLog(typeof(AliDDNS), "配置文件中的"待解析的协议类型"不能为空。", NLogLevel.Warn);
        return;
    }

    string regionId = ConfigurationManager.AppSettings["RegionId"];
    string accessKeyID = ConfigurationManager.AppSettings["AccessKeyID"];
    string accessKeySecret = ConfigurationManager.AppSettings["AccessKeySecret"];
    string domainName = ConfigurationManager.AppSettings["DomainName"];
    string rR = ConfigurationManager.AppSettings["RR"];

    string[] rRTypes = rR.Split('|');

    // regionId:地区节点
    // accessKeyID:阿里云Key
    // accessKeySecret:阿里云密钥
    AlibabaCloudCredentialsProvider provider = new AccessKeyCredentialProvider(accessKeyID, accessKeySecret);
    IClientProfile profile = DefaultProfile.GetProfile(regionId);
    DefaultAcsClient client = new DefaultAcsClient(profile, provider);

    List<DescribeDomainRecordsResponse.DescribeDomainRecords_Record> recordList = DescribeDomainRecords(client, domainName);

    string[] recordTypeArray = recordTypes.Split('|');
    foreach (string recordType in recordTypeArray)
    {
        if (recordType == "A")
        {
            #region IPv4解析记录
            try
            {
                string urls = ConfigurationManager.AppSettings["GetIPFromUrl"];
                string ipv4 = CommonHelper.GetExtranetIP(urls.Split('|').ToList());
                if (string.IsNullOrWhiteSpace(ipv4))
                {
                    NLogHelper.WriteLog(typeof(AliDDNS), "未获取到外网IPv4地址!", NLogLevel.Warn);
                    return;
                }

                if (IsAddSuccessLog)
                {
                    NLogHelper.WriteLog(typeof(AliDDNS), "获取到的外网IPv4地址为:" + ipv4, NLogLevel.Info);
                }

                foreach (string rRItem in rRTypes)
                {
                    if (string.IsNullOrWhiteSpace(rRItem))
                    {
                        continue;
                    }

                    List<DescribeDomainRecordsResponse.DescribeDomainRecords_Record> ipv4Records = recordList.Where(r => r.Type == recordType && r.RR == rRItem).ToList();
                    if (ipv4Records == null || ipv4Records.Count() == 0)
                    {
                        AddDNSRecord(client, domainName, rRItem, recordType, ipv4);
                    }
                    else
                    {
                        #region 更新解析记录

                        // 非ipv4记录
                        List<DescribeDomainRecordsResponse.DescribeDomainRecords_Record> otherRecords = ipv4Records.Where(r => r._Value != ipv4).ToList();
                        // ipv4记录
                        List<DescribeDomainRecordsResponse.DescribeDomainRecords_Record> tempList = ipv4Records.Where(r => r._Value == ipv4).ToList();
                        if (tempList == null || tempList.Count == 0)
                        {
                            // 如果不存在该IPv4的记录,则删除所有记录ipv4Records,并新增记录
                            AddDNSRecord(client, domainName, rRItem, recordType, ipv4);

                            DeleteDNSRecord(client, ipv4Records);
                        }
                        else if (tempList.Count == 1)  // 如果只存在一条该IPv4记录,则记录日志,如果有其他记录则删除
                        {
                            NLogHelper.WriteLog(typeof(AliDDNS), string.Format("同类型("{0}"类型)的解析记录(IPv4:{1})已存在,无需更新!", rRItem, ipv4), NLogLevel.Info);
                            if (ipv4Records.Count != tempList.Count)
                            {
                                // 存在其他记录,则删除其他记录otherRecords
                                DeleteDNSRecord(client, otherRecords);
                            }
                        }
                        else
                        {
                            // 如果存在多条该IPv4记录,则取第一条,其他的记录都删除
                            tempList.RemoveRange(0, 1);
                            otherRecords.AddRange(tempList);
                            DeleteDNSRecord(client, otherRecords);
                        }
                        #endregion
                    }
                }
            }
            catch (Exception ex)
            {
                NLogHelper.WriteLog(typeof(AliDDNS), "查询并更新IPv4解析记录时异常:" + ex.ToString(), NLogLevel.Warn);
            }

            #endregion
        }
        else if (recordType == "AAAA")
        {
            #region IPv6解析记录
            try
            {
                List<string> ipv6List = CommonHelper.GetLocalIPv6();
                if (ipv6List == null || ipv6List.Count() == 0)
                {
                    NLogHelper.WriteLog(typeof(AliDDNS), "未获取到本机IPv6地址!", NLogLevel.Warn);
                    return;
                }

                if (IsAddSuccessLog)
                {
                    NLogHelper.WriteLog(typeof(AliDDNS), "获取到的本地IPv6地址为:" + string.Join(",", ipv6List), NLogLevel.Info);
                }

                string defaultIPv6 = ipv6List[0];  // 默认只添加第一个IPv6地址

                foreach (string rRItem in rRTypes)
                {
                    if (string.IsNullOrWhiteSpace(rRItem))
                    {
                        continue;
                    }

                    List<DescribeDomainRecordsResponse.DescribeDomainRecords_Record> ipv6Records = recordList.Where(r => r.Type == recordType && r.RR == rRItem).ToList();
                    if (ipv6Records == null || ipv6Records.Count() == 0)
                    {
                        AddDNSRecord(client, domainName, rRItem, recordType, defaultIPv6);
                    }
                    else
                    {
                        #region 更新解析记录

                        // 非ipv6记录
                        List<DescribeDomainRecordsResponse.DescribeDomainRecords_Record> otherRecords = ipv6Records.Where(r => r._Value != defaultIPv6).ToList();
                        // ipv6记录
                        List<DescribeDomainRecordsResponse.DescribeDomainRecords_Record> tempList = ipv6Records.Where(r => r._Value == defaultIPv6).ToList();
                        if (tempList == null || tempList.Count == 0)
                        {
                            // 如果不存在该IPv6的记录,则删除所有记录ipv6Records,并新增记录
                            AddDNSRecord(client, domainName, rRItem, recordType, defaultIPv6);

                            DeleteDNSRecord(client, ipv6Records);
                        }
                        else if (tempList.Count == 1)  // 如果只存在一条该IPv6记录,则记录日志,如果有其他记录则删除
                        {
                            NLogHelper.WriteLog(typeof(AliDDNS), string.Format("同类型("{0}"类型)的解析记录(IPv6:{1})已存在,无需更新!", rRItem, defaultIPv6), NLogLevel.Info);
                            if (ipv6Records.Count != tempList.Count)
                            {
                                // 存在其他记录,则删除其他记录otherRecords
                                DeleteDNSRecord(client, otherRecords);
                            }
                        }
                        else
                        {
                            // 如果存在多条该IPv6记录,则取第一条,其他的记录都删除
                            tempList.RemoveRange(0, 1);
                            otherRecords.AddRange(tempList);
                            DeleteDNSRecord(client, otherRecords);
                        }

                        #endregion
                    }
                }
            }
            catch (Exception ex)
            {
                NLogHelper.WriteLog(typeof(AliDDNS), "查询并更新IPv6解析记录时异常:" + ex.ToString(), NLogLevel.Warn);
            }
            #endregion
        }
    }
}

// 获取指定主域名的所有解析记录列表
public List<DescribeDomainRecordsResponse.DescribeDomainRecords_Record> DescribeDomainRecords(DefaultAcsClient client, string domainName)
{
    List<DescribeDomainRecordsResponse.DescribeDomainRecords_Record> records = new List<DescribeDomainRecordsResponse.DescribeDomainRecords_Record>();
    try
    {
        DescribeDomainRecordsRequest request = new DescribeDomainRecordsRequest();
        request.DomainName = domainName;

        记录类型 官网支持A/CNAME/MX/AAA/TXT/NS/SRV/CAA/URL隐性(显性)转发如果有需要可将该值配置为参数传入
        //request.Type = recordType;

        try
        {
            DescribeDomainRecordsResponse response = client.GetAcsResponse(request);
            if (IsAddSuccessLog)
            {
                NLogHelper.WriteLog(typeof(AliDDNS), "查询到的解析记录:" + System.Text.Encoding.Default.GetString(response.HttpResponse.Content), NLogLevel.Info);
            }

            if (response.DomainRecords != null)
            {
                records = response.DomainRecords;
            }
        }
        catch (Exception ex)
        {
            NLogHelper.WriteLog(typeof(AliDDNS), "调用DescribeDomainRecords接口时发生异常:" + ex.ToString(), NLogLevel.Error);
        }
    }
    catch (Exception ex)
    {
        NLogHelper.WriteLog(typeof(AliDDNS), "创建DescribeDomainRecords接口调用对象时发生异常:" + ex.ToString(), NLogLevel.Error);
    }
    return records;
}

// 新增解析记录
public void AddDNSRecord(DefaultAcsClient client, string domainName, string rRItem, string recordType, string ipValue)
{
    #region 新增解析记录

    string recordStr = string.Format("(RR:{0},Type:{1},Value:{2})", rRItem, recordType, ipValue);
    try
    {
        var request = new AddDomainRecordRequest();
        request.DomainName = domainName;
        request.RR = rRItem;
        request.Type = recordType;
        request._Value = ipValue;
        request.TTL = 600;  // 免费版,默认600秒,10分钟

        var response = client.GetAcsResponse(request);
        if (IsAddSuccessLog)
        {
            NLogHelper.WriteLog(typeof(AliDDNS), string.Format("新增解析记录{0}时接口返回内容:{1}", recordStr, Encoding.Default.GetString(response.HttpResponse.Content)), NLogLevel.Info);
        }
    }
    catch (Exception ex)
    {
        NLogHelper.WriteLog(typeof(AliDDNS), string.Format("新增解析记录{0}时发生异常:{1}", recordStr, ex.ToString()), NLogLevel.Error);
    }
    #endregion
}

// 删除解析记录
public void DeleteDNSRecord(DefaultAcsClient client, List<DescribeDomainRecordsResponse.DescribeDomainRecords_Record> deleteList)
{
    #region 删除解析记录

    foreach (DescribeDomainRecordsResponse.DescribeDomainRecords_Record record in deleteList)
    {
        string recordStr = string.Format("(RR:{0},Type:{1},Value:{2})", record.RR, record.Type, record._Value);
        try
        {
            DeleteDomainRecordRequest request = new DeleteDomainRecordRequest();
            request.RecordId = record.RecordId;

            DeleteDomainRecordResponse response = client.GetAcsResponse(request);
            if (IsAddSuccessLog)
            {
                NLogHelper.WriteLog(typeof(AliDDNS), string.Format("删除解析记录{0}时接口返回内容:{1}", recordStr, Encoding.Default.GetString(response.HttpResponse.Content)), NLogLevel.Info);
            }
        }
        catch (Exception ex)
        {
            NLogHelper.WriteLog(typeof(AliDDNS), string.Format("删除解析记录{0}时发生异常:{1}", recordStr, ex.ToString()), NLogLevel.Error);
        }
    }

    #endregion
}
相关推荐
小曲曲1 小时前
接口上传视频和oss直传视频到阿里云组件
javascript·阿里云·音视频
梓仁沐白2 小时前
ubuntu+windows双系统切换后蓝牙设备无法连接
windows·ubuntu
向宇it6 小时前
【unity小技巧】unity 什么是反射?反射的作用?反射的使用场景?反射的缺点?常用的反射操作?反射常见示例
开发语言·游戏·unity·c#·游戏引擎
九鼎科技-Leo6 小时前
什么是 WPF 中的依赖属性?有什么作用?
windows·c#·.net·wpf
为什么每天的风都这么大7 小时前
Vscode/Code-server无网环境安装通义灵码
ide·vscode·阿里云·编辑器·ai编程·code-server
Heaphaestus,RC7 小时前
【Unity3D】获取 GameObject 的完整层级结构
unity·c#
baivfhpwxf20237 小时前
C# 5000 转16进制 字节(激光器串口通讯生成指定格式命令)
开发语言·c#
直裾7 小时前
Scala全文单词统计
开发语言·c#·scala
Yang.998 小时前
基于Windows系统用C++做一个点名工具
c++·windows·sql·visual studio code·sqlite3
我不瘦但很逗8 小时前
Windows下使用DBeaver连接云数据库(MySQL)
数据库·windows