From 0eda1007bb22269313939e6e7385cd421c6b5938 Mon Sep 17 00:00:00 2001 From: Max Berger Date: Sat, 23 Dec 2017 22:47:48 +0100 Subject: [PATCH] ddns-scripts: Support Amazon AWS Route53 as a ddns provider Based on a sh-only route53 update script by Yuval Adam https://github.com/yuvadm/route53-ddns/blob/master/route53.sh Signed-off-by: Max Berger --- net/ddns-scripts/Makefile | 61 ++++++++++++- net/ddns-scripts/files/services | 1 + net/ddns-scripts/files/services_ipv6 | 1 + net/ddns-scripts/files/update_route53_v1.sh | 97 +++++++++++++++++++++ 4 files changed, 158 insertions(+), 2 deletions(-) create mode 100644 net/ddns-scripts/files/update_route53_v1.sh diff --git a/net/ddns-scripts/Makefile b/net/ddns-scripts/Makefile index d4023c01fa..fbc716e8f2 100755 --- a/net/ddns-scripts/Makefile +++ b/net/ddns-scripts/Makefile @@ -9,10 +9,10 @@ include $(TOPDIR)/rules.mk PKG_NAME:=ddns-scripts # Version == major.minor.patch # increase on new functionality (minor) or patches (patch) -PKG_VERSION:=2.7.6 +PKG_VERSION:=2.7.7 # Release == build # increase on changes of services files or tld_names.dat -PKG_RELEASE:=21 +PKG_RELEASE:=1 PKG_LICENSE:=GPL-2.0 PKG_MAINTAINER:=Christian Schoenebeck @@ -112,6 +112,21 @@ define Package/ddns-scripts_nsupdate/config endef +###### ************************************************************************* +define Package/ddns-scripts_route53-v1 + $(call Package/ddns-scripts/Default) + TITLE:=Amazon AWS Route 53 API v1 + DEPENDS:=ddns-scripts +curl +openssl-util +endef +define Package/ddns-scripts_route53-v1/description + Dynamic DNS Client scripts extension for Amazon AWS Route53. Note: You + must also install ca-certificate or ca-bundle. + It requires: + "option username" to be a valid AWS access key id + "option password" to be the matching AWS secret key id + "option domain" to contain the hosted zone ID +endef + ###### ************************************************************************* define Build/Configure endef @@ -387,6 +402,47 @@ define Package/ddns-scripts_nsupdate/prerm exit 0 # suppress errors endef +###### ************************************************************************* +define Package/ddns-scripts_route53-v1/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/ddns-scripts_route53-v1/install + $(INSTALL_DIR) $(1)/etc/uci-defaults + $(INSTALL_BIN) $(PKG_BUILD_DIR)/files/ddns.defaults $(1)/etc/uci-defaults/ddns_route53-v1 + $(INSTALL_DIR) $(1)/usr/lib/ddns + $(INSTALL_BIN) $(PKG_BUILD_DIR)/files/update_route53_v1.sh $(1)/usr/lib/ddns +endef +define Package/ddns-scripts_route53-v1/postinst + #!/bin/sh + # remove old services file entries + /bin/sed -i '/route53-v1/d' $${IPKG_INSTROOT}/etc/ddns/services >/dev/null 2>&1 + /bin/sed -i '/route53-v1/d' $${IPKG_INSTROOT}/etc/ddns/services_ipv6 >/dev/null 2>&1 + # and create new + printf "%s\\t%s\\n" '"route53-v1"' '"update_route53_v1.sh"' >> $${IPKG_INSTROOT}/etc/ddns/services + printf "%s\\t%s\\n" '"route53-v1"' '"update_route53_v1.sh"' >> $${IPKG_INSTROOT}/etc/ddns/services_ipv6 + # on real system restart service if enabled + [ -z "$${IPKG_INSTROOT}" ] && { + [ -x /etc/uci-defaults/ddns_route53-v1 ] && \ + /etc/uci-defaults/ddns_route53-v1 && \ + rm -f /etc/uci-defaults/route53.com-v1 >/dev/null 2>&1 + /etc/init.d/ddns enabled \ + && /etc/init.d/ddns start >/dev/null 2>&1 + } + exit 0 # suppress errors +endef +define Package/ddns-scripts_route53-v1/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 'route53-v1/d' $${IPKG_INSTROOT}/etc/ddns/services >/dev/null 2>&1 + /bin/sed -i 'route53-v1/d' $${IPKG_INSTROOT}/etc/ddns/services_ipv6 >/dev/null 2>&1 + exit 0 # suppress errors +endef + ###### ************************************************************************* $(eval $(call BuildPackage,ddns-scripts)) $(eval $(call BuildPackage,ddns-scripts_cloudflare)) @@ -394,3 +450,4 @@ $(eval $(call BuildPackage,ddns-scripts_cloudflare.com-v4)) $(eval $(call BuildPackage,ddns-scripts_godaddy.com-v1)) $(eval $(call BuildPackage,ddns-scripts_no-ip_com)) $(eval $(call BuildPackage,ddns-scripts_nsupdate)) +$(eval $(call BuildPackage,ddns-scripts_route53-v1)) diff --git a/net/ddns-scripts/files/services b/net/ddns-scripts/files/services index c66c34b46c..d84dfc5ab2 100644 --- a/net/ddns-scripts/files/services +++ b/net/ddns-scripts/files/services @@ -37,6 +37,7 @@ #.cloudflare.com-v4 !!! Please install additional package "ddns-scripts_cloudflare.com-v4" #.godaddy.com-v1 !!! Please install additional package "ddns-scripts_godaddy.com-v1" #.no-ip.com / noip.com !!! Please install additional package "ddns-scripts_no-ip_com" +#.route53-v1 !!! Please install additional package "ddns-scripts_route53-v1" "3322.org" "http://[USERNAME]:[PASSWORD]@members.3322.org/dyndns/update?system=dyndns&hostname=[DOMAIN]&myip=[IP]" diff --git a/net/ddns-scripts/files/services_ipv6 b/net/ddns-scripts/files/services_ipv6 index 3ea2974b16..1a2ffee5fe 100644 --- a/net/ddns-scripts/files/services_ipv6 +++ b/net/ddns-scripts/files/services_ipv6 @@ -37,6 +37,7 @@ #.cloudflare.com-v4 !!! Please install additional package "ddns-scripts_cloudflare.com-v4" #.godaddy.com-v1 !!! Please install additional package "ddns-scripts_godaddy.com-v1" #.no-ip.com / noip.com !!! Please install additional package "ddns-scripts_no-ip_com" +#.route53-v1 !!! Please install additional package "ddns-scripts_route53-v1" "afraid.org-basicauth" "http://[USERNAME]:[PASSWORD]@freedns.afraid.org/nic/update?hostname=[DOMAIN]&myip=[IP]" "afraid.org-keyauth" "http://freedns.afraid.org/dynamic/update.php?[PASSWORD]&address=[IP]" diff --git a/net/ddns-scripts/files/update_route53_v1.sh b/net/ddns-scripts/files/update_route53_v1.sh new file mode 100644 index 0000000000..6b9b029e0a --- /dev/null +++ b/net/ddns-scripts/files/update_route53_v1.sh @@ -0,0 +1,97 @@ +#!/bin/sh +#.Distributed under the terms of the GNU General Public License (GPL) version 2.0 +#.based on Yuval Adam's route53.sh found at https://github.com/yuvadm/route53-ddns/blob/master/route53.sh +#.2017 Max Berger +[ -z "$CURL_SSL" ] && write_log 14 "Amazon AWS Route53 communication require cURL with SSL support. Please install" +[ -z "$username" ] && write_log 14 "Service section not configured correctly! Missing key as 'username'" +[ -z "$password" ] && write_log 14 "Service section not configured correctly! Missing secret as 'password'" +[ -z "$domain" ] && write_log 14 "Service section not configured correctly! Missing zone id as 'domain'" + +set -euo pipefail +IFS=$'\n\t' + +ENDPOINT="route53.amazonaws.com" +RECORD_TTL=300 +RECORD_NAME="$lookup_host". +[ $use_ipv6 -eq 0 ] && RECORD_TYPE="A" +[ $use_ipv6 -eq 1 ] && RECORD_TYPE="AAAA" +RECORD_VALUE="$LOCAL_IP" +HOSTED_ZONE_ID="$domain" +API_PATH="/2013-04-01/hostedzone/${HOSTED_ZONE_ID}/rrset/" + +AWS_ACCESS_KEY_ID="$username" +AWS_SECRET_ACCESS_KEY="$password" +AWS_REGION='us-east-1' +AWS_SERVICE='route53' + +hash() { + msg=$1 + echo -en "$msg" | openssl dgst -sha256 | sed 's/^.* //' +} + +sign_plain() { + # Sign message using a plaintext key + key=$1 + msg=$2 + echo -en "$msg" | openssl dgst -hex -sha256 -hmac "$key" | sed 's/^.* //' +} + +sign() { + # Sign message using a hex formatted key + key=$1 + msg=$2 + echo -en "$msg" | openssl dgst -hex -sha256 -mac HMAC -macopt "hexkey:${key}" | sed 's/^.* //' +} + +request_body=" \ + \ + \ + \ + \ + UPSERT \ + \ + ${RECORD_NAME} \ + ${RECORD_TYPE} \ + ${RECORD_TTL} \ + \ + \ + ${RECORD_VALUE} \ + \ + \ + \ + \ + \ + \ +" + +fulldate=$(date --utc +%Y%m%dT%H%M%SZ) +shortdate=$(date --utc +%Y%m%d) +signed_headers="host;x-amz-date" +request_hash=$(hash "$request_body") +canonical_request="POST\n${API_PATH}\n\nhost:route53.amazonaws.com\nx-amz-date:${fulldate}\n\n${signed_headers}\n${request_hash}" + +date_key=$(sign_plain "AWS4${AWS_SECRET_ACCESS_KEY}" "${shortdate}") +region_key=$(sign "$date_key" $AWS_REGION) +service_key=$(sign "$region_key" $AWS_SERVICE) +signing_key=$(sign "$service_key" aws4_request) + +credential="${shortdate}/${AWS_REGION}/${AWS_SERVICE}/aws4_request" +sigmsg="AWS4-HMAC-SHA256\n${fulldate}\n${credential}\n$(hash "$canonical_request")" + +signature=$(sign "$signing_key" "$sigmsg") + +authorization="AWS4-HMAC-SHA256 Credential=${AWS_ACCESS_KEY_ID}/${credential}, SignedHeaders=${signed_headers}, Signature=${signature}" + +ANSWER=$(curl \ + -X "POST" \ + -H "Host: route53.amazonaws.com" \ + -H "X-Amz-Date: ${fulldate}" \ + -H "Authorization: ${authorization}" \ + -H "Content-Type: text/xml" \ + -d "$request_body" \ + "https://${ENDPOINT}${API_PATH}") +write_log 7 "${ANSWER}" + +echo ${ANSWER} | grep Error >/dev/null && return 1 +echo ${ANSWER} | grep ChangeInfo >/dev/null && return 0 +return 2 -- 2.30.2