Introduction

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

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.

PPP

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.

Setup

  1. First, provided that you are signed-up with CloudFlare, go to your account page and grab the API key.
  2. Edit the script below to configure your zone.
  3. Drop the script in /etc/ppp/ip-up.d/ and /etc/ppp/ip-down.d/

and you are done.

Design

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.

Diagrams

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.

Limitations

  • DNS records usually take time to update, so the transition is certainly not instantaneous. For large websites, DNS will replicate quite fast, although that greatly depends on many factors.

Code

00030failover
#!/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

networking/cloudflare/cloudflare_failover.txt ยท Last modified: 2022/04/19 08:27 by 127.0.0.1

Access website using Tor Access website using i2p Wizardry and Steamworks PGP Key


For the contact, copyright, license, warranty and privacy terms for the usage of this website please see the contact, license, privacy, copyright.