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

news/2024/7/6 0:00:48 标签: c#, 阿里云, windows, DDNS, 动态域名解析

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

(私信可全程指导)

部署步骤:

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

下载地址:私信获取

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

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

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

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

3、启动服务

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

源代码:


/// <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
}


http://www.niftyadmin.cn/n/5272725.html

相关文章

21.Servlet 技术

JavaWeb应用的概念 在Sun的Java Servlet规范中&#xff0c;对Java Web应用作了这样定义&#xff1a;“Java Web应用由一组Servlet、HTML页、类、以及其它可以被绑定的资源构成。它可以在各种供应商提供的实现Servlet规范的 Servlet容器 中运行。” Java Web应用中可以包含如下…

Vue中表单数据和过滤器的简单使用

收集表单数据 v-model的三个修饰符: lazy:失去焦点在收集数据 number: 输入字符串转为有效数字 trim:输入首尾空格过滤 < input type"text" v-model"person.account">则v-model收集的是value值&#xff0c;用户输入的就是value值 < input type…

开源 AI 研发提效方案 Unit Mesh 总结

回顾 2023 年&#xff0c;可以明显地看到生成式 AI 带给软件工程带来的新思考&#xff0c;每个组织也在探索结合生成式 AI 的可能性。Unit Mesh (https://github.com/unit-mesh) GitHub 组织正是基于我与我的同事的研究&#xff0c;所构建的一系列围绕于生成式 AI 应用于软件研…

ceph更换硬盘

ceph -s //检查故障 k8s70132:~$ ceph -scluster:id: d10b3028-b78d-4b23-bacb-ca26c0a35c99health: HEALTH_WARN1 daemons have recently crashedservices:mon: 5 daemons, quorum k8sceph70201,k8sceph70202,k8sceph70203,k8sceph70204,k8sceph70205 (age 4d)mgr: k8sc…

apache shiro 反序列化漏洞解决方案

apache shiro 反序列化漏洞解决方案 反序列化漏洞解决方案产生原因解决方案1&#xff1a;1.升级shiro至最新版本1.7.1解决方案2&#xff1a;修改rememberMe默认密钥&#xff0c;生成随机密钥。 反序列化漏洞解决方案 反序列化漏洞介绍 序列化&#xff1a;把对象转换为字符串或…

提高软件交付速度的6种架构策略

本文向您展示如何评估软件交付性能&#xff0c;并向您介绍可用于提高软件交付性能的六种策略。 如何评估软件的交付速度 软件交付速度能够促进业务发展&#xff0c;那么我们如何评估软件的交付速度呢&#xff1f;主要有以下4个指标 一个功能从开发到上线运营使用需要多久&#…

5.6 Linux rsync 服务

1、rsync 概念介绍 官方网站&#xff1a;rsync rsync(Remote Sync) 是一个Unix/linux系统下的文件同步和传输工具。Rsync通过“rsync算法”提供了一个客户机和远程服务器的文件同步的快速方法。 采用C/S模式 端口tcp:873 a. rsync 特性 ① 可以镜像保存整个目录树和文件系…

Kafka--从Zookeeper数据理解Kafka集群工作机制

从Zookeeper数据理解Kafka集群工作机制 这一部分主要是理解Kafka的服务端重要原理。但是Kafka为了保证高吞吐&#xff0c;高性能&#xff0c;高可扩展的三高架构&#xff0c;很多具体设计都是相当复杂的。如果直接跳进去学习研究&#xff0c;很快就会晕头转向。所以&#xff0c…