PKG_NAME:=ddns-scripts
PKG_VERSION:=2.8.2
-PKG_RELEASE:=48
+PKG_RELEASE:=49
PKG_LICENSE:=GPL-2.0
"option domain" to be the FQDN for which to configure DDNS
endef
+define Package/ddns-scripts-huaweicloud
+ $(call Package/ddns-scripts/Default)
+ TITLE:=Extension for huaweicloud.com API
+ DEPENDS:=ddns-scripts +curl +openssl-util
+endef
+
+define Package/ddns-scripts-huaweicloud/description
+ Dynamic DNS Client scripts extension for huaweicloud.com API (require curl and openssl)
+endef
define Build/Configure
endef
rm $(1)/usr/share/ddns/default/ns1.com.json
rm $(1)/usr/share/ddns/default/one.com.json
rm $(1)/usr/share/ddns/default/porkbun.com-v3.json
+ rm $(1)/usr/share/ddns/default/huaweicloud.com.json
endef
endef
+define Package/ddns-scripts-huaweicloud/install
+ $(INSTALL_DIR) $(1)/usr/lib/ddns
+ $(INSTALL_BIN) ./files/usr/lib/ddns/update_huaweicloud_com.sh \
+ $(1)/usr/lib/ddns
+
+ $(INSTALL_DIR) $(1)/usr/share/ddns/default
+ $(INSTALL_DATA) ./files/usr/share/ddns/default/huaweicloud.com.json \
+ $(1)/usr/share/ddns/default/
+endef
+
+define Package/ddns-scripts-huaweicloud/prerm
+#!/bin/sh
+if [ -z "$${IPKG_INSTROOT}" ]; then
+ /etc/init.d/ddns stop
+fi
+exit 0
+endef
+
+
$(eval $(call BuildPackage,ddns-scripts))
$(eval $(call BuildPackage,ddns-scripts-services))
$(eval $(call BuildPackage,ddns-scripts-utils))
$(eval $(call BuildPackage,ddns-scripts-ns1))
$(eval $(call BuildPackage,ddns-scripts-one))
$(eval $(call BuildPackage,ddns-scripts-porkbun))
+$(eval $(call BuildPackage,ddns-scripts-huaweicloud))
--- /dev/null
+#!/bin/sh
+#
+# script for sending updates to huaweicloud.com
+# 2023-2024 sxlehua <sxlehua at qq dot com>
+# API documentation at https://support.huaweicloud.com/api-dns/dns_api_62003.html
+# API signature documentation at https://support.huaweicloud.com/api-dns/dns_api_30003.html
+#
+# This script is parsed by dynamic_dns_functions.sh inside send_update() function
+#
+# useage:
+# using following options from /etc/config/ddns
+# option username - huaweicloud Access Key Id
+# option password - huaweicloud Secret Access Key,AK、SK documentation from https://support.huaweicloud.com/devg-apisign/api-sign-provide-aksk.html
+# option domain - "
[email protected]" # syntax changed to remove split_FQDN() function and tld_names.dat.gz
+#
+
+# Check inputs
+[ -z "$username" ] && write_log 14 "Configuration error! [username] cannot be empty"
+[ -z "$password" ] && write_log 14 "Configuration error! [password] cannot be empty"
+
+[ -z "$CURL" ] && [ -z "$CURL_SSL" ] && write_log 14 "huaweicloud API require cURL with SSL support. Please install"
+command -v openssl >/dev/null 2>&1 || write_log 14 "huaweicloud API require openssl-util support. Please install"
+
+# public variable
+local __HOST __DOMAIN __TYPE __ZONE_ID __RECORD_ID
+local __ENDPOINT="dns.cn-north-1.myhuaweicloud.com"
+local __TTL=120
+[ $use_ipv6 -eq 0 ] && __TYPE="A" || __TYPE="AAAA"
+
+# Get host and domain from $domain
+[ "${domain:0:2}" == "@." ] && domain="${domain/./}" # host
+[ "$domain" == "${domain/@/}" ] && domain="${domain/./@}" # host with no sperator
+__HOST="${domain%%@*}"
+__DOMAIN="${domain#*@}"
+[ -z "$__HOST" -o "$__HOST" == "$__DOMAIN" ] && __HOST="@"
+
+hcloud_transfer() {
+ local method=$1
+ local path=$2
+ local query=$3
+ local body=$4
+
+ local timestamp=$(date -u +'%Y%m%dT%H%M%SZ')
+ local contentType=""
+ if [ ! "$method" = "GET" ]; then
+ contentType="application/json"
+ fi
+ local _H_Content_Type=""
+
+ local canonicalUri="${path}"
+ # add / if need
+ echo $canonicalUri | grep -qE "/$" || canonicalUri="$canonicalUri/"
+ local canonicalQuery="$query" # for extend
+
+ local canonicalHeaders="host:$__ENDPOINT\nx-sdk-date:$timestamp\n"
+ local signedHeaders="host;x-sdk-date"
+
+ if [ ! "$contentType" = "" ]; then
+ canonicalHeaders="content-type:$contentType\n${canonicalHeaders}"
+ signedHeaders="content-type;$signedHeaders"
+ _H_Content_Type="Content-Type: ${contentType}"
+ fi
+
+ local hexencode=$(printf "%s" "$body" | openssl dgst -sha256 -hex 2>/dev/null | sed 's/^.* //')
+ local canonicalRequest="$method\n$canonicalUri\n$canonicalQuery\n$canonicalHeaders\n$signedHeaders\n$hexencode"
+ canonicalRequest="$(printf "$canonicalRequest%s")"
+
+ local stringToSign="SDK-HMAC-SHA256\n$timestamp\n$(printf "%s" "$canonicalRequest" | openssl dgst -sha256 -hex 2>/dev/null | sed 's/^.* //')"
+ stringToSign="$(printf "$stringToSign%s")"
+
+ local signature=$(printf "%s" "$stringToSign" | openssl dgst -sha256 -hmac "$password" 2>/dev/null | sed 's/^.* //')
+ authorization="SDK-HMAC-SHA256 Access=$username, SignedHeaders=$signedHeaders, Signature=$signature"
+
+ reqUrl="$__ENDPOINT$path"
+ if [ ! -z "$query" ]; then
+ reqUrl="$reqUrl""?$query"
+ fi
+
+ curl -s -X "${method}" \
+ -H "Host: $__ENDPOINT" \
+ -H "$_H_Content_Type" \
+ -H "Authorization: $authorization" \
+ -H "X-Sdk-Date: $timestamp" \
+ -d "${body}" \
+ "https://$reqUrl"
+
+ if [ $? -ne 0 ]; then
+ write_log 14 "rest api error"
+ fi
+}
+
+get_zone() {
+ local resp=`hcloud_transfer GET /v2/zones "name=$__DOMAIN.&search_mode=equal" ""`
+ __ZONE_ID=`printf "%s" $resp | grep -Eo '"id":"[a-z0-9]+"' | cut -d':' -f2 | tr -d '"'`
+ if [ "$__ZONE_ID" = "" ]; then
+ write_log 14 "error, no zone"
+ fi
+}
+
+upd_record() {
+ local body="{\"name\":\"$__HOST.$__DOMAIN.\",\"type\":\"$__TYPE\",\"records\":[\"$__IP\"],\"ttl\":$__TTL}"
+ local resp=`hcloud_transfer PUT /v2/zones/"$__ZONE_ID"/recordsets/$__RECORD_ID "" "$body"`
+ local recordId=`printf "%s" $resp | grep -Eo '"id":"[a-z0-9]+"' | cut -d':' -f2 | tr -d '"'`
+ if [ ! "$recordId" = "" ]; then
+ write_log 7 "upd [$recordId] success [$__TYPE] [$__IP]"
+ else
+ write_log 14 "upd ecord error [$resp]"
+ fi
+}
+
+add_record() {
+ local body="{\"name\":\"$__HOST.$__DOMAIN.\",\"type\":\"$__TYPE\",\"records\":[\"$__IP\"],\"ttl\":$__TTL}"
+ local resp=`hcloud_transfer POST /v2/zones/"$__ZONE_ID"/recordsets "" "$body"`
+ local recordId=`printf "%s" $resp | grep -Eo '"id":"[a-z0-9]+"' | cut -d':' -f2 | tr -d '"'`
+ if [ ! "$recordId" = "" ]; then
+ write_log 7 "add [$recordId] success [$__TYPE] [$__IP]"
+ else
+ write_log 14 "add record error [$resp]"
+ fi
+}
+
+# Get DNS record
+get_record() {
+ local ret=0
+ local resp=`hcloud_transfer GET /v2/zones/$__ZONE_ID/recordsets "name=$__HOST.$__DOMAIN.&search_mode=equal" ""`
+ __RECORD_ID=`printf "%s" $resp | grep -Eo '"id":"[a-z0-9]+"' | cut -d':' -f2 | tr -d '"' | head -1`
+ if [ "$__RECORD_ID" = "" ]; then
+ # Record needs to be add
+ ret=1
+ else
+ local remoteIp=`printf "%s" $resp | grep -Eo '"records":\[[^]]+]' | cut -d ':' -f 2-10 | tr -d '[' | tr -d ']' | tr -d '"' | head -1`
+ if [ ! "$remoteIp" = "$__IP" ]; then
+ # Record needs to be updated
+ ret=2
+ fi
+ fi
+ return $ret
+}
+
+get_zone
+get_record
+
+ret=$?
+if [ $ret -eq 0 ]; then
+ write_log 7 "nochg [$__IP]"
+fi
+if [ $ret -eq 1 ]; then
+ add_record
+fi
+if [ $ret -eq 2 ]; then
+ upd_record
+fi