From 703cac8d18d8ef7a0da1b381522e3f0536c6e7b8 Mon Sep 17 00:00:00 2001 From: Rui Coelho Date: Mon, 29 Jan 2024 22:33:54 +0000 Subject: [PATCH] Use functions --- cloudflare-template.sh | 214 +++++++++++++++++++++-------------------- 1 file changed, 111 insertions(+), 103 deletions(-) diff --git a/cloudflare-template.sh b/cloudflare-template.sh index 32cbaa8..66b48b3 100644 --- a/cloudflare-template.sh +++ b/cloudflare-template.sh @@ -14,110 +14,118 @@ slackuri="" # URI for Slack WebHook "htt discorduri="" # URI for Discord WebHook "https://discordapp.com/api/webhooks/xxxxx" -########################################### -## Check if we have a public IP -########################################### -ipv4_regex='([01]?[0-9]?[0-9]|2[0-4][0-9]|25[0-5])\.([01]?[0-9]?[0-9]|2[0-4][0-9]|25[0-5])\.([01]?[0-9]?[0-9]|2[0-4][0-9]|25[0-5])\.([01]?[0-9]?[0-9]|2[0-4][0-9]|25[0-5])' -ip=$(curl -s -4 https://cloudflare.com/cdn-cgi/trace | grep -E '^ip'); ret=$? -if [[ ! $ret == 0 ]]; then # In the case that cloudflare failed to return an ip. - # Attempt to get the ip from other websites. - ip=$(curl -s https://api.ipify.org || curl -s https://ipv4.icanhazip.com) -else - # Extract just the ip from the ip line from cloudflare. - ip=$(echo $ip | sed -E "s/^ip=($ipv4_regex)$/\1/") -fi - -# Use regex to check for proper IPv4 format. -if [[ ! $ip =~ ^$ipv4_regex$ ]]; then - logger -s "DDNS Updater: Failed to find a valid IP." - exit 2 -fi - -########################################### -## Check and set the proper auth header -########################################### -if [[ "${auth_method}" == "global" ]]; then - auth_header="X-Auth-Key:" -else - auth_header="Authorization: Bearer" -fi - -########################################### -## Seek for the A record -########################################### - -logger "DDNS Updater: Check Initiated" -record=$(curl -s -X GET "https://api.cloudflare.com/client/v4/zones/$zone_identifier/dns_records?type=A&name=$record_name" \ - -H "X-Auth-Email: $auth_email" \ - -H "$auth_header $auth_key" \ - -H "Content-Type: application/json") - -########################################### -## Check if the domain has an A record -########################################### -if [[ $record == *"\"count\":0"* ]]; then - logger -s "DDNS Updater: Record does not exist, perhaps create one first? (${ip} for ${record_name})" - exit 1 -fi - -########################################### -## Get existing IP -########################################### -old_ip=$(echo "$record" | sed -E 's/.*"content":"(([0-9]{1,3}\.){3}[0-9]{1,3})".*/\1/') -# Compare if they're the same -if [[ $ip == $old_ip ]]; then - logger "DDNS Updater: IP ($ip) for ${record_name} has not changed." - exit 0 -fi - -########################################### -## Set the record identifier from result -########################################### -record_identifier=$(echo "$record" | sed -E 's/.*"id":"([A-Za-z0-9_]+)".*/\1/') - -########################################### -## Change the IP@Cloudflare using the API -########################################### -update=$(curl -s -X PATCH "https://api.cloudflare.com/client/v4/zones/$zone_identifier/dns_records/$record_identifier" \ - -H "X-Auth-Email: $auth_email" \ - -H "$auth_header $auth_key" \ - -H "Content-Type: application/json" \ - --data "{\"type\":\"A\",\"name\":\"$record_name\",\"content\":\"$ip\",\"ttl\":\"$ttl\",\"proxied\":${proxy}}") - -########################################### -## Report the status -########################################### -case "$update" in -*"\"success\":false"*) - echo -e "DDNS Updater: $ip $record_name DDNS failed for $record_identifier ($ip). DUMPING RESULTS:\n$update" | logger -s - if [[ $slackuri != "" ]]; then - curl -L -X POST $slackuri \ - --data-raw '{ - "channel": "'$slackchannel'", - "text" : "'"$sitename"' DDNS Update Failed: '$record_name': '$record_identifier' ('$ip')." - }' +validate_variables(){ + # Validate required variables + if [[ -z $auth_email || -z $auth_key || -z $zone_identifier || -z $record_name ]]; then + echo "Missing required variables. Please provide values for 'auth_email', 'auth_key', 'zone_identifier', and 'record_name'." + exit 1 + fi +} + +check_ipv4_is_available(){ + ipv4_regex='([01]?[0-9]?[0-9]|2[0-4][0-9]|25[0-5])\.([01]?[0-9]?[0-9]|2[0-4][0-9]|25[0-5])\.([01]?[0-9]?[0-9]|2[0-4][0-9]|25[0-5])\.([01]?[0-9]?[0-9]|2[0-4][0-9]|25[0-5])' + + ip=$(curl -s -4 https://cloudflare.com/cdn-cgi/trace | grep -E '^ip'); ret=$? + if [[ ! $ret == 0 ]]; then # In the case that cloudflare failed to return an ip. + # Attempt to get the ip from other websites. + ip=$(curl -s https://api.ipify.org || curl -s https://ipv4.icanhazip.com) + else + # Extract just the ip from the ip line from cloudflare. + ip=$(echo $ip | sed -E "s/^ip=($ipv4_regex)$/\1/") fi - if [[ $discorduri != "" ]]; then - curl -i -H "Accept: application/json" -H "Content-Type:application/json" -X POST \ - --data-raw '{ - "content" : "'"$sitename"' DDNS Update Failed: '$record_name': '$record_identifier' ('$ip')." - }' $discorduri + + # Use regex to check for proper IPv4 format. + if [[ ! $ip =~ ^$ipv4_regex$ ]]; then + logger -s "DDNS Updater: Failed to find a valid IP." + exit 2 fi - exit 1;; -*) - logger "DDNS Updater: $ip $record_name DDNS updated." - if [[ $slackuri != "" ]]; then - curl -L -X POST $slackuri \ - --data-raw '{ - "channel": "'$slackchannel'", - "text" : "'"$sitename"' Updated: '$record_name''"'"'s'""' new IP Address is '$ip'" - }' +} + +set_auth_headers(){ + if [[ "${auth_method}" == "global" ]]; then + auth_header="X-Auth-Key:" + else + auth_header="Authorization: Bearer" fi - if [[ $discorduri != "" ]]; then - curl -i -H "Accept: application/json" -H "Content-Type:application/json" -X POST \ - --data-raw '{ - "content" : "'"$sitename"' Updated: '$record_name''"'"'s'""' new IP Address is '$ip'" - }' $discorduri +} + + +check_if_a_record_exists(){ + logger "DDNS Updater: Check Initiated" + record=$(curl -s -X GET "https://api.cloudflare.com/client/v4/zones/$zone_identifier/dns_records?type=A&name=$record_name" \ + -H "X-Auth-Email: $auth_email" \ + -H "$auth_header $auth_key" \ + -H "Content-Type: application/json") + + if [[ $record == *"\"count\":0"* ]]; then + logger -s "DDNS Updater: Record does not exist, perhaps create one first? (${ip} for ${record_name})" + exit 1 fi - exit 0;; -esac +} + +get_current_ip_from_cloudflare(){ + old_ip=$(echo "$record" | sed -E 's/.*"content":"(([0-9]{1,3}\.){3}[0-9]{1,3})".*/\1/') + # Compare if they're the same + if [[ $ip == $old_ip ]]; then + logger "DDNS Updater: IP ($ip) for ${record_name} has not changed." + exit 0 + fi +} + +update_ip_on_cloudflare(){ + record_identifier=$(echo "$record" | sed -E 's/.*"id":"([A-Za-z0-9_]+)".*/\1/') + + + update=$(curl -s -X PATCH "https://api.cloudflare.com/client/v4/zones/$zone_identifier/dns_records/$record_identifier" \ + -H "X-Auth-Email: $auth_email" \ + -H "$auth_header $auth_key" \ + -H "Content-Type: application/json" \ + --data "{\"type\":\"A\",\"name\":\"$record_name\",\"content\":\"$ip\",\"ttl\":\"$ttl\",\"proxied\":${proxy}}") +} + +send_webhooks(){ + case "$update" in + *"\"success\":false"*) + echo -e "DDNS Updater: $ip $record_name DDNS failed for $record_identifier ($ip). DUMPING RESULTS:\n$update" | logger -s + if [[ $slackuri != "" ]]; then + curl -L -X POST $slackuri \ + --data-raw '{ + "channel": "'$slackchannel'", + "text" : "'"$sitename"' DDNS Update Failed: '$record_name': '$record_identifier' ('$ip')." + }' + fi + if [[ $discorduri != "" ]]; then + curl -i -H "Accept: application/json" -H "Content-Type:application/json" -X POST \ + --data-raw '{ + "content" : "'"$sitename"' DDNS Update Failed: '$record_name': '$record_identifier' ('$ip')." + }' $discorduri + fi + exit 1;; + *) + logger "DDNS Updater: $ip $record_name DDNS updated." + if [[ $slackuri != "" ]]; then + curl -L -X POST $slackuri \ + --data-raw '{ + "channel": "'$slackchannel'", + "text" : "'"$sitename"' Updated: '$record_name''"'"'s'""' new IP Address is '$ip'" + }' + fi + if [[ $discorduri != "" ]]; then + curl -i -H "Accept: application/json" -H "Content-Type:application/json" -X POST \ + --data-raw '{ + "content" : "'"$sitename"' Updated: '$record_name''"'"'s'""' new IP Address is '$ip'" + }' $discorduri + fi + exit 0;; + esac +} + +main(){ + validate_variables + check_ipv4_is_available + set_auth_headers + check_if_a_record_exists + get_current_ip_from_cloudflare + update_ip_on_cloudflare + send_webhooks +} \ No newline at end of file