在 RouterOS 添加一个脚本执行后将公网IPv4/IPv6解析到指定域名,该脚本改自 github 的 viritt/cloudflare_update.script 相比原版本增加IPv6解析以及双栈的支持。

前提条件

注意:脚本是基于RouterOS v6.46.4 编写的,大于小于此版本都可能导致一些命令问题

确认正确的公网地址

IPv4验证方法:

脚本提取 (WinBox –> IP –> Address List) 内指定接口的IP地址进行解析

ROS终端运行:/ip address get [/ip address find interface=接口名称] address

IPv6验证方法:

脚本提取 DHCPv6 Client 获取的 Prefix 并加上指定的IPv6后缀进行解析

ROS终端运行:/ipv6 dhcp-client get [find interface=接口名称] status

查看读出的数据是否为公网地址,

提前新建子域名

在 CloudFlare 新建需要解析的子域名,若需要解析IPv6
和双栈还需要建立IPv4同名子域名和单独子域名,单独子域名用于IPv6是否更新的判断

  1. ipv4.hscbook.com(A记录)
  2. ipv4.hscbook.com(AAAA记录)
  3. ipv6.hscbook.com(AAAA记录)

建立脚本

使用 WinBox 客户端连接至 RouterOS ;依次 System –> Scripts 进入脚本列表,新建一个名为DDNS_CloudFlare 脚本,将下面内容复制粘贴。

1
#########################################################################
2
#         ==================================================            #
3
#         $ Mikrotik RouterOS update script for CloudFlare $            #
4
#         ==================================================            #
5
#              Credits for Samuel Tegenfeldt, CC BY-SA 3.0              #
6
#                        Modified by kiler129                           #
7
#                        Modified by viritt                             #
8
#                        Modified by hscpro                             #
9
#########################################################################
10
11
################# 程序配置信息 #################
12
#调试信息 true/false
13
:local CFDebug "false"
14
#IPV4使用的接口
15
:global WANInterface4 "pppoe-out1"  
16
#IPV6使用的接口
17
:global WANInterface6 "pppoe-out1"  
18
#IPV6后缀("::"解析到RouterOS;可填写局域网内LAN固定后缀解析到内网某个设备,)
19
:local LANipv6end ":xxxx:xxxx:xxxx:xxxx"
20
#TTL
21
:local CFttl "120"
22
#主域名
23
:local CFzone "hscbook.com"
24
#IPv4子域名
25
:local CFdomain "ipv4.hscbook.com"
26
:local CFdomainid "087dxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
27
#双栈IPv6域名ID
28
:local CFdomainid46 "8adcxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
29
#IPv6子域名 true/false
30
:local switchv6 "true"
31
:local CFdomain6 "ipv6.hscbook.com"
32
:local CFdomainid6 "f100xxxxxxxxxxxxxxxxxxxxxxxxxxxx"
33
#CloudFlare账号与APIKEY
34
:local CFemail "xxxxx@xxxxxx.com"
35
:local CFtkn "101fbxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
36
:local CFzoneid "c25abxxxxcxxxxxxxxxxxxxxxxxxxxxx"
37
38
################# 内部变量 #################
39
#ipv4
40
:local currentIP ""
41
:local resolvedIP ""
42
:global WANip ""
43
#ipv6
44
:local currentIP6 ""
45
:local resolvedIP6 ""
46
:global WANip6 ""
47
48
################# 解析和设置IP变量 #################
49
#获取公网IPv4
50
:set currentIP [/ip address get [/ip address find interface=$WANInterface4 ] address];
51
:set WANip [:pick $currentIP 0 [:find $currentIP "/"]];
52
#获取域名IPv4
53
:set resolvedIP [:resolve $CFdomain];
54
#获取公网IPv6(DHCP方式)以及域名IPv6
55
:if ([/ipv6 dhcp-client get [find interface=$WANInterface6] status] = "bound") do={
56
    :if ([/ipv6 dhcp-client get [find interface=$WANInterface6 status=bound] prefix] != "true") do={
57
        :set currentIP6 [/ipv6 dhcp-client get [find interface=$WANInterface6 status=bound] prefix];
58
        #IPv6地址=公网IPv6前缀+设定的后缀
59
        :set WANip6 ([:pick $currentIP6 0 [:find $currentIP6 "::/"]] . $LANipv6end);
60
        :set resolvedIP6 [:resolve $CFdomain6];
61
    };
62
} else={
63
    :log info ("CF: 本机没有启用IPv6或配置不正确")
64
    :set switchv6 "false"
65
}
66
################# 生成 CloudFlare API 链接 (v4) #################
67
#IPv4
68
:local CFurl4 "https://api.cloudflare.com/client/v4/zones/"
69
:set CFurl4 ($CFurl4 . "$CFzoneid/dns_records/$CFdomainid");
70
#IPv6
71
:local CFurl46 "https://api.cloudflare.com/client/v4/zones/"
72
:local CFurl6 "https://api.cloudflare.com/client/v4/zones/"
73
:if ($switchv6 = "true") do={
74
    :set CFurl46 ($CFurl46 . "$CFzoneid/dns_records/$CFdomainid46");
75
    :set CFurl6 ($CFurl6 . "$CFzoneid/dns_records/$CFdomainid6");
76
};
77
78
################# 将调试信息写入日志 #################
79
:if ($CFDebug = "true") do={
80
    :log info ("CF: 调试模式打开")
81
    :log info ("CF: 解析域名 $CFdomain")
82
    :log info ("CF: 域名解析IPv4 $resolvedIP")
83
    :log info ("CF: 当前公网IPv4 $WANip")
84
    :log info ("CF: 使用的API地址v4 $CFurl4&content=$WANip")
85
    :if ($switchv6 = "true") do={
86
        :log info ("CF: 域名解析IPv6 $resolvedIP6")
87
        :log info ("CF: 当前公网IPv6 $WANip6")
88
        :log info ("CF: 使用的API地址v6 $CFurl6&content=$WANip")
89
    };
90
    :put "Get CFdomainid: curl -X GET \"https://api.cloudflare.com/client/v4/zones/$CFzoneid/dns_records\" -H \"X-Auth-Email: $CFemail\" -H \"X-Auth-Key: $CFtkn\" -H \"Content-Type: application/json\" | python -mjson.tool"
91
};
92
 
93
################# IPv4比较和更新域名记录 #################
94
:if ($resolvedIP != $WANip) do={
95
    :log info ("CF: 正在更新 IPv4 解析地址 $CFdomain = $WANip")
96
    /tool fetch http-method=put mode=https url="$CFurl4" http-header-field="X-Auth-Email:$CFemail,X-Auth-Key:$CFtkn,content-type:application/json" as-value output=user http-data="{\"type\":\"A\",\"name\":\"$CFdomain\",\"content\":\"$WANip\",\"ttl\":$CFttl,\"proxied\":false}"
97
    #/ip dns cache flush 执行间隔时大于TTS一倍可免于清理dns(TTS120->5m TTS300->10m)
98
} else={
99
    :log info "CF: IPv4公网地址与解析的地址匹配无需更新!"
100
}
101
102
################# IPv6比较和更新域名记录 #################
103
:if ($switchv6 = "true") do={
104
    :if ($resolvedIP6 != $WANip6) do={
105
        #双栈
106
        :log info ("CF: 正在更新 IPv6 解析地址 $CFdomain = $WANip6")
107
        /tool fetch http-method=put mode=https url="$CFurl46" http-header-field="X-Auth-Email:$CFemail,X-Auth-Key:$CFtkn,content-type:application/json" as-value output=user http-data="{\"type\":\"AAAA\",\"name\":\"$CFdomain\",\"content\":\"$WANip6\",\"ttl\":$CFttl,\"proxied\":false}"
108
        #单IPv6域名
109
        :log info ("CF: 正在更新 IPv6 解析地址 $CFdomain6 = $WANip6")
110
        /tool fetch http-method=put mode=https url="$CFurl6" http-header-field="X-Auth-Email:$CFemail,X-Auth-Key:$CFtkn,content-type:application/json" as-value output=user http-data="{\"type\":\"AAAA\",\"name\":\"$CFdomain6\",\"content\":\"$WANip6\",\"ttl\":$CFttl,\"proxied\":false}"
111
        #/ip dns cache flush
112
    } else={
113
        :log info "CF: IPv6公网地址与解析的地址匹配无需更新!"
114
    }
115
}

配置脚本

在 CloudFlare 域名主页的最下面 API 处

  1. 将 Zone ID 填入脚本的 CFzoneid 变量
  2. 点击 Get your API token 获取 API token 填入脚本的 CFtkn 变量
  3. 将 CloudFlare 的邮箱账号填入 CFemail 变量

根据三项信息套入 url -X GET \"https://api.cloudflare.com/client/v4/zones/$CFzoneid/dns_records\" -H \"X-Auth-Email: $CFemail\" -H \"X-Auth-Key: $CFtkn\" -H \"Content-Type: application/json\" | python -mjson.tool" 并在 linux 终端中运行可取得子域名的 CFid 并填入 CFdomainid 变量

其他变量根据注释以实际情况自行修改后点击 Run Script 运行脚本测试,查看系统日志无报错即可

创建任务计划

修改好脚本后使用 WinBox 客户端连接至 RouterOS ;依次 System –> Scheduler进入任务计划列表新建一个任务计划间隔时间建议为 TTL 变量的两倍,内容为 /system script run "DDNS_CloudFlare";

END

参考文档:MikroTik Wiki

原脚本:Automatic script for Mikrotik RouterOS updating record on CloudFlare.

获取 CFid 可使用 API 调试工具,例:Postwoman(ApiDebug)