From 0b27cbb9defc0ef95a5490b6610cb8a44e7951c4 Mon Sep 17 00:00:00 2001 From: ssn Date: Thu, 12 Mar 2026 20:38:26 +0100 Subject: [PATCH] Added bash & nushell versions --- fixDNS.nu | 30 ++++++++++++++++++++++++++++++ fixDNS.sh | 54 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 84 insertions(+) create mode 100644 fixDNS.nu create mode 100644 fixDNS.sh diff --git a/fixDNS.nu b/fixDNS.nu new file mode 100644 index 0000000..46b5afe --- /dev/null +++ b/fixDNS.nu @@ -0,0 +1,30 @@ +#!/usr/bin/env nu +#First stab at a nushell script, let's fix Cloudflare DNS +let timeStamp = date now | format date "%Y-%m-%dT%H:%M:%S" +let cfToken = "gbkanjmrKgCEqusC28anY3PNTrOdovurXTmbackA" +let myIp = http get https://api.ipify.org +let cfAPIBaseURI = "https://api.cloudflare.com/client/v4/" +let authHeader = { + Authorization: $"Bearer ($cfToken)" +} +let dnsZones = (http get $"($cfAPIBaseURI)zones" --headers $authHeader).result +#Iterate through the array of dnsZones +$dnsZones | each { + |zone| + #Get all the non-Tailscale A-records (those where the IP does not start with 100) that don't match $myIp + let badRecords = ((http get $"($cfAPIBaseURI)zones/($zone.id)/dns_records" --headers $authHeader).result | where type == "A" and content =~ "^(?!^100)" and content != $myIp) + $badRecords | each { + |badRecord| + #Update the DNS record to the correct IP + let recordBody = { + comment: $"($timeStamp) | Updated automatically from ($badRecord.content) to ($myIp)" + content: $"($myIp)" + } + let updateResult = (http patch $"($cfAPIBaseURI)zones/($zone.id)/dns_records/($badRecord.id)" $recordBody --headers $authHeader --content-type application/json) + if $updateResult.success { + print $"Successfully changed the DNS record for ($badRecord.name) from ($badRecord.content) to ($myIp)" + } else { + print $"Failed to change the DNS record for ($badRecord.name) from ($badRecord.content) to ($myIp)" + } + } +} | compact --empty #Don't output empty lists diff --git a/fixDNS.sh b/fixDNS.sh new file mode 100644 index 0000000..0482da3 --- /dev/null +++ b/fixDNS.sh @@ -0,0 +1,54 @@ +#!/bin/bash +#Handle Cloudflare DNS for my domains automatically +#But with a shell script instead of Powershell this time +timeStamp=$(date +"%Y-%m-%dT%H:%M:%S") +cfToken="gbkanjmrKgCEqusC28anY3PNTrOdovurXTmbackA" +myIp=$(curl "api.ipify.org" -s) +cfAPIBaseURI="https://api.cloudflare.com/client/v4/" +authHeader="Authorization: Bearer $cfToken" +zones=$(curl -X GET "${cfAPIBaseURI}zones" --header "$authHeader" -s) +#Stuff it all in a Bash array +readarray -t zoneArray < <(jq -c '.result.[]' <<< $zones) +# iterate through the Bash array +for zone in "${zoneArray[@]}"; do + zoneName=$(jq --raw-output '.name' <<< "$zone") + #echo $zoneName + zoneId=$(jq -r '.id' <<< "$zone") + #Pull the DNS records + dnsRecords=$(curl -X GET "${cfAPIBaseURI}zones/${zoneId}/dns_records" --header "$authHeader" -s) + #Stuff it all in a Bash array + readarray -t dnsRecordsArray < <(jq -c '.result.[]' <<< $dnsRecords) + # iterate through the Bash array + for dnsRecord in "${dnsRecordsArray[@]}"; do + dnsRecordType=$(jq -r '.type' <<< "$dnsRecord") + #A records only, pls + if [ $dnsRecordType == "A" ] + then + #Check the IP + dnsRecordIp=$(jq -r '.content' <<< "$dnsRecord") + #Never mind the TailScale ones and the ones matching myIp (The latter 'cause they don't need to be changed) + [[ "$dnsRecordIp" =~ ^100|$myIp ]] && continue || + #echo "Found a mismatch in the A record for zone ID ${zoneId}" + #Get the record ID + dnsRecordId=$(jq -r '.id' <<< "$dnsRecord") + comment="${timeStamp} | Updated automatically from ${dnsRecordIp} to ${myIp}" + content="${myIp}" + #Build a JSON array to send to Cloudflare as the request body + recordBody=$(jq -n -c \ + --arg comment "${comment}" \ + --arg content "${content}" \ + '{comment: $comment, content: $content}') + #Now send that body to Cloudflare so the changes are made + result=$(curl -X PATCH "${cfAPIBaseURI}zones/${zoneId}/dns_records/${dnsRecordId}" --header "$authHeader" --header "Content-Type: application/json" -d "${recordBody}" -s) + #Parse the JSON result + success=$(jq -r '.success' <<< "$result") + #echo $success + if [ $success ] + then + echo "Successfully updated the A record for ${zoneName} from ${dnsRecordIp} to ${myIp}" + else + echo "Failed to update the A record for ${zoneName} from ${dnsRecordIp} to ${myIp}" + fi + fi + done +done \ No newline at end of file