IPTables Simplified

One common problem I come across when conducting vulnerability assessments is the lack of a host firewall or understanding on its configuration. IPTables is the standard firewall on most linux based OSes and once understood is a simple to configure and powerful packet filtering firewall. Often I see unnecessarily complex IPTables rules and the use of automated tools without fully understanding what they are doing. So, lets walk through IPTables and develop a simple set of base rules that could be used on pretty much any server.

IPTables is a packet filtering firewall based on ipfw and IPChains of the past. Pretty much every linux flavour has IPTables available, usually installed with a default ACCEPT everything and no particular ruleset. The simplest way to see what is being applied to a box is by using the command iptables -L, you should see something like this on most vanilla installs,

[email protected]:~# iptables -L
Chain INPUT (policy ACCEPT)
target     prot opt source               destination
Chain FORWARD (policy ACCEPT)
target     prot opt source               destination
Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination

If you do see some preexisting rules you can clear these out and start fresh by flushing these rules with iptables -F. (Don’t do this on production boxes or they maybe left exposed) Now we have a blank slate of IPTables default chains INPUT, FORWARD and OUTPUT all with a default policy of ACCEPT. This basically means that if a packet is processed either coming to, from or through (forwarded) the server and does not match any of our rules it will be allowed to proceed.

As we will be mainly dealing with filtering packets coming to the server, lets begin with the INPUT chain and a few basic rules. First of all we should put in some anti-spoofing rules so local loopback traffic can’t be spoofed by traffic coming in on external interfaces.

iptables -A INPUT -i lo -j ACCEPT
iptables -A INPUT ! -i lo -d 127.0.0.0/8 -j REJECT

We will also need to add a rule so that IPTables accepts traffic related to or part of an already established connection, this is one of the powerful features of IPTables in that it can track connections and associated packets.

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

Now we can get into what we want to allow and this can vary based on the purpose of the server, for a web server you will probably want to allow ping ICMP traffic, web traffic on 80 and 443 and ssh (preferably on a different port then 22).

iptables -A INPUT -p icmp -m icmp –icmp-type 8 -j ACCEPT
iptables -A INPUT -p tcp -m state –state NEW –dport 22 -j ACCEPT
iptables -A INPUT -p tcp –dport 80 -j ACCEPT
iptables -A INPUT -p tcp –dport 443 -j ACCEPT

Now lets block everything else, set a rule to reject any packet that doesn’t match our other input rules and also change the default policy of the input chain to drop as a precaution.

iptables -A INPUT -j REJECT
iptables -P INPUT DROP

The FORWARD and OUTPUT chains may need some attention too however if your not forwarding packets through your server it should be set to drop, OUTPUT on the other hand is usually unrestricted.

iptables -A FORWARD -j DROP
iptables -P FORWARD DROP
iptables -A OUTPUT -j ACCEPT

This is our basic ruleset, now lets run iptables -L again,

[email protected]:~# iptables -L
Chain INPUT (policy DROP)
target     prot opt source               destination
ACCEPT     all  –  anywhere             anywhere
REJECT     all  –  anywhere             loopback/8  reject-with icmp-port-unreachable
ACCEPT     all  –  anywhere             anywhere    state RELATED,ESTABLISHED
ACCEPT     icmp –  anywhere             anywhere    icmp echo-request
ACCEPT     tcp  –  anywhere             anywhere    state NEW tcp dpt:ssh
ACCEPT     tcp  –  anywhere             anywhere            tcp dpt:www
ACCEPT     tcp  –  anywhere             anywhere            tcp dpt:https
REJECT     all  –  anywhere             anywhere            reject-with icmp-port-unreachable
Chain FORWARD (policy DROP)
target     prot opt source               destination
DROP       all  –  anywhere             anywhere
Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination
ACCEPT     all  –  anywhere             anywhere

Now that we have our rules we will need to make sure they are loaded at startup each time, this varies between OSes however for Debian,

Output the rules to a file using iptables-save > /etc/iptables.rules
Now edit /etc/networking/interfaces to load this file when bringing up the network interface, add pre-up iptables-restore < /etc/iptables.rules after iface lo inet loopback.

In my next post I will talk about logging and some more complex rules to protect your servers. Also, becareful when flushing your rules with iptables -F because this will now drop all your connections with a default policy of drop for INPUT.