2 min read

Update Cloudflare DNS entry

When a system is behind a NAT device that also has a dynamic WAN IP address, it may be necessary to dynamically update a DNS entry on your DNS server. This article shows how to do it by using a simple bash script.

For systems behind a NAT-ed IP, to dynamically change the DNS entry, follow these steps.

Step-by-step guide

  • Create a script:
#!/bin/bash
 
# A bash script to update a Cloudflare DNS A record with the external IP of the source machine
# Used to provide DDNS service for my home
# Needs the DNS record pre-creating on Cloudflare
 
# Proxy - uncomment and provide details if using a proxy
#export https_proxy=http://<proxyuser>:<proxypassword>@<proxyip>:<proxyport>
 
# Cloudflare zone is the zone which holds the record
zone=domain.com
# dnsrecord is the A record which will be updated
dnsrecord=name.domain.com
 
## Cloudflare authentication details
## keep these private
[email protected]
cloudflare_auth_key=somekey
 
 
# Get the current external IP address
ip=$(curl -s -X GET https://checkip.amazonaws.com)
 
echo "Current IP is $ip"
 
if host $dnsrecord 1.1.1.1 | grep "has address" | grep "$ip"; then
  echo "$dnsrecord is currently set to $ip; no changes needed"
  exit
fi
 
# if here, the dns record needs updating
 
# get the zone id for the requested zone
zoneid=$(curl -s -X GET "https://api.cloudflare.com/client/v4/zones?name=$zone&status=active" \
  -H "X-Auth-Email: $cloudflare_auth_email" \
  -H "X-Auth-Key: $cloudflare_auth_key" \
  -H "Content-Type: application/json" | jq -r '{"result"}[] | .[0] | .id')
 
echo "Zoneid for $zone is $zoneid"
 
# get the dns record id
dnsrecordid=$(curl -s -X GET "https://api.cloudflare.com/client/v4/zones/$zoneid/dns_records?type=A&name=$dnsrecord" \
  -H "X-Auth-Email: $cloudflare_auth_email" \
  -H "X-Auth-Key: $cloudflare_auth_key" \
  -H "Content-Type: application/json" | jq -r '{"result"}[] | .[0] | .id')
 
echo "DNSrecordid for $dnsrecord is $dnsrecordid"
 
# update the record
curl -s -X PUT "https://api.cloudflare.com/client/v4/zones/$zoneid/dns_records/$dnsrecordid" \
  -H "X-Auth-Email: $cloudflare_auth_email" \
  -H "X-Auth-Key: $cloudflare_auth_key" \
  -H "Content-Type: application/json" \
  --data "{\"type\":\"A\",\"name\":\"$dnsrecord\",\"content\":\"$ip\",\"ttl\":1,\"proxied\":true}" | jq
  • run the script with:
bash scriptname.sh
  • If successful, results will be similar to thi:
Current IP is XXX.XXX.XXX.XXX
Zoneid for domain.com is zoneid
DNSrecordid for name.domain.com is dnsrecordid
{
  "result": {
    "id": "id",
    "zone_id": "zoneid",
    "zone_name": "domain.com",
    "name": "name.domain.com",
    "type": "A",
    "content": "XXX.XXX.XXX.XXX",
    "proxiable": true,
    "proxied": true,
    "ttl": 1,
    "locked": false,
    "meta": {
      "auto_added": false,
      "managed_by_apps": false,
      "managed_by_argo_tunnel": false,
      "source": "primary"
    },
    "created_on": "2021-01-08T23:57:39.632266Z",
    "modified_on": "2021-01-08T23:57:39.632266Z"
  },
  "success": true,
  "errors": [],
  "messages": []
}

Following variables/parameters need to be adapted based on the CloudFlare API keys and DNS records settings:

zone=domain.com - this is the domain you want to update

dnsrecord=name.domain.com - this is the entry that you want to update

[email protected] - this is the email address used to register an account with CloudFlare

cloudflare_auth_key=somekey - this is your domain Global API key

Read more