Skip to content

Instantly share code, notes, and snippets.

@zikeji
Created September 12, 2020 01:19
Show Gist options
  • Save zikeji/87c0b750e60eeff833db5cf173521c58 to your computer and use it in GitHub Desktop.
Save zikeji/87c0b750e60eeff833db5cf173521c58 to your computer and use it in GitHub Desktop.
#!/bin/bash
CF_TOKEN="Gh_0000000000000000000000000000000000000" # generated API token with DNS edit on your zone ID
CF_ZONE_ID="00000000000000000000000000000000" # the zone ID found in the Overview tab
CF_RECORD="dynamic.example.domain" # your record within the zone you want to update
# SCRIPT BELOW - DON'T EDIT
RESET=$(tput sgr0)
DATE_ANSI=$(tput setaf 4)
HEADER_ANSI="$(tput setaf 6)$(tput bold)"
ERROR_ANSI="$(tput setab 1)$(tput setaf 7)$(tput bold)"
log() {
echo "${DATE_ANSI}[`date -u`]${RESET}" "${HEADER_ANSI}[CloudFlare DDNS]${RESET} $@"
}
log_error() {
log "${ERROR_ANSI}[$1]${RESET}" "${@:2}"
}
if ! command -v jq &> /dev/null; then
log_error "Error" "jq is not installed."
exit 1
fi
if ! command -v curl &> /dev/null; then
log_error "Error" "curl is not installed."
exit 1
fi
api() {
local result;
result=$(curl -s -X $1 \
-H "Authorization: Bearer $CF_TOKEN" \
-H "Content-Type: application/json" \
--data "$3" \
"https://api.cloudflare.com/client/v4/zones/$CF_ZONE_ID/dns_records$2")
if [[ "$?" != "0" ]]; then
log_error "CURL Error" "Returned non-zero. Check your WAN connectivity."
exit 1
fi
if [[ $(echo "$result" | jq -r '.success') == "false" ]]; then
log_error "CloudFlare Error" "CloudFlare call did not succeed. Check credentials."
exit 1
fi
echo "$result"
}
UPDATES=false
IPV4=$(dig -4 TXT +short o-o.myaddr.l.google.com @ns1.google.com | awk -F'"' '{ print $2 }')
IPV6=$(dig -6 TXT +short o-o.myaddr.l.google.com @ns1.google.com | awk -F'"' '{ print $2 }')
RESULT=$(api GET "?name=$CF_RECORD")
if [[ "$?" != "0" ]]; then
echo "$RESULT"
exit 1
fi
RECORD_IPV4=$(echo "$RESULT" | jq -r '.result[] | select(.type == "A") | .content')
RECORD_IPV4_ID=$(echo "$RESULT" | jq -r '.result[] | select(.type == "A") | .id')
if [[ "$RECORD_IPV4_ID" == "" ]]; then
log "Warning: No A record found for $CF_RECORD. Skipped A update."
elif [[ "$RECORD_IPV4" != "$IPV4" ]]; then
IPV4_RESULT=$(api PUT "/$RECORD_IPV4_ID" "{\"id\":\"$RECORD_IPV4_ID\",\"type\":\"A\",\"proxied\":false,\"name\":\"$CF_RECORD\",\"content\":\"$IPV4\"}")
if [[ "$?" != "0" ]]; then
echo "$RESULT"
exit 1
fi
UPDATES=true
log "Updated A $CF_RECORD to $IPV4"
fi
RECORD_IPV6=$(echo "$RESULT" | jq -r '.result[] | select(.type == "AAAA") | .content')
RECORD_IPV6_ID=$(echo "$RESULT" | jq -r '.result[] | select(.type == "AAAA") | .id')
if [[ "$RECORD_IPV6_ID" == "" ]]; then
log "Warning: No AAAA record found for $CF_RECORD. Skipped AAAA update."
elif [[ "$RECORD_IPV6" != "$IPV6" ]]; then
IPV6_RESULT=$(api PUT "/$RECORD_IPV6_ID" "{\"id\":\"$RECORD_IPV6_ID\",\"type\":\"AAAA\",\"proxied\":false,\"name\":\"$CF_RECORD\",\"content\":\"$IPV6\"}")
if [[ "$?" != "0" ]]; then
echo "$RESULT"
exit 1
fi
UPDATES=true
log "Updated AAAA $CF_RECORD to $IPV6"
fi
if [[ "$UPDATES" == "false" ]]; then
log "No updates needed."
fi
@zikeji
Copy link
Author

zikeji commented Sep 12, 2020

I have it installed as a crontab in my $HOME/bin folder. My crontab looks like this:

TERM=xterm
*/5 * * * * $HOME/bin/cloudflare-ddns.sh >>$HOME/bin/.cloudflare-ddns.log 2>&1

Keep in mind because I'm using tput in the script to make it fancy you should set the TERM=xterm in either the script or the crontab. You could also change the formatting lines (at the top) to remove the tput reliance.

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