Dynamic DNS Script

Hi folks - using MIAB to host my personal domains and absolutely love it! One thing I needed a little help with was some dynamic DNS capabilities…

Long story short - MIAB hosts one of my domains for email & web, but I wanted to have a subdomain I could use to access my VPN & NAS servers at home.

So, I wrote a shell script that runs on my pfSense gateway at home, which updates the subdomain records on the MIAB.

For Example:
box.mydomain.com (my MIAB) / IP address 1.2.3.4 hosts:
www.mydomain.com
mail.mydomain.com

But I want vpn.mydomain.com and nas.mydomain.com to point to 5.6.7.8 (which is my home, dynamic IP).

So I run the attached shell script via cron on my pfSense gateway, and it will update the vpn.mydomain.com and nas.mydomain.com entries on the MIAB whenever my IP address changes.

Make sense?

Hope this is useful for someone – it is for me!

Thanks,

–Dennis

--------- CONTENTS OF dm-dyndns.sh below ---------
#!/bin/sh
# dm-dyndns v1.0, dmurphy@dmurphy.com
# Shell script to provide dynamic DNS to a mail-in-the-box platform.
# Requirements:
# dig installed
# curl installed
# OpenDNS myip service availability (myip.opendns.com)
# Mailinabox host (see https://mailinabox.email)
# Mailinabox admin username/password in the CFGFILE below
# one line file of the format (curl cfg file):
# user = “username:password”
# Dynamic DNS name to be set
# DYNDNSNAMELIST file contains one hostname per line that needs to be set to this IP.

MYNAME="dm-dyndns"
CURRENTIPFILE="$MYNAME.ip"
CFGFILE="$MYNAME.cfg"
DIGCMD="/usr/local/bin/dig"
CURLCMD="/usr/local/bin/curl"
CATCMD="/bin/cat"
DOMAIN="mydomain.com"
MIABHOST="box.$DOMAIN"
DYNDNSNAMELIST="$MYNAME.dynlist"

if [ ! -x $DIGCMD ]; then
  echo "$MYNAME: dig command $DIGCMD not found.  Check and fix please."
  exit 99
fi

if [ ! -x $CURLCMD ]; then
  echo "$MYNAME: curl command $CURLCMD not found.  Check and fix please."
  exit 99
fi

if [ ! -x $CATCMD ]; then
  echo "$MYNAME: cat command $CATCMD not found.  Check and fix please."
  exit 99
fi

if [ ! -f $CFGFILE ]; then
  echo "$MYNAME: $CFGFILE not found.  Check and fix please."
  exit 99
fi

if [ ! -f $DYNDNSNAMELIST ]; then
   echo "$MYNAME: $DYNDNSNAMELIST not found.  Check and fix please."
   exit 99
fi

MYIP="`$DIGCMD +short myip.opendns.com @resolver1.opendns.com`"

  if [ -z "$MYIP" ]; then
    echo "$MYNAME: dig output was blank.  Check myip.opendns.com services."
    exit 99
  fi

for DYNDNSNAME in `$CATCMD $DYNDNSNAMELIST`
do
  PREVIP="`$DIGCMD +short $DYNDNSNAME @$MIABHOST`"
  if [ -z "$PREVIP" ]; then
    echo "$MYNAME: dig output was blank.  Check $MIABHOST DNS server."
    exit 99
  fi

    if [ "x$PREVIP" = "x$MYIP" ]; then
      echo "$MYNAME: $DYNDNSNAME hasn't changed."
    else
      echo "$MYNAME: $DYNDNSNAME changed (previously: $PREVIP, now: $MYIP)"
  STATUS="`$CURLCMD -X PUT -K $CFGFILE -s -d $MYIP https://$MIABHOST/admin/dns/custom/$DYNDNSNAME`"
  case $STATUS in
     "OK") echo "$MYNAME: mailinabox API returned OK, cmd succeded but no update.";;
     "updated DNS: $DOMAIN") echo "$MYNAME: mailinabox API updated $DYNDNSNAME OK.";;
     *) echo "$MYNAME: other status from mailinabox API. Please check.";;
     esac

    fi
done
    exit 0

----- Contents of dm-dyndns.cfg file below -----
user = "admin@mydomain.com:MYADMINPASSWORD"

------ Contents of dm-dyndns.dynlist below -----
vpn.mydomain.com
nas.mydomain.com

4 Likes

Have you tried my Dynamic DNS script? https://github.com/mitchellurgero/mailinabox_dynamic_dns_script

Written in PHP it allows end users to create and delete DNS entries (A records only right now). With domain checking (allowing users to only delete the domains they add.) it’s alright for internal use. Probably not secure for use by external users.

1 Like

Thanks Mitchell! Your PHP script is a little different use case, in that it allows end users to login and create their own A records, etc. Mine is a quick and dirty hack to allow my firewall to automatically update some entries if/when my home IP address changes. I wanted something no-touch so when my ISP changes my IP address, the DNS entries get automatically updated. Right now I have cron running my script every 10 minutes, so if my IP address changes, within 10 minutes, the A records will catch up. That’s good enough for my simple use!

Great job working on your PHP scripts; you’ve got a nice GUIfied interface to allow self-support for end users. Mine is a quick and dirty hack to solve my corner case!

Thanks!

–Dennis

3 Likes

Hoping this works out well. I have static IP at first ISP & dynamic on standby from dual wan Merlin router. Will attempt this evening.

Works fine :+1: I decided to keep the script on my server hosting the services.

1 Like

Awesome! So glad it’s working for you… it’s saved my bacon when traveling more than once. Enjoy the weekend!

1 Like

Here is another quick and dirty hack to access your home box, if you don’t necessarily need end users to access it, you just need the IP… I run basically the following in a cron job, output it to a sync’ed nextcloud directory… My address doesn’t change often (I just stick it with a name in .ssh/config for my purposes), but I can just look here on my other sync’ed systems to find it (I could theoretically write a cron job to keep a hosts file updated with the IP in this sync’ed directory if I wanted)

IP=$(/usr/bin/curl http://checkip.dyndns.org/ )
echo $IP| cut -d “>” -f 7 |cut -d “<” -f1 > /home/jay/ownCloud/home_ip.txt

Even better:

IP=$(/usr/bin/curl http://icanhazip.com) && echo $IP > /home/jay/ownCloud/ip.txt

One liners always better :wink:

2 Likes

Here’s something similar that I hacked together for the sake of sharing. I just run it in rc.local on all my VMs but cron might be better. There is no automated cleanup, so if you take a system out of production you need to cleanup manually. Make sure you set permissions on files in rc.local.d. I have mine set to root access only.

--------------------- rc.local

#!/bin/bash

# get userid, password, and public name for server
# multiple names can map to the same server

for file in /etc/rc.local.d/*
do
  read -r machine server login username secret password <"$file"
  sitename=`basename $file`

  # set IPv4 and IPV6 names; comment out what you don't want to set
  curl -4 -X PUT --netrc-file $file https://$server/admin/dns/custom/$sitename/A
  curl -6 -X PUT --netrc-file $file https://$server/admin/dns/custom/$sitename/AAAA
done

For the files in rc.local.d, name them the FDQN of what you want to set. Example name the file “home.example.com”. Add as many files as you want to create aliases. You can even set on multiple separate MIAB “boxes” by changing the “machine” and login.

------file in rc.local.d named home.example.com

machine box.example.com login yourboxadminid@example.com password youradminpassword

Hi Denis,

Can this also be done with Powershell on my Windows home server?

Thank you, @dmurphy!

Hi everybody!

I have two-ish questions for clarification regarding the shell script at the top of this thread.

I’m trying to set up a subdomain on a domain that’s managed by MiaB’s built-in DNS for the purpose of allowing my brother to VNC into a computer on my home network.

Assuming:

  • My MiaB is running in a data center, not on my home network.
  • I’m the only person using my MiaB, so I can do whatever I want in the admin interface or over ssh.
  • The DNS on MiaB is fully functional, but I don’t remember how to do per-alias subdomains.
  • I’ve already set up the alias vnc@example.com.
  • I have port-forwarding set up so I can already VNC into my home IP address.

My two questions are:

  1. Where do I go in the MiaB web interface to set up the subdomain vnc.example.com for the alias vnc@example.com? I tried adding it in the “Custom DNS” page in the admin interface, but I feel like that’s the wrong way of doing it? Or does the shell script make that unnecessary?
  2. Do I just run the shell script on any (Linux) computer on my local network via cron? If so, which variables would I need to change? Do I just change the contents of the files dm-dyndns.cfg and dm-dyndns.dynlist, or do I change parts of the shell script itself?

And the “-sh”:

  1. What about TLS? Do I need to run certbot while I’m at it? Or is that unnecessary for VNC?
  2. If I were to use one of the alternative scripts further down the thread, do I just run that in cron instead? Or is there additional configuration necessary?

Thanks!

Regarding VNC:

RealVNC, the people that created VNC, have a product you should look at… VNC Connect.

It will let you connect to machines that are behind an Router/NAT from anywhere on the web.

It is free for home use and can connect to up to 5 machines. That group is tied to an email you supply.

They have servers for Windows, Linux, and a lot more.

They have clients for even more. I can drive my Macs and Pi’s from my phone or tablet.

It is built in to the Pi software.

Hope this helps.