Skip to content

Instantly share code, notes, and snippets.

@riipandi
Last active January 15, 2022 23:20
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save riipandi/992f26381e0e3f9d9730baaef1fd4cd2 to your computer and use it in GitHub Desktop.
Save riipandi/992f26381e0e3f9d9730baaef1fd4cd2 to your computer and use it in GitHub Desktop.
Dynamic DNS Updater
#!/bin/bash
## Forked from https://github.com/K0p1-Git/cloudflare-ddns-updater
# Sample crontab per 6 hours: 0 */6 * * * /usr/bin/cloudflare-ddns-updater.sh
AUTH_METHOD="token" # Set to "global" for Global API Key or "token" for Scoped API Token
AUTH_EMAIL="CF_AUTH_EMAIL" # The email used to login 'https://dash.cloudflare.com'
AUTH_KEY="CF_AUTH_KEY" # Your API Token or Global API Key
ZONE_IDENTIFIER="CF_ZONE_ID" # Can be found in the "Overview" tab of your domain
RECORD_NAME="CF_RECORD_NAME" # Example: "sub.domain.com"
PROXY="false" # Set the proxy to true or false
TELEGRAM_BOT_KEY="TG_BOTKEY" # Telegram Bot Key
TELEGRAM_CHAT_ID="TG_CHATID" # Telegram Chat ID
sendTelegramNotification() {
if [[ $TELEGRAM_BOT_KEY != "" ]]; then
MESSAGE="*Cloudflare DDNS Updater:*
\`\`\`
Status : $1
Record : $2
Old IP : $3
New IP : $4
$5
\`\`\`"
TELEGRAM_API_URL="https://api.telegram.org/bot$TELEGRAM_BOT_KEY/sendMessage"
for user in "${TELEGRAM_CHAT_ID[@]}"; do
curl -Lsd "chat_id=$user&text=$MESSAGE&disable_web_page_preview=true&parse_mode=markdown" $TELEGRAM_API_URL >/dev/null 2>&1
done
fi
}
# ----------------------------------------------------------------------------------------
## Check if we have a public IP
# ----------------------------------------------------------------------------------------
ip=$(curl -s https://api.ipify.org || curl -s https://ipv4.icanhazip.com/)
if [ "${ip}" == "" ]; then
logger -s "DDNS Updater: No public IP found"
exit 1
fi
# ----------------------------------------------------------------------------------------
## Check and set the proper auth header
# ----------------------------------------------------------------------------------------
if [ "${AUTH_METHOD}" == "global" ]; then
auth_header="X-Auth-Key:"
else
auth_header="Authorization: Bearer"
fi
# ----------------------------------------------------------------------------------------
## Seek for the A record
# ----------------------------------------------------------------------------------------
logger -s "DDNS Updater: Check Initiated"
record=$(curl -s -X GET "https://api.cloudflare.com/client/v4/zones/$ZONE_IDENTIFIER/dns_records?type=A&name=$RECORD_NAME" \
-H "X-Auth-Email: $AUTH_EMAIL" \
-H "$auth_header $AUTH_KEY" \
-H "Content-Type: application/json")
# ----------------------------------------------------------------------------------------
## Check if the domain has an A record
# ----------------------------------------------------------------------------------------
if [[ $record == *"\"count\":0"* ]]; then
logger -s "DDNS Updater: Record does not exist, perhaps create one first? (${ip} for ${RECORD_NAME})"
exit 1
fi
# ----------------------------------------------------------------------------------------
## Get existing IP
# ----------------------------------------------------------------------------------------
old_ip=$(echo "$record" | sed -E 's/.*"content":"(([0-9]{1,3}\.){3}[0-9]{1,3})".*/\1/')
# Compare if they're the same
if [[ $ip == $old_ip ]]; then
logger -s "DDNS Updater: IP ($ip) for ${RECORD_NAME} has not changed."
exit 0
fi
# ----------------------------------------------------------------------------------------
## Set the record identifier from result
# ----------------------------------------------------------------------------------------
record_identifier=$(echo "$record" | sed -E 's/.*"id":"(\w+)".*/\1/')
# ----------------------------------------------------------------------------------------
## Change the IP@Cloudflare using the API
# ----------------------------------------------------------------------------------------
update=$(curl -s -X PATCH "https://api.cloudflare.com/client/v4/zones/$ZONE_IDENTIFIER/dns_records/$record_identifier" \
-H "X-Auth-Email: $AUTH_EMAIL" \
-H "$auth_header $AUTH_KEY" \
-H "Content-Type: application/json" \
--data "{\"type\":\"A\",\"name\":\"$RECORD_NAME\",\"content\":\"$ip\",\"ttl\":\"3600\",\"proxied\":${PROXY}}")
# ----------------------------------------------------------------------------------------
## Send notification via Telegram
# ----------------------------------------------------------------------------------------
case "$update" in
*"\"success\":false"*)
parsedResult=$(echo "$update" | jq)
logger -s "Failed to update Cloudflare DNS record for ${RECORD_NAME} to $ip."
if [[ $TELEGRAM_BOT_KEY != "" ]]; then
sendTelegramNotification "Failed" "${RECORD_NAME}" "$old_ip" "$ip" "$parsedResult"
fi
exit 1;;
*)
parsedResult=$(echo "$update" | jq)
logger -s "Success updated Cloudflare DNS record for ${RECORD_NAME} to $ip."
if [[ $TELEGRAM_BOT_KEY != "" ]]; then
sendTelegramNotification "Success" "${RECORD_NAME}" "$old_ip" "$ip"
fi
exit 0;;
esac
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment