diff --git a/package/lean/ddns-scripts_dnspod/Makefile b/package/lean/ddns-scripts_dnspod/Makefile new file mode 100644 index 000000000..3f564bd48 --- /dev/null +++ b/package/lean/ddns-scripts_dnspod/Makefile @@ -0,0 +1,78 @@ +include $(TOPDIR)/rules.mk + +PKG_NAME:=ddns-scripts_dnspod +PKG_VERSION:=1.0.1 +PKG_RELEASE:=1 + +PKG_LICENSE:=GPLv2 +PKG_MAINTAINER:=Small_5 + +PKG_BUILD_PARALLEL:=1 + +include $(INCLUDE_DIR)/package.mk + +define Package/$(PKG_NAME) + SECTION:=net + CATEGORY:=Network + SUBMENU:=IP Addresses and Names + TITLE:=DDNS extension for Dnspod.com/Dnspod.cn + PKGARCH:=all + DEPENDS:=+ddns-scripts +wget +ca-certificates +endef + +define Package/$(PKG_NAME)/description + Dynamic DNS Client scripts extension for Dnspod.com/Dnspod.cn +endef + +define Build/Configure +endef + +define Build/Compile + $(CP) ./*.sh $(PKG_BUILD_DIR) +endef + +define Package/$(PKG_NAME)/preinst + #!/bin/sh + # if NOT run buildroot then stop service + [ -z "$${IPKG_INSTROOT}" ] && /etc/init.d/ddns stop >/dev/null 2>&1 + exit 0 # suppress errors +endef + +define Package/$(PKG_NAME)/install + $(INSTALL_DIR) $(1)/usr/lib/ddns + $(INSTALL_BIN) $(PKG_BUILD_DIR)/*.sh $(1)/usr/lib/ddns +endef + +define Package/$(PKG_NAME)/postinst + #!/bin/sh + # remove old services file entries + /bin/sed -i '/dnspod\.com/d' $${IPKG_INSTROOT}/etc/ddns/services >/dev/null 2>&1 + /bin/sed -i '/dnspod\.cn/d' $${IPKG_INSTROOT}/etc/ddns/services >/dev/null 2>&1 + /bin/sed -i '/dnspod\.com/d' $${IPKG_INSTROOT}/etc/ddns/services_ipv6 >/dev/null 2>&1 + /bin/sed -i '/dnspod\.cn/d' $${IPKG_INSTROOT}/etc/ddns/services_ipv6 >/dev/null 2>&1 + # and create new + printf "%s\\t\\t%s\\n" '"dnspod.com"' '"update_dnspod_com.sh"' >> $${IPKG_INSTROOT}/etc/ddns/services + printf "%s\\t\\t%s\\n" '"dnspod.cn"' '"update_dnspod_cn.sh"' >> $${IPKG_INSTROOT}/etc/ddns/services + printf "%s\\t\\t%s\\n" '"dnspod.com"' '"update_dnspod_com.sh"' >> $${IPKG_INSTROOT}/etc/ddns/services_ipv6 + printf "%s\\t\\t%s\\n" '"dnspod.cn"' '"update_dnspod_cn.sh"' >> $${IPKG_INSTROOT}/etc/ddns/services_ipv6 + # on real system restart service if enabled + [ -z "$${IPKG_INSTROOT}" ] && { + /etc/init.d/ddns enabled && \ + /etc/init.d/ddns start >/dev/null 2>&1 + } + exit 0 # suppress errors +endef + +define Package/$(PKG_NAME)/prerm + #!/bin/sh + # if NOT run buildroot then stop service + [ -z "$${IPKG_INSTROOT}" ] && /etc/init.d/ddns stop >/dev/null 2>&1 + # remove services file entries + /bin/sed -i '/dnspod\.com/d' $${IPKG_INSTROOT}/etc/ddns/services >/dev/null 2>&1 + /bin/sed -i '/dnspod\.cn/d' $${IPKG_INSTROOT}/etc/ddns/services >/dev/null 2>&1 + /bin/sed -i '/dnspod\.com/d' $${IPKG_INSTROOT}/etc/ddns/services_ipv6 >/dev/null 2>&1 + /bin/sed -i '/dnspod\.cn/d' $${IPKG_INSTROOT}/etc/ddns/services_ipv6 >/dev/null 2>&1 + exit 0 # suppress errors +endef + +$(eval $(call BuildPackage,$(PKG_NAME))) diff --git a/package/lean/ddns-scripts_dnspod/update_dnspod_cn.sh b/package/lean/ddns-scripts_dnspod/update_dnspod_cn.sh new file mode 100644 index 000000000..ec2e0a929 --- /dev/null +++ b/package/lean/ddns-scripts_dnspod/update_dnspod_cn.sh @@ -0,0 +1,151 @@ +#!/bin/sh + +#检查传入参数 +[ -z "$username" ] && write_log 14 "Configuration error! [User name] cannot be empty" +[ -z "$password" ] && write_log 14 "Configuration error! [Password] cannot be empty" + +#检查外部调用工具 +[ -n "$WGET_SSL" ] || write_log 13 "GNU Wget support is required to use Alibaba Cloud API. Please install first" + +# 变量声明 +local __URLBASE __HOST __DOMAIN __TYPE __CMDBASE __POST __POST1 __RECIP __RECID __value __TTL +__URLBASE="https://dnsapi.cn/" + +# 从 $domain 分离主机和域名 +[ "${domain:0:2}" == "@." ] && domain="${domain/./}" # 主域名处理 +[ "$domain" == "${domain/@/}" ] && domain="${domain/./@}" # 未找到分隔符,兼容常用域名格式 +__HOST="${domain%%@*}" +__DOMAIN="${domain#*@}" +[ -z "$__HOST" -o "$__HOST" == "$__DOMAIN" ] && __HOST="@" + +# 设置记录类型 +[ $use_ipv6 -eq 0 ] && __TYPE="A" || __TYPE="AAAA" + +# 构造基本通信命令 +build_command() { + __CMDBASE="$WGET_SSL -nv -t 1 -O $DATFILE -o $ERRFILE" + # 绑定用于通信的主机/IP + if [ -n "$bind_network" ]; then + local bind_ip run_prog + [ $use_ipv6 -eq 0 ] && run_prog="network_get_ipaddr" || run_prog="network_get_ipaddr6" + eval "$run_prog bind_ip $bind_network" || \ + write_log 13 "Unable to get local IP address with '$run_prog $ bind_network' - error code: '$?'" + write_log 7 "Forced use of IP '$bind_ip' communication" + __CMDBASE="$__CMDBASE --bind-address=$bind_ip" + fi + # 强制设定IP版本 + if [ $force_ipversion -eq 1 ]; then + [ $use_ipv6 -eq 0 ] && __CMDBASE="$__CMDBASE -4" || __CMDBASE="$__CMDBASE -6" + fi + # 设置CA证书参数 + if [ $use_https -eq 1 ]; then + if [ "$cacert" = "IGNORE" ]; then + __CMDBASE="$__CMDBASE --no-check-certificate" + elif [ -f "$cacert" ]; then + __CMDBASE="$__CMDBASE --ca-certificate=${cacert}" + elif [ -d "$cacert" ]; then + __CMDBASE="$__CMDBASE --ca-directory=${cacert}" + elif [ -n "$cacert" ]; then + write_log 14 "A valid certificate for HTTPS communication was not found in '$cacert'" + fi + fi + # 如果没有设置,禁用代理 (这可能是 .wgetrc 或环境设置错误) + [ -z "$proxy" ] && __CMDBASE="$__CMDBASE --no-proxy" + __CMDBASE="$__CMDBASE --post-data" +} + +# 用于Dnspod API的通信函数 +dnspod_transfer() { + local __A=$1 + local __CNT=0 + local __ERR=0 + local __B PID_SLEEP + case "$__A" in + 0) + __B="$__CMDBASE '$__POST' ${__URLBASE}Record.List" + ;; + 1) + __B="$__CMDBASE '$__POST1' ${__URLBASE}Record.Create" + ;; + 2) + __B="$__CMDBASE '$__POST1&record_id=$__RECID&ttl=$__TTL' ${__URLBASE}Record.Modify" + ;; + esac + + while : ; do + write_log 7 "#> $__B" + eval $__B + __ERR=`jsonfilter -i $DATFILE -e "@.status.code"` + + [ $__ERR -eq 1 ] && return 0 + [ $__ERR -ne 0 ] && write_log 3 "Error message:[$(jsonfilter -i $DATFILE -e "@.status.message")]" + + if [ $VERBOSE -gt 1 ]; then + write_log 4 "Transfer failed - detailed mode: $VERBOSE - Do not try again after an error" + return 1 + fi + + __CNT=$(( $__CNT + 1 )) + [ $retry_count -gt 0 -a $__CNT -gt $retry_count ] && write_log 14 "Transfer failed after $retry_count retries" + + write_log 4 "Transfer failed - $__CNT Try again in $RETRY_SECONDS seconds" + sleep $RETRY_SECONDS & + PID_SLEEP=$! + wait $PID_SLEEP + PID_SLEEP=0 + done +} + +#添加解析记录 +add_domain() { +dnspod_transfer 1 +write_log 7 "Add new parsing record [${__HOST}.${__DOMAIN}],[type:$__TYPE],[ip:$__IP] successfully!" +return 0 +} + +#修改解析记录 +update_domain() { +dnspod_transfer 2 +write_log 7 "Modify new parsing record [${__HOST}.${__DOMAIN}],[type:$__TYPE],[ip:$__IP],[TTL:$__TTL] successfully!" +return 0 +} + +#获取域名解析记录 +describe_domain() { + ret=0 + __POST="login_token=$username,$password&format=json&domain=$__DOMAIN" + __POST1="$__POST&sub_domain=$__HOST&value=$__IP&record_type=$__TYPE&record_line_id=0" + dnspod_transfer 0 + __value=`jsonfilter -i $DATFILE -e "@.records[@.name='$__HOST'].name"` + if [ "$__value" == "" ]; then + write_log 7 "Parsing record:[${__HOST}.${__DOMAIN}] does not exist" + ret=1 + else + __value=`jsonfilter -i $DATFILE -e "@.records[@.name='$__HOST'].type"` + if [ "$__value" != "$__TYPE" ]; then + write_log 7 "Current parsing [type:$__TYPE], get mismatched [type:$__value]" + ret=2 + else + __RECID=`jsonfilter -i $DATFILE -e "@.records[@.name='$__HOST'].id"` + write_log 7 "Get parsing recordID:[$__RECID]" + __RECIP=`jsonfilter -i $DATFILE -e "@.records[@.name='$__HOST'].value"` + if [ "$__RECIP" != "$__IP" ]; then + write_log 7 "Address needs to be modified, local address:[$__IP]" + ret=2 + fi + fi + __TTL=`jsonfilter -i $DATFILE -e "@.records[@.name='$__HOST'].ttl"` + fi +} + +build_command +describe_domain +if [ $ret == 1 ];then + sleep 3 && add_domain +elif [ $ret == 2 ];then + sleep 3 && update_domain +else + write_log 7 "Local IP:[$__IP] parsing records IP:[$__RECIP] address does not need to be modified" +fi + +return 0 diff --git a/package/lean/ddns-scripts_dnspod/update_dnspod_com.sh b/package/lean/ddns-scripts_dnspod/update_dnspod_com.sh new file mode 100644 index 000000000..576ce4fbc --- /dev/null +++ b/package/lean/ddns-scripts_dnspod/update_dnspod_com.sh @@ -0,0 +1,161 @@ +#!/bin/sh + +#检查传入参数 +[ -z "$username" ] && write_log 14 "Configuration error! [User name] cannot be empty" +[ -z "$password" ] && write_log 14 "Configuration error! [Password] cannot be empty" + +#检查外部调用工具 +[ -n "$WGET_SSL" ] || write_log 13 "GNU Wget support is required to use Alibaba Cloud API. Please install first" + +# 变量声明 +local __URLBASE __HOST __DOMAIN __TYPE __CMDBASE __TOKEN __POST __POST1 __RECIP __RECID __value __TTL +__URLBASE="https://api.dnspod.com/" + +# 从 $domain 分离主机和域名 +[ "${domain:0:2}" == "@." ] && domain="${domain/./}" # 主域名处理 +[ "$domain" == "${domain/@/}" ] && domain="${domain/./@}" # 未找到分隔符,兼容常用域名格式 +__HOST="${domain%%@*}" +__DOMAIN="${domain#*@}" +[ -z "$__HOST" -o "$__HOST" == "$__DOMAIN" ] && __HOST="@" + +# 设置记录类型 +[ $use_ipv6 -eq 0 ] && __TYPE="A" || __TYPE="AAAA" + +# 构造基本通信命令 +build_command() { + __CMDBASE="$WGET_SSL -nv -t 1 -O $DATFILE -o $ERRFILE" + # 绑定用于通信的主机/IP + if [ -n "$bind_network" ]; then + local bind_ip run_prog + [ $use_ipv6 -eq 0 ] && run_prog="network_get_ipaddr" || run_prog="network_get_ipaddr6" + eval "$run_prog bind_ip $bind_network" || \ + write_log 13 "Unable to get local IP address with '$run_prog $ bind_network' - error code: '$?'" + write_log 7 "Forced use of IP '$bind_ip' communication" + __CMDBASE="$__CMDBASE --bind-address=$bind_ip" + fi + # 强制设定IP版本 + if [ $force_ipversion -eq 1 ]; then + [ $use_ipv6 -eq 0 ] && __CMDBASE="$__CMDBASE -4" || __CMDBASE="$__CMDBASE -6" + fi + # 设置CA证书参数 + if [ $use_https -eq 1 ]; then + if [ "$cacert" = "IGNORE" ]; then + __CMDBASE="$__CMDBASE --no-check-certificate" + elif [ -f "$cacert" ]; then + __CMDBASE="$__CMDBASE --ca-certificate=${cacert}" + elif [ -d "$cacert" ]; then + __CMDBASE="$__CMDBASE --ca-directory=${cacert}" + elif [ -n "$cacert" ]; then + write_log 14 "A valid certificate for HTTPS communication was not found in '$cacert'" + fi + fi + # 如果没有设置,禁用代理 (这可能是 .wgetrc 或环境设置错误) + [ -z "$proxy" ] && __CMDBASE="$__CMDBASE --no-proxy" + __CMDBASE="$__CMDBASE --post-data" +} + +# 用于Dnspod API的通信函数 +dnspod_transfer() { + local __A=$1 + local __CNT=0 + local __ERR=0 + local __B __C PID_SLEEP + case "$__A" in + 0) + __B="$__CMDBASE 'login_email=$username&login_password=$password&format=json' ${__URLBASE}Auth" + __C=$__B + ;; + 1) + __B="$__CMDBASE '$__POST' ${__URLBASE}Record.List" + __C=1 + ;; + 2) + __B="$__CMDBASE '$__POST1' ${__URLBASE}Record.Create" + __C=1 + ;; + 3) + __B="$__CMDBASE '$__POST1&record_id=$__RECID&ttl=$__TTL' ${__URLBASE}Record.Modify" + __C=1 + ;; + esac + + while : ; do + [ $__C -eq 1 ] && __C=$(echo -e "$__B" | sed -e "s/${__TOKEN#*,}/***PW***/g") + write_log 7 "#> $__C" + eval $__B + __ERR=`jsonfilter -i $DATFILE -e "@.status.code"` + + [ $__ERR -eq 1 ] && return 0 + [ $__ERR -ne 0 ] && write_log 3 "Error message:[$(jsonfilter -i $DATFILE -e "@.status.message")]" + + if [ $VERBOSE -gt 1 ]; then + write_log 4 "Transfer failed - detailed mode: $VERBOSE - Do not try again after an error" + return 1 + fi + + __CNT=$(( $__CNT + 1 )) + [ $retry_count -gt 0 -a $__CNT -gt $retry_count ] && write_log 14 "Transfer failed after $retry_count retries" + + write_log 4 "Transfer failed - $__CNT Try again in $RETRY_SECONDS seconds" + sleep $RETRY_SECONDS & + PID_SLEEP=$! + wait $PID_SLEEP + PID_SLEEP=0 + done +} + +#添加解析记录 +add_domain() { +dnspod_transfer 2 +write_log 7 "Add new parsing record [${__HOST}.${__DOMAIN}],[type:$__TYPE],[ip:$__IP] successfully!" +return 0 +} + +#修改解析记录 +update_domain() { +dnspod_transfer 3 +write_log 7 "Modify new parsing record [${__HOST}.${__DOMAIN}],[type:$__TYPE],[ip:$__IP],[TTL:$__TTL] successfully!" +return 0 +} + +#获取域名解析记录 +describe_domain() { + ret=0 + dnspod_transfer 0 + __TOKEN=`jsonfilter -i $DATFILE -e "@.user_token"` + __POST="user_token=$__TOKEN&format=json&domain=$__DOMAIN" + __POST1="$__POST&sub_domain=$__HOST&value=$__IP&record_type=$__TYPE&record_line=default" + dnspod_transfer 1 + __value=`jsonfilter -i $DATFILE -e "@.records[@.name='$__HOST'].name"` + if [ "$__value" == "" ]; then + write_log 7 "Parsing record:[${__HOST}.${__DOMAIN}] does not exist" + ret=1 + else + __value=`jsonfilter -i $DATFILE -e "@.records[@.name='$__HOST'].type"` + if [ "$__value" != "$__TYPE" ]; then + write_log 7 "Current parsing [type:$__TYPE], get mismatched [type:$__value]" + ret=2 + else + __RECID=`jsonfilter -i $DATFILE -e "@.records[@.name='$__HOST'].id"` + write_log 7 "Get parsing recordID:[$__RECID]" + __RECIP=`jsonfilter -i $DATFILE -e "@.records[@.name='$__HOST'].value"` + if [ "$__RECIP" != "$__IP" ]; then + write_log 7 "Address needs to be modified, local address:[$__IP]" + ret=2 + fi + fi + __TTL=`jsonfilter -i $DATFILE -e "@.records[@.name='$__HOST'].ttl"` + fi +} + +build_command +describe_domain +if [ $ret == 1 ];then + sleep 3 && add_domain +elif [ $ret == 2 ];then + sleep 3 && update_domain +else + write_log 7 "Local IP:[$__IP] parsing records IP:[$__RECIP] address does not need to be modified" +fi + +return 0