PandoraBox下部署阿里云(aliyun)DDNS动态域名更新(shell脚本)
来源自https://jidili.com/?id=20的脚本,做了小修改以支持IPv6的解析
一、环境准备
实现这个脚本需要curl,openssl这两个插件的支持,可以在PandroaBox下的Luci界面里的系统-软件包中选择安装,也可以以命令方式安装,命令如下:
opkg update && opkg install curl openssl-util
检查是否正确安装只需要命令下输入curl,openssl回车即可,不是-ash:Not Found “xxx”一般就是正确安装了。
补充:PandroaBox的源如果不能访问请自行百度镜像源,这里也提供了软件包的打包合集
https://pan.baidu.com/s/1p3r6IciTQPPXJUfFfv8KaQ
二、支持IPv4脚本的脚本
#!/bin/sh
#前置函数
urlencode1() {
local length="${#1}"
i=0
out=""
for i in $(awk "BEGIN { for ( i=0; i<$length; i++ ) { print i; } }")
do
local c="${1:$i:1}"
case $c in
[a-zA-Z0-9.~'&'=_-]) out="$out$c" ;;
*) out="$out`printf '%%%02X' "'$c"`" ;;
esac
i=$(($i + 1))
done
echo -n $out
}
urlencode2() {
local length="${#1}"
i=0
out=""
for i in $(awk "BEGIN { for ( i=0; i<$length; i++ ) { print i; } }")
do
local c="${1:$i:1}"
case $c in
[a-zA-Z0-9.~_-]) out="$out$c" ;;
*) out="$out`printf '%%%02X' "'$c"`" ;;
esac
i=$(($i + 1))
done
echo -n $out
}
send_request() {
args="AccessKeyId=$ak&Action=$1&Format=json&$2&Version=2015-01-09"
StringToSign1="$(urlencode1 $args)"
StringToSign2="GET&%2F&$(urlencode2 $StringToSign1)"
hash=$(urlencode2 $(echo -n "$StringToSign2" | openssl dgst -sha1 -hmac $sk -binary | openssl base64))
RESULT=$(curl -k -s "https://alidns.aliyuncs.com/?$args&Signature=$hash") ## 2> /dev/null)
echo $RESULT
}
query_recordid() {
if [ "$host" = "@" ]; then
echo `send_request "DescribeSubDomainRecords" "SignatureMethod=HMAC-SHA1&SignatureNonce=$timestamp&SignatureVersion=1.0&SubDomain=$domain&Timestamp=$timestamp"`
else
echo `send_request "DescribeSubDomainRecords" "SignatureMethod=HMAC-SHA1&SignatureNonce=$timestamp&SignatureVersion=1.0&SubDomain=$host.$domain&Timestamp=$timestamp"`
fi
}
update_record() {
echo `send_request "UpdateDomainRecord" "RR=$host&RecordId=$1&SignatureMethod=HMAC-SHA1&SignatureNonce=$timestamp&SignatureVersion=1.0&Timestamp=$timestamp&Type=A&Value=$ip"`
}
add_record() {
echo `send_request "AddDomainRecord&DomainName=$domain" "RR=$host&SignatureMethod=HMAC-SHA1&SignatureNonce=$timestamp&SignatureVersion=1.0&Timestamp=$timestamp&Type=A&Value=$ip"`
}
##配置信息
##主程序入口
host="host" #主机名
domain="example.com" #你的域名
ip_network="wan"
timestamp=`date -u +"%Y-%m-%dT%H:%M:%SZ"`
ak="" #你的阿里云app key
sk="" #“你的阿里云app secret&” 注意后面多个“&”
#读取本地数据库存储的信息,若有
ipfilename=$(echo $(basename $0)) #获取自身文件名
ipfilename=$(cd "$(dirname "$0")"; pwd)/${ipfilename%.*}
if [ -f "$ipfilename"_ip ]
then
. "$ipfilename"_ip
else
record_id="" ;saved_ip="" ;saved_host="" ;saved_domain=""
fi
echo record_id="$record_id" saved_ip="$saved_ip" saved_host="$saved_host" saved_domain="$saved_domain"
ip=""
RETRY="0"
while [ $RETRY -lt 5 ]; do #获取本机ipv4地址信息
ip=$(ubus call network.interface.$ip_network status | grep \"address\" | grep -oE '[0-9]{0,3}\.[0-9]{0,3}\.[0-9]{0,3}\.[0-9]{0,3}')
RETRY=$((RETRY+1))
if [ -z "$ip" ];then
sleep 3
else
break
fi
echo $ip
done
#获取DNS域名服务器对域名解析的ipv4地址
#此处由jethroso指正,在此以表感谢
if [ "$ip" = "$saved_ip" ];then
if [ $host = "@" -o $host = "" ];then
IPDNS=$(nslookup $domain dns16.hichina.com 2>/dev/null | sed -n 's/Address 1: \([0-f.]*\)/\1/p' | sed -n '2p' | grep -oE '[0-9]{0,3}\.[0-9]{0,3}\.[0-9]{0,3}\.[0-9]{0,3}')
else
IPDNS=$(nslookup $host.$domain dns16.hichina.com 2>/dev/null | sed -n 's/Address 1: \([0-f.]*\)/\1/p' | sed -n '2p' | grep -oE '[0-9]{0,3}\.[0-9]{0,3}\.[0-9]{0,3}\.[0-9]{0,3}')
fi
fi
#检查比对本地数据库存储的ip
#也可以与IPDNS进行比较,替换saved_ip为IPDNS即可
if [ "$ip" = "$saved_ip" -a "$host" = "$saved_host" -a "$domain" = "$saved_domain" ];then
echo "$(date +"%Y-%m-%d %H:%M:%S")--Host:[$host.$domain] Already updated."
exit 0
fi
#查询解析记录信息
RESULT=`query_recordid`
record_id=$(echo $RESULT | grep -o "RR\":\"$host\",\"Status\":\"[a-zA-Z.]*\",\"Value\":\"[0-9.]*\",\"Weight\":[0-9]*,\"RecordId\":\"[0-9]*\"" | grep -o "\"RecordId\":\"[0-9]*\"" | grep -o "[0-9]*")
if [ "$record_id" = "" ]
then
#新增解析记录
RESULT=`add_record`
record_id=$(echo $RESULT | grep -o "RecordId\":\"[0-9]*\"" | grep -o "[0-9]*")
echo "$RESULT"
if [ "$record_id" != "" ]
then
echo "$(date +"%Y-%m-%d %H:%M:%S") -- Added Host [$host.$domain] (IP: $ip)"
echo "record_id=$record_id ;saved_ip=$ip ;saved_host=$host ;saved_domain=$domain" > "$ipfilename"_ip
else
echo "Not Find Such Host $host.$domain"
fi
else
#更新解析记录
RESULT=`update_record $record_id`
record_id=$(echo $RESULT | grep -o "RecordId\":\"[0-9]*\"" | grep -o "[0-9]*")
echo "$RESULT"
echo "$(date +"%Y-%m-%d %H:%M:%S") -- Update Host [$host.$domain] (IP: $ip)"
echo "record_id=$record_id ;saved_ip=$ip ;saved_host=$host ;saved_domain=$domain" > "$ipfilename"_ip
fi
本脚本在原者基础上仅做小幅修改,修正request_id不能正确通过REQUST得到的BUG(在自己的路由器上是这样的)
三、支持IPv6脚本的脚本
#!/bin/sh
#前置函数
urlencode1() {
local length="${#1}"
i=0
out=""
for i in $(awk "BEGIN { for ( i=0; i<$length; i++ ) { print i; } }")
do
local c="${1:$i:1}"
case $c in
[a-zA-Z0-9.~'&'=_-]) out="$out$c" ;;
*) out="$out`printf '%%%02X' "'$c"`" ;;
esac
i=$(($i + 1))
done
echo -n $out
}
urlencode2() {
local length="${#1}"
i=0
out=""
for i in $(awk "BEGIN { for ( i=0; i<$length; i++ ) { print i; } }")
do
local c="${1:$i:1}"
case $c in
[a-zA-Z0-9.~_-]) out="$out$c" ;;
*) out="$out`printf '%%%02X' "'$c"`" ;;
esac
i=$(($i + 1))
done
echo -n $out
}
send_request() {
args="AccessKeyId=$ak&Action=$1&Format=json&$2&Version=2015-01-09"
StringToSign1="$(urlencode1 $args)"
StringToSign2="GET&%2F&$(urlencode2 $StringToSign1)"
hash=$(urlencode2 $(echo -n "$StringToSign2" | openssl dgst -sha1 -hmac $sk -binary | openssl base64))
RESULT=$(curl -k -s "https://alidns.aliyuncs.com/?$args&Signature=$hash") ## 2> /dev/null)
echo $RESULT
}
query_recordid() {
if [ "$host" = "@" ]; then
echo `send_request "DescribeSubDomainRecords" "SignatureMethod=HMAC-SHA1&SignatureNonce=$timestamp&SignatureVersion=1.0&SubDomain=$domain&Timestamp=$timestamp"`
else
echo `send_request "DescribeSubDomainRecords" "SignatureMethod=HMAC-SHA1&SignatureNonce=$timestamp&SignatureVersion=1.0&SubDomain=$host.$domain&Timestamp=$timestamp"`
fi
}
update_record() {
echo `send_request "UpdateDomainRecord" "RR=$host&RecordId=$1&SignatureMethod=HMAC-SHA1&SignatureNonce=$timestamp&SignatureVersion=1.0&Timestamp=$timestamp&Type=AAAA&Value=$ip"`
}
add_record() {
echo `send_request "AddDomainRecord&DomainName=$domain" "RR=$host&SignatureMethod=HMAC-SHA1&SignatureNonce=$timestamp&SignatureVersion=1.0&Timestamp=$timestamp&Type=AAAA&Value=$ip"`
}
##配置信息
##主函数入口
host="host" #主机名
domain="example.com" #你的域名
ip_network="wan6"
timestamp=`date -u +"%Y-%m-%dT%H:%M:%SZ"`
ak="" #你的阿里云app key
sk="" #“你的阿里云app secret&” 注意后面多个“&”
#读取本地数据库存储的信息,若有
ipfilename=$(echo $(basename $0)) #获取自身文件名
ipfilename=$(cd "$(dirname "$0")"; pwd)/${ipfilename%.*}
if [ -f "$ipfilename"_ip ]
then
. "$ipfilename"_ip
else
record_id="" ;saved_ip="" ;saved_host="" ;saved_domain=""
fi
ip=""
RETRY="0"
while [ $RETRY -lt 5 ]; do #获取本机ipv6地址信息
ip=$(ubus call network.interface.$ip_network status | grep \"address\" | grep -oE '[0-f]{0,4}\:[0-f]{0,4}\:[0-f]{0,4}\:[0-f]{0,4}\:[0-f]{0,4}\:[0-f]{0,4}\:[0-f]{0,4}\:[0-f]{0,4}')
RETRY=$((RETRY+1))
if [ -z "$ip" ];then
sleep 3
else
break
fi
done
#获取DNS域名服务器对域名解析的ipv6地址
#此处由jethroso指正,再次表示感谢
if [ "$ip" = "$saved_ip" ];then
if [ $host = "@" -o $host = "" ];then
IPDNS=$(nslookup $domain dns16.hichina.com 2>/dev/null | sed -n 's/Address 1: \([0-f.]*\)/\1/p' | sed -n '2p' | grep -oE '[0-f]{0,4}\:[0-f]{0,4}\:[0-f]{0,4}\:[0-f]{0,4}\:[0-f]{0,4}\:[0-f]{0,4}\:[0-f]{0,4}\:[0-f]{0,4}')
else
IPDNS=$(nslookup $host.$domain dns16.hichina.com 2>/dev/null | sed -n 's/Address 1: \([0-f.]*\)/\1/p' | sed -n '2p' | grep -oE '[0-f]{0,4}\:[0-f]{0,4}\:[0-f]{0,4}\:[0-f]{0,4}\:[0-f]{0,4}\:[0-f]{0,4}\:[0-f]{0,4}\:[0-f]{0,4}')
fi
fi
#检查比对本地数据库存储的ip
#也可以与IPDNS进行比较,替换saved_ip为IPDNS即可
if [ "$ip" = "$saved_ip" -a "$host" = "$saved_host" -a "$domain" = "$saved_domain" ];then
echo "$(date +"%Y-%m-%d %H:%M:%S")--Host:[$host.$domain] Already updated."
exit 0
fi
#查询解析记录信息
RESULT=`query_recordid`
record_id=$(echo $RESULT | grep -o "RR\":\"$host\",\"Status\":\"[a-zA-Z]*\",\"Value\":\"[0-f:]*\",\"Weight\":[0-9]*,\"RecordId\":\"[0-9]*\"" | grep -o "RecordId\":\"[0-9]*\""|grep -o "[0-9]*")
if [ "$record_id" = "" ]
then
#新增解析记录
RESULT=`add_record`
record_id=$(echo $RESULT | grep -o "RecordId\":\"[0-9]*\"" | grep -o "[0-9]*")
echo "$RESULT"
if [ "$record_id" != "" ];then
echo "$(date +"%Y-%m-%d %H:%M:%S") -- Added Host [$host.$domain] (IP: $ip)"
echo "record_id=$record_id; saved_ip=$ip ;saved_host=$host ;saved_domain=$domain" > "$ipfilename"_ip
else
echo "Not Find Such Host $host.$domain"
fi
else
#更新解析记录
RESULT=`update_record $record_id`
#record_id=$(echo $RESULT | grep -o "RecordId\":\"[0-9]*\"" | grep -o "[0-9]*")
echo "$RESULT"
echo "$(date +"%Y-%m-%d %H:%M:%S") -- Update Host [$host.$domain] (IP: $ip)"
echo "record_id=$record_id; saved_ip=$ip ;saved_host=$host ;saved_domain=$domain" > "$ipfilename"_ip
fi
修改代码前面配置中 的“ak”、“sk”、“ domain“ 、”host“,"ip_network"
“ak”和“sk”可以在你的阿里云帐户中的“Access Key管理”中找到。
”host”为你的子域名,如 op.example.com 中的 op,如果想直接用“example.com"二级域名,就让host="@", "ip_network"为外网接口(IPv6一般默认是wan6)
可把脚本文件命名为aliyun.sh,用WinSCP登录路由器,放入路由器/usr/lib/ddns目录下,也可以放在其他目录下,我默认放/root。
在路由器上执行以下命令,赋予脚本执行权限
chmod a+x aliyun.sh
也可以使用WinSCP直接修改文件属性
四、支持IPv6脚本的脚本(二)
因为当时出错的原因,误以为三的脚本失效,自己ash语言基底很差,这个也是参考得来的,所以看着一脸懵逼,索性将构造请求字符串的签名函数用C语言重写, 后面发现是IPv6格式问题,心态爆炸啊,结果反正都写出来了,就也贴一个得了。
#!/bin/sh
#前置函数
send_request() {
#args生成请求字符串
args="https://alidns.aliyuncs.com/?AccessKeyId=$ak&Action=$1&Format=json&$2&Version=2015-01-09"
#调用c程序生成签名校验字符串并格式化输出全部的HTTP请求字符串
submit=`./alidns $args $sk`
RESULT=$(curl -k -s "$submit") ## 2> /dev/null)
echo $RESULT
}
query_recordid() {
if [ "$host" = "@" ]; then
echo `send_request "DescribeSubDomainRecords" "SignatureMethod=HMAC-SHA1&SignatureNonce=$timestamp&SignatureVersion=1.0&SubDomain=$domain&Timestamp=$timestamp"`
else
echo `send_request "DescribeSubDomainRecords" "SignatureMethod=HMAC-SHA1&SignatureNonce=$timestamp&SignatureVersion=1.0&SubDomain=$host.$domain&Timestamp=$timestamp"`
fi
}
update_record() {
echo `send_request "UpdateDomainRecord" "RR=$host&RecordId=$1&SignatureMethod=HMAC-SHA1&SignatureNonce=$timestamp&SignatureVersion=1.0&Timestamp=$timestamp&Type=AAAA&Value=$ip"`
}
add_record() {
echo `send_request "AddDomainRecord&DomainName=$domain" "RR=$host&SignatureMethod=HMAC-SHA1&SignatureNonce=$timestamp&SignatureVersion=1.0&Timestamp=$timestamp&Type=AAAA&Value=$ip"`
}
##配置信息
##主函数入口
host="host" #主机名
domain="example.com" #你的域名
ip_network="wan6"
timestamp=`date -u +"%Y-%m-%dT%H:%M:%SZ"`
ak="LTAIKDRnsK7wBAVy" #你的阿里云app key
sk="ZQzezqwDiP5W01quiLgcndqa6nJZV5&" #“你的阿里云app secret&” 注意后面多个“&”
#读取本地数据库存储的信息,若有
ipfilename=$(echo $(basename $0)) #获取自身文件名
ipfilename=$(cd "$(dirname "$0")"; pwd)/${ipfilename%.*}
if [ -f "$ipfilename"_ip ]
then
. "$ipfilename"_ip
else
record_id="" ;saved_ip="" ;saved_host="" ;saved_domain=""
fi
ip=""
RETRY="0"
while [ $RETRY -lt 5 ]; do #获取本机ipv4地址信息
ip=$(ubus call network.interface.$ip_network status | grep \"address\" | grep -oE '[0-f]{0,4}\:[0-f]{0,4}\:[0-f]{0,4}\:[0-f]{0,4}\:[0-f]{0,4}\:[0-f]{0,4}\:[0-f]{0,4}\:[0-f]{0,4}')
RETRY=$((RETRY+1))
if [ -z "$ip" ];then
sleep 3
else
break
fi
echo $ip
done
#获取DNS域名服务器对域名解析的ipv4地址
#此处由jethroso指正,再次感谢
if [ "$ip" = "$saved_ip" ];then
if [ $host = "@" -o $host = "" ];then
IPDNS=$(nslookup $domain dns16.hichina.com 2>/dev/null | sed -n 's/Address 1: \([0-f.]*\)/\1/p' | sed -n '2p' | grep -oE '[0-f]{0,4}\:[0-f]{0,4}\:[0-f]{0,4}\:[0-f]{0,4}\:[0-f]{0,4}\:[0-f]{0,4}\:[0-f]{0,4}\:[0-f]{0,4}')
else
IPDNS=$(nslookup $host.$domain dns16.hichina.com 2>/dev/null | sed -n 's/Address 1: \([0-f.]*\)/\1/p' | sed -n '2p' | grep -oE '[0-f]{0,4}\:[0-f]{0,4}\:[0-f]{0,4}\:[0-f]{0,4}\:[0-f]{0,4}\:[0-f]{0,4}\:[0-f]{0,4}\:[0-f]{0,4}')
fi
fi
#检查比对本地数据库存储的ip
#也可以与IPDNS进行比较,替换saved_ip为IPDNS即可
if [ "$ip" = "$saved_ip" -a "$host" = "$saved_host" -a "$domain" = "$saved_domain" ];then
echo "$(date +"%Y-%m-%d %H:%M:%S")--Host:[$host.$domain] Already updated."
exit 0
fi
#查询解析记录信息
RESULT=`query_recordid`
record_id=$(echo $RESULT | grep -o "RR\":\"$host\",\"Status\":\"[a-zA-Z.]*\",\"Value\":\"[0-9.]*\",\"Weight\":[0-9]*,\"RecordId\":\"[0-9]*\"" | grep -o "\"RecordId\":\"[0-9]*\"" | grep -o "[0-9]*")
if [ "$record_id" = "" ]
then
#新增解析记录
RESULT=`add_record`
record_id=$(echo $RESULT | grep -o "RecordId\":\"[0-9]*\"" | grep -o "[0-9]*")
if [ "$record_id" != "" ]
then
echo "$(date +"%Y-%m-%d %H:%M:%S") -- Added Host [$host.$domain] (IP: $ip)"
echo "record_id=$record_id ;saved_ip=$ip ;saved_host=$host ;saved_domain=$domain" > "$ipfilename"_ip
else
echo "Not Find Such Host $host.$domain"
fi
else
#更新解析记录
RESULT=`update_record $record_id`
record_id=$(echo $RESULT | grep -o "RecordId\":\"[0-9]*\"" | grep -o "[0-9]*")
echo "$RESULT"
echo "$(date +"%Y-%m-%d %H:%M:%S") -- Update Host [$host.$domain] (IP: $ip)"
echo "record_id=$record_id ;saved_ip=$ip ;saved_host=$host ;saved_domain=$domain" > "$ipfilename"_ip
fi
注:编写的C程序需按顺序传入两个参数,HTTP请求字符串,你的阿里云secert key。输出带上签名参数的HTTP请求字符串。
加密算法已经内置C程序里了,无需外部依赖,所以你可以不需要安装openssl
链接: https://pan.baidu.com/s/18hBYaJhvfNkdsTgGUh48hA 密码: vtqm
这个是针对Pandorabox 17.09版本编译的,3.14的内核版本。
我提供该程序的源码,并提请有意使用的人遵循GNU GPLv3协议,谢谢。
源码地址:https://github.com/jsp1256/alidns_sign
在系统的计划任务中添加如下命令
*/10 * * * * /usr/lib/ddns/aliyun.sh
表示每隔10分钟运行一次脚本。
如果需要检测是否运行的话,将命令替换成以下命令:
*/10 * * * * /usr/lib/ddns/aliyun.sh>> /tmp/log/aliyun.log
每隔10分钟运行一次脚本,并输出日志到/tmp/log/aliyun.log,日志输出到这个目录下重启路由器后就会清空(因为是放在内存里)
可以删除 aliyun_ip 文件等待10分钟检查log是不是成功运行。

浙公网安备 33010602011771号