电信宽带一般能申请到公网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){// 存在其他记录,则删除其他记录otherRecordsDeleteDNSRecord(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){// 存在其他记录,则删除其他记录otherRecordsDeleteDNSRecord(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
}