The following article describes how to use CloudFlare to fail-over multiple IP addresses. Suppose that you have a server with multiple interfaces such as ppp0
and ppp1
and that they are both connected to the internet. Behind those interfaces, you have a server that is capable to listen to multiple addresses, for example, a web-server.
What we want to accomplish, is that when one of the interfaces goes down (ppp0
or ppp1
) the other interface should take over all the traffic from the interface that went down. For example, suppose that the server is a web-server capable of listening on all interfaces, both ppp0
and ppp1
, serving domain names for each interface.
When an interface goes down, the solution is to update the DNS records in order to point to the interface that is still up. Furthermore, if the downed interface comes back up, we want to update the records again so that the DNS records point back to the original IP address.
CloudFlare is an online DNS records manager - and more. It essentially acts as a nameserver for your zones. Sign-up is free of charge and managing the zones is also free of charge. Most importantly, CloudFlare has an API that allows you to manage the zones programmatically using a REST-like API.
We use that API in order to dynamically update and A-record on CloudFlare automatically when either of the interfaces (ppp0
or ppp1
) go up or down.
On Linux, specifically Debian, PPP connections use start and stop scripts that are placed in /etc/ppp/ip-up.d/
and /etc/ppp/ip-down.d/
which are run when an interface comes up, respectively when an interface goes down.
We thus create the script below, called 0030failover
and place it in both directories so it is run whenever an interface goes up and down.
/etc/ppp/ip-up.d/
and /etc/ppp/ip-down.d/
and you are done.
The script queries ifconfig
for the IP addresses supplied in the IPS
list. If one of those IP addresses is not found in the ifconfig
output, then it is skipped and the script proceeds to the next IP address.
If one of the addresses is found, the script first queries CloudFlare for the ID of the zone and then sets the DNS-A record to point to the IP address that it found and the script terminates.
The IPS
list in the script lists IPs in order of precedence. For example, if ppp0
is meant to have the IP address 63.143.64.40
, the script will first try to see whether that IP address is found to be up (by using ifconfig
). If it is not up, it will then proceed to the second IP address 24.165.34.50
. The reason for a precedence of IP addresses is that when the interface ppp0
comes back up again, the script will restore the IP address to what it was meant to be, in this case 63.143.64.40
and will not bother with the next fail-over address 24.165.34.50
.
Suppose that we have a web-server listening on two IP addresses 63.143.64.40
and 24.165.34.50
, each on the interfaces ppp0
and ppp1
.
The primary interface ppp0
is up and www.zone.com
is resolved by CloudFlare to the IP 63.143.64.40
. Also, ppp1
is up and is used for something else.
Now suppose that ppp0
dies:
Then the script first attempts to map www.zone.com
to 63.143.64.40
but since 63.143.64.40
is down, it sends a request to CloudFlare to map www.zone.com
to 24.165.34.50
.
Now, let's say that ppp0
comes back up:
and the script will restore the mapping of www.zone.com
to the original address 63.143.64.40
, freeing up the fail-over IP 24.165.34.50
.
#!/bin/bash ########################################################################### ## Copyright (C) Wizardry and Steamworks 2013 - License: GNU GPLv3 ## ## Please see: http://www.gnu.org/licenses/gpl.html for legal details, ## ## rights of fair usage, the disclaimer and warranty conditions. ## ########################################################################### ########################################################################### ## CONFIGURATION ## ########################################################################### # Set this to the cloudflare zone name. ZONE='zone.com' # Set this to the A record name. RECORD_NAME='www.zone.com' # Set this to your account e-mail address. EMAIL='support@zone.com' # Set this to your API key. API_KEY='336d5ebc5436534e61d16e63ddfca327' # This is a list of IPs to fail over. The preceedence # is from left to right. The script will attempt the # first address, then the second address, etc... IPS=( 63.143.64.40 24.165.34.50 ) ########################################################################### ## INTERNALS ## ########################################################################### for ip in "${IPS[@]}"; do IP=`ifconfig | grep $ip | grep 'inet addr:' | cut -d: -f2 | awk '{ print $1 }'` if [ -z $IP ]; then continue fi FLARE=$(curl -s https://www.cloudflare.com/api_json.html \ -d 'a=rec_load_all' \ -d "tkn=$API_KEY" \ -d "email=$EMAIL" \ -d "z=$ZONE") RECORD_ID=`echo $FLARE | sed -E "s/.*\"rec_id\":\"([0-9]+?)\",.*,\"zone_name\":\"($ZONE)\",.*,\"type\":\"A\",.*/\1/"` FLARE=$(curl -s https://www.cloudflare.com/api_json.html \ -d 'a=rec_edit' \ -d "tkn=$API_KEY" \ -d "id=$RECORD_ID" \ -d "email=$EMAIL" \ -d "z=$ZONE" \ -d 'type=A' \ -d "name=$RECORD_NAME" \ -d "content=$IP" \ -d 'service_mode=1' \ -d 'ttl=1') RESULT=`echo $FLARE | sed -E "s/.*,\"result\":\"(.*?)\",.*/\1/"` if [ $RESULT == "success" ]; then echo "A record for $RECORD_NAME updated to: $IP" exit 0 fi exit 1 done