基于阿里云 DNS API 实现的 DDNS 工具

0.简要介绍 0.1 思路说明

AliDDNSNet 是基于 .NET Core 开发的动态 DNS 解析工具,借助于阿里云的 DNS API 来实现域名与动态 IP 的绑定功能。工具核心就是调用了阿里云 DNS 的两个 API ,一个 API 获取指定域名的所有解析记录,然后通过比对与当前公网 IP 是否一致,一致则不进行更改,不一致则通过另外一个修改 API 来修改指定子域名的修改记录。

0.2 使用说明

使用时请更改同目录下的 settings.json.example 为 settings.json 文件,同时也可以显示通过 -f 参数来制定配置文件路径。例如:

dotnet ./AliDDNSNet.dll -f ./settings.json2 ./AliDDNSNet -f ./settings.json3

NAS 运行效果图:

基于阿里云 DNS API 实现的 DDNS 工具

0.3.配置说明:

通过更改 settings.json/settings.json.example 的内容来实现 DDNS 更新。

{ // 阿里云的 Access Id "access_id": "", // 阿里云的 Access Key "access_key": "", // TTL 时间 "interval": 600, // 主域名 "domain": "example.com", // 子域名前缀 "sub_domain": "test", // 记录类型 "type": "A" }

其中 Access Id 与 Access Key 可以登录阿里云之后在右上角可以得到。

2.代码说明 2.1 主程序流程

主要流程代码在 Program.cs 文件当中编写,这里依次讲解一下。

首先加载配置文件,如果用户传入了 -f 参数,则使用用户传入的配置文件路径,否则的话直接使用当前目录的默认 settings.json 配置文件,读取成功之后存放到 Utils.config 属性当中以便 Utils 使用。

// 加载配置文件: var filePath = attachments.HasValue() ? attachments.Value() : $"{Environment.CurrentDirectory}{Path.DirectorySeparatorChar}settings.json"; if (!File.Exists(filePath)) { Console.WriteLine("当前目录没有配置文件,或者配置文件位置不正确。"); return -1; } var config = await Utils.ReadConfigFile(filePath); Utils.config = config;

之后通过 Utils.GetCurentPublicIP() 方法获取到当前设备的公网 IP,再判断指定的二级域名解析是否存在,如果不存在的话,则直接返回,这里并没有做新增解析操作,后续版本可能会加上。

// 获得当前 IP var currentIP = (await Utils.GetCurentPublicIP()).Replace("\n", ""); var subDomains = JObject.Parse(await Utils.SendGetRequest(new DescribeDomainRecordsRequest(config.domain))); if (subDomains.SelectToken($"$.DomainRecords.Record[?(@.RR == '{config.sub_domain}')]") == null) { Console.WriteLine("指定的子域名不存在,请新建一个子域名解析。"); return 0; }

如果找到了对应二级域名的解析,则输出当前解析的记录值,然后进行比较,如果当前主机的公网 IP 与记录值一样则无需进行变更。

Console.WriteLine("已经找到对应的域名与解析"); Console.WriteLine("======================"); Console.WriteLine($"子域名:{config.sub_domain}{config.domain}"); var dnsIp = subDomains.SelectToken($"$.DomainRecords.Record[?(@.RR == '{config.sub_domain}')].Value").Value<string>(); Console.WriteLine($"目前的 A 记录解析 IP 地址:{dnsIp}"); if (currentIP == dnsIp) { Console.WriteLine("解析地址与当前主机 IP 地址一致,无需更改."); return 0; }

当阿里云 DNS 解析记录与当前主机公网 IP 不一致的时候调用更新 API,传入之前的域名的 rrId 去进行变更,完成即退出。

Console.WriteLine("检测到 IP 地址不一致,正在更改中......"); var rrId = subDomains.SelectToken($"$.DomainRecords.Record[?(@.RR == '{config.sub_domain}')].RecordId").Value<string>(); var response = await Utils.SendGetRequest(new UpdateDomainRecordRequest(rrId, config.sub_domain, config.type, currentIP, config.interval.ToString())); var resultRRId = JObject.Parse(response).SelectToken("$.RecordId").Value<string>(); if (resultRRId == null || resultRRId != rrId) { Console.WriteLine("更改记录失败,请稍后再试。"); } else { Console.WriteLine("更改记录成功。"); } return 0; 2.1 Utils 详解

Utils.cs 主要存放一些功能性方法,比如说将 SortedDictionary 字典转为请求字符串,还有就是加密方法,请求方法等。

2.2.1 生成通用参数字典

因为 API 请求的时候有很多共有参数,所以这里单独用了一个静态方法来生成这个公有请求参数的字典。

/// <summary> /// 生成通用参数字典 /// </summary> public static SortedDictionary<string, string> GenerateGenericParameters() { var dict = new SortedDictionary<string, string>(StringComparer.Ordinal) { {"Format", "json"}, {"AccessKeyId", config.access_id}, {"SignatureMethod", "HMAC-SHA1"}, {"SignatureNonce", Guid.NewGuid().ToString()}, {"Version", "2015-01-09"}, {"SignatureVersion", "1.0"}, {"Timestamp", DateTime.UtcNow.ToString("yyyy-MM-ddTHH:mm:ssZ")} }; return dict; }

可以看到这里使用了 SortedDictionary<string,string> 来处理,这是因为阿里云 API 必须要求按大小写敏感来排序请求参数,所以这里直接使用了 ```SortedDictionary 来处理这种情况。

2.2.2 根据字典构建请求字符串

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wpdgsw.html