Using IPTables with Dynamic IP hostnames like dyndns.org

Whenever IPTables has a hostname in a rule it looks up the hostname’s IP address and uses that instead of the actual hostname – so it’s stuck with the IP until the next time IPTables is flushed/restarted. Here’s a quick little python script to stick in a crontab which checks the IP of your dynamic IP hostname (free ones provided by dyndns.org) and will restart iptables if it catches a change in your hostname. The script was made for CentOS so should work on Red Hat based distributions – if you don’t have an /etc/init.d/iptables file you’ll have to modify the reload iptables command in the source. Viewable Source After Jump

I just set this up as root and in root’s crontab.

Download Source

Source:

#!/usr/bin/python
 
import os
 
def gettextoutput(cmd):
    """Return (status, output) of executing cmd in a shell."""
    pipe = os.popen('{ ' + cmd + '; } 2>&1', 'r')
    pipe = os.popen(cmd + ' 2>&1', 'r')
    text = pipe.read()
    if text[-1:] == '\n': text = text[:-1]
    return text
 
home_dyndns = "example.dyndns.org"
log_dyndns = "./new_home_ip_check.log"
last_dyndns = gettextoutput("cat " + log_dyndns)
cur_dyndns = gettextoutput("host " + home_dyndns)
 
print "Log: "+ last_dyndns
print "Cur: "+ cur_dyndns
 
if last_dyndns == cur_dyndns:
    print "IPs match, no restart necessary"
else:
    print "Updating last IP with current"
    os.system("echo '" + cur_dyndns + "' > " + log_dyndns)
    print "Restarting iptables to update"
    os.system("/etc/init.d/iptables restart")

Output looks like:

Log: example.dyndns.org has address 114.76.37.112
Cur: example.dyndns.org has address 114.76.37.112
IPs match, no restart necessary
 
Log: example.dyndns.org has address 114.76.37.113
Cur: example.dyndns.org has address 114.76.37.112
Updating last IP with current
Restarting iptables to update
Flushing firewall rules:                                   [  OK  ]
Setting chains to policy ACCEPT: filter                    [  OK  ]
Unloading iptables modules:                                [  OK  ]
Applying iptables firewall rules:                          [  OK  ]
Loading additional iptables modules: ip_conntrack_netbios_n[  OK  ]
Share and Enjoy:
  • Print
  • Facebook
  • Reddit
  • Digg
  • Tumblr
  • Google Bookmarks
  • del.icio.us
  • StumbleUpon
This entry was posted in code, linux, python. Bookmark the permalink.

5 Responses to Using IPTables with Dynamic IP hostnames like dyndns.org

  1. Darrell Dillman says:

    Thanks, EXACTLY what I needed!

  2. Curt says:

    I have this script working except when it restarts the iptables the ip address that gets listed in my iptables doesn’t change. I’m adding the host to my iptables using
    iptables -I INPUT -i eth1 -s hostname -j ACCEPT
    if I check my iptables with
    iptables -L -n
    I get the rule and it has substituted the current IP address for the host name. and everything works. but if the IP for the host name changes this script detects it and restarts the iptables but the IP address listed doing an iptables -L -n doesn’t change. I’m pretty new to the whole IP tables so maybe I’m doing it wrong? any ideas? thanks

    • Curt says:

      So I couldn’t get the dns name in the IP tables to work so I took your idea and wrtoe a bash script that looks up the host name adds it to the iptables and if the IP changes removes the old rule and adds a new one for the new ip.

      #!/bin/bash
      #allow a dyndns name

      HOSTNAME=HOST_NAME_HERE
      LOGFILE=LOGFILE_NAME_HERE

      Current_IP=$(host $HOSTNAME | cut -f4 -d' ')

      if [ $LOGFILE = "" ] ; then
      iptables -I INPUT -i eth1 -s $Current_IP -j ACCEPT
      echo $Current_IP > $LOGFILE
      else

      Old_IP=$(cat $LOGFILE)

      if [ "$Current_IP" = "$Old_IP" ] ; then
      echo IP address has not changed
      else
      iptables -D INPUT -i eth1 -s $Old_IP -j ACCEPT
      iptables -I INPUT -i eth1 -s $Current_IP -j ACCEPT
      echo $Current_IP > $LOGFILE
      echo iptables have been updated
      fi
      fi

      then just add this line to your crontab and it will check every 5 mins and keep your iptables up-to-date.
      */5 * * * * /root/NAME_OF_SCRIPT.sh > /dev/null 2>&1

      • diginc says:

        Nice work.

        What flavor of linux are you running? If you didn’t have an iptables init.d script, that might have been the problem. does /etc/init.d/iptables exist?
        I see you’ve already come up with a work around though – I went ahead and edited the articles to add a note about the iptables reload command being Red Hat based and needing to probably be modified for other system types.

Leave a Reply

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

*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>