0%

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

RouterOS 系统真的非常好用,目前感觉唯一不足的就是对 ddns 更新不支持。但是Ros的脚本很强大,我们可以通过脚本调用 php 的方式,实现自动更新域名解析。

因为本人是在 PVE 上搭建的 Ros ,为了能在不开启其他设备的情况下,实现软路由自动更新,所以选择直接在 PVE 上安装 nginx 和 PHP 服务。

PVE 本身就是 debian 的变体,直接 apt install 就可以了。(网上资料很多,此处不赘述,注意安装php-curl)

在 php 服务目录添加 aliddns.php 文件,调用阿里云 API 上传IP。

aliddns.php代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
<?php
#需要配置的项
define('ACCESSKEYID','(访问ID)'); #阿⾥云⽤户密钥ID 获取⽅法 https://help.aliyun.com/knowledge_detail/38738.html
define('ACCESSKEYSECRET','(访问密钥)');#阿⾥云⽤户密钥
define('RR','@'); #⼆级域名的记录名 如果是⼀级 请⽤@
define('DOMAIN','hnsac.com'); #完整域名
define('RECORDID','(记录ID)'); #解析记录ID
/*关键如何获取解析记录ID ,需要在下⾯这个地址中
https://api.aliyun.com/?spm=a2c4g.11186623.2.26.79ae2846d9RBBa#/?product=Alidns&api=AddDomainRecord&params={}&tab=DEMO&lang=JAVA
先设置⼀个记录(⼆级域名) 然后返回结果中获取这个ID 添加记录所需的参数⽂档在下⾯这⾥查看
https://help.aliyun.com/document_detail/29772.html?spm=a2c4g.11186623.4.3.392b5eb4SAeph9

*/
function GetHTTP($url)
{
$curl_samples = curl_init();
$options = [CURLOPT_URL => $url,CURLOPT_RETURNTRANSFER => 1,CURLOPT_FOLLOWLOCATION => 1,CURLOPT_SSL_VERIFYPEER => 0];
curl_setopt_array($curl_samples, $options);
curl_setopt($curl_samples, CURLOPT_CUSTOMREQUEST, 'GET');
$result = curl_exec($curl_samples);
$info = curl_getinfo($curl_samples);
$curl_err = curl_errno($curl_samples);
curl_close($curl_samples);
if( 0 != $curl_err )
{
echo "getip error:".date('Y-m-d H:i:s',time());
var_dump($info);
echo PHP_EOL;
var_dump($result);
echo PHP_EOL;
echo $curl_err;
echo PHP_EOL;
exit;
}
return $result;
}

function Encoding($string)
{
$result = urlencode($string);
$result = str_replace(['+', '*'], ['%20', '%2A'], $result);
$result = preg_replace('/%7E/', '~', $result);
return $result;
}

function CalcSign($parameters,$method="GET")
{
ksort($parameters);
$canonicalizedQuery = '';
foreach ($parameters as $key => $value)
{
$canonicalizedQuery .= '&' . Encoding($key) . '=' . Encoding($value);
}

$stringToBeSigned = $method. '&%2F&'. Encoding(substr($canonicalizedQuery, 1));
return base64_encode(hash_hmac('sha1', $stringToBeSigned, ACCESSKEYSECRET . '&', true));
}

function Main()
{
if($_SERVER['REQUEST_METHOD']=="POST"){
$request = $_POST;
}
if($_SERVER['REQUEST_METHOD']=="GET"){
$request = $_GET;
}

#获取现在⽹络的IP
$ip = $request['ip'];
#请求dns的API重新做解析
$api_url = 'https://alidns.aliyuncs.com/?';
$data = [];
#公共参数
$data['Format'] = 'json';
$data['Version'] = '2015-01-09';
$data['SignatureMethod'] = 'HMAC-SHA1';
$data['SignatureNonce'] = uniqid();
$data['SignatureVersion']= '1.0';
$data['AccessKeyId'] = ACCESSKEYID;
$data['Timestamp'] = gmdate("Y-m-d\TH:i:s\Z");
#专⽤参数
$data['Action'] = 'UpdateDomainRecord';
$data['RecordId'] = RECORDID; #解析记录的ID,此参数在添加解析时会返回,在获取域名解析列表时会返回
$data['RR'] = RR; #主机记录
$data['Type'] = 'A';
$data['Value'] = $ip;
$data['TTL'] = 600;
#$data['Priority'] = 10; #MX记录的优先级,取值范围[1,10],记录类型为MX记录时,此参数必须
$data['Line'] = 'default';
#签名
$data['Signature'] = CalcSign($data);
#请求接⼝
$json = GetHTTP($api_url . http_build_query($data));
$result = json_decode($json);
}
Main();

Ros新建Script,代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#PPPoE
:local pppoe "pppoe-out1"

:global ipold
#从pppoe接口获取最新动态IP
:local ipnew [/ip address get [/ip address find interface=$pppoe] address]
:set ipnew [:pick $ipnew 0 ([len $ipnew] -3)]
#新IP与旧IP不同则调用PHP更新域名解析地址,10.0.0.1换成自己的php服务地址
:if ($ipnew != $ipold) do={
:local url "http://10.0.0.1\?ip=$ipnew"
/tool fetch url=$url mode=http keep-result=no
#将新IP值赋给旧IP,用于之后变化检测
:set ipold $ipnew
log info "DDNS: Sending UPDATE!"
}