#!/bin/sh NAME=aliddns log_file=/var/log/$NAME.log uci_get_by_name() { local ret=$(uci get $NAME.$1.$2 2>/dev/null) echo ${ret:=$3} } uci_bool_by_name() { case "$(uci_get_by_name $1 $2)" in 1|on|true|yes|enabled) return 0;; esac return 1 } intelnetip() { tmp_ip=`curl -sL --connect-timeout 3 members.3322.org/dyndns/getip` if [ "Z$tmp_ip" == "Z" ]; then tmp_ip=`curl -sL --connect-timeout 3 api-ipv4.ip.sb/ip` fi if [ "Z$tmp_ip" == "Z" ]; then tmp_ip=`curl -sL --connect-timeout 3 v4.myip.la` fi if [ "Z$tmp_ip" == "Z" ]; then tmp_ip=`curl -sL --connect-timeout 3 whatismyip.akamai.com` fi echo -n $tmp_ip } intelnetip6() { tmp_ip6=`curl -sL --connect-timeout 3 ipv6.whatismyip.akamai.com` if [ "Z$tmp_ip6" == "Z" ]; then tmp_ip6=`curl -sL --connect-timeout 3 speed.neu6.edu.cn/getIP.php` fi if [ "Z$tmp_ip6" == "Z" ]; then tmp_ip6=`curl -sL --connect-timeout 3 v6.ident.me` fi if [ "Z$tmp_ip6" == "Z" ]; then tmp_ip6=`curl -sL --connect-timeout 3 api-ipv6.ip.sb/ip` fi echo -n $tmp_ip6 } resolve2ip() { # resolve2ip domain domain=$1 tmp_ip=`nslookup $domain ns1.alidns.com 2>/dev/null | sed '/^Server/d; /#53$/d' | grep -oE '[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}' | tail -n1` if [ "Z$tmp_ip" == "Z" ]; then tmp_ip=`nslookup $domain ns2.alidns.com 2>/dev/null | sed '/^Server/d; /#53$/d' | grep -oE '[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}' | tail -n1` fi if [ "Z$tmp_ip" == "Z" ]; then tmp_ip=`nslookup $domain 114.114.115.115 2>/dev/null | sed '/^Server/d; /#53$/d' | grep -oE '[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}' | tail -n1` fi if [ "Z$tmp_ip" == "Z" ]; then tmp_ip=`curl -sL --connect-timeout 3 "119.29.29.29/d?dn=$domain"` fi echo -n $tmp_ip } resolve2ip6() { # resolve2ip6 domain domain=$1 tmp_ip6=`nslookup $domain ns1.alidns.com 2>/dev/null | sed '/^Server/d; /#53$/d' | grep -oE '([0-9A-Fa-f]{0,4}:){2,7}([0-9A-Fa-f]{1,4}$|((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)(\.|$)){4})' | tail -n1` if [ "Z$tmp_ip6" == "Z" ]; then tmp_ip6=`nslookup $domain ns2.alidns.com 2>/dev/null | sed '/^Server/d; /#53$/d' | grep -oE '([0-9A-Fa-f]{0,4}:){2,7}([0-9A-Fa-f]{1,4}$|((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)(\.|$)){4})' | tail -n1` fi if [ "Z$tmp_ip6" == "Z" ]; then tmp_ip6=`nslookup $domain 114.114.115.115 2>/dev/null | sed '/^Server/d; /#53$/d' | grep -oE '([0-9A-Fa-f]{0,4}:){2,7}([0-9A-Fa-f]{1,4}$|((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)(\.|$)){4})' | tail -n1` fi if [ "Z$tmp_ip6" == "Z" ]; then tmp_ip6=`curl -sL --connect-timeout 3 "119.29.29.29/d?dn=$domain&type=AAAA"` fi echo -n $tmp_ip6 } check_aliddns() { echo "$DATE WAN-IP: ${ip}" if [ "Z$ip" == "Z" ]; then echo "$DATE ERROR, cant get WAN-IP..." return 0 fi current_ip=$(resolve2ip "$dm_real") if [ "Z$current_ip" == "Z" ]; then rrid='' # NO Resolve IP Means new Record_ID fi echo "$DATE DOMAIN-IP: ${current_ip}" if [ "Z$ip" == "Z$current_ip" ]; then echo "$DATE IP dont need UPDATE..." return 0 else echo "$DATE UPDATING..." return 1 fi } check_aliddns6() { echo "$DATE WAN6-IP: ${ip6}" if [ "Z$ip6" == "Z" ]; then echo "$DATE ERROR, cant get WAN6-IP..." return 0 fi current_ip6=$(resolve2ip6 "$dm_real") #urlencode current_ip6 current_ip6_urlencode=$(urlencode "$current_ip6") if [ "Z$current_ip6_urlencode" == "Z" ]; then rrid6='' # NO Resolve IP Means new Record_ID fi echo "$DATE DOMAIN-IP6: ${current_ip6_urlencode}" if [ "Z$ip6" == "Z$current_ip6_urlencode" ]; then echo "$DATE IPv6 dont need UPDATE..." return 0 else echo "$DATE UPDATING AAAA..." return 1 fi } urlencode() { # urlencode url out='' for c in $(echo -n $1 | sed 's/[^\n]/&\n/g'); do case $c in [a-zA-Z0-9._-]) out="$out$c" ;; *) out="$out$(printf '%%%02X' "'$c")" ;; esac done echo -n $out } send_request() { # send_request action args local args="AccessKeyId=$ak_id&Action=$1&Format=json&$2&Version=2015-01-09" local hash=$(urlencode $(echo -n "GET&%2F&$(urlencode $args)" | openssl dgst -sha1 -hmac "$ak_sec&" -binary | openssl base64)) curl -sSL --connect-timeout 10 "http://alidns.aliyuncs.com/?$args&Signature=$hash" } get_recordid() { sed 's/RR/\n/g' | sed -n 's/.*RecordId[^0-9]*\([0-9]*\).*/\1\n/p' | sort -ru | sed /^$/d } query_recordid() { send_request "DescribeSubDomainRecords" "SignatureMethod=HMAC-SHA1&SignatureNonce=$timestamp&SignatureVersion=1.0&SubDomain=$dm_escape&Timestamp=$timestamp&Type=A" } query_recordid6() { send_request "DescribeSubDomainRecords" "SignatureMethod=HMAC-SHA1&SignatureNonce=$timestamp&SignatureVersion=1.0&SubDomain=$dm_escape&Timestamp=$timestamp&Type=AAAA" } update_record() { send_request "UpdateDomainRecord" "RR=$sub_dm_escape&RecordId=$1&SignatureMethod=HMAC-SHA1&SignatureNonce=$timestamp&SignatureVersion=1.0&Timestamp=$timestamp&Type=A&Value=$ip" } add_record() { send_request "AddDomainRecord&DomainName=$main_dm" "RR=$sub_dm_escape&SignatureMethod=HMAC-SHA1&SignatureNonce=$timestamp&SignatureVersion=1.0&Timestamp=$timestamp&Type=A&Value=$ip" } update_record6() { send_request "UpdateDomainRecord" "RR=$sub_dm_escape&RecordId=$1&SignatureMethod=HMAC-SHA1&SignatureNonce=$timestamp&SignatureVersion=1.0&Timestamp=$timestamp&Type=AAAA&Value=$ip6_escape" } add_record6() { send_request "AddDomainRecord&DomainName=$main_dm" "RR=$sub_dm_escape&SignatureMethod=HMAC-SHA1&SignatureNonce=$timestamp&SignatureVersion=1.0&Timestamp=$timestamp&Type=AAAA&Value=$ip6_escape" } del_record() { send_request "DeleteDomainRecord" "RecordId=$1&SignatureMethod=HMAC-SHA1&SignatureNonce=$timestamp&SignatureVersion=1.0&Timestamp=$timestamp" } do_ddns_record() { if uci_bool_by_name base clean ; then query_recordid | get_recordid | while read rr; do echo "$DATE Clean record $dm_show: $rr" del_record $rr >/dev/null timestamp=$(date -u "+%Y-%m-%dT%H%%3A%M%%3A%SZ") done rrid='' fi if [ "Z$rrid" == "Z" ]; then rrid=`query_recordid | get_recordid` fi if [ "Z$rrid" == "Z" ]; then rrid=`add_record | get_recordid` echo "$DATE ADD record $rrid" else update_record $rrid >/dev/null 2>&1 echo "$DATE UPDATE record $rrid" fi if [ "Z$rrid" == "Z" ]; then # failed echo "$DATE # ERROR, Please Check Config/Time" else # save rrid uci set aliddns.base.record_id=$rrid uci commit aliddns echo "$DATE # UPDATED($ip)" fi } do_ddns_record6() { if uci_bool_by_name base clean ; then query_recordid6 | get_recordid | while read rr; do echo "$DATE Clean record $dm_show: $rr" del_record $rr >/dev/null timestamp=$(date -u "+%Y-%m-%dT%H%%3A%M%%3A%SZ") done rrid6='' fi if [ "Z$rrid6" == "Z" ]; then rrid6=`query_recordid6 | get_recordid` fi if [ "Z$rrid6" == "Z" ]; then rrid6=`add_record6 | get_recordid` echo "$DATE ADD record $rrid6" else update_record6 $rrid6 >/dev/null 2>&1 echo "$DATE UPDATE record $rrid6" fi if [ "Z$rrid6" == "Z" ]; then # failed echo "$DATE # ERROR, Please Check Config/Time" else # save rrid6 uci set aliddns.base.record_id6=$rrid6 uci commit aliddns echo "$DATE # UPDATED($ip6)" fi } clean_log() { if [ $(cat $log_file 2>/dev/null | wc -l) -ge 16 ]; then rm -f $log_file && touch $log_file echo "$DATE Log Cleaned" fi } [ -x /usr/bin/openssl -a -x /usr/bin/curl -a -x /bin/sed ] || { echo "Need [ openssl + curl + sed ]" exit 1 } ipv4=$(uci_get_by_name base ipv4) ipv6=$(uci_get_by_name base ipv6) ak_id=$(uci_get_by_name base app_key) ak_sec=$(uci_get_by_name base app_secret) rrid=$(uci_get_by_name base record_id) rrid6=$(uci_get_by_name base record_id6) main_dm=$(uci_get_by_name base main_domain) sub_dm=$(uci_get_by_name base sub_domain) if [ "Z$sub_dm" == "Z@" -o "Z$sub_dm" == "Z" ]; then dm_real="$main_dm" else dm_real="$sub_dm.$main_dm" fi dm_show="$sub_dm.$main_dm" dm_escape=`urlencode "$sub_dm.$main_dm"` sub_dm_escape=`urlencode "$sub_dm"` iface=$(uci_get_by_name base interface) if [ "Z$iface" == "Zinternet" -o "Z$iface" == "Z" ]; then ip=$(intelnetip) else ip=$(ubus call network.interface.$iface status | grep '"address"' | grep -oE '[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}' | head -1) fi DATE=$(date +'%Y-%m-%d %H:%M:%S') timestamp=$(date -u "+%Y-%m-%dT%H%%3A%M%%3A%SZ") clean_log # uci_bool_by_name base ipv4 && check_aliddns || do_ddns_record if [ $ipv4 -eq 1 ]; then check_aliddns || do_ddns_record fi # exit if ipv6 not-enabled # uci_bool_by_name base ipv6 || exit 0 iface6=$(uci_get_by_name base interface6) if [ "Z$iface6" == "Zinternet" -o "Z$iface6" == "Z" ]; then ip6=$(intelnetip6) else ip6=$(ubus call network.interface.$iface6 status | grep '"address"' | grep -oE '([0-9A-Fa-f]{0,4}:){2,7}([0-9A-Fa-f]{1,4}|((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){4})' | head -1) fi ip6_escape=`urlencode "$ip6"` # clean_log # uci_bool_by_name base ipv6 && check_aliddns6 || do_ddns_record6 if [ $ipv6 -eq 1 ]; then check_aliddns6 || do_ddns_record6 fi