Automatically Update IPTables on DDWRT with Dynamic IP Address

I’m running a Netgear router with DDWRT installed and a NAS behind it. The Synology NAS runs a nice service called Cloud Station. It’s basically a private dropbox service. I’d like to restrict access to Cloud Station to a handful of hosts. Each family member has an IP, but they are all dynamic and can change.

If you’d like to open up a port or service on an open source router, it’s difficult when the IP address may change. Typically you would enter this information in the GUI/Admin interface. The problem is knowing when the IP address changes and getting it updated as quick as possible.

To overcome this issue, I wrote a simple bash script that will query and store the IP address of the dynamic host. Then it will modify rules based on if the IP address has changed.

Thanks to Dave Horner for the inspiration.

#!/bin/sh

# setup variables
HOST=$1
HOSTFILE="/tmp/root/hosts/host-$HOST"
IPTABLES="/usr/sbin/iptables"

# check to make sure we have enough args passed (1).
if [ $# -eq 0 ]; then
    echo "$0 hostname"
    echo "You must supply a hostname to update in iptables."
    exit
fi

# lookup host name from dns tables using ping, if invalid hostname, dns server ip responds (67.215.65.132)
IP=`ping -c 1 ${HOST} | egrep -m1 -o '[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}'`
if [ "${IP}" = "67.215.65.132" ]; then
    echo "Couldn't lookup hostname for $HOST, failed."
    exit
fi

# check if hostfile exists (-e) and if so, read the contents
OLDIP=""
if [ -e $HOSTFILE ]; then
    OLDIP=`cat $HOSTFILE`
    echo "CAT returned: $?"
fi

# has address changed?
if [ "$OLDIP" == "$IP" ]; then
    echo "Old and new IP addresses match."
    exit
fi

# save new ip to host file.
echo $IP>$HOSTFILE

echo "Updating $HOST in iptables."
if [ "${#OLDIP}" != "0" ]; then
    echo "Removing old rule ($OLDIP)"
	`${IPTABLES}  -t nat -D PREROUTING -p tcp -s ${IP} -d $(nvram get wan_ipaddr) --dport XXXX -j DNAT --to 192.168.1.XXXX:XXXX`
	`${IPTABLES} -D FORWARD -p tcp -s ${IP} -d 192.168.1.XXXX --dport XXXX -j ACCEPT`
fi
echo "Inserting new rule ($IP)"
# route and forward all traffic from ip XXXX to port XXXX
`${IPTABLES}  -t nat -I PREROUTING -p tcp -s ${IP} -d $(nvram get wan_ipaddr) --dport XXXX -j DNAT --to 192.168.1.XXXX:XXXX`
`${IPTABLES} -I FORWARD -p tcp -s ${IP} -d 192.168.1.XXXX --dport XXXX -j ACCEPT`

Leave a Comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.