How to set up a small rule set for iptables

In this how-to I will give you an introduction to iptables and show you how to set up a small rule set for iptables. If you want more detailed information I recommend the man page of iptables (its great).

This post is deprecated

I wrote an updated version: click here

1. Basic informations
2. Chain policies
3. Setting port rules
4. Saving rules

1. Basic informations

With iptables you can configure the tables of the IPv4 Linux kernel packet filter. The tablenames of the packet filter are filter, nat, mangle, raw and security. I will focus on the default table filter. This table is always used when you are not using the option -t.
Each table contains (built-in) chains. The table filter contains the following three built-in chains:

INPUT (for packets destined to local sockets)
FORWARD (for packets being routed through the box)
OUTPUT (for locally-generated packets)

Each chain contains a list of rules and each rule specifies what to do with a packet that matches the criteria of this rule. Each packet will be checked against the first rule of the list. If it doesn’t match the criteria it will be checked against the second, and so on until it reaches the end of the list or it matches the criteria of a rule.

Before we start let’s have a look at the current configuration (you’ll need root access):
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

You can see that no rule is defined for any chain (INPUT, FORWARD and OUTPUT). You can also see the policy for every (built-in) chain (policy ACCEPT).

2. Chain policies

The first step is to change the policy for every chain to DROP. DROP is the hardest policy. It will drop every packet which is not allowed to pass the firewall and will not send a replay to the source host telling it that the packet has been dropped.
But be careful, your connection will be closed immediately, if you change the policy of the INPUT chain on a remote host to DROP. First let’s start with the FORWARD and OUTPUT chains.

iptables -P OUTPUT DROP
iptables -P FORWARD DROP

Before we change the policy of the INPUT chain to DROP, we have to append a rule to INPUT to keep all connections established which are currently connected.

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

Let’s have a closer look at this rule.

  • -A INPUT append the rule to the INPUT chain
  • -m state use packet matching module state
  • –state … criteria. packet must belong to a connection which state is RELATED or ESTABLISHED
  • -j ACCEPT -j <target> this means jump to target ACCEPT –> packets will be accepted

The jump option sounds a bit strange, but you can use other tables as targets and the packet will be passed to the given table. But you can also use special built-in targets like ACCEPT, DROP, REJECT, etc.

Now we can change the policy of the INPUT chain to DROP.

iptables -P INPUT DROP

Let’s have a look at the current configuration, it should look like this:

Chain INPUT (policy DROP)
target prot opt source destination
ACCEPT all -- anywhere anywhere state RELATED,ESTABLISHED

Chain FORWARD (policy DROP)
target prot opt source destination

Chain OUTPUT (policy DROP)
target prot opt source destination

3. Setting port rules

The next step is to allow every traffic from and to the loopback interface lo. Some processes uses the loopback interface for interprocess-communication.

iptables -A INPUT -i lo -j ACCEPT
iptables -A OUTPUT -o lo -j ACCEPT

Here we have two new options -i and -o. The option -i specifies the interface for incoming traffic and -o the interface for outgoing traffic. If you have more than one network interface you can set rules specified to every network interface, e.g. SSH traffic is only allowed at eth2.

Now let’s set up a few standard rules for FTP (port 21), SSH (port 22), DNS (port 53), HTTP (port 80) and HTTPS (port 443).

iptables -A OUTPUT -p tcp --dport 21 -j ACCEPT
iptables -A OUTPUT -p tcp --dport 22 -j ACCEPT
iptables -A OUTPUT -p udp --dport 53 -j ACCEPT
iptables -A OUTPUT -p tcp --dport 80 -j ACCEPT
iptables -A OUTPUT -p tcp --dport 443 -j ACCEPT

Feel free to add more ports, e.g. 25 (SMTP), 43 (whois), 143 (IMAP), 993 (IMAPS), 6667 (IRC), 6697 (SSL-IRC), 8080 (often used by proxies). You can also add the interface to the rule (e.g. -o eth2). If you run a webserver you can also append rules to the INPUT chain to allow input-traffic, e.g.:

iptables -A INPUT -p tcp --dport 80 -j ACCEPT
iptables -A INPUT -p tcp --dport 443 -j ACCEPT

The last rules we have to append is to allow pings. But we will only allow ten input pings per second.

iptables -A INPUT -p icmp --icmp-type echo-request -m limit --limit 10/second -j ACCEPT
iptables -A OUTPUT -p icmp -j ACCEPT

Now we’ve set up a small iptables rule set. The last thing we have to do is to save the settings.

4. Saving rule set

If you restart your computer now, all rules will be deleted. We have to save the rule set and to restore it every time we boot the OS. To save the rule set we can use iptables-save.

touch /etc/iptables/firewall.conf && iptables-save > /etc/iptables/firewall.conf

Now we have saved all rules to a file. To restore it every time we will use iptables-restore and the direcory /etc/network/if-pre-up.d/. Every script inside the directory will be executed before the network is initialized. I use a little bash-script written by c0re. Copy, paste it and save it in /etc/network/if-pre-up.d/.

IPSTATE=/etc/iptables/firewall.conf #change the path to your table here
test -x $RESTORE || exit 0
test -x $STAT || exit 0
if test `$STAT --format="%a" $IPSTATE` -ne "600"; then
echo "Permissions for $IPSTATE must be 600 (rw-------)"
exit 0
if test `$STAT --format="%u" $IPSTATE` -ne "0"; then
echo "The superuser must have ownership for $IPSTATE (uid 0)"
exit 0

You can see that the script checks the permission of our rule set. The last thing we have to do is to change the permissions of /etc/iptables/firewall.conf and to change the owner of the script.

chmod +x /etc/network/if-pre-up.d/iptables && chmod 0600 /etc/iptables/firewall.conf
chown root:root /etc/network/if-pre-up.d/iptables

Now the rule set will be restored if you reboot your computer.

Thanks to c0re who wrote the article “how to secure a linux box” which includes the basics of iptables.

Posted on September 21, 2012, in Configure, Network, Security and tagged , , , , , , . Bookmark the permalink. Leave a comment.

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: