iptables and dynamic DNS – part 3

This is an updated post for this updated article.

I just found back an old note about using iptables in combination with dyndns to open up access from a remote location. For instance, if you have a laptop that you take everywhere and you want to connect to your home or office. The script the other site suggested was broken, so let's write a new one.

Step 1: Create a new chain in the firewall

Create a new chain in the firewall where we can plug in the dynamic rules. On my Fedora machine, the firewall is located in /etc/sysconfig/iptables. I added the bold lines to this example.


*nat
:PREROUTING ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
:POSTROUTING ACCEPT [0:0]
COMMIT
*filter
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
<b>:DYNAMICPARENT - [0:0]
-A INPUT -j DYNAMICPARENT</b>
-A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
-A INPUT -p icmp -j ACCEPT
-A INPUT -i lo -j ACCEPT
-A INPUT -j REJECT --reject-with icmp-host-prohibited
-A FORWARD -j REJECT --reject-with icmp-host-prohibited
COMMIT

Step 2: Write a script

#!/bin/bash
 
HOSTNAME=myname.dyndns.org
CHECK_INTERVAL=60 #once a minute
 
IP="" #initialize $IP
while [ true ]; do
        OIP=$IP
        IP=$(dig +short $HOSTNAME | grep -iE "^[0-9]+.[0-9]+.[0-9]+.[0-9]+$"|head -n 1)
        if [ "$OIP" != "$IP" -a "$IP" != "" ]; then
                echo "Changing ip to $IP"
                /sbin/iptables -N DYNAMICNEW                    # create new rule
                /sbin/iptables -I DYNAMICNEW -s $IP -j ACCEPT   # allow new ip
                /sbin/iptables -I DYNAMICPARENT -j DYNAMICNEW   # attach new rule to its parent
 
                while [ true ]; do  # unlink old rule - if multiple exist, remove all
                        /sbin/iptables -D DYNAMICPARENT -j DYNAMICCHILD 2>/dev/null || break
                done
                /sbin/iptables -F DYNAMICCHILD #flush all old rules
                /sbin/iptables -X DYNAMICCHILD #flush all old rules
 
                /sbin/iptables -E DYNAMICNEW DYNAMICCHILD #rename new to "current"
        fi
        sleep $CHECK_INTERVAL
done

In this case, the firewall accepts all traffic from $IP, but of course you could restrict it to 1 port. Also, I focussed on IPv4, but you could easily rewrite this script to IPv6 using ip6tables. I saved the file to /usr/local/bin/dynfirewall.sh

Step 3: Run the script

I'd prefer running the script from inittab, but since Fedora doesn't work like this anymore, I put the following line in /etc/rc.d/rc.local:

/usr/local/bin/dynfirewall.sh >>/var/log/dynfirewall 2>>/var/log/dynfirewall &

Please don't forget the ampersand at the end to fork the script!!

Why is this script better than previous version?

- This script can handle cnames
- The old script used to delete old rules, before creating new ones. This one does not. Therefore, it will never leave a second where you cannot connect.

© GeekLabInfo iptables and dynamic DNS - part 3 is a post from GeekLab.info. You are free to copy materials from GeekLab.info, but you are required to link back to http://www.geeklab.info

1 Star2 Stars3 Stars4 Stars5 Stars (2 votes, average: 5.00 out of 5)
Loading...

iptables and dynamic DNS – part 2

In 2011, I wrote this post on Dynamic DNS: https://www.geeklab.info/2011/02/iptables-and-dynamic-dns. While this is still useful, I found a newer, cooler way to do Dynamic DNS in combination with iptables. It's called libnetfilter_queue.

iptables is used to change the inner netfilter tables of the kernel. And because the kernel has no internal resolver, it is impossible for the kernel to do on-the-fly dns lookups. But by offloading this decision to userspace, it is possible. The libnetfilter_queue lib offers that functionality.

libnetfilter_queue is a userspace library providing an API to packets that have been queued by the kernel packet filter. It has bindings for Python and several other languages.

Requirements for my setup

python-NetfilterQueue - https://github.com/kti/python-netfilterqueue

libnfnetlink

libnetfilter_queue

libmnl

You may need to build the first dependency yourself. The other 3 are available in Fedora 20 by default. If you're running RHEL/CentOS, the Fedora packages can be recompiled for your setup.

iptables rule

First, you need to get iptables to enqueue specific packets to your queue.

iptables -I INPUT -p tcp --dport 631 -m state --state NEW -j NFQUEUE --queue-num 6789 -m comment --comment "Remote CUPS printer"

Queue handler

Then we write a script that handles the queue. A quick-and-dirty implementation:

#!/usr/bin/python
 
import socket
from netfilterqueue import NetfilterQueue
 
def getIP(d):
    """
    This method returns the first IP address string
    that responds as the given domain name
    """
    try:
        data = socket.gethostbyname(d)
        #ip = repr(data)
        return data
    except Exception:
        # fail gracefully!
        return False
 
def dnsfilter(pkt):
        if pkt.get_payload_len() < 0x10:
                "Don't know how to handle this too small packet"
                pkt.drop()
                return False
 
        payload=pkt.get_payload()
        srcip=".".join("{:d}".format(ord(c)) for c in payload[0x0c:0x10])
        allowedip=getIP('localhost')
        print "Debug: SRC="+srcip+" ALLOWED="+allowedip+" RESULT=",
        if srcip==allowedip:
                print "Accept"
                pkt.accept()
        else:
                print "Drop"
                pkt.drop()
 
nfqueue = NetfilterQueue()
nfqueue.bind(6789, dnsfilter)
try:
        nfqueue.run()
except KeyboardInterrupt:
        print

This is a quick-and-dirty implementation that misses basic features such as caching the result of gethostbyname. This may introduce terrible delays if used wrong.

Ubuntu/Debian

I'm running RedHat-based software on all of my machines. Above information may be useful for Ubuntu/Debian users, but it's not tested and I'm not supporting it.

Servers: RedHat Enterprise Linux/CentOS is more suitable for servers, as there's a lot of professional level support available. I think that's important, because if I say, get a car accident, I want the servers to be managable by another professional.

Desktops/Laptops: RPM packages are pretty exchangable between RedHat-based platforms. That's a good reason to run Fedora on the desktop.
© GeekLabInfo iptables and dynamic DNS - part 2 is a post from GeekLab.info. You are free to copy materials from GeekLab.info, but you are required to link back to http://www.geeklab.info

1 Star2 Stars3 Stars4 Stars5 Stars (No Ratings Yet)
Loading...

iptables and dynamic DNS

Please read other posts in this section as well.
They may provide better options.

I just found back an old note about using iptables in combination with dyndns to open up access from a remote location. For instance, if you have a laptop that you take everywhere and you want to connect to your home or office. The script the other site suggested was broken, so let's write a new one.

Step 1: Create a new chain in the firewall

Create a new chain in the firewall where we can plug in the dynamic rules. On my Fedora machine, the firewall is located in /etc/sysconfig/iptables. I added the bold lines to this example.


*nat
:PREROUTING ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
:POSTROUTING ACCEPT [0:0]
COMMIT
*filter
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
<b>:DYNAMIC - [0:0]
-A INPUT -j DYNAMIC</b>
-A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
-A INPUT -p icmp -j ACCEPT
-A INPUT -i lo -j ACCEPT
-A INPUT -j REJECT --reject-with icmp-host-prohibited
-A FORWARD -j REJECT --reject-with icmp-host-prohibited
COMMIT

Step 2: Write a script

#!/bin/bash
 
HOSTNAME=myname.dyndns.org
CHECK_INTERVAL=60 #once a minute
 
/sbin/iptables -F DYNAMIC #flush all existing rules
IP="" #initialize $IP
while [ true ]; do
    OIP=$IP
    IP=$(host $HOSTNAME | grep -iE "[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+" |cut -f4 -d' '|head -n 1)
    if [ "$OIP" != "$IP" -a "$IP" != "" ]; then
         echo "Changing ip to $IP"
         /sbin/iptables -F DYNAMIC #flush all old rules
         /sbin/iptables -I DYNAMIC -s $IP -j ACCEPT #the new rule
    fi
    sleep $CHECK_INTERVAL
done

In this case, the firewall accepts all traffic from $IP, but of course you could restrict it to 1 port. Also, I focussed on IPv4, but you could easily rewrite this script to IPv6 using ip6tables. I saved the file to /usr/local/bin/dynfirewall.sh

Step 3: Run the script

I'd prefer running the script from inittab, but since Fedora doesn't work like this anymore, I put the following line in /etc/rc.d/rc.local:

/usr/local/bin/dynfirewall.sh >>/var/log/dynfirewall 2>>/var/log/dynfirewall &

Please don't forget the ampersand at the end to fork the script!!

© GeekLabInfo iptables and dynamic DNS is a post from GeekLab.info. You are free to copy materials from GeekLab.info, but you are required to link back to http://www.geeklab.info

1 Star2 Stars3 Stars4 Stars5 Stars (2 votes, average: 5.00 out of 5)
Loading...