commit 0cbaeec52cc3dc1335ad922942eaebac00347b06 Author: yulewang Date: Sat Jun 30 21:31:20 2018 +0800 Init diff --git a/cf-v4-ddns.sh b/cf-v4-ddns.sh new file mode 100644 index 0000000..659dbc7 --- /dev/null +++ b/cf-v4-ddns.sh @@ -0,0 +1,129 @@ +#!/usr/bin/env bash +set -o errexit +set -o nounset +set -o pipefail + +# Automatically update your CloudFlare DNS record to the IP, Dynamic DNS +# Can retrieve cloudflare Domain id and list zone's, because, lazy + +# Place at: +# /usr/local/bin/cf-ddns.sh +# run `crontab -e` and add next line: +# 0 * * * * /usr/local/bin/cf-ddns.sh >/dev/null 2>&1 +# or you need log: +# */1 * * * * /usr/local/bin/cf-ddns.sh >> /var/log/cf-ddns.log 2>&1 + + +# Usage: +# cf-ddns.sh -k cloudflare-api-key \ +# -u user@example.com \ +# -h host.example.com \ # fqdn of the record you want to update +# -z example.com \ # will show you all zones if forgot, but you need this + +# Optional flags: +# -f false|true \ # force dns update, disregard local stored ip + +# default config + +# API key, see https://www.cloudflare.com/a/account/my-account, +# incorrect api-key results in E_UNAUTH error +CFKEY= + +# Username, eg: user@example.com +CFUSER= + +# Zone name, will list all possible if missing, eg: example.com +CFZONE_NAME= + +# Hostname to update, eg: homeserver.example.com +CFRECORD_NAME= + +# Cloudflare TTL for record, between 120 and 86400 seconds +CFTTL=120 + +# Ignore local file, update ip anyway +FORCE=false + +# Site to retrieve WAN ip, other examples are: bot.whatismyipaddress.com, https://api.ipify.org/ ... +WANIPSITE="http://icanhazip.com" + +# get parameter +while getopts k:u:h:z:f: opts; do + case ${opts} in + k) CFKEY=${OPTARG} ;; + u) CFUSER=${OPTARG} ;; + h) CFRECORD_NAME=${OPTARG} ;; + z) CFZONE_NAME=${OPTARG} ;; + f) FORCE=${OPTARG} ;; + esac +done + +# If required settings are missing just exit +if [ "$CFKEY" = "" ]; then + echo "Missing api-key, get at: https://www.cloudflare.com/a/account/my-account" + echo "and save in ${0} or using the -k flag" + exit 2 +fi +if [ "$CFUSER" = "" ]; then + echo "Missing username, probably your email-address" + echo "and save in ${0} or using the -u flag" + exit 2 +fi +if [ "$CFRECORD_NAME" = "" ]; then + echo "Missing hostname, what host do you want to update?" + echo "save in ${0} or using the -h flag" + exit 2 +fi + +# If the hostname is not a FQDN +if [ "$CFRECORD_NAME" != "$CFZONE_NAME" ] && ! [ -z "${CFRECORD_NAME##*$CFZONE_NAME}" ]; then + CFRECORD_NAME="$CFRECORD_NAME.$CFZONE_NAME" + echo " => Hostname is not a FQDN, assuming $CFRECORD_NAME" +fi + +# Get current and old WAN ip +WAN_IP=`curl -s ${WANIPSITE}` +if [ -f $HOME/.wan_ip-cf.txt ]; then + OLD_WAN_IP=`cat $HOME/.wan_ip-cf.txt` +else + echo "No file, need IP" + OLD_WAN_IP="" +fi + +# Get zone_identifier & record_identifier +ID_FILE=$HOME/.id-cf.txt +if [ -f $ID_FILE ] && [ $(wc -l $ID_FILE | cut -d " " -f 1) == 2 ]; then + CFZONE_ID=$(head -1 $ID_FILE) + CFRECORD_ID=$(tail -1 $ID_FILE) +else + CFZONE_ID=$(curl -s -X GET "https://api.cloudflare.com/client/v4/zones?name=$CFZONE_NAME" -H "X-Auth-Email: $CFUSER" -H "X-Auth-Key: $CFKEY" -H "Content-Type: application/json" | grep -Po '(?<="id":")[^"]*' | head -1 ) + CFRECORD_ID=$(curl -s -X GET "https://api.cloudflare.com/client/v4/zones/$CFZONE_ID/dns_records?name=$CFRECORD_NAME" -H "X-Auth-Email: $CFUSER" -H "X-Auth-Key: $CFKEY" -H "Content-Type: application/json" | grep -Po '(?<="id":")[^"]*') + echo "$CFZONE_ID" > $ID_FILE + echo "$CFRECORD_ID" >> $ID_FILE +fi + +# If WAN IP is unchanged an not -f flag, exit here +if [ "$WAN_IP" = "$OLD_WAN_IP" ] && [ "$FORCE" = false ]; then + echo "WAN IP Unchanged, to update anyway use flag -f true" + exit 0 +fi + +# If WAN is changed, update cloudflare +echo "Updating DNS to $WAN_IP" + +RESPONSE=$(curl -s -X PUT "https://api.cloudflare.com/client/v4/zones/$CFZONE_ID/dns_records/$CFRECORD_ID" \ + -H "X-Auth-Email: $CFUSER" \ + -H "X-Auth-Key: $CFKEY" \ + -H "Content-Type: application/json" \ + --data "{\"id\":\"$CFZONE_ID\",\"type\":\"A\",\"name\":\"$CFRECORD_NAME\",\"content\":\"$WAN_IP\", \"ttl\":\"$CFTTL\"}") + +if [ "$RESPONSE" != "${RESPONSE%success*}" ] && [ $(echo $RESPONSE | grep "\"success\":true") != "" ]; then + echo "Updated succesfuly!" + echo $RESPONSE + echo $WAN_IP > $HOME/.wan_ip-cf.txt + exit +else + echo 'Something went wrong :(' + echo "Response: $RESPONSE" + exit 1 +fi \ No newline at end of file