Skip to content

Instantly share code, notes, and snippets.

@luginbash
Last active May 1, 2019 00:41
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save luginbash/7c9dac4653855df1a2c1 to your computer and use it in GitHub Desktop.
Save luginbash/7c9dac4653855df1a2c1 to your computer and use it in GitHub Desktop.
Dynamic DNS endpoint IP address update script with Mikrotik router
#!/bin/bash
function snmpGetIP
{
local SNMP_HOST=$1
local SNMP_COMM=$2
local SNMP_IFID=$3
snmpwalk -Os -c ${SNMP_COMM} -v 2c ${SNMP_HOST} ipAdEntIf | grep "INTEGER: ${SNMP_IFID}" | grep -o '[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}'
}
function cfGetZone
{
curl -sX "GET" "https://api.cloudflare.com/client/v4/zones/" \
-H "X-Auth-Key: ${cfSecret}" \
-H "Content-Type: application/json" \
-H "X-Auth-Email: ${cfLogin}" -o ${TEMP_DIR}/zone.json
}
function cfGetZoneId
{
cfDomain=$1
jq -r '.result[]|select(.name=="'${cfDomain}'")|.id' \
$TEMP_DIR/zone.json
}
function cfGetRecords
{
cfZoneId=$1
curl -sX GET "https://api.cloudflare.com/client/v4/zones/${cfZoneId}/dns_records?type=A" \
-H "X-Auth-Email: ${cfLogin}" \
-H "X-Auth-Key: ${cfSecret}" \
-H "Content-Type: application/json" \
-o $TEMP_DIR/records.json
}
function cfGetRecordId
{
local recName=$1
jq -r ".result|.[]|select(.name == \"${recName}.${cfDomain}\")|.id" $TEMP_DIR/records.json
}
function cfPushRecord
{
local cfZoneId=$1
local cfRecordId=$2
local recName=$3
local recVal=$4
t_exec=$(date -u +%s)
validateStr=$t_exec\ \#$(sha1sum <<< $t_exec|cut -c-8)
curl -sX "PUT" "https://api.cloudflare.com/client/v4/zones/${cfZoneId}/dns_records/${cfRecordId}" \
-H "X-Auth-Key: ${cfSecret}" \
-H "Content-Type: application/json" \
-H "X-Auth-Email: ${cfLogin}" \
-d "{\"type\":\"A\",\"name\":\"$recName\",\"content\":\"$recVal\",\"proxied\":false,\"ttl\":120}" \
-o $TEMP_DIR/result.json
echo $validateStr
}
function cfPushTxtRecord
{
local cfZoneId=$1
local cfRecordId=$2
local recName=$3
local recVal=$4
curl -sX "PUT" "https://api.cloudflare.com/client/v4/zones/${cfZoneId}/dns_records/${cfRecordId}" \
-H "X-Auth-Key: ${cfSecret}" \
-H "Content-Type: application/json" \
-H "X-Auth-Email: ${cfLogin}" \
-d "{\"type\":\"TXT\",\"name\":\"$recName\",\"content\":\"$recVal\",\"proxied\":false,\"ttl\":120}" \
-o $TEMP_DIR/txt.json
}
function cleanUp
{
rm -rf ${TEMP_DIR}
}
#!/usr/bin/env bash
# Dynamic DNS endpoint IP address update script with Mikrotik
# This script uses ssh to get IP address from Mikrotik router
# The hostname(subdomains) parts has to be stored as global
# variables FIRST.
#
# To setup on a Mikrotik:
# https://gist.github.com/methou/f9622e6cc15b5055096e
#
# only current user can rw intermediate files genereated by this script
umask 066
# CloudFlare Configuration
# Secret
tkn=<api key>
# cloudflare login, must be an email address
email=<email address>
# domain name, naked.
domain=<domain name>
# subdomains, please remember set up on the Mikrotik router side
# e.g. subdomains=("a01" "a02" "a03" "a04")
# for a01.example.org etc.
subdomains=<an array of subdomains>
# Router Configuraion
mikrotikHost="192.168.88.1"
# SSH Port number
PORT=22
TEMP_DIR=$(mktemp -d) # create a temp only us can rw from/to
# source functions
. ./functions.sh
# int main(){ ... }
NUM_CHG=0
# compare first IP
for i in $(seq ${#cfRecordNames[*]}); do
sampleIpAddr=$(snmpGetIP ${mkHostIp} ${mkSnmpCommunity} ${mkSnmpIfId[$i-1]})
recordIpAddr=$(dig @$nameServer +adflag +short ${cfRecordNames[i-1]}.$cfDomain)
# echo -e "${mkSnmpIfId[i-1]}:\t rec:${recordIpAddr}\tsampled:${sampleIpAddr}"
if [[ ${sampleIpAddr} == ${recordIpAddr} ]]; then
echo -e "(${cfRecordNames[i-1]}: NOCHG, no need to update)"
else
((NUM_CHG+=1))
fi
done
#echo $NUM_CHG
if [ ${NUM_CHG} -ge 1 ] || [[ ${1:-auto} != "auto" ]] ; then
exit 1
echo "Mismatch found, updating..."
cfGetZone
zoneId=$(cfGetZoneId ${cfDomain})
cfGetRecords ${zoneId}
for i in $(seq ${#cfRecordNames[*]}); do
thisRecId=$(cfGetRecordId ${cfRecordNames[i-1]})
#thisTxtRecId=$(cfGetRecordId _${cfRecordNames[i-1]})
thisIpAddr=$(snmpGetIP ${mkHostIp} ${mkSnmpCommunity} ${mkSnmpIfId[i-1]})
thisFqdn=${cfRecordNames[i-1]}\.${cfDomain};
validateStr=$(cfPushRecord ${zoneId} ${thisRecId} ${cfRecordNames[i-1]} ${thisIpAddr})
#cfPushTxtRecord ${zoneId} ${thisTxtRecId} _${cfRecordNames[i-1]} "${validateStr}"
done
cleanUp
else
exit -1
echo "(All NOCHG: no need to update at all)"
fi
@zhentianxincun
Copy link

zhentianxincun commented Apr 22, 2018

update.sh functions.sh and hostIp.func.rsc, the three seem to have no connection, how to use? There are no common global variable between them.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment