Rolling your own dynamic DNS

First let me acknowledge that there are many ways to accomplish this. An easy solution for me would have been to simply use dyndns.com, no-ip.com, or one of the other commercial DDNS services supported by my router. For various reasons, I decided not to use one of those. Actually I did use duckdns.org for a while, but there were occasional issues that I got tired of dealing with.

I’m currently using Porkbun for DNS. They’re cheap, reliable, and have a decent user interface. They, like many other DNS services, also provide an API to make changes programmatically, without needing to log into their web site and make manual changes.

In my case, I have a shell script that runs as a cron job every 5 minutes. It checks my router for the WAN address and compares it to the last recorded address. If the two are not the same, it emails me and runs a Python script to update DNS.

I realize that some of this is pretty specific to my setup. Still, it might be a useful starting point. I found the Python script to update Porkbun DNS on their web site. The command to check the WAN IP address at the router may work for yours, or you may need to take a different approach.

#!/bin/bash

# Read the old IP address from a file.  The EOL will go into a variable we don't use.  This is necessary.
read OldIP b < /home/dale/myipaddress.txt
# Get our curent IP address from the router.
OUTFILE=~/myipstatus.txt
MyIP=`ssh -o StrictHostKeyChecking=no [username]@[router.ip] "ifconfig eth0 \
| grep inet | sed -e 's/.*addr:\([^ ]*\) .*/\1/'"`

while [[ $MyIP == "" ||  $MyIP == "192.168."*  ]] ; do
 sleep 10
 MyIP=`ssh -o StrictHostKeyChecking=no [username]@[router.ip] "ifconfig eth0 \
 | grep inet | sed -e 's/.*addr:\([^ ]*\) .*/\1/'"`
done

if [  "$OldIP" != "$MyIP" ] ; then
  echo "`date`" > $OUTFILE
  echo "Found new IP $MyIP, which is different from our previous $OldIP!" >> $OUTFILE
  echo "Updating Porkbun DNS entries..." >> $OUTFILE
  python3 ~/porkbun/porkbun-ddns.py ~/porkbun/config.json <mydomain.com> <hostname> >> $OUTFILE
  mail -s "IP address change detected" <myemail@domain.com>  < $OUTFILE
  echo $MyIP > ~/myipaddress.txt
else
 echo -n "." >> $OUTFILE
fi

In practice, this can result in a 5-10 minute lag between the time your IP address changes and the time your DNS is updated. If your ISP changes your IP address frequently, it may be too long. In my case, our ISP only changes our IP on rare occasions — typically less than once a year.

Again, there are other approaches, but most will not update DNS entries in your own domain. You can get around this to a certain extent by using CNAME entries, but this was the best way that I found to update my own domain’s DNS.