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
}
相关推荐
Jasmine_llq1 小时前
《 火星人 》
算法·青少年编程·c#
亽仒凣凣1 小时前
Windows安装Redis图文教程
数据库·windows·redis
炫彩@之星1 小时前
Windows和Linux安全配置和加固
linux·windows·安全·系统安全配置和加固
小奥超人2 小时前
RAR压缩算法的文件修复功能详解
windows·经验分享·winrar·办公技巧
军训猫猫头3 小时前
20.抽卡只有金,带保底(WPF) C#
ui·c#·wpf
Clockwiseee12 小时前
php伪协议
windows·安全·web安全·网络安全
向宇it13 小时前
【从零开始入门unity游戏开发之——C#篇25】C#面向对象动态多态——virtual、override 和 base 关键字、抽象类和抽象方法
java·开发语言·unity·c#·游戏引擎
唐宋元明清218813 小时前
.NET 阻止系统睡眠/息屏
windows·电源
向宇it14 小时前
【从零开始入门unity游戏开发之——C#篇24】C#面向对象继承——万物之父(object)、装箱和拆箱、sealed 密封类
java·开发语言·unity·c#·游戏引擎
yylの博客15 小时前
Windows通过git-bash安装zsh
windows·git·bash·zsh