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是不是成功運行。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM