内网主机充当服务器,如果使用DDNS,多数是应用了第三方DDNS服务或者采用了定时扫描脚本,基本原理都是设定定时任务、周期扫描IP地址变化,发生变化时请求更新DNS记录。其实无论是Linux还是Windows,都具有事件驱动与触发机制,更可以自定义事件触发程序。本文即说明借助Windows的事件驱动机制,通过任务计划程序配置执行自定义脚本刷新DNS记录。
1.事件驱动机制
应用DHCPv6时,无论采用有状态还是无状态的机制,内网主机均可获得全局唯一IPv6地址。我们需要配置的是当且仅当IPv6地址发生时才执行自定义脚本一次(注意,更新记录脚本只在地址变化时执行一次)。Windows定义了庞大复杂的事件驱动模型,了解win32或者使用过MFC的对windows的事件驱动模型想必都似曾相识,这里不做展开。我们打开事件查看器,就会略知一二。
我们要做的就是找到并匹配上“IPv6地址发生变化”这一事件发生时执行一次DNS记录更新脚本,而不是设置脚本24小时运行并每隔N分钟扫描、比对一下IPv6地址是否发生了变化,要知道,很多光猫上DHCPv6默认的租期是30天。
2.核心脚本代码
2.1 IPv6地址选择
默认情况下,出于安全考虑,Windows会绑定2个IPv6地址,一个是临时IPv6地址、一个是公用IPv6地址。临时IPv6地址也是全球单播地址,设计初衷是为了隐私和安全,加大第三方非法用户的地址追踪难度。因此,临时IPv6地址在重启设备、或网络断开重新连接会变化,但系统定义的行为是应用程序访问网络优先使用临时ipv6地址。点击下述链接可以查询到自己的windows正在使用哪个IPv6地址,一般情况下都会是临时地址。
https://v6r.ipip.net/?format=callback
可以通过以下命令开启和关闭IPv6临时地址。
netsh interface ipv6 set privacy state=disable #关闭,需要重启网卡 netsh interface ipv6 set privacy state=enable #开启,需要重启网卡
本文以及教程适配脚本遵循Microsft的设计初衷,使用临时IPv6地址,希望使用公有IPv6地址的,直接修改脚本中网络接口名称的”临时“为”公有“即可。
2.2 最小开销核心代码
说起Windows下的任务计划程序,除掉和Linux crontab一样的功能之外,任务计划程序可以指定在“发生事件时”作为触发某一操作或脚本、命令、程序的条件。
因此,我们要做的就是定义好脚本,在“IPv6地址变化”事件发生时执行一下就好。以下核心代码是以Cloudflare为例,要执行的仅仅是使用其API更新一下AAAA记录,适当修改,可适配主流的DNS解析服务提供商,包括国内的DNSPod、阿里、字节火山等平台。
for /f "tokens=3" %%a in ('netsh interface ipv6 show address %NicID% ^| findstr /i "global"') do set ipv6=%%a for /f %%a in ('curl -sX GET "https://api.cloudflare.com/client/v4/zones/%zone_id%/dns_records?type=AAAA&name=%record%" -H "X-Auth-Email: %email%" -H "X-Auth-Key: %apikey%" -H "Content-Type: application/json" ^| jq -r ".result[0].id"') do set record_id=%%a
3.配置过程
首先下载、运行脚本。因为jq默认只有官方github链接和windows系统默认安装有curl的缘故,建议下载不含jq、curl下载、安装的版本,双击运行输入Cloudflare账户邮箱、API Key、主/根域名、计划使用的域名,指定任务计划触发脚本的安装文件夹,就完成了任务计划触发脚本的生成和安装。
下一步确认触发脚本安装目录后,即在指定安装目录下生成Win-CF-DDNS6.bat文件,后续在任务计划程序中将触发脚本指定该bat文件。接下来通过【Windows徽标键+R】调出运行命令,然后输入taskschd.msc,回车后打开任务计划程序。
在任务计划程序中,点开【操作】菜单,选择【创建任务】。
【常规】选项卡中,为任务定义一个名称(比如这里的”AAAA记录更新“),勾选【使用最高权限运行】,根据需要调整是否【只在用户登录时运行】或者【不管用户是否登录都要运行】。
【触发器】选项卡中,点击左下角【新建】打开新建触发器对话框。在新建触发器对话框中,将【开始任务】下拉列表中将任务触发条件设定为【发生事件时】,采用【基本】设置即可,更细颗粒度的定义可以选择【自定义】。然后,将【日志】选择为【Microsoft-Windows-DHCPv6 CLient Event/Admin】后,其下的【源】可选择为【DHCPv6-Client】,【事件ID】输入51001/50013等(如果是SLAAC无状态配置,DHCPv6不会触发这里的事件),然后点击右下角的确定按钮。这个事件ID表示DHCPv6客户端成功地从DHCPv6服务器获取了一个IPv6地址。这个事件的描述为:DHCPv6客户端已从DHCPv6服务器接收到一个IPv6地址。接口名称:%1,IPv6地址:%2,租约时间(秒):%3。当这个事件发生时,很可能意味着IPv6地址发生变化,我们可以用它作为触发器的条件。
上述触发事件仅作为参考,需要结合自己的系统组合尝试。基于SLAAC和DHCPv6两种不同的配置,涉及网关、路由的动态地址分配总是需要通过RA实现,因此,涉及RA类的事件(如ID 1006)可以考虑,同时,事件ID 10000在网络接口已连接、获取完整网络配置时总是会触发,建议加入触发器组合。
这样,就可以在触发器选项卡中看到刚刚定义的触发器,并且处于启动状态。
接下来,打开【操作】选项卡,点击左下角【新建】按钮新建一个操作,在打开的【新建操作】对话框中程序或脚本栏,点击【浏览】,打开并选择刚刚生成的脚本文件。
脚本选择确认之后,回到【操作】选项卡,点击【确定】完成配置并保存任务计划。可以手动运行一下生成的脚本文件,避免IPv6地址变化前的解析空档期。
文章评论
WIN7运行这个脚本,输入计划使用的主机名以后,提示域XXX.cn不存在,但是这个域名我已经在CF使用了,一直都是正常的