Skip to content

Instantly share code, notes, and snippets.

@kernelkaribou
Last active May 14, 2024 21:31
Show Gist options
  • Save kernelkaribou/5bd4a1b845ad005df6ab595c55e7dbeb to your computer and use it in GitHub Desktop.
Save kernelkaribou/5bd4a1b845ad005df6ab595c55e7dbeb to your computer and use it in GitHub Desktop.
Used to regularly update a Cloudflare DNS record from your Synology NAS.
#!/bin/bash
####################################################################################
# Author: Kernelkaribou@github
#
# Purpose: Update a DNS record hosted at Cloudflare to represent network public IP.
# Based upon Cloudflare API v4
#
# Additional Notes: This will send notifications to Synology log center.
# Comment out writeLog lines if not desired or on Synology platform
#
# Last Update: 10/22/2022
####################################################################################
### User Defined
#Main domain zone e.g. example.com
ZONE_DOMAIN="example.com"
#DNS Record to update e.g. home.example.com
DNS_RECORD="record.example.com"
#API Key generated with Zone Read and DNS Edit permissions on above Main Zone, NOT A GLOBAL KEY!
API_KEY="MyCloudFlareDomainApiKey"
#Send message of execution to log center on Synology
writeLog()
{
LOG_MESSAGE=$(synologset1 sys $1 0x11800000 "Cloudflare DDNS - $2")
echo $2
}
### Main Script
#Get my public IP address
PUBLIC_IP=$(curl -s ifconfig.me)
#Get current DNS Record configured IP from Cloudflare
CURRENT_DNS_IP=$(nslookup -type=a $DNS_RECORD 1.1.1.1 | grep 'Address' | awk -F":" 'NF==2' | awk '{ if($2 !~ /#/){print $2}}')
#CHECK IF DNS Record matches Public IP
if [[ $CURRENT_DNS_IP == $PUBLIC_IP ]]; then
#IP Matches no need to continue
MESSAGE="$DNS_RECORD IP: $CURRENT_DNS_IP, Public IP: $PUBLIC_IP Match! No DNS update necessary!"
MESSAGE_TYPE="info"
writeLog "$MESSAGE_TYPE" "$MESSAGE"
else
MESSAGE="$DNS_RECORD IP $CURRENT_DNS_IP, Public IP: $PUBLIC_IP Mismatch! Updating!"
MESSAGE_TYPE="info"
writeLog "$MESSAGE_TYPE" "$MESSAGE"
#Getting Domain Zone ID
ZONE_RESULT=$(curl -s -X GET "https://api.cloudflare.com/client/v4/zones?name=$ZONE_DOMAIN" \
-H "Authorization: Bearer $API_KEY" \
-H "Content-Type: application/json")
ZONE_ID=$(echo $ZONE_RESULT | grep -oP "(?<={\"result\":\[{\"id\":\").*?(?=\",)")
echo "ZONE ID: $ZONE_ID"
if [ -z "$ZONE_ID" ]; then
MESSAGE="Unable to get ID for Zone '$ZONE_DOMAIN', check script configuration and API key"
MESSAGE_TYPE="err"
sendNotification "$NOTIFICATION"
writeLog "$MESSAGE_TYPE" "$MESSAGE"
echo $ZONE_RESULT
exit 1
fi
#Getting DNS Record ID
RECORD_RESULT=$(curl -s -X GET "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/dns_records?name=$DNS_RECORD" \
-H "Authorization: Bearer $API_KEY" \
-H "Content-Type: application/json")
DNS_ID=$(echo $RECORD_RESULT | grep -oP "(?<={\"result\":\[{\"id\":\").*?(?=\",)")
echo "DNS RECORD ID: $DNS_ID"
if [ -z "$DNS_ID" ]; then
MESSAGE="Unable to get ID for DNS Record '$DNS_RECORD', check script configuration and Zone ID"
MESSAGE_TYPE="err"
sendNotification "$NOTIFICATION"
writeLog "$MESSAGE_TYPE" "$MESSAGE"
echo $RECORD_RESULT
exit 1
fi
#Updating DNS record.
RESPONSE=$(curl -s -X PUT https://api.cloudflare.com/client/v4/zones/$ZONE_ID/dns_records/$DNS_ID \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $API_KEY" \
-H "cache-control: no-cache" \
-d "{\"type\" : \"A\", \"name\" : \"$DNS_RECORD\", \"content\" : \"$PUBLIC_IP\" }")
#Update failed
ERROR_STRING='"success":false,'
if [[ "$RESPONSE" == *"$ERROR_STRING"* ]]; then
ERROR_MESSAGE=""
if [[ $RESPONSE =~ \"errors\"\:[{.*[A-Za-z0-9].*}\] ]]; then
ERROR_MESSAGE=$(echo ${BASH_REMATCH[0]} | sed 's/[^a-z A-Z:0-9]/ /g')
else
ERROR_MESSAGE="Unable to parse error message"
fi
MESSAGE="DNS Record $DNS_RECORD error on update: $PUBLIC_IP - $ERROR_MESSAGE"
MESSAGE_TYPE="err"
#Update was successful
else
MESSAGE="DNS Record $DNS_RECORD successfully updated to $PUBLIC_IP"
MESSAGE_TYPE="info"
NOTIFICATION="$DNS_RECORD was successfully updated to $PUBLIC_IP"
fi
writeLog "$MESSAGE_TYPE" "$MESSAGE"
fi
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment