diff options
author | Christian Cleberg <hello@cleberg.net> | 2024-03-29 01:42:38 -0500 |
---|---|---|
committer | Christian Cleberg <hello@cleberg.net> | 2024-03-29 01:42:38 -0500 |
commit | 00b2726e0561f174393ae600f0f11adb8afebaab (patch) | |
tree | a4733d553ce68f64277ffa3a52f800dc58ff72de /content/blog/2022-03-23-cloudflare-dns-api.org | |
parent | 8ba3d90a0f3db7e5ed29e25ff6d0c1b557ed3ca0 (diff) | |
parent | 41bd0ad58e44244fe67cb36e066d4bb68738516f (diff) | |
download | cleberg.net-00b2726e0561f174393ae600f0f11adb8afebaab.tar.gz cleberg.net-00b2726e0561f174393ae600f0f11adb8afebaab.tar.bz2 cleberg.net-00b2726e0561f174393ae600f0f11adb8afebaab.zip |
merge org branch into main
Diffstat (limited to 'content/blog/2022-03-23-cloudflare-dns-api.org')
-rw-r--r-- | content/blog/2022-03-23-cloudflare-dns-api.org | 190 |
1 files changed, 190 insertions, 0 deletions
diff --git a/content/blog/2022-03-23-cloudflare-dns-api.org b/content/blog/2022-03-23-cloudflare-dns-api.org new file mode 100644 index 0000000..39d6fac --- /dev/null +++ b/content/blog/2022-03-23-cloudflare-dns-api.org @@ -0,0 +1,190 @@ +#+title: Dynamic DNS with Cloudflare API +#+date: 2022-03-23 +#+description: Learn how to dynamically update DNS records for changing IPs with Cloudflare. +#+filetags: :sysadmin: + +* DDNS: Dynamic DNS +If you're hosting a service from a location with dynamic DNS (where your +IP may change at any time), you must have a solution to update the DNS +so that you can access your service even when the IP of the server +changes. + +The process below uses the [[https://api.cloudflare.com/][Cloudflare +API]] 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: + +#+begin_src sh +sudo apt install jq +#+end_src + +Next, create a location for your DDNS update scripts and open the first +script: + +#+begin_src sh +mkdir ~/ddns +nano ~/ddns/update.sh +#+end_src + +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. + +#+begin_src sh +# 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 +#+end_src + +Next, open up the =ddns.sh= script. Paste the following into the script +and update the =api_token= and =email= variables. + +#+begin_src sh +nano ~/ddns/ddns.sh +#+end_src + +*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=. + +#+begin_src sh +# 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 +#+end_src + +Once the script is saved and closed, make the scripts executable: + +#+begin_src sh +chmod +x ~/ddns/ddns.sh +chmod +x ~/ddns/update.sh +#+end_src + +You can test the script by running it manually: + +#+begin_src sh +./update.sh +#+end_src + +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: + +#+begin_src sh +crontab -e +#+end_src + +In the cron file, paste the following at the bottom of the editor: + +#+begin_src sh +,*/5 ** ** ** ** bash /home/<your_username>/ddns/update.sh +#+end_src |