敏感信息:正式笔记中使用占位符,实际 Token、Zone ID、Record ID 不建议写入普通笔记。
这篇由原始 AI 对话提炼而来,原对话中的 Token、Zone ID、Record ID、域名等敏感值已改为占位符。
需要准备
- Cloudflare API Token,权限至少包含目标 Zone 的 DNS 编辑权限。
- Zone ID。
- DNS Record ID。
- 需要更新的域名,例如
home.example.com。 - RouterOS 上可识别公网地址的接口名,例如
pppoe-out1。
RouterOS 脚本坑点
- System -> Scripts 里不要使用 shell 风格的反斜杠换行。
/tool fetch在脚本中尽量写成一条完整命令。- 变量名大小写要完全一致。
- IPv6 地址通常带
/64,提交给 Cloudflare 前需要去掉前缀长度。 - RouterOS 证书校验可能报 CA 或 CRL 相关错误,临时可用
check-certificate=no,长期建议升级 RouterOS 并正确导入 CA。
IPv6 获取逻辑
:global PUB6 "";
:foreach i in=[/ipv6/address/print as-value] do={
:if (($i->"interface" = "pppoe-out1") && ([:pick ($i->"address") 0 4] != "fe80")) do={
:set PUB6 ($i->"address");
}
}
:if ($PUB6 != "") do={
:set PUB6 [:pick $PUB6 0 [:find $PUB6 "/"]];
}
Cloudflare 更新脚本模板
:global CFAPITOKEN "YOUR_CLOUDFLARE_API_TOKEN";
:global CFZONEID "YOUR_ZONE_ID";
:global CFRECORDID "YOUR_RECORD_ID";
:global CFDNSNAME "home.example.com";
:global LAST6;
:global PUB6 "";
:foreach i in=[/ipv6/address/print as-value] do={
:if (($i->"interface" = "pppoe-out1") && ([:pick ($i->"address") 0 4] != "fe80")) do={
:set PUB6 ($i->"address");
}
}
:if ($PUB6 != "") do={
:set PUB6 [:pick $PUB6 0 [:find $PUB6 "/"]];
:if ($PUB6 != $LAST6) do={
:log info ("CF-DDNS: IPv6 changed to " . $PUB6 . ", updating");
/tool fetch mode=https check-certificate=no http-method=put keep-result=no url=("https://api.cloudflare.com/client/v4/zones/" . $CFZONEID . "/dns_records/" . $CFRECORDID) http-header-field=("Authorization: Bearer " . $CFAPITOKEN . ",Content-Type: application/json") http-data=("{"type":"AAAA","name":"" . $CFDNSNAME . "","content":"" . $PUB6 . "","ttl":120,"proxied":false}");
:set LAST6 $PUB6;
} else={
:log info ("CF-DDNS: IPv6 not changed (" . $PUB6 . "), skipping");
}
}
定时任务
/system scheduler add name=CloudflareDDNS interval=5m on-event="/system script run CloudflareDDNS"
调试
/system script run CloudflareDDNS
/log print
如果报 syntax error,优先检查引号、变量大小写和 /tool fetch 是否被拆成了多行。