5  路由器

5.1 备忘录

  • ROS: admin@82.1+!1#1
  • ESXI: root@82.25+Z!2349
  • OpenWrt: root@82.3+!0m0
  • VPN L2TP: xzhang@!1@1
  • Docker Ports
    • NAS: admin@82.245:1819
    • Calibre: admin@NAS:8083+!0m0
    • qBittorrent:admin@NAS:8085+!0@0

5.2 Router OS动态更新阿里域名云解析

主要是利用vercel和github,采用PHP语言实现

5.2.1 创建访问控制RAM的AccessKey

这部分内容主要参考博文RouterOS利用aliyun的API接口实现DDNS动态解析中的第一部分内容。

1、阿里云网站 –> 产品 –> 安全 –> 应用身份服务,这个就是控制API ,用户管理,新建用户,填写用户名和勾上”为该用户自动生成AccessKey”,保存好这个accesskey。

2、策略管理 –> 自定义授权策略,新建授权策略,选择空白模版,授权策略名称随便填(如alidns),策略内容为下面的内容(修改下面内容中的域名为你自己要做DDNS的域名)

action是api的接口,只接受AddDomainRecord(增加域名解析),DescribeDomainRecords(输出域名解析列表)和UpdateDomainRecord(修改域名解析记录)

Resource是指被授权的具体对象,这边domain/abc.com需要修改成你自己的域名domain/xxx.com。这样就是授权对象是该域名

{
  "Version": "1",
  "Statement": [
    {
      "Action": [
        "alidns:AddDomainRecord",
        "alidns:DescribeDomainRecords",
        "alidns:UpdateDomainRecord"
      ],
      "Resource": "acs:alidns:*:*:domain/abc.com",
      "Effect": "Allow"
    }
  ]
}

3、用户管理,对上面创建的用户,点击授权,选择刚才自定义创建的策略,确定。

5.2.2 PHP制作aliyun API动态解析接口

  • PHP源码Git仓库创建

    1. 利用xinzhangseu/vercel-php仓库模板在自己的github账户新建仓库
    2. 将api文件夹中的index.php更改为下面内容(源码来自77bx/alidns-api-php), 并将”Location: //xxxxx.xxxx.com/” 改为后面自己vercel生成的网址即可。
<?php
/***
* Alidns-api-php V1.3
* By Star.Yu
***/
if($_SERVER['REQUEST_METHOD']=="POST"){
  $request = $_POST;
}
if($_SERVER['REQUEST_METHOD']=="GET"){
  $request = $_GET;
}
if(is_array($request)&&count($request)<1){
  Header("Location: //xxxxx.xxxx.com/");
  exit('2');
}

if(empty($request['id'])){
  exit('2');
}elseif(empty($request['secret'])){
  exit('2');
}elseif(empty($request['domain'])){
  exit('2');
}elseif(empty($request['record'])){
  exit('2');
}else{
  $ip = empty($request['ip']) ? $_SERVER['REMOTE_ADDR'] : addslashes($request['ip']);
  $accessKeyId = addslashes($request['id']);
  $accessKeySecret = addslashes($request['secret']);
  $record = addslashes($request['record']);
  $domain = addslashes($request['domain']);
  $type = empty($request['type']) || $request['type']!='AAAA' ? 'A' : addslashes($request['type']);
}

if($type === 'A' && !filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4)){
  exit('1');
}
if($type === 'AAAA' && !filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6)){
  exit('1');
}

//公共参数Timestamp GMT时间
$Timestamp = gmdate('Y-m-d\TH:i:s\Z',time());

//Signature percentEncode函数
function percentEncode($str) {
  $res = urlencode($str);
  $res = str_replace(array('+', '*'), array('%20', '%2A'), $res);
  $res = preg_replace('/%7E/', '~', $res);
  return $res;
}

//唯一数,用于防止网络重放攻击
function generateByMicrotime() {
  $microtime = microtime(true);
  $microtime = str_replace('.', '', $microtime);
  return $microtime;
}

//sign
function sign($parameters, $accessKeySecret){
  ksort($parameters);
  $canonicalizedQueryString = '';
  foreach ($parameters as $key => $value) {
    $canonicalizedQueryString .= '&' . percentEncode($key) . '=' . percentEncode($value);
  }
  $stringToBeSigned = 'POST&%2F&' . percentEncode(substr($canonicalizedQueryString, 1));
  $signature = base64_encode(hash_hmac('sha1', $stringToBeSigned, $accessKeySecret. '&', true));
  return $signature;
}

function geturl($public, $request, $accessKeySecret){
  $params = array_merge($public, $request);
  $params['Signature'] =  sign($params, $accessKeySecret);
  $uri = http_build_query($params);
  $url = 'https://alidns.aliyuncs.com/?'.$uri;
  return $url;
}

function ssl_post($url){
  $curl = curl_init();
  curl_setopt($curl, CURLOPT_URL, $url);
  curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, 0);
  curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, 0);
  curl_setopt($curl, CURLOPT_POST, 1);
  curl_setopt($curl, CURLOPT_TIMEOUT, 30);
    curl_setopt($curl, CURLOPT_HEADER, 0);
    curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
  $tmpInfo = curl_exec($curl);
  if (curl_errno($curl)) {
     echo 'Errno'.curl_error($curl);
  }
  curl_close($curl);
  return $tmpInfo;
}

$public = array(
  'Format'    =>  'json',
  'Version' =>    '2015-01-09',
  'AccessKeyId'   =>  $accessKeyId,
  'SignatureMethod'   =>  'HMAC-SHA1',
  'Timestamp' =>  $Timestamp,
  'SignatureVersion'  =>  '1.0',
  'SignatureNonce'    =>  generateByMicrotime()
  );
$search = array(
  'Action'    =>  'DescribeDomainRecords',
  'DomainName'    =>  $domain,
  'PageSize' => '500',
  'RRKeyWord' => $record,
  'Type' => $type
  );

//搜索record相关的记录列表
$data = json_decode(ssl_post(geturl($public,$search, $accessKeySecret)),true);

if(empty($data['DomainRecords'])){
  exit('1');
}else{
  foreach($data['DomainRecords']['Record'] as $value){
    $record_arr = array();
    if($value['RR'] == $record){
      $record_id = $value['RecordId'];
      $record_arr = $value;
      break;
    }
  }

  if(empty($record_id)){
    $add = array(
      'Action'    =>  'AddDomainRecord',
      'DomainName'    =>  $domain,
      'RR'    =>  $record,
      'Type'    =>  $type,
      'Value'    =>  $ip,
      'TTL'    =>  '600',
    );
    $data = json_decode(ssl_post(geturl($public,$add, $accessKeySecret)),true);
    if(empty($data['RecordId'])){
      exit('1');
    }else{
      exit('0');
    }
  }else{
    if($record_arr['Value'] == $ip){
      exit('0');
    }else{
      $edit = array(
        'Action'    =>  'UpdateDomainRecord',
        'RecordId'    =>  $record_id,
        'RR'    =>  $record,
        'Type'    =>  $type,
        'Value'    =>  $ip,
        'TTL'    =>  '600',
      );
      $data = json_decode(ssl_post(geturl($public,$edit, $accessKeySecret)),true);
      if(empty($data['RecordId'])){
        exit('1');
      }else{
        exit('0');
      }
    }
  }
}

5.2.3 ROS script

Ros新建Script,代码如下:

#aliyun Access Key
:local id "阿里云的AccessKey ID"
:local secret "阿里云的AccessKey secret"

#domain
:local domain "abc.com"#更改为自己的需要ddns的域名
:local record "@"     # @ 或者 www 

#PPPoE-out
:local pppoe "pppoe-out1"

:global aliip "8.8.8.8" #随机填写的ip地址,运行script后会更新为家庭网络的公网ip
:local ipaddr [/ip address get [/ip address find interface=$pppoe] address]
:set ipaddr [:pick $ipaddr 0 ([len $ipaddr] -3)]

:if ($ipaddr != $aliip) do={
  :log info "[Cloudflare DDNS] WAN IPv4 address for interface $wanif has been changed to $ip4new."
  :local result [/tool fetch url="https://aliyun-ddns-api.vercel.app/api/index.php?id=$id&secret=$secret&domain=$domain&record=$record&ip=$ipaddr" as-value output=user]
:if ($result->"status" = "finished") do={
:if ($result->"data" = "0") do={
:set aliip $ipaddr
:log info "alidns update ok";
} else={
:log info "alidns update error";
}
}
}

5.3 相关链接

  1. RouterOS配合PHP实现动态更新阿里域名云解析

  2. RouterOS利用aliyun的API接口实现DDNS动态解析

  3. Examples & Sample Projects for Vercel

  4. PHP Runtime for Vercel