Technical Resources for Technical People
Header

Manage a Dynamic Remote IP in iptables firewall automatically

November 22nd, 2011 | Posted by techblog in Linux

Having a backup server (or any other server) behind a dynamic IP is quite common; and for us it’s no different. Which of course we treat this off-site server like any other – it must communicate with our master servers through a strict set of firewall rules. (We can’t put enough emphasis on the importance of a strict firewall which explicitly accepts traffic only from known hosts – if it’s not for the public to see, don’t let them see it.)

In this example we’re setting up an iptables rule on our master Splunk server which allows the remote (dynamic) machine from an external network to forward logs accordingly. Your use case may vary, but the general idea still applies. (We assume you’ll be using a dynamic DNS service which resolves a hostname to an ip).

#!/bin/bash
#remote-ip-check.sh
GETIP=`ping -c 1 remote.dynamic.tld | grep 'PING' | awk '{print $3}' | sed 's/[(,)]//g'`
TABLES=`/sbin/iptables --list INPUT -n | grep $GETIP`

echo "* CHECKING IF REMOTE IP OF ($GETIP) EXISTS IN IPTABLES..."

if [ -z "$TABLES" -a "${TABLES+xxx}" = "xxx" ]; then

  echo "=== NO."
  echo "* CHECKING FOR OLD IPTABLES ENTRY..."

  # FIND OLD FIREWALL RULE FOR IP
  OLDIP=`/sbin/iptables --list INPUT -n | grep -E '\b[[:digit:]]{1,3}\.[[:digit:]]{1,3}\.[[:digit:]]{1,3}\.[[:digit:]]{1,3}\b.{30,36}9997' | awk '{print $4}'`

  if [ -z "$OLDIP" -a "${OLDIP+xxx}" = "xxx" ]; then
    echo "=== NO."
    ADD=1

  else
    echo "=== YES."
    echo "** REMOVING OLD IP ENTRY OF ($OLDIP)"
    echo "=== /sbin/iptables -D INPUT -s $OLDIP -p tcp --destination-port 9997 -j ACCEPT"
    /sbin/iptables -D INPUT -s $OLDIP -p tcp --destination-port 9997 -j ACCEPT

    echo "* CHECKING IF REMOVAL SUCCESSFUL..."
    IPCHK=`/sbin/iptables --list INPUT -n | grep -E '\b[[:digit:]]{1,3}\.[[:digit:]]{1,3}\.[[:digit:]]{1,3}\.[[:digit:]]{1,3}\b.{30,36}9997' | awk '{print $4}'`
    if [ -z "$IPCHK" -a "${IPCHK+xxx}" = "xxx" ]; then
      echo "=== YES."
      ADD=1
    else
      echo "=== NO."
    fi

  fi

  if [ "$ADD" = "1" ]; then
    echo "** ADDING NEW VALUE OF ($GETIP) TO IPTABLES..."
    echo "=== /sbin/iptables -A INPUT -s $GETIP -p tcp --destination-port 9997 -j ACCEPT"
    /sbin/iptables -A INPUT -s $GETIP -p tcp --destination-port 9997 -j ACCEPT
  else
    echo "* NO NEW ENTRY ADDED"
  fi

else
  echo "=== Existing ip rule available, nothing to do."
  echo "=== $TABLES"
fi

  echo "* EOF *"

What this script does is simply ping your remote host address in order to resolve the IP. It then checks to see if the iptables rule already exists for that address, or if an older address exists in your rules.

(This of course is making the assumption we’re only using the 1 ip entry at all times. If you have multiple ip’s using the same rule/port please adjust regex accordingly). This script does work with an existing entry of our internal network 10.10.10.0/24 for the same port.

All that’s left now is to create a cron entry that checks every 4 hours.

0 */4 * * * /root/remote-ip-check.sh

To silence email output:

0 */4 * * * /root/remote-ip-check.sh >> /dev/null 2>&1

You can follow any responses to this entry through the RSS 2.0 You can leave a response, or trackback.

One Response



Leave a Reply

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