Skip to content

Instantly share code, notes, and snippets.

@wiserain
Created April 14, 2020 02:22
Show Gist options
  • Save wiserain/8d9a0997e66c1e1b2343d305e5dc0e39 to your computer and use it in GitHub Desktop.
Save wiserain/8d9a0997e66c1e1b2343d305e5dc0e39 to your computer and use it in GitHub Desktop.
Cloudflare DDNS
#!/bin/bash
# cloudflare api v4
# https://gist.github.com/benkulbertis/fff10759c2391b6618dd
#
# user-defined variables
#
CFUSER="[email protected]"
CFKEY="cloudflare_globalkey"
ZONE_NAME="domain.com"
REC_NAMES="*.domain.com sub.domain.com"
# DISCORD_WEBHOOK="if you want to get notification via discord"
#
# system variables
#
hostname=`cat /etc/hostname`
script_dir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null && pwd )"
script_file=$(basename "$0")
ip_file="${script_dir}/${script_file%.*}.ip"
id_file="${script_dir}/${script_file%.*}.id"
ip=`wget http://ipinfo.io/ip -qO -`
#
# functions
#
send_message() {
curl -X POST $DISCORD_WEBHOOK \
-H "Content-Type: application/json" \
-d@- << EOF
{
"username": "DDNS",
"avatar_url": "https://www.cloudflare.com/img/cf-facebook-card.png",
"embeds": [{
"title": "${1}",
"description": "${2}",
"footer": {
"text": "${3}"
}
}]
}
EOF
}
update_record () {
# $1=$zone_id
# $2=$rec_name
# $3=$rec_id
# $4=$ip
curl -s -X PUT "https://api.cloudflare.com/client/v4/zones/$1/dns_records/$3" \
-H "Content-Type:application/json" \
-H "X-Auth-Key:${CFKEY}" \
-H "X-Auth-Email:${CFUSER}" \
--data '{"id": "'"$1"'", "type": "A", "name": "'"$2"'", "content": "'"$4"'"}'
}
# early termination
if [ -f $ip_file ]; then
old_ip=`cat "$ip_file"`
if [ $ip == $old_ip ]; then
echo "No Changes in IP Adddress: ${old_ip}"
exit 0
fi
fi
# get zone_id
if [ -f $id_file ] && grep -qF "zone $ZONE_NAME" $id_file; then
zone_id=$(grep -F "zone $ZONE_NAME" $id_file | cut -d " " -f 3)
else
zone_id=$(curl -s -X GET "https://api.cloudflare.com/client/v4/zones?name=$ZONE_NAME" -H "X-Auth-Email: $CFUSER" -H "X-Auth-Key: $CFKEY" -H "Content-Type: application/json" | grep -Po '(?<="id":")[^"]*' | head -1 )
echo "zone $ZONE_NAME $zone_id" >> $id_file
fi
# get rec_id
for rec_name in $REC_NAMES; do
if ! grep -qF "record $rec_name" $id_file; then
rec_id=$(curl -s -X GET "https://api.cloudflare.com/client/v4/zones/$zone_id/dns_records?name=$rec_name" -H "X-Auth-Email: $CFUSER" -H "X-Auth-Key: $CFKEY" -H "Content-Type: application/json" | grep -Po '(?<="id":")[^"]*')
echo "record $rec_name $rec_id" >> $id_file
fi
done
echo "IP has changed: $ip"
for rec_name in $REC_NAMES; do
rec_id=$(grep -F "record $rec_name" $id_file | cut -d " " -f 3)
update=$(update_record $zone_id $rec_name $rec_id $ip)
if [[ $update == *"\"success\":false"* ]]; then
echo -e "Update failed: ${rec_name}\n$update"
else
echo "Update successful: ${rec_name}"
fi
done
# notification
if [ ! -z $DISCORD_WEBHOOK ]; then
if [ -z $old_ip ]; then
send_message "Back online" "$ip" "detected on '$hostname'" &> /dev/null
else
send_message "IP changed" "$ip" "detected on '$hostname'" &> /dev/null
fi
fi
# save updated ip for comparison
echo $ip > "$ip_file"
exit 0
@wiserain
Copy link
Author

Usage

  1. Save this script to the preferred location.

  2. Edit user-defined variables: CFUSER, CFKEY, ZONE_NAME, REC_NAMES, DISCORD_WEBHOOK(Optional)

  3. Add to crontab, like */30 * * * * /home/username/ddns/cfddns.sh >/dev/null 2>&1

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment