Skip to content

Instantly share code, notes, and snippets.

@Sizzl
Forked from m-wild/cloudflaredns.sh
Last active April 25, 2018 13:24
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Sizzl/73018e45140cfdcc8ff7 to your computer and use it in GitHub Desktop.
Save Sizzl/73018e45140cfdcc8ff7 to your computer and use it in GitHub Desktop.
CloudFlare dynamic dns updater module for Synology
#!/bin/sh
# cloudflareddns.sh - dynamic dns updater module for Synology
#
# Author:
# Michael Wildman (http://mwild.me) [v0.2]
# Chris Moore [v0.3]
#
# Version:
# 0.3
#
# Description:
# copy to /sbin/cloudflaredns.sh
# make executable (chmod +x)
# add the following entry to /etc.defaults/ddns_provider.conf
#
# [CloudFlare]
# modulepath=/sbin/cloudflaredns.sh
# queryurl=https://www.cloudflare.com/api_json.html?a=rec_edit&tkn=__PASSWORD__&email=__USERNAME__&z=__HOSTNAME__&content=__MYIP__
#
# (note that URL is not actually used, DSM will pass us the variables)
# run a rec_load_all query to get the record id
# (see https://www.cloudflare.com/docs/client-api.html)
#
# Changelog:
# 0.2:
# - Simplified this thing to its most basic requirements (curl + logging)
# - Now either returns 'good' or the result (no checking for cases -- the log was always more useful anyway!)
# 0.3:
# - Added __CFBASEURL__
# - Added code to fetch all zones and find the right one to update
# - Added code to fetch the record ID and name for the hostname
# - Changed final __URL__
#
# v0.3 Based on cloudflaredns.sh by Michael Wildman (https://gist.github.com/tehmantra/)
# v0.2 Based on Brian Schmidt Pedersen (http://blog.briped.net) gratisdns.sh
# TODO
# read addition parameters from cloudflare api calls
#
__CFBASEURL__="https://www.cloudflare.com/api_json.html"
# these variables are passed by DSM
# username is your email
__USERNAME__="$(echo ${@} | cut -d' ' -f1)"
# password is your cloudflare API key
__PASSWORD__="$(echo ${@} | cut -d' ' -f2)"
__HOSTNAME__="$(echo ${@} | cut -d' ' -f3)"
__MYIP__="$(echo ${@} | cut -d' ' -f4)"
# log location
__LOGFILE__="/var/log/cloudflareddns.log"
# additional parameters needed for CloudFlare
__RECTYPE__="A"
__RECID__=""
__RECNAME__=""
__TTL__="1"
__SERVICEMODE__="0"
log() {
__LOGTIME__=$(date +"%b %e %T")
if [ "${#}" -lt 1 ]; then
false
else
__LOGMSG__="${1}"
fi
if [ "${#}" -lt 2 ]; then
__LOGPRIO__=7
else
__LOGPRIO__=${2}
fi
logger -p ${__LOGPRIO__} -t "$(basename ${0})" "${__LOGMSG__}"
echo "${__LOGTIME__} $(basename ${0}) (${__LOGPRIO__}): ${__LOGMSG__}" >> ${__LOGFILE__}
}
# Fetch all zones available
__URL__="${__CFBASEURL__}?a=zone_load_multi&tkn=${__PASSWORD__}&email=${__USERNAME__}"
__RESPONSE__=$(curl --silent "${__URL__}")
# Parse the response
__REGEX__="\"zone_name\":\"([a-zA-Z0-9]+([-.]?[a-zA-Z0-9]+)*.[a-zA-Z]+)"
__ZONES__=$(echo ${__RESPONSE__} | grep -rosE "${__REGEX__}" | awk -F ':"' '{print $2}')
# Check which zone the __HOSTNAME__ belongs to
for zone in ${__ZONES__}
do
# Match on either sub-domain or root domain (e.g. if the hostname is the root itself):
if [ `echo ${__HOSTNAME__} | grep -E "(.*\.${zone//\./\\\.}$|^${zone//\./\\\.}$)"` ]
then
__ZONE__=${zone}
fi
done
if [ '${__ZONE__}' != '' ]
then
# Fetch the zone for this hostname and get the record ID
__URL__="${__CFBASEURL__}?a=rec_load_all&tkn=${__PASSWORD__}&email=${__USERNAME__}&z=${__ZONE__}"
__RESPONSE__=$(curl --silent "${__URL__}")
# Parse the response to get the record ID and name
__REGEX__="\"rec_id\":\"([0-9]*)\",\"rec_hash\":\"[a-z0-9]*\",\"zone_name\":\"${__ZONE__}\",\"name\":\"${__HOSTNAME__}\",\"display_name\":\"[A-z0-9]*"
__RECID__=$(echo ${__RESPONSE__} | grep -rosE "${__REGEX__}" | awk -F ':"' '{print $2}' | awk -F '"' '{print $1}')
__RECNAME__=$(echo ${__RESPONSE__} | grep -rosE "${__REGEX__}" | awk -F ':"' '{print $6}')
else
log "Not sending update, no zone match for: ${__HOSTNAME__}" 7
__RESULT__="nohost"
fi
if [ '${__RECID__}' != '' ] && [ ${__RECID__} -ge 0 ]
then
# Send the update to CF API
__URL__="${__CFBASEURL__}?a=rec_edit&tkn=${__PASSWORD__}&email=${__USERNAME__}&z=${__ZONE__}&type=${__RECTYPE__}&id=${__RECID__}&name=${__RECNAME__}&content=${__MYIP__}&ttl=${__TTL__}&service_mode=${__SERVICEMODE__}"
# Update DNS record:
log "Updating with ${__MYIP__}..." 7
__RESPONSE__=$(curl --silent "${__URL__}")
# Strip the result element from response json
__RESULT__=$(echo ${__RESPONSE__} | grep -o -E .result.:.[A-z]+.)
else
log "Not sending update, no record found for ${__HOSTNAME__} in zone: ${__ZONE__}" 7
__RESULT__="nohost"
fi
case ${__RESULT__} in
'"result":"success"')
__STATUS__='good'
true
;;
*)
__STATUS__="${__RESULT__}"
log "__RESPONSE__=${__RESPONSE__}" 5
false
;;
esac
log "Status: ${__STATUS__}" 6
printf "%s" "${__STATUS__}"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment