月度归档:2021年11月

获取用于DDNS的阿里云Access Key ID/Secret

该教程是配合上一篇文章 RouterOS Aliyun DDNS 脚本 一起食用的。

1. 进入阿里云的 RAM 访问控制 功能

2. 在 权限管理->权限策略 里,创建权限策略。
策略名称可以自行起名,配置模式选择脚本配置,输入以下权限策略。
将策略中的 xxx.yyy 替换成你想要更新的域名 (主域名,非子域名)

{
  "Version": "1",
  "Statement": [
    {
      "Action": [
        "alidns:DescribeSubDomainRecords",
        "alidns:UpdateDomainRecord"
      ],
      "Resource": "acs:alidns:*:*:domain/xxx.yyy",
      "Effect": "Allow"
    }
  ]
}

3. 在 身份管理->用户 里,创建一个用户,登录名称/显示名称可以自行起名,需要勾选 访问方式 中的 OpenAPI调用访问

4. 在 创建用户用户信息 界面上,保存上面显示的 AccessKey IDAccessKey Secret。该信息只会显示一次。

5. 编辑刚创建的用户,添加权限,将第二步创建的权限策略添加到账户内

RouterOS 阿里云 DDNS 脚本

将以下脚本添加到 System Scheduler 里,设置 Interval 为 00:01:00,并修改开头的四个变量,即可实现阿里云域名的DDNS。

注意事项:
该脚本只适用于WAN口能直接获取到公网IP的情形。
该脚本不会自动在阿里云DNS里创建子域名,要更新的子域名必须事先添加好。

:local "accessKeyId" "你的阿里云Access Key ID";
:local "accessKeySecret" "你的阿里云Access Key Secret";
:local "domain" "你的域名";
:local "wanInterface" "WAN口接口名称"

# ==========

:local "localIP"
:local "resolvedIP";
:local "epicFail" false;


:do {
  :set $localIP [ /ip address get [ find interface=$wanInterface ] address ];
  :set $localIP [ :pick $localIP 0 [ :find $localIP "/" ] ];
  :set $localIP [ :toip $localIP ];
} \
on-error {
  :set $epicFail true;
  :log error ("DDNS: Get local IP failed.");
}


:do {
  :set $resolvedIP [ :resolve $domain ];
} \
on-error {
  :set $epicFail true;
  :log error ("DDNS: Resolve domain " . $domain . " failed.");
}


:if ($epicFail = false && $localIP != $resolvedIP) \
do={
  :local "callUrl" ("https://ddns.vsean.net/aliyun/index.php");
  :local "postData" ("domain=" . $domain . "&id=" . $accessKeyId . "&secret=" . $accessKeySecret);
  :local result [ /tool fetch url=$callUrl mode=https http-method=post http-data=$postData as-value output=user ];
  :log info ("DDNS: " . $result->"data");
}

关于如何获取 Access Key ID / Secret 的教程可以参考下一篇文章:
获取用于DDNS的阿里云Access Key ID/Secret

服务器端脚本源代码看这里:
https://github.com/vibbow/aliyun-ddns-script


更新:如果你的接口无法直接获取到公网IP(如DMZ或者1:1 NAT),则可用以下代码取代获取 localIP 部分的代码

:do {
  :local result [/tool fetch url="http://ip.3322.net/" mode=http as-value output=user];
  :set $localIP ($result->"data")
  :set $localIP [ :pick $localIP 0 [ :find $localIP "\n" ] ];
  :set $localIP [ :toip $localIP ]
} \
on-error {
  :set $epicFail true;
  :log error ("DDNS: Get local IP failed.");
}