Background I want to dynamically update my DNS A records from my DHCP server, both running on the same synology NAS. Unfortunately Synology has (still) not provided a working solution for this.
I have been using a shell script to accomplish this, but it seems to work imperfectly in that after a while (days, weeks) my DNS server does not resolve my local addresses anymore, most likely because the shell scripts puts the dns records in an incompatible order.
So..
Never mind, I found a different way than c# and mono to update my local dns dynamically.
The script I tried in the first place was the one I found here, but after a couple of days my local DNS queries did not work anymore for some unknown reason.
As it turns out the dhcp server on my Synology NAS (DS214Play) calls a bash script after leases have changed, in the location /usr/share/dhcpd/dhcpd-script.sh
After I found out you can actually change your (local) dns records easily using the nsupdate command, I updated the existing script to the one below. The lines I added are marked with my initials HH.
As for security on the dns update: I did not use a key, as my DNS server only accepts updates from the internal network and local host anyway.
If you found my answer useful, please also upvote the question if it's still negative. (I answered it myself) NOTE1: I found out that DSM updates may revert the file to its original NOTE2: Some of my markings were lost, so I updated the code below
#!/bin/sh
# Copyright (c) 2000-2013 Synology Inc. All rights reserved.
#HH20191123 Updated for dynamic DNS updates
DHCPD_DIR="/etc/dhcpd/"
LEASE_FILE="${DHCPD_DIR}/dhcpd.conf.leases"
LOG_FILE="${DHCPD_DIR}/dhcpd-leases.log"
TMP_FILE="${DHCPD_DIR}/tmp-dhcpd-leases.log"
# HH20191123: Define the zone (local domain name) here, but without a trailing point
ZONE_NAME="hhbhasenack.local"
# HH20191123: Prepare a file for updating the DNS through the nsupdate command
TMP_NSUPDATE="${DHCPD_DIR}/tmp-nsupdate.log"
NSUPDATE_LOG_FILE="${DHCPD_DIR}/nsupdate.log"
echo "server 127.0.0.1" > ${TMP_NSUPDATE}
echo "zone ${ZONE_NAME}." >> ${TMP_NSUPDATE}
del_leases() { # $2: mac
local mac=$2
grep -v "${mac}" ${LOG_FILE} > ${TMP_FILE}
cp ${TMP_FILE} ${LOG_FILE}
}
renew_record() { # $1: expired $2 mac $3 ip $4 hostname $5 iface
local record=$@
local mac=$2
local iface=$5
grep -v "${mac}" ${LOG_FILE} > ${TMP_FILE}
echo "${record}" >> ${TMP_FILE}
cp ${TMP_FILE} ${LOG_FILE}
#HH20191123: Prepare dns update command
local ip="$3"
local hostname="$4"
echo "update delete ${hostname}.${ZONE_NAME} A" >> ${TMP_NSUPDATE}
echo "update add ${hostname}.${ZONE_NAME} 3600 A ${ip}" >> ${TMP_NSUPDATE}
}
add_new_record() {
local record="$@"
local mac=$2
# when disable dhcp-server and any lease is expired, then next time the dhcp client
# renew the lease the action will be add, so remove the old record has same MAC address
grep -v "${mac}" ${LOG_FILE} > ${TMP_FILE}
cp ${TMP_FILE} ${LOG_FILE}
if [ -s ${LOG_FILE} ]; then
sed -i "1 i${record}" ${LOG_FILE}
else
echo ${record} >> ${LOG_FILE}
fi
#HH20191123: Prepare dns update command
local ip="$3"
local hostname="$4"
echo "update add ${hostname}.${ZONE_NAME} 3600 A ${ip}" >> ${TMP_NSUPDATE}
}
get_hostname_from_logfile() {
local mac="$1"
local filename="";
local line="`grep \"${mac}\" ${LOG_FILE}`"
local tokens=( $line )
if [ 5 -eq ${#tokens[@]} ]; then
filename=${tokens[3]}
fi
echo $filename
}
get_new_record() {
local mac="$2"
local ip="$3"
local hostname="$4"
local fileHostname=$(get_hostname_from_logfile $mac)
if [ "x" = "x${hostname}" ] && [ "xold" = "x${ACTION}" ];then
if [ "x" != "x${DNSMASQ_SUPPLIED_HOSTNAME}" ]; then
hostname=${DNSMASQ_SUPPLIED_HOSTNAME}
elif [ "x" != "x${fileHostname}" ]; then
hostname=${fileHostname}
fi
fi
NEW_RECORD="${DNSMASQ_LEASE_EXPIRES} ${mac} ${ip} ${hostname} ${DNSMASQ_INTERFACE}"
}
# record format: action mac ip hostname
NEW_RECORD=$@
ACTION=`echo ${NEW_RECORD} | awk '{print $1}'`
if [ "${DNSMASQ_INTERFACE}" = "" ]; then
exit 0
fi
get_new_record ${NEW_RECORD}
case "${ACTION}" in
old)
renew_record ${NEW_RECORD}
;;
add)
add_new_record ${NEW_RECORD}
;;
del)
del_leases ${NEW_RECORD}
;;
*)
;;
esac
#HH20191123: complete command file for nsupdate with a send command
echo "send" >> ${TMP_NSUPDATE}
#HH20191123: actually execute the nsupdate command
nsupdate ${TMP_NSUPDATE} >>${NSUPDATE_LOG_FILE}
exit 0