The script requires three information:
- Cloudflare API Token with the necessary permission
- Your DNS Zone ID
- Your DNS Record name & ID
Creating an API Token
To create the API Token required for this script, head down to My Profile from the top right corner, select API Tokens.
Choose Create Token, and use the Edit zone DNS template. The default template would allow editing any DNS records within your account. To further limit the Token’s permission, you can specify the specific domain name it could modify, and optionally include IP Address Filtering rules, if you happen to know the IP prefixes of the host.
Getting the Zone ID
You can get this dynamically via the script using the DNS name, if your API Token has the relevant read permissions. But I feel resolving that dynamically each time the script is run (i.e. every minute) is not necessary, as the resource ID is a static string that doesn’t change over time.
Head down to your Cloudflare portion, and click on the domain name. The Zone ID is in the URL:
https://dash.cloudflare.com/<Zone ID>/abc.com
The Zone ID is a 32-character hex string.
Getting the Record ID
Getting the Record ID is more involving. If you are using a Cloudflare Partner portal, you can obtain this from the partner site’s URL via a similar method as getting the Zone ID. Otherwise, you will have to do an API query to list all the DNS records in a zone, using the List DNS Records API. It is another 32-character hex string.
Putting everything together
#!/bin/bash
# CHANGE THESE
api_token="<API Token>"
zone="<Zone ID>"
record="<Record ID>"
dns_name="<DDNS name>"
ip=$(curl -s ifconfig.co)
ip_file="ip.txt"
log_file="cloudflare.log"
# LOGGER
log() {
if [ "$1" ]; then
echo -e "[$(date)] - $1" >> $log_file
fi
}
# SCRIPT START
log "Check Initiated"
if ! [[ "$ip" =~ ^([0-9]{1,3}\.){3}[0-9]{1,3}$ ]]; then
message="Fetched IP does not look valid! Quitting"
log "$message"
echo -e "$message"
exit 1
fi
if [ -f $ip_file ]; then
old_ip=$(cat $ip_file)
if [ $ip == $old_ip ]; then
echo "IP has not changed."
exit 0
fi
fi
update=$(curl -s -X PUT "https://api.cloudflare.com/client/v4/zones/$zone/dns_records/$record" -H "Authorization: Bearer $api_token" -H "Content-Type: application/json" --data "{\"type\":\"A\",\"name\":\"$dns_name\",\"content\":\"$ip\",\"ttl\":120}")
if [[ $update == *"\"success\":false"* ]]; then
message="API UPDATE FAILED. DUMPING RESULTS:\n$update"
log "$message"
echo -e "$message"
exit 1
else
message="IP changed to: $ip"
echo "$ip" > $ip_file
log "$message"
echo -e "$message"
fi
Finally, give the execute (+x) permission to the script, and set a crontab to execute it every 1 or 2 minutes, and you’re good to go!
Leave a Reply