Using nsupdate to update a DNS server using docker

Summary

This sets up a continual check (using cron) to obtain the current external IP, and if it has changed from the last check, update the remote dns server (that you need full access to). Notes do not as yet show how to set up the dns server and certs.

Suggestions for simplifying welcome, maybe holding the current IP address in memory might be useful, and with busybox I need to make a few changes to the date comparisons if I want to eliminate the need for coreutils.

I also plan to get it to publish to my MQTT server, so along with my network speed tests I can see when/how often the IP address changes.

In the config directory, will be the nsupdater.sh script (below), the cronjobs file (below), and the K key file(s) that are generated for the name service (not shown).

dockerfile

FROM alpine:3.12

# Make the app directory
RUN mkdir -p /app
RUN apk add --no-cache bind-tools coreutils

# Copy nsupdate script and make only root executable
COPY config/nsupdater.sh /app
RUN chmod 0744 /app/nsupdater.sh

# Copy nameserver certificates
COPY config/K* /app/

# Copy crontabs for root user
COPY config/cronjobs /etc/crontabs/root
# Start crond with log level 8 in foreground, output to stderr
CMD ["crond", "-f", "-d", "8"]

docker-compose.yml file

---
version: '3.3'
services:
    nsupdater:
        container_name: nsupdater
        hostname: nsupdater
        build: .
        volumes:
            - "/dockervolumes/nsupdater/data:/data"
            - "/etc/localtime:/etc/localtime:ro"
            - "/etc/timezone:/etc/timezone:ro"
        restart: unless-stopped

./config/cronjobs file

# Crontab, check IP address every 10 mins
*/10 * * * * /app/nsupdater.sh 2>&1

./config/nsupdater.sh file

#! /bin/sh
 
# modified: 2020-10-22 (dockerizing, zorruno)
# modified: 2020-08-28 05:21:31 (toaster/karlmw)
 
#==========================================================================
# Config and setup
SERVER="myserver.mydomain.com"
DOMAIN="home.mydomain.com"
 
# data directory for keys, logs, cache
DATA_DIR="/data"
[ -d "${DATA_DIR}" ] || /bin/mkdir -p "${DATA_DIR}"
 
# where our keys are stored
KEY_DIR="/app"
# the key filename might need fiddling
KEY="${KEY_DIR}/K${DOMAIN}.+123+45678.key"
 
# logfile
LOG="${DATA_DIR}/${DOMAIN}.log"
 
# cache for last IP
CACHE="${DATA_DIR}/${DOMAIN}.IP_cache.txt"
[ -r "${CACHE}" ] || touch "${CACHE}"
 
#==========================================================================
 
# lookup last IP we had
CACHED_IP="$(cat "${CACHE}")"
 
# get our current external IP address
EXT_IP=$(/usr/bin/dig @resolver1.opendns.com ANY myip.opendns.com +short 2>/dev/null)
[ "$EXT_IP" ] || {
   MSG="dig failed"
   echo "$(/bin/date +"%F %T"): ${MSG}" >> "${LOG}"
   exit 0
}
 
# uncomment to debug
#echo "External IP: $EXT_IP"
 
MSG=
if [ "${CACHED_IP}" != "${EXT_IP}" ]; then
   MSG="new IP: ${EXT_IP}"
   echo "${EXT_IP}" > "${CACHE}"
fi
 
if [ ! "${MSG}" ]; then
   # check if we've not updated for a while
   if [ $(/bin/date +%s -r "${CACHE}") -lt $(/bin/date +%s --date="7 days ago") ]; then
      MSG="refreshing existing IP: ${EXT_IP}"
      touch "${CACHE}"
   fi
fi
 
if [ "${MSG}" ]; then
   echo "$(/bin/date +"%F %T"): ${MSG}" >> "${LOG}"
   echo "${MSG}"
 
   cat <<EOF | /usr/bin/nsupdate -k "$KEY"
server $SERVER
zone $DOMAIN
update delete ${DOMAIN}. A
update add ${DOMAIN}. 60 A $EXT_IP
send
EOF

Leave a Reply

Your email address will not be published. Required fields are marked *

Post comment