Given a scenario where services are placed behind an Airport router that leases IP addresses dynamically from an ISP which in-turn are managed by CloudFlare one would wish to be able to update the CloudFlare A
record to point to the new address once the ISP leases a different IP address to the Airport router. This project presents a script based on SNMP that accesses both the Apple Airport router and CloudFlare in order to update the IP address.
snap
and snmp-mibs-downloader
./usr/share/snmp/mibs/
).
Download the script in the code section, configure the script by editing the parameters in the configuration section at the top and then place it in, say /etc/cron/cron.hourly
. The script is created such that it will not return any output in case the CloudFlare name already resolves to the Airport external address. However, the script will announce when the IP has been updated or in case there are any errors in attempting to do so.
#!/bin/sh ########################################################################### ## Copyright (C) Wizardry and Steamworks 2015 - License: GNU GPLv3 ## ## Please see: http://www.gnu.org/licenses/gpl.html for legal details, ## ## rights of fair usage, the disclaimer and warranty conditions. ## ########################################################################### # This script sets a zone's A record on CloudFlare to point to an Airport # basestation's external IP address and is meant to be run regularly. # # Requires a complete installation of SNMP along with relevant MIBs. # On Debian, the packages: snmp, snmp-mibs-downloader must be installed. # Airport MIB file must be downloaded from Apple and installed accordingly. ########################################################################### ## CONFIGURATION ## ########################################################################### # Airport IP or hostname AIRPORT_LOCAL_ADDRESS='192.168.0.1' # Set this to the cloudflare zone name. DOMAIN='slap.com' # Set this to the A record name. RECORD_NAME='forward.slap.com' # Set this to your account e-mail address. EMAIL='mongoose@whatever.tld' # Set this to your CloudFlare API key. API_KEY='1d10ab0dd09abfda6cc3dd0a92ca75de75671' ########################################################################### ## INTERNALS ## ########################################################################### AIRPORT_EXTERNAL_ADDRRESS=`snmpwalk \ -v1 \ -c public $AIRPORT_LOCAL_ADDRESS \ -m AIRPORT-BASESTATION-3-MIB \ RFC1213-MIB::ipAdEntAddr | \ head -1 | \ awk '{ print $4 }'` #echo $AIRPORT_EXTERNAL_ADDRRESS if [ -z $AIRPORT_EXTERNAL_ADDRRESS ]; then echo "Unable to retrieve Airport external address." echo "Please check that the Airport has SNMP enabled." exit 1 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=$DOMAIN") if [ -z $FLARE ]; then echo "Unable to retrieve CloudFlare zone." echo "Please check the API key." exit 1 fi ZONE_ADDRESS=`echo $FLARE | sed -E "s/.*,\"name\":\"$RECORD_NAME\",[^}]*?,\"type\":\"A\",[^}]*?,\"content\":\"([0-9\.]+?)\",.*/\1/"` if [ -z $ZONE_ADDRESS ]; then echo "Unable to retrieve the CloudFlare zone IP address." exit 1 fi # if the airport external address matches the zone address terminate if [ $AIRPORT_EXTERNAL_ADDRRESS = $ZONE_ADDRESS ]; then exit 0 fi RECORD_ID=`echo $FLARE | sed -E "s/.*\"rec_id\":\"([0-9]+?)\",[^}]*?,\"name\":\"$RECORD_NAME\",[^}]*?,\"type\":\"A\",.*/\1/"` if [ -z $RECORD_ID ]; then echo "Unable to retrieve CloudFlare record ID for the zone." exit 1 fi 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=$DOMAIN" \ -d 'type=A' \ -d "name=$RECORD_NAME" \ -d "content=$AIRPORT_EXTERNAL_ADDRRESS" \ -d 'service_mode=0' \ -d 'ttl=1') RESULT=`echo $FLARE | sed -E "s/.*,\"result\":\"([^\,]*?)\",.*/\1/"` if [ $RESULT = "success" ]; then echo "$RECORD_NAME now points to $AIRPORT_EXTERNAL_ADDRRESS" exit 0 fi exit 1