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,
root@tank:~# iptables -L
Chain INPUT (policy ACCEPT)
target prot opt source destinationChain FORWARD (policy ACCEPT)
target prot opt source destinationChain 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,
root@tank:~# 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-unreachableChain FORWARD (policy DROP)
target prot opt source destination
DROP all – anywhere anywhereChain 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.
Wow this article was so helpful, I must add it to my bookmarks!