Script updates for DLink DDNS

This describes how to setup a Linux box to automatically update the DLink Dynamic DNS facility.

DLink offers a dynamic DNS service to it's customers.

If your router is directly connected to the Internet then the setup and configuration is very straight forward. Just use the product documentation to set it up.

If your router is not directly connected to the Internet then this may be of some help.

I have a DLink DSR-250 connecting to an upstream router. The upstream router NATs it's connection to the Internet. This results in the DSR-250 having a WAN IP like Not much help if you're using the built-in DDNS facility.

To work around this, I wrote a cron script that retrieves the public IP in use and compares it to the last value retrieved. If they are different then an update is sent to the DDNS server.

function updateDlinkDDNS() {
   typeset -i RTN_CODE=1
   readonly IPADDRESS="${1}"
   readonly TEMPLATE="UpdateDlinkDSR250IPAddress.template"
   readonly TEMPFILE="updateDlinkDDNS.$$"
   if [[ -f ${TEMPLATE} ]]; then
      sed -e "s/$1/" < ${TEMPLATE} >| ${TEMPFILE}
      cat ${TEMPFILE} | nc 80 >| response.$$
      if tail -1 response.$$ | grep -q good; then
         echo "$(date) Update from $(<myipaddress.existing) to $(<"
         cat response.$$ >&2
         echo "" >&2
      rm response.$$
      rm ${TEMPFILE}
      echo "Missing template file" >&2
   return ${RTN_CODE}
cd /home/jardine/Projects/UpdateDlinkDSR250IPAddress
if wget -qnv -O >>/dev/null; then
   if [[ ! -f myipaddress.existing ]]; then
      touch myipaddress.existing
   # Check if current IP address is different than existing IP address
   if ! diff myipaddress.existing >>/dev/null; then
      if updateDlinkDDNS "$(<"; then
         cp myipaddress.existing
      echo "$(date) No work. Previous IP $(<myipaddress.existing) is the same as current IP $(<"
   echo "$(date) Failed to get my own IP address. wget returned $?" >&2
fi >> UpdateDlinkDSR250IPAddress.stdout 2>> UpdateDlinkDSR250IPAddress.stderr

The real trick was to figure out what was being sent by the router. I used WireShark to capture an update from my router and saw this:

GET /nic/update?system=dyndns& HTTP/1.0
Authorization: Basic <Password Hash>
User-Agent: D-Link/DSR-250/1.09B32
Connection: close
Pragma: no-cache

I changed the IP address to "" and used it as a template file. The cron script does a search/replace with public IP.

Hints on finding the router update within the WireShark capture:

  • Capturing the right data
    • Start the capture
    • Configure DLinkDDNS on the router & save
    • Stop the capture
  • Search for DNS Lookups
    • Display Filter: (udp.dstport == 53)
    • Find a lookup for ""
    • Note the IP address in the response
  • Search for packets to the noted IP address
    • Display Filter: (ip.addr == ?)
    • Right-Click the first packet and Follow TCP Stream