前言
在国内想要申请公网的IPV4,机会渺茫,不过还好,现在三大运营商基本上都已经提供了IPV6了,等于给我们留了另外一条路,这次在做映射时,从网上找了些资料,发现几乎都没有公开源码,我对安全隐私方面还是比较讲究的,所以只能自己动手写一个了,希望可以帮助到相应的人。相应的源码请查看连接:(29条消息) AliDDNS.rar-网络基础文档类资源-优快云文库https://download.youkuaiyun.com/download/rongrongZHR/41218114
我这次使用的是阿里云的DDNS,阿里云官方已经提供了相应的SDK给我们使用,所以程序写起来还是比较简单的,本次使用到的阿里云SDK如下:aliyun-net-sdk-alidns.2.6.32、aliyun-net-sdk-core.1.5.10。
一、申请域名
域名申请这种事情网上已经有很详细的教程,这里推荐直接参考阿里云的教程就可以了:注册通用域名 (aliyun.com)https://help.aliyun.com/document_detail/54068.html
二、添加解析
1、选择对应的记录类型,AAAA表示IPV6的解析
2、主机记录自己定义
3、记录值可以先随便填一个,例如:2400::1,只要符合IPV6的格式就可以了
三、获取密钥
如下图所示,记住自己的accessKeyId以及secret,等一下要用到。
四、使用程序
在下载下来的源码中,进入AliDDNS\aliyunddns\bin\Debug,修改配置文件Config.json里面的内容,如下图所示:
1、SubDomain:填写需要解析的域名
2、填入从阿里云获取的accessKeyId以及secret
3、填入电脑中对应网卡的MAC地址
修改完毕之后,执行AliDDNS\aliyunddns\bin\Debug\aliyunddns.exe,执行完毕之后,查看logs文件中的信息,如果有报错,则根据报错提示进行相应的修改。
如果没有报错,说明前面的配置都是OK的,此时已经可以使用域名进行操作了,例如想要访问电脑上部署的网站,可以在另外一台有IPV6的电脑上直接访问:域名:端口
五、定时执行
因为IPV6的地址也不会固定的,隔一段时间会发生变更,如果不嫌麻烦,每隔一段时间就手动执行一下软件,到第四步基本上已经可以结束了,不过人总是会变懒的嘛,所以就在电脑上做一个定时任务就可以了。步骤如下:
1、打开“任务计划管理器”
2、创建任务
3、设置常规项:“无论是否登录都执行”。
3、设置触发器
4、设置需要操作的程序
5、 其他设置,根据自己的需要进行设置即可
设置成功后,可以立即执行一次,查看logs文件中是否有报错。
六、源码说明
1、程序结构
2、配置文件内容
3、实体类不用自己编写,这里推荐一个网站:在线JSON转C#实体类,JSON转Java实体类 (sojson.com)https://www.sojson.com/json2entity.html
4、Nlog配置文件,这个插件写日志特别好用,但是一直不会高级用法,现在都是使用配置文件中的默认方法,希望有高手可以指点一下。
5、主函数
using System;
using System.Text;
using Aliyun.Acs.Alidns.Model.V20150109;
using Aliyun.Acs.Core;
using Aliyun.Acs.Core.Profile;
using Newtonsoft.Json;
using System.Text.RegularExpressions;
namespace aliyunddns
{
class Program
{
static void Main(string[] args)
{
try
{
//获取Config文件并解析
string configJson = Tool.GetConfig();
ConfigJson json = JsonConvert.DeserializeObject<ConfigJson>(configJson);
string SubDomain = json.SubDomain;
string accessKeyId = json.accessKeyId;
string secret = json.secret;
string mac = Regex.Replace(json.mac, "-", "");
//获取本地IPV6地址
string localipv6str = Tool.GetAddr(mac);
//调用阿里云查询接口获取域名的解析记录
DescribeSubDomainRecordsRequest describeSubDomainRecordsRequest = new DescribeSubDomainRecordsRequest{SubDomain = SubDomain};
IClientProfile profile = DefaultProfile.GetProfile("cn-hangzhou", accessKeyId, secret);
DefaultAcsClient client = new DefaultAcsClient(profile);
DescribeSubDomainRecordsResponse _get = client.GetAcsResponse(describeSubDomainRecordsRequest); //获取解析数据
string getHttpResponse = Encoding.Default.GetString(_get.HttpResponse.Content); //获取解析数据的字符内容
AliyunResponse aliyunResponse = JsonConvert.DeserializeObject<AliyunResponse>(getHttpResponse); //将字符内容转为实体类
//如果远程记录的IP地址与本地记录的不一致,则进行修改
if (localipv6str != aliyunResponse.DomainRecords.Record[0].Value)
{
//定义修改远程解析所需要的信息
UpdateDomainRecordRequest updateDomainRecordRequest = new UpdateDomainRecordRequest
{
RR = aliyunResponse.DomainRecords.Record[0].RR, //子域名
Type = aliyunResponse.DomainRecords.Record[0].Type, //记录类型
_Value = localipv6str, //需要修改的IP
RecordId = aliyunResponse.DomainRecords.Record[0].RecordId //记录ID
};
var response = client.GetAcsResponse(updateDomainRecordRequest); //调用接口进行修改
Tool.MessageManager("远程IP地址已修改为:" + localipv6str, MsgTypeEnum.info);
}
else
{
Tool.MessageManager("远程记录IP地址与本地一致,不需修改,IP地址为:" + localipv6str, MsgTypeEnum.info);
}
}
catch (Exception e)
{
Tool.MessageManager("故障:" + e.Message, MsgTypeEnum.error);
}
}
}
}
6、一些辅助函数,主要包括:读取配置文件、写log、获取本机有效IPV6
using NLog;
using System;
using System.IO;
using System.Net.NetworkInformation;
using System.Text;
namespace aliyunddns
{
/// <summary>
/// 消息类型枚举
/// </summary>
public enum MsgTypeEnum
{
/// <summary>
/// 软件Bug
/// </summary>
error,
/// <summary>
/// 正常消息显示
/// </summary>
info,
/// <summary>
/// 运行Bug
/// </summary>
debug
};
public class Tool
{
static readonly private Logger logger = LogManager.GetCurrentClassLogger();
public static void MessageManager(string msg, MsgTypeEnum type)
{
switch (type.ToString())
{
case "error": logger.Error(msg); break; //软件级BUG
case "info": logger.Info(msg); break; //运行BUG
case "debug": logger.Debug(msg); break; //正常消息展示
default: break;
}
}
/// <summary>
/// 读取文件函数
/// </summary>
/// <param name="path"></param>
/// <returns></returns>
public static string GetConfig()
{
string configPath = AppDomain.CurrentDomain.BaseDirectory + "Config.json"; //配置文件路径
try
{
FileStream fileStream = new FileStream(configPath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
int seekLength = (int)(fileStream.Length);
byte[] buffer = new byte[seekLength];
fileStream.Read(buffer, 0, seekLength);
fileStream.Close(); //读取文本数据之后马上释放资源
return Encoding.Default.GetString(buffer);
}
catch (Exception ex)
{
throw new Exception("读取【" + configPath + "】失败,失败原因:" + ex.Message);
}
}
/// <summary>
/// 获取IPV6
/// </summary>
/// <returns>有效IPV6地址</returns>
public static string GetAddr(string mac)
{
try
{
if (!string.IsNullOrEmpty(mac))
{
NetworkInterface[] nics = NetworkInterface.GetAllNetworkInterfaces();
foreach (NetworkInterface adapter in nics)
{
PhysicalAddress _mac = adapter.GetPhysicalAddress(); //网卡Mac地址
if (_mac.ToString() == mac)
{
IPInterfaceProperties ip = adapter.GetIPProperties(); //获取以太网卡网络接口信息
UnicastIPAddressInformationCollection ipCollection = ip.UnicastAddresses; //获取单播地址集
foreach (UnicastIPAddressInformation ipadd in ipCollection)
{
if (ipadd.Address.AddressFamily == System.Net.Sockets.AddressFamily.InterNetworkV6) //只获取IPV6
{
if (!ipadd.Address.ToString().ToLower().Contains("fe80")) //fe80开头的IP为无效IP
{
return ipadd.Address.ToString();
}
}
}
}
}
throw new Exception("本机不存在mac地址为:" + mac + "的网卡,请检查配置文件");
}
else
throw new Exception("配置文件中mac为空,请检查配置文件");
}
catch (Exception ex)
{
throw new Exception(ex.Message);
}
}
}
}