Screwing Around with IPTables When It Doesn’t Play Nice

FirewallSo you may not have noticed (hopefully) but I recently moved signal-chief from a shared hosting instance on GoDaddy to a dedicated VPS system.  I did this for a variety of reasons but one of the most important was so that I could start using SSL (more to follow on that in a future post).  My VPS is using Centos 7 as it’s operating system, something I am fairly familiar with.  As a cyber guy, one of the first things I wanted to do was to start with some basic security so of course step one is to run yum update to update all of my packages, and step two was to setup some firewall rules.

When I am setting up IPTables, the first rule I always run is:

iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT

To allow me to initial a connection (DNS, http, whatever) from the server and get the return traffic back.  Unfortunately when I tried to run this command I got “iptables: No chain/target/match by that name” sent back to me.  Well that’s frustrating.  After digging around on the interweb a bit I found several posts that stated that GoDaddy was nice enough to use a custom kernal which is missing a variety of things that the normal kernel is not, including among other things the state module that IPTables depends on to track the state of a connection.

Well, this is even more frustrating.  By doing this, GoDaddy makes it very very difficult for me (or pretty much anyone) to properly secure their VPS and still allow traffic to get out.  So after thinking about this for a minute, I came up with an idea.  When a machine starts a connection is formed that has some unique features.  The source IP is the IP address of the guy sending the packets, the destination IP is the IP address of the guy getting the packets, the destination port is the port number the server is listening on (i.e. 80 for HTTP) and the source port is a “random” port number picked by the guy who starts the connection.  According to RFC 6065, this port number should fall in the range between 49152 and 65535 however since GoDaddy screwed around with IPTables, I had no way of knowing if they screwed around with that.  With that in mind, I decided to add another rule that allows anything with a port number greater than 20,000 to come back in (I figured 20,000 was high enough to avoid anything dangerous and low enough to include any source ports my VM might come up with.

The other thing that I wanted to do was limit SSH into the VM to my home computer.  Unfortunately, I don’t have a static IP address at home, so I had to get a little creative.  I setup a dynamic DNS host for my home router with noip.com and configured my home router to check in with it periodically.  Next I put together this script and put it as a cron job to run every 10 minutes.  It looks up the IP address that my router resolves to, and if need be adjusts the firewall to allow me to SSH in.

#!/bin/sh

/usr/bin/nslookup <mydomain-name> > /root/temp
found=0
address=""
while read LINE
do
 if [[ "$LINE" == Address* ]]; then
        let found++
        if [[ $found == 2 ]]; then
                address=${LINE:8};
                /sbin/iptables-save > /root/rulesdump
                while read LINE2
                do
                        if [[ "$LINE2" == *$address* ]]; then
                                ruleexists=1;
                        fi
                done < /root/rulesdump;
                if [[ "$ruleexists" != 1 ]]; then
                        /sbin/iptables -P INPUT ACCEPT
                        /sbin/iptables -F
                        /sbin/iptables -A INPUT -p tcp --dport 80 -j ACCEPT
                        /sbin/iptables -A INPUT -p tcp --dport 443 -j ACCEPT
                        /sbin/iptables -A INPUT -p tcp -s $address --dport 22 -j ACCEPT
                        /sbin/iptables -A INPUT -p tcp --dport 22 -j DROP
                        /sbin/iptables -A INPUT -p tcp --dport 111 -j DROP
                        /sbin/iptables -A INPUT -p tcp --match multiport --dports 20000:65535 -j ACCEPT
                        /sbin/iptables -A INPUT -p udp --match multiport --dports 20000:65535 -j ACCEPT
                        /sbin/iptables -A INPUT -p icmp --icmp-type echo-request -j ACCEPT
                        /sbin/iptables -P INPUT DROP
                fi
        fi
 fi
done < /root/temp;

So there you have it.  Not what I would like to have on there, but in the end, I think it will work and do what I need it to do.

Leave a Reply

XHTML: You can use these tags: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>