Skip to content

Instantly share code, notes, and snippets.

@stefanpejcic
Forked from Ara4Sh/cloudflare-failover.sh
Created October 11, 2020 06:21
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save stefanpejcic/5c443c46539d5195f8893572b1edc924 to your computer and use it in GitHub Desktop.
Save stefanpejcic/5c443c46539d5195f8893572b1edc924 to your computer and use it in GitHub Desktop.
CloudFlare A records failover script using CloudFlare api v4 (https://api.cloudflare.com) required jq and curl to run.
#!/bin/bash
# Copyright (C) 2016 Arash Shams <https://github.com/Ara4Sh>.
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#Setting Environment
#set -o errexit
#set -o nounset
#set -o pipefail
#CloudFlare Configs
#CloudFlare API Key : https://www.cloudflare.com/a/account/my-account
CF_KEY=
#Zone Name : example.com
CF_ZONE=
#Zone Identifier
CF_ID=
#CloudFlare Username : user@example.com
CF_USER=
#Cloudflare TTL for record, between 120 and 86400 seconds
CF_TTL=
#Domain Name to check
DOMAIN=
#IP Addresses
A_IPS=()
#Get Params
while getopts k:z:i:u:t:d:a: opts; do
case ${opts} in
k) CF_KEY=${OPTARG} ;;
z) CF_ZONE=${OPTARG};;
i) CF_ID=${OPTARG} ;;
u) CF_USER=${OPTARG} ;;
t) CF_TTL=${OPTARG} ;;
d) DOMAIN=${OPTARG} ;;
a) A_IPS+=(${OPTARG}) ;;
esac
done
#Checking for Required Parameters
if [[ "$CF_KEY" = "" ]]; then
echo "Missing API Key, get at https://www.cloudflare.com/a/account/my-account"
echo "and save in ${0} or using -k flag"
exit 2
fi
if [[ "$CF_USER" = "" ]]; then
echo "Missing Username , its your Email address that registered in CloudFlare"
echo "and save in ${0} or using the -u flag"
exit 2
fi
if [[ "$CF_TTL" = "" ]]; then
echo "Missing TTL , Choose between 120 and 86400 seconds "
echo "Setting default TTL to 120"
CF_TTL=120
echo "You can specify TTL manually and save in ${0} or using the -t flag"
fi
if [[ "$CF_ZONE" = "" ]]; then
echo "Missing Zone parameter"
echo "Listing All Available zones (Make sure API is valid)"
curl -s -X GET "https://api.cloudflare.com/client/v4/zones" \
-H "X-Auth-Email: $CF_USER" \
-H "X-Auth-Key: $CF_KEY" \
-H "Content-Type: application/json" \
| jq -r '.result[].name'
echo "Please specify one of available zone in ${0} or specify using the -z flag"
exit 2
fi
if [[ "$DOMAIN" = "" ]]; then
echo "Missing Domain Name"
echo "Automatically set Domain name to $CF_ZONE"
DOMAIN=$CF_ZONE
echo "You can specify domain name manually in ${0} or using -d flag"
fi
if [[ "$CF_ID" = "" ]]; then
echo "Missing Zone Identifier"
echo "Set Automatically zone Identifier"
CF_ID=$(curl -s -X GET https://api.cloudflare.com/client/v4/zones?name=$CF_ZONE \
-H "X-Auth-Email: $CF_USER" \
-H "X-Auth-Key: $CF_KEY" \
-H "Content-Type: application/json" \
| jq -r '.result[].id')
echo "Zone Identifier is now $CF_ID"
if [[ -z $CF_ID ]]; then
echo "Problem in Automaticly set CF_ID"
echo "Please specify CF_ID in ${0} or specify using the -i flag"
fi
fi
if [[ "${#A_IPS[@]}" -eq 0 ]]; then
echo "Missing A Records"
echo "Please specify A_IPS in ${0} or specify using multiple -a flag"
echo "Listing Available A records"
curl -s -X GET "https://api.cloudflare.com/client/v4/zones/$CF_ID/dns_records?type=A&name=$DOMAIN" \
-H "X-Auth-Email: $CF_USER" \
-H "X-Auth-Key: $CF_KEY" \
-H "Content-Type: application/json" \
| jq -r '.result[].content'
exit 2
fi
check_domains() {
domain=$1
check_domain=$(curl -s -X GET "https://api.cloudflare.com/client/v4/zones" \
-H "X-Auth-Email: $CF_USER" \
-H "X-Auth-Key: $CF_KEY" \
-H "Content-Type: application/json" \
| jq -r '.result[].name'\
| grep -c $domain)
if [[ $check_domain -eq 0 ]]; then
echo "Error : $domain is not present in CloudFlare"
exit 2
fi
}
add_a_record() {
a_record=$1
check_a=$(curl -s -X GET "https://api.cloudflare.com/client/v4/zones/$CF_ID/dns_records?type=A&name=$DOMAIN" \
-H "X-Auth-Email: $CF_USER" \
-H "X-Auth-Key: $CF_KEY" \
-H "Content-Type: application/json" \
| jq -r '.result[].content' \
| grep -c $a_record)
if [[ $check_a -eq 0 ]]; then
curl -s -X POST "https://api.cloudflare.com/client/v4/zones/$CF_ID/dns_records" \
-H "X-Auth-Email: $CF_USER" \
-H "X-Auth-Key: $CF_KEY" \
-H "Content-Type: application/json" \
--data '{"type":"A","name":"'$DOMAIN'","content":"'$a_record'","ttl":'$CF_TTL'}' > /dev/null 2>&1
fi
}
delete_a_record() {
a_record=$1
REC_ID=$(curl -s -X GET "https://api.cloudflare.com/client/v4/zones/$CF_ID/dns_records?type=A&name=$DOMAIN&content=$a_record" \
-H "X-Auth-Email: $CF_USER" \
-H "X-Auth-Key: $CF_KEY" \
-H "Content-Type: application/json" \
| jq -r '.result[].id')
curl -s -X DELETE "https://api.cloudflare.com/client/v4/zones/$CF_ID/dns_records/$REC_ID" \
-H "X-Auth-Email: $CF_USER" \
-H "X-Auth-Key: $CF_KEY" \
-H "Content-Type: application/json" > /dev/null 2>&1
}
#Gathering Recordst
#A_RECS=($(curl -s -X GET "https://api.cloudflare.com/client/v4/zones/$CF_ID/dns_records?type=A&name=$DOMAIN" \
# -H "X-Auth-Email: $CF_USER" \
# -H "X-Auth-Key: $CF_KEY" \
# -H "Content-Type: application/json" \
# | jq -r '.result[].content'))
for ip in "${A_IPS[@]}"
do
CHK_REC=$(curl -s -m 2 -I "Host: $domain" $ip | head -n1 | grep -c 200)
if [[ $CHK_REC -eq 0 ]]; then
delete_a_record $ip
else
add_a_record $ip
fi
done
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment