Lab / Network

RouterOS Cloudflare DDNS 配置

用 RouterOS 脚本更新 Cloudflare AAAA 记录,包含 IPv6 获取逻辑、完整脚本模板、定时任务和调试方法。

敏感信息:正式笔记中使用占位符,实际 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 是否被拆成了多行。