Skip to content

Instantly share code, notes, and snippets.

@frgomes
Last active May 12, 2021
Embed
What would you like to do?
bash - sysadm - /usr/sbin/ddns-update
#!/bin/bash -eu
#######################################################################
## ##
## A simple, lightweight and self contained alternative to ddclient. ##
## ##
## NOTE: This script only works with HE FreeDNS http://dns.he.net ##
## ##
#######################################################################
#
# Configuration
# -------------
#
# Create a configuration file at: /etc/ddns/update.conf
# For example:
#
# password=secret
# iface=wlo1,inet,global,laptop.example.com
# iface=eth0,all,global,laptop-wired.example.com
# iface=eth1,inet6,link,laptop.local.example.com,another-password
# ipv4-prefix=ipv4-
# ipv6-prefix=
#
# which means:
#
# 1. define a default password for updating DDNS records;
# 2. update record laptop.example.com from IPv4 global scoped address from interface wlo1;
# 3. update record laptop.example.com from IPv4 and IPv6 global scoped addresses from interface eth0;
# 4. update record laptop.local.example.com from IPv6 link scoped address from interface eth1, employing a distinct password.
# 5. An IPv4 prefix "ipv4-" will be prepended to the fqdn when an IPv4 address is updated.
# 6. An IPv6 prefix "" (i.e.: nothing in this example) will be prepended to the fqdn when an IPv6 address is updated.
#
# What if you do not pass any information at all?
#
# It will grab the first interface which is UP, if any, assume all protocols, global scope and your FQDN.
#
#
# Installation
# ------------
#
# 1. Copy this script onto /usr/sbin/ddns-update
# 2. Remember to make it executable
# 3. Create an entry on /etc/crontab like this:
#
# 0,5,10,15,20,25,30,35,40,45,50,55 * * * * /usr/sbin/ddns-update
#
function ddns_update_record {
local iface=$1
local proto=$2
local scope=$3
local fqdn=$4
local password=$5
if [[ ! -z "$(ip link show dev ${iface} | head -1 | fgrep 'state UP')" ]] ;then
local myip=$(ip -${proto} address show dev ${iface} | fgrep "scope ${scope}" | head -1 | sed -r 's/[ \t]+/ /g' | cut -d' ' -f3 | cut -d/ -f1)
if [ ! -z "${myip}" ] ;then
echo /usr/bin/curl -${proto} -s "https://dyn.dns.he.net/nic/update" -d "myip=${myip}" -d "hostname=${fqdn}" -d "password=[HIDDEN]"
/usr/bin/curl -${proto} -s "https://dyn.dns.he.net/nic/update" -d "myip=${myip}" -d "hostname=${fqdn}" -d "password=${password}"
echo ""
else
echo "ERROR: could not find IPv${proto} address for interface ${iface}"
fi
fi
}
function ddns_update {
if [[ -f /etc/ddns-update.conf ]] ; then
local password=$(cat /etc/ddns-update.conf | fgrep password= | cut -d= -f2)
local ipv4prefix=$(cat /etc/ddns-update.conf | fgrep ipv4-prefix= | cut -d= -f2)
local ipv6prefix=$(cat /etc/ddns-update.conf | fgrep ipv6-prefix= | cut -d= -f2)
local hostname=$(hostname --fqdn)
if [[ $(cat /etc/ddns-update.conf | fgrep iface= | grep -v -E '^#' | wc -l) != 0 ]] ;then
cat /etc/ddns-update.conf | fgrep iface= | grep -v -E '^#' | while read line ;do
local args=$(echo "${line}" | cut -s -d= -f2)
# obtain parameters
local iface=$(echo "${args}" | cut -d, -f1)
local proto=$(echo "${args}" | cut -s -d, -f2)
local scope=$(echo "${args}" | cut -s -d, -f3)
local fqdn=$(echo "${args}" | cut -s -d, -f4)
local pass=$(echo "${args}" | cut -s -d, -f5)
# assume defaults
proto=${proto:-all}
scope=${scope:-global}
fqdn=${fqdn:-${hostname}}
pass=${pass:-${password}}
# handle protocol
if [[ "${proto}" == "all" ]] ;then
ddns_update_record ${iface} 4 ${scope} ${ipv4prefix}${fqdn} ${pass}
ddns_update_record ${iface} 6 ${scope} ${ipv6prefix}${fqdn} ${pass}
elif [[ "${proto}" == "inet" ]] ;then
ddns_update_record ${iface} 4 ${scope} ${ipv4prefix}${fqdn} ${pass}
elif [[ "${proto}" == "inet6" ]] ;then
ddns_update_record ${iface} 6 ${scope} ${ipv6prefix}${fqdn} ${pass}
else
echo "ERROR: unknown protocol ${proto}"
fi
done
else
local iface=$(ip link | fgrep 'state UP' | head -1 | cut -d' ' -f2 | cut -d: -f1)
if [[ ! -z "${iface}" ]] ;then
local scope=${scope:-global}
local fqdn=${fqdn:-${hostname}}
local pass=${pass:-${password}}
ddns_update_record ${iface} 4 ${scope} ${ipv4prefix}${fqdn} ${pass}
ddns_update_record ${iface} 6 ${scope} ${ipv6prefix}${fqdn} ${pass}
fi
fi
fi
}
# see: https://www.urbanautomaton.com/blog/2014/09/09/redirecting-bash-script-output-to-syslog/
exec 1> >(logger -s -t $(basename $0)) 2>&1
ddns_update
@frgomes

This comment has been minimized.

Copy link
Owner Author

@frgomes frgomes commented Aug 3, 2018

Create configuration file /etc/ddns-update.conf

$ echo password=secret | sudo tee /etc/ddns-update.conf
$ sudo chmod 400 /etc/ddns-update.conf

Create entry on /etc/crontab

$ echo "0,5,10,15,20,25,30,35,40,45,50,55 * * * * /usr/sbin/ddns-update" | sudo tee -a /etc/crontab
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment