From 15d60da9bcdf687809d47626f435cfc4bfccb288 Mon Sep 17 00:00:00 2001 From: Michael Qu Date: Tue, 3 Sep 2019 14:05:11 +0800 Subject: [PATCH] support dnspod api by token --- package/lean/luci-app-dnspod/files/dnspod.sh | 262 ++++++++---------- .../files/root/etc/config/dnspod | 4 +- .../files/root/etc/init.d/dnspod | 16 +- .../usr/lib/lua/luci/model/cbi/dnspod.lua | 13 +- 4 files changed, 130 insertions(+), 165 deletions(-) diff --git a/package/lean/luci-app-dnspod/files/dnspod.sh b/package/lean/luci-app-dnspod/files/dnspod.sh index 55366f4b4..77295f52d 100755 --- a/package/lean/luci-app-dnspod/files/dnspod.sh +++ b/package/lean/luci-app-dnspod/files/dnspod.sh @@ -1,193 +1,159 @@ -#!/bin/sh -#written by benson huang -#admin@zhetenger.com -#http://www.terryche.me/openwrt-dnspod-ddns.html +#!/bin/bash +#written by Michael Qu +#greennyreborn@gmail.com -#dnspod帐号名 -email=`uci get dnspod.base_arg.login_email` - -#dnspod密码 -password=`uci get dnspod.base_arg.login_password 2>/dev/null` +#dnspod api token +token=`uci get dnspod.base_arg.login_token` #域名 -domainname=`uci get dnspod.base_arg.main_domain 2>/dev/null` +domain=`uci get dnspod.base_arg.main_domain 2>/dev/null` -#需要更新的子域名列表,多个的话,以空格分割。 -#例如: -# sub_domains='www home' -sub_domains=`uci get dnspod.base_arg.sub_domain 2>/dev/null` + +#需要更新的子域名,只允许一个 +#由于*linux会被脚本解析为当前目录下的所有文件,所以请填写\* +# sub_domain='\*' +sub_domain=`uci get dnspod.base_arg.sub_domain 2>/dev/null` +if [ $sub_domain = "\*" ];then + sub_domain="*" +fi #check for changed ip every 300 seconds wait=300 +wait_second=`uci get dnspod.base_arg.wait_second 2>/dev/null` +if [[ $wait_second =~ ^[1-9][0-9]*$ ]]; then + wait=$wait_second +fi -#检查是否安装curl +#检查curl是否安装 curl_status=`which curl 2>/dev/null` [ -n "$curl_status" ] || { echo "curl is not installed";exit 3; } os=$(uname -a | egrep -io 'openwrt' | tr [A-Z] [a-z]) API_url="https://dnsapi.cn" +LOG_FILE="/tmp/dnspod.log" +MAX_LOG_SIZE=1*1024*1024 +PROGRAM=$(basename $0) + format='json' lang='en' record_type='A' -offset="2" -length="" -common_options="--data-urlencode \"login_email=${email}\"\ - --data-urlencode \"login_password=${password}\"\ - --data-urlencode \"format=${format}\"\ - --data-urlencode \"lang=${lang}\"" -PROGRAM=$(basename $0) +common_options="login_token=$token&format=${format}&lang=${lang}" + is_svc=0 +last_modified_ip= + +getFileSize() { + local file=$1 + wc -c $file +} + +clearLog() { + local file_size=$(getFileSize $LOG_FILE) + if [ $file_size -gt $MAX_LOG_SIZE ]; then + echo "" > $LOG_FILE + fi + +} printMsg() { - local msg="$1" - if [ $is_svc -eq 1 ];then - logger -t ${PROGRAM} "${msg}" - else - echo $msg - fi + local time=$(date "+%Y-%m-%d %H:%M:%S") + local msg="$1" + if [ $is_svc -eq 1 ];then + echo "$time: $msg" >> $LOG_FILE + # logger -t ${PROGRAM} "${msg}" + else + echo "$time: $msg" + fi } getIp() { -# curl -s http://checkip.dyndns.com | sed -n 's/.*: \([0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}\).*/\1/p' - curl -s http://members.3322.org/dyndns/getip -} - -getJsonValue(){ - local params="$1" - echo $json_data | sed 's/\\\\\//\//g' | sed 's/[{}]//g;s/\(\[\|\]\)//g' |\ - awk -F ',' '{ for (i=1;i<=NF;i++) { print $i }}' |\ - sed 's/":/\|/g;s/"//g' |\ - awk -v k="$params" -F'|' '{ if ($(NF - 1) == k ) print $NF }' +# curl -s http://checkip.dyndns.com | sed -n 's/.*: \([0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}\).*/\1/p' + curl -s whatismyip.akamai.com } execAPI() { - local action="$1" - local extra_options="$2" - eval "curl -k -A 'xddns' ${API_url}/${action} ${common_options} ${extra_options}" + local action="$1" + local extra_options="$2" + + eval "curl -k -X POST \"${API_url}/${action}\" -d \"${common_options}&${extra_options}\"" } -getDomainId() { - local extra_options="--data-urlencode \"domain=${domainname}\"" - json_data=$(execAPI "Domain.info" "${extra_options}") - getJsonValue id -} - -getRecordId() { - local extra_options - for sub_domain in $sub_domains;do - extra_options="--data-urlencode \"record_type=${record_type}\"\ - --data-urlencode \"domain_id=${domain_id}\"\ - --data-urlencode \"sub_domain=${sub_domain}\"\ - --data-urlencode \"offset=${offset}\"\ - --data-urlencode \"length=${length}\"" - - json_data=$(execAPI "Record.List" "${extra_options}") - - #check if record type is NS - IS_NS=$(getJsonValue type | grep -o 'NS' | head -n1) - - #if there are multi @ subdomains, get the first non-NS record id only - if [ "$IS_NS" = "NS" ];then - numofline=$(getJsonValue id | sed '/^[0-9]\{7\}$/d' | wc -l) - [ $numofline -eq 3 ] && tmp_result_id="$(getJsonValue id | sed '/^[0-9]\{7\}$/d' | head -n1 )" || continue - else - tmp_result_id="$(getJsonValue id | sed '/^[0-9]\{7\}$/d')" - fi - #if result_id is not empty or unset, append a space to split record id - result_id="${result_id:+${result_id} }${tmp_result_id}" - done - echo $result_id - exit +getRecordList() { + local extra_options="domain=$domain" + echo $(execAPI "Record.List" "$extra_options") + exit } updateRecord() { - local record_id_list - local extra_options - local tmp=${sub_domains} - local tmp_sub_domains - printMsg 'Start update records' - record_id_list=$(getRecordId) - printMsg "Records IDs: ${record_id_list}" - for record_id in $record_id_list;do - tmp_sub_domains=$(echo $tmp | awk '{ print $1 }') - tmp=${tmp#* } - extra_options="--data-urlencode \"domain_id=${domain_id}\"\ - --data-urlencode \"record_id=${record_id}\"\ - --data-urlencode \"sub_domain=${tmp_sub_domains}\"\ - --data-urlencode \"record_type=${record_type}\"\ - --data-urlencode \"record_line=默认\"\ - --data-urlencode \"value=${pub_ip_addr}\"\ - --data-urlencode \"mx=1\"" - json_data=$(execAPI "Record.Modify" "${extra_options}") - printMsg "Update [${tmp_sub_domains}.${domainname}] ${record_type} record to [${pub_ip_addr}] : $(getJsonValue message)" - done - printMsg 'Update records finish' + local ip=$1 + local record_list=`getRecordList` + local old_ip=`jsonfilter -s "$record_list" -e "@.records[@.name='$sub_domain'].value"` + local id=`jsonfilter -s "$record_list" -e "@.records[@.name='$sub_domain'].id"` + printMsg "Change record: $sub_domain.$domain from $old_ip to $ip" + + local extra_options="domain=$domain&record_id=$id&value=$ip&record_type=A&record_line_id=0&sub_domain=$sub_domain" + local response=$(execAPI "Record.Modify" "$extra_options") + + local code=`jsonfilter -s "$response" -e "@.status.code"` + if [ "$code" == "1" ]; then + last_modified_ip=$ip + fi + local message=`jsonfilter -s "$response" -e "@.status.message"` + printMsg "response: $message" + } checkip() { - local oldip=$pub_ip_addr - pub_ip_addr=$(getIp) - printMsg "old ip: [$oldip], new ip: [$pub_ip_addr]" - if [ "$pub_ip_addr" != "$oldip" ];then - return 8 - else - return 3 - fi -} - -updateTunnelBroker() { - printMsg "Start Update Tunnel Broker" - printMsg "User Name: ***, Tunnel ID: ***" - result=$(curl -s --insecure https://ipv4.tunnelbroker.net/nic/update --data-urlencode "username=***" --data-urlencode "password=***" --data-urlencode "hostname=***") - printMsg "Update Tunnel Broker: ${result}" - printMsg "Update Tunnel Broker finish" + local wan_ip=$1 + printMsg "old ip: [$last_modified_ip], new ip: [$wan_ip]" + if [ "$wan_ip" != "$last_modified_ip" ];then + return 8 + else + return 3 + fi } execSvc() { - local ip - #check that whether the network is ok - while [ 1 ];do - ip=$(getIp) - if [ -n "$ip" ];then - printMsg "WAN IP: ${ip}" - break; - else - printMsg "Can't get wan ip" - sleep 30 - fi - done + local ip + #check that whether the network is ok + while [ 1 ];do + ip=$(getIp) + if [ -n "$ip" ];then + printMsg "WAN IP: ${ip}" + break; + else + printMsg "Can't get wan ip" + sleep 30 + fi + done - domain_id=`getDomainId $domainname` - printMsg "domain_id: ${domain_id}" - while [ 1 ];do - checkip - if [ $? -eq 8 ];then - updateRecord - #updateTunnelBroker - fi - sleep $wait - done + while [ 1 ];do + clearLog + ip=$(getIp) + checkip $ip + if [ $? -eq 8 ];then + updateRecord $ip + #updateTunnelBroker + fi + sleep $wait + done } execUpdate() { - domain_id=`getDomainId $domainname` - pub_ip_addr=$(getIp) - updateRecord + local ip=`getIp` + updateRecord $ip } case $1 in - --svc) - is_svc=1; - printMsg 'Start in Service mode'; - printMsg "domain: ${domainname}, sub_domains: ${sub_domains}"; - execSvc;; - --ipv6) - is_svc=0; - printMsg "Start update HE Tunnel Broker"; - updateTunnelBroker;; - *) - is_svc=0; - printMsg "Start update record, domain: ${domainname}, sub_domains: ${sub_domains}"; - execUpdate;; + --svc) + is_svc=1; + clearLog; + printMsg "Start in Service mode, check in every $wait seconds"; + printMsg "domain: ${domain}, sub_domain: ${sub_domain}"; + execSvc;; + *) + is_svc=0; + printMsg "Start update record, domain: ${domain}, sub_domain: ${sub_domain}"; + execUpdate;; esac diff --git a/package/lean/luci-app-dnspod/files/root/etc/config/dnspod b/package/lean/luci-app-dnspod/files/root/etc/config/dnspod index 6cebd6d7a..4ec49531f 100644 --- a/package/lean/luci-app-dnspod/files/root/etc/config/dnspod +++ b/package/lean/luci-app-dnspod/files/root/etc/config/dnspod @@ -1,6 +1,6 @@ config base_arg "base_arg" - option login_email '' - option login_password '' option main_domain '' option sub_domain '' + option login_token '' + option wait_second '' diff --git a/package/lean/luci-app-dnspod/files/root/etc/init.d/dnspod b/package/lean/luci-app-dnspod/files/root/etc/init.d/dnspod index 70c2a1253..036fa308e 100755 --- a/package/lean/luci-app-dnspod/files/root/etc/init.d/dnspod +++ b/package/lean/luci-app-dnspod/files/root/etc/init.d/dnspod @@ -1,18 +1,18 @@ #!/bin/sh /etc/rc.common START=80 -run_reboot() -{ - killall dnspod.sh - /sbin/dnspod.sh --svc -} - start() { - /sbin/dnspod.sh --svc + /usr/sbin/dnspod.sh --svc & } stop() { - killall dnspod.sh + ps | grep dnspod.sh | grep -v 'grep' | awk '{print $1}' | xargs kill +} + +run_reboot() +{ + stop + start } diff --git a/package/lean/luci-app-dnspod/files/root/usr/lib/lua/luci/model/cbi/dnspod.lua b/package/lean/luci-app-dnspod/files/root/usr/lib/lua/luci/model/cbi/dnspod.lua index a36605037..1f5038029 100644 --- a/package/lean/luci-app-dnspod/files/root/usr/lib/lua/luci/model/cbi/dnspod.lua +++ b/package/lean/luci-app-dnspod/files/root/usr/lib/lua/luci/model/cbi/dnspod.lua @@ -7,7 +7,7 @@ Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at - http://www.apache.org/licenses/LICENSE-2.0 + http://www.apache.org/licenses/LICENSE-2.0 ]]-- require("luci.sys") @@ -18,15 +18,14 @@ s = m:section(TypedSection, "base_arg", "") s.addremove = false s.anonymous = true -email = s:option(Value, "login_email", translate("登录邮箱"),"登录DNSPOD的用户名") -pass = s:option(Value, "login_password", translate("登录密码"),"登录DNSPOD的密码") -pass.password=true -main = s:option(Value, "main_domain", translate("主域名"),"想要解析的主域名,例如:baidu.com") -sub = s:option(Value, "sub_domain", translate("子域名"),"想要解析的子域名,多个以空格分开,例如:test hehe") +email = s:option(Value, "login_token", translate("DNSPOD Token"), "格式: ID,Token") +main = s:option(Value, "main_domain", translate("主域名"), "想要解析的主域名,例如:baidu.com") +sub = s:option(Value, "sub_domain", translate("子域名"), "想要解析的子域名,只允许填写一个。如果想解析*子域名,请填写 \\*") +wait = s:option(Value, "wait_second", translate("更新周期(s)"), "请填写数字,默认为300s") local apply = luci.http.formvalue("cbi.apply") if apply then - io.popen("/etc/init.d/dnspod restart &") + io.popen("/etc/init.d/dnspod restart &") end return m