Skip to content

Instantly share code, notes, and snippets.

@fffonion
Created September 5, 2017 01:27
Show Gist options
  • Save fffonion/8fabf5397c618458fc5cfa66f7cbc0da to your computer and use it in GitHub Desktop.
Save fffonion/8fabf5397c618458fc5cfa66f7cbc0da to your computer and use it in GitHub Desktop.
Dynamic DNS script using Cloudflare API v4 or CloudXNS API v2
#!/bin/bash
# can be A or AAAA
do_record=AAAA
# the interface to get ipv6 address
iface=eth0
# the static suffix we should add to
v6_suf=53
# cloudflare stuff
cf_mail="me@email.com"
cf_authkey="012345689abcdef0123456789abcdef012345"
# cloudxns stuff
cx_apikey="012345689abcdef0123456789abcdef"
cx_seckey="012345689abcdef0"
USE="cloudxns"
record=aaa.com
cachef=/tmp/ddns-$record
update () {
if [[ $USE = "cloudflare" ]]; then
cfupdate $@
else
cxupdate $@
fi
}
_cfapi() {
uri=$1
data=$@
if [[ -z $data ]]; then
curl -s -X GET "https://api.cloudflare.com/client/v4/$uri" \
-H "X-Auth-Email: $cf_mail" \
-H "X-Auth-Key: $cf_authkey" \
-H "Content-Type: application/json"
else
curl -s -X PUT "https://api.cloudflare.com/client/v4/$uri" \
-H "X-Auth-Email: $cf_mail" \
-H "X-Auth-Key: $cf_authkey" \
-H "Content-Type: application/json" \
--data "$data"
fi
}
cfupdate () {
_type=$1
_addr=$2
echo "Update $_type record for $record to $_addr"
ret=$(_cfapi "zones/$zoneid/dns_records/$recordid" "{\"type\":\"$_type\",\"name\":\"$record\",\"content\":\"$_addr\"}")
if [[ -z $(echo $ret|grep -oP "success\":[^\"]+"|grep true) ]]; then
echo $ret
else
echo "OK."
fi
}
_cxapi() {
uri=$1
data=$2
url="https://www.cloudxns.net/api2/$uri"
timestamp=$(date -R)
mac_raw="${cx_apikey}${url}${data}${timestamp}${cx_seckey}"
mac=$(echo -n $mac_raw | md5sum | awk '{print $1}')
if [[ -z $data ]]; then
curl -s -k $url \
-H "API-KEY:$cx_apikey" \
-H "API-REQUEST-DATE:$timestamp" \
-H "API-HMAC:$mac" \
-H "API-FORMAT:json"
else
curl -s -k -X PUT $url -d "$data" \
-H "API-KEY:$cx_apikey" \
-H "API-REQUEST-DATE:$timestamp" \
-H "API-HMAC:$mac" \
-H "API-FORMAT:json"
fi
}
cxupdate () {
_type=$1
_addr=$2
echo "Update $_type record for $record to $_addr"
_record=${record/.$domain/}
data="{\"domain_id\":$zoneid,\"host\":\"${_record}\",\"value\":\"$_addr\",\"type\":\"$_type\",\"ttl\":300,\"line_id\":1}"
ret=$(_cxapi "record/$recordid" "$data")
if [[ -z $(echo $ret|grep success) ]]; then
echo $ret
else
echo "OK."
fi
}
if [[ ! -e $cachef ]]; then
touch $cachef
fi
domain=$(echo $record |grep -oP "[^.]+\.[^.]+$")
if [[ $(cat $cachef|grep "id,"|wc -l) -eq 2 ]]; then
recordid=$(cat $cachef|grep "recordid,$do_record"|grep -oP "[a-f\d]{3,}")
zoneid=$(cat $cachef|grep zoneid|grep -oP "[a-f\d]{3,}")
else
if [[ $USE = "cloudflare" ]]; then
ret=$(_cfapi "zones?name=$domain" "")
zoneid=$(echo $ret|grep -oP "\"id\":\"[a-f\d]{32}"|grep -oP "[a-f\d]{32}"|head -n1)
ret=$(_cfapi "zones/$zoneid/dns_records?name=$record&type=$do_record" "")
recordid=$(echo $ret|grep -oP "\"id\":\"[a-f\d]{32}"|grep -oP "[a-f\d]{32}"|head -n1)
echo "recordid,$do_record,$recordid" >> $cachef
echo "zoneid,$zoneid" >> $cachef
else
ret=$(_cxapi "domain" "")
zoneid=$(echo $ret|grep -oP "id\":\"\d+\",\"domain\":\"$domain"|grep -oP "\d+"|head -n1)
_record=${record/.$domain/}
ret=$(_cxapi "host/$zoneid?host_name=$_record" "")
_hostid=$(echo $ret|grep -oP "id\":\"\d+\""|grep -oP "\d+"|head -n1)
ret=$(_cxapi "record/$zoneid?host_id=$_hostid" "")
recordid=$(echo $ret|grep -oP "id\":\"\d+\""|grep -oP "\d+"|head -n1)
echo "recordid,$do_record,$recordid" >> $cachef
echo "zoneid,$zoneid" >> $cachef
fi
fi
if [[ -z $recordid || -z $zoneid ]]; then
echo "Unable to get recordid or zoneid"
rm -f $cachef
exit 0
fi
if [[ $do_record = "A" ]]; then
addr_v4=$(curl ipip.tk/ip -4s)
if [[ -z $(cat $cachef|grep $addr_v4) ]]; then
sed -i "/v4,/d" $cachef
echo "v4,$addr_v4" >> $cachef
update "A" $addr_v4
fi
else
# check if we have ipv6 address
if [[ -z $(ifconfig $iface|grep inet6|grep -P "2[\da-f:]{4,}") ]]; then exit ; fi
addr_v6_prefix=$(curl ipip.tk/ip -6s|grep -oP "[\da-f]+:[\da-f]+:[\da-f]+:[\da-f]+"|cut -f1|head -n1 )
# check if we really can use ipv6
if [[ -z $addr_v6_prefix ]]; then exit; fi
addr_v6="$addr_v6_prefix::$v6_suf"
if [[ -z $(ifconfig $iface|grep $addr_v6) ]]; then
echo "Adding $addr_v6 to $iface"
ip -6 addr add $addr_v6/64 dev $iface
fi
if [[ -z $(cat $cachef|grep $addr_v6) ]]; then
sed -i "/v6,/d" $cachef
echo "v6,$addr_v6" >> $cachef
update "AAAA" $addr_v6
fi
fi
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment