AliDDNSNet 是基于 .NET Core 开发的动态 DNS 解析工具,借助于阿里云的 DNS API 来实现域名与动态 IP 的绑定功能。工具核心就是调用了阿里云 DNS 的两个 API ,一个 API 获取指定域名的所有解析记录,然后通过比对与当前公网 IP 是否一致,一致则不进行更改,不一致则通过另外一个修改 API 来修改指定子域名的修改记录。
使用时请更改同目录下的 settings.json.example
为 settings.json
文件,同时也可以显示通过 -f
参数来制定配置文件路径。例如:
dotnet ./AliDDNSNet.dll -f ./settings.json2
./AliDDNSNet -f ./settings.json3
NAS 运行效果图:
通过更改 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 可以登录阿里云之后在右上角可以得到。
回到顶部
主要流程代码在 Program.cs 文件当中编写,这里依次讲解一下。
首先加载配置文件,如果用户传入了 -f
参数,则使用用户传入的配置文件路径,否则的话直接使用当前目录的默认 settings.json
配置文件,读取成功之后存放到 Utils.config 属性当中以便 Utils 使用。
之后通过 Utils.GetCurentPublicIP()
方法获取到当前设备的公网 IP,再判断指定的二级域名解析是否存在,如果不存在的话,则直接返回,这里并没有做新增解析操作,后续版本可能会加上。
如果找到了对应二级域名的解析,则输出当前解析的记录值,然后进行比较,如果当前主机的公网 IP 与记录值一样则无需进行变更。
当阿里云 DNS 解析记录与当前主机公网 IP 不一致的时候调用更新 API,传入之前的域名的 rrId 去进行变更,完成即退出。
Utils.cs 主要存放一些功能性方法,比如说将 SortedDictionary
字典转为请求字符串,还有就是加密方法,请求方法等。
因为 API 请求的时候有很多共有参数,所以这里单独用了一个静态方法来生成这个公有请求参数的字典。
/// /// 生成通用参数字典/// 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
来处理,这是因为阿里云 API 必须要求按大小写敏感来排序请求参数,所以这里直接使用了 ```SortedDictionary
来处理这种情况。
因为阿里云 DNS 的 API 基本上都是 GET 请求,所以通过这个方法可以将之前的 SortedDictionary
字典构建成请求字符串。
核心就是遍历这个字典,通过 StringBuilder
来构建这个请求字符串。
这一步也是最重要的一步,因为阿里云所有的 API 接口都需要传递签名参数,这个签名参数是根据你提交的参数集合 AccessKey 来进行计算的。
这里之前我是按照阿里云 API 来进行开发的,不过有一点需要注意的是,返回的 Signature 值是不需要进行 URL 编码的。就因为这一点,我白白浪费了 3 个小时来排查问题,看看官方 API 文档说的:
说需要将签名值编码之后再提交,扯淡,如果编码之后再提交的话,接口会一直返回:
Specified signature is not matched with our calculation.
这里直接返回 HMACSHA1 加密结果的 Base64 字符串即可。
构建好一切之后我们就需要发送请求了,这里统一是使用的 SendRequest()
方法来进行处理,可以看到我们先获得签名,然后将获取到的签名追加到请求体内部,一起进行请求。
这里传入的 IRequest
接口,是有具体实现的,可以转到 Main 方法里面看一下:
await Utils.SendGetRequest(new DescribeDomainRecordsRequest(config.domain));
await Utils.SendGetRequest(new UpdateDomainRecordRequest(rrId, config.sub_domain, config.type, currentIP, config.interval.ToString()));
这里的 DescribeDomainRecordsRequest
与 UpdateDomainRecordRequest
就是具体的请求体,定义很简单,就是实现了 IRequest
接口而已,然后在各自的内部添加一些特殊的参数。
异步的 Main 方法需要 C# 7.1 以上版本才能支持,你只需要右键你的项目选择属性,左侧栏选择生成,找到高级按钮,更改当前 C# 语言版本即可。
效果如下:
static async Task<int> Main(string[] args){ // 代码....
return await Task.FromResult(0);
}
编写控制台程序,最主要的是接受参数然后处理,而 Microsoft.Extensions.CommandLineUtils
库提供了方便快捷的方式来为我们处理用户输入的参数。
使用方法如下:
https://github.com/GameBelial/AliDDNSNet
有兴趣的朋友可以 star 关注一下。
程序打包了 Linux-x64 与 Linux arm 环境的二进制可执行文件,你可以直接下载对应的压缩包解压到你的路由器或者 NAS 里面进行运行。
如果你的设备支持 Docker 环境,建议通过 Docker 运行 .NET Core 2.1 环境来执行本程序。
原文地址:https://www.cnblogs.com/myzony/p/9349578.html
.NET社区新闻,深度好文,欢迎访问公众号文章汇总 http://www.csharpkit.com