content/blog/2022-03-23-cloudflare-dns-api.org
192 lines · 7059 bytes
1 symbol in this file
Dynamic DNS Updates via the Cloudflare API
DDNS: Dynamic DNS
If you're hosting a service from a location with DDNS (Dynamic Domain Name System), where your internet protocol (IP)address may change at any time, you must have a solution to update the DNS (Domain Name System) so that you can access your service even when the IP of the server changes.
The process below uses the Cloudflare API (application programming interface) to
update DNS A and AAAA records with the server's current IP. If you use
another DNS provider, you will have to find a way to update your DNS (or find a
way to get a static IP).
First, install jq since we will use it in the next script:
sudo apt install jq
Next, create a location for your DDNS update scripts and open the first script:
mkdir ~/ddns
nano ~/ddns/update.sh
The following update.sh script will take all of your domains and subdomains
and check Cloudflare to see if the current A and AAAA records match your
server's IP address. If not, it will update the records.
# file: update.sh
#!/bin/bash
# Update TLDs
domains=(example.com example.net)
for domain in "${domains[@]}"
do
echo -e "\nUpdating $domain..."
zone_name=$domain /home/<your-username>/ddns/ddns.sh
done
# Update subdomains for example.com
domain=example.com
subdomains=(photos.example.com)
for subdomain in "${subdomains[@]}"
do
echo -e "\nUpdating $subdomain..."
zone_name=$domain dns_record=$subdomain /home/<your-username>/ddns/ddns.sh
done
Next, open up the ddns.sh script. Paste the following into the script and
update the api_token and email variables.
nano ~/ddns/ddns.sh
Note: If you want your DNS records to be proxied through Cloudflare, find and
update the following snippet: "proxied":false}" to say true instead of
false.
# file: ddns.sh
#!/bin/bash
# based on https://gist.github.com/Tras2/cba88201b17d765ec065ccbedfb16d9a
# initial data; they need to be filled by the user
## API token
api_token=<YOUR_API_TOKEN>
## email address associated with the Cloudflare account
email=<YOUR_EMAIL>
# get the basic data
ipv4=$(curl -s -X GET -4 https://ifconfig.co)
ipv6=$(curl -s -X GET -6 https://ifconfig.co)
user_id=$(curl -s -X GET "https://api.cloudflare.com/client/v4/user/tokens/verify" \
-H "Authorization: Bearer $api_token" \
-H "Content-Type:application/json" \
| jq -r '{"result"}[] | .id'
)
echo "Your IPv4 is: $ipv4"
echo "Your IPv6 is: $ipv6"
# check if the user API is valid and the email is correct
if [ $user_id ]
then
zone_id=$(curl -s -X GET "https://api.cloudflare.com/client/v4/zones?name=$zone_name&status=active" \
-H "Content-Type: application/json" \
-H "X-Auth-Email: $email" \
-H "Authorization: Bearer $api_token" \
| jq -r '{"result"}[] | .[0] | .id'
)
# check if the zone ID is
if [ $zone_id ]
then
# check if there is any IP version 4
if [ $ipv4 ]
then
dns_record_a_id=$(curl -s -X GET "https://api.cloudflare.com/client/v4/zones/$zone_id/dns_records?type=A&name=$dns_record" \
-H "Content-Type: application/json" \
-H "X-Auth-Email: $email" \
-H "Authorization: Bearer $api_token"
)
# if the IPv6 exist
dns_record_a_ip=$(echo $dns_record_a_id | jq -r '{"result"}[] | .[0] | .content')
echo "The set IPv4 on Cloudflare (A Record) is: $dns_record_a_ip"
if [ $dns_record_a_ip != $ipv4 ]
then
# change the A record
curl -s -X PUT "https://api.cloudflare.com/client/v4/zones/$zone_id/dns_records/$(echo $dns_record_a_id | jq -r '{"result"}[] | .[0] | .id')" \
-H "Content-Type: application/json" \
-H "X-Auth-Email: $email" \
-H "Authorization: Bearer $api_token" \
--data "{"type":"A","name":"$dns_record","content":"$ipv4","ttl":1,"proxied":false}" \
| jq -r '.errors'
else
echo "The current IPv4 and DNS record IPv4 are the same."
fi
else
echo "Could not get your IPv4. Check if you have it; e.g. on https://ifconfig.co"
fi
# check if there is any IP version 6
if [ $ipv6 ]
then
dns_record_aaaa_id=$(curl -s -X GET "https://api.cloudflare.com/client/v4/zones/$zone_id/dns_records?type=AAAA&name=$dns_record" \
-H "Content-Type: application/json" \
-H "X-Auth-Email: $email" \
-H "Authorization: Bearer $api_token"
)
# if the IPv6 exist
dns_record_aaaa_ip=$(echo $dns_record_aaaa_id | jq -r '{"result"}[] | .[0] | .content')
echo "The set IPv6 on Cloudflare (AAAA Record) is: $dns_record_aaaa_ip"
if [ $dns_record_aaaa_ip != $ipv6 ]
then
# change the AAAA record
curl -s -X PUT "https://api.cloudflare.com/client/v4/zones/$zone_id/dns_records/$(echo $dns_record_aaaa_id | jq -r '{"result"}[] | .[0] | .id')" \
-H "Content-Type: application/json" \
-H "X-Auth-Email: $email" \
-H "Authorization: Bearer $api_token" \
--data "{"type":"AAAA","name":"$dns_record","content":"$ipv6","ttl":1,"proxied":false}" \
| jq -r '.errors'
else
echo "The current IPv6 and DNS record IPv6 are the same."
fi
else
echo "Could not get your IPv6. Check if you have it; e.g. on https://ifconfig.co"
fi
else
echo "There is a problem with getting the Zone ID. Check if the Zone Name is correct."
fi
else
echo "There is a problem with either the email or the password"
fi
Once the script is saved and closed, make the scripts executable:
chmod +x ~/ddns/ddns.sh
chmod +x ~/ddns/update.sh
You can test the script by running it manually:
./update.sh
To make sure the scripts run automatically, add it to the cron file so that it
will run on a schedule. To do this, open the cron file:
crontab -e
In the cron file, paste the following at the bottom of the editor:
,*/5 ** ** ** ** bash /home/<your_username>/ddns/update.sh