Configuring your Linux Firewall using iptables
When I first started out using Linux, I was quite daunted by ‘iptables’, the built-in firewall that is bundled with the Linux kernel. Given there is a general misconception from a lot of people’s that configuring it is anything but easy has also compounded towards my reluctance to try to learn it in detail initially - but no surprises here, as the good tutorial I’ve referenced has 16 chapters and 10 appendices! It’s little wonder why some people might be scared away by that.
But there is a good reason why a tutorial about iptables is that big - computer security is all about the details, most of the time you know all the details on the different aspects of network security to understand the whole picture before you can design a comprehensive firewall that provides all features you want without letting malicious traffic through.
Still, if you’re just setting up a simple home network + firewall, it shouldn’t be that difficult. And it isn’t really. I’ll show you a few recipes you can use to set things up properly without having too much RTFM.
For illustration, I’ll use the following setup that I’m running at home as an example:
My server is an old Celeron PC
which acts as the firewall. It has an ethernet card which connects to a
wireless switch where the Internet connection gets shared by all my
laptops connected to My LAN.
How the server connects to the Internet is via my Huawei E220 broadband
modem.
It just convenient to have my configuration this way as well, since my
old iBookG4 has no suitable drivers. The broadband device is recognized
as ppp0 as shown in the diagram above. Let me now show you a few
interesting things you can do with your ‘iptables’ firewall.
Recipe #1 Forward Internet Connections
using IP Masquerading
You want to let your LAN make connections from the Internet. This is one
of the cool features that iptables provide that makes it more than just
a firewall. Before you make changes to your firewall entries, you’ll
need to make some changes to your kernel’s configuration to enable it to
forward IP traffic. To do this dynamically, run the following command:
echo 1 > /proc/sys/net/ipv4/ip_forward
The changes you’ve made above will be lost the next time you reset your
computer. To make this change permanent, you have to make changes to
/etc/sysctl.conf
to include the following line:
net.ipv4.ip_forward=1
Once that’s set up, we can issue the commands to iptables
to start
forwarding traffic from the LAN to the Internet:
iptables -t nat -A POSTROUTING -o ppp0 -j MASQUERADE
iptables -A FORWARD -i eth0 -o ppp0 -j ACCEPT
iptables -A FORWARD -i ppp0 -o eth0 -m state --state RELATED,ESTABLISHED -j ACCEPT
The formal name for forwarding network traffic is called ‘Network
Address Translation’, or NAT for short. This explains why the first
iptables
command has nat
in it. It basically instructs the firewall
to remember the connection that gets forwarded out the Internet. It
needs to do this do multiplex different connections from the LAN into a
single connection out to the Internet, and then smartly demultiplexes
the received data back to the requesters. The next two iptables
directives tell the firewall to allow forwarding of packets to the
Internet from the LAN, and only allow data packets from the Internet to
be sent back to the LAN only if there previously are connections
requesting for it. This effectively denies any illegal traffic from
coming into the LAN unless computers within it explicitly allows it
to.
Recipe #2 Differentiating Traffic
between LAN and the Internet
Often, you’ll want to assign different rights to traffic from your LAN
vs. the Internet. Traffic from your LAN is usually trusted, and hence is
within the safe boundary, while
Internet traffic is regarded as hostile, hence classified as unsafe. Like the diagram shown in my
example above, data from the Internet via device ppp0 is the unsafe network which I’ll want to
have differentiating rules from my safe LAN network originating from
eth0.
Firstly we want to create the two different chains to represent traffic from eth0 and ppp0:
iptables -N ETH0_FILTER
iptables -N PPP0_FILTER
Once the chains are created, we have to tell the main INPUT traffic chain to segregate the traffic between the two networks:
iptables -A INPUT -i eth0 -j ETH0_FILTER
iptables -A INPUT -i ppp0 -j PPP0_FILTER
Once the different changes are linked to the main input, we can now provide rules to treat the different networks separately. For example, if we want to let our LAN network access everything, and only allow SSH traffic from the Internet, we can put rules like these:
iptables -A ETH0_FILTER -j ACCEPT
iptables -A PPP0_FILTER -p tcp -m tcp --dport 22 -j ACCEPT
iptables -A PPPo_FILTER -j DROP
This will drop all other traffic except SSH on ppp0
. For other
interesting ways of configuring how you want to filter your traffic
between the different chains keep reading the remaining tips.
Recipe #3 Logging Suspicious Traffic
How would you know if you are under attack by malicious Internet
traffic? Simple, by logging these intrusions. Here’s one way of logging
these intrusions:
iptables -A PPP0_FILTER -p tcp -m tcp --dport 22 -m state --state NEW -m recent --update --seconds 60 --hitcount 2 --name DEFAULT --rsource -j LOG --log-prefix "DROPPED:"
The example above says that if there are more than 2 consecutive connections from the Internet to my SSH port (22) within the last 60 seconds, then LOG the message with the prefix “DROPPED:". Obviously, this line only logs the connection, what I’ve omitted is to drop the connection (see Recipe #4 below).
Recipe #4 Rate Limit Spam Traffic
Bots and spammers usually rely on software that repeatedly scan
and access your server to try to bruteforce their way in. On machines
with a noisy harddisk like mine, the repeated clicking sound is a
dead-giveaway (not to mention the annoyance!) So to stop from them from
repeatedly doing so, we enact a rule that drops packets if too many
incoming new connections are attempted within a short period of
time:
iptables -A PPP0_FILTER -p tcp -m tcp --dport 22 -m state --state NEW -m recent --update --seconds 60 --hitcount 2 --name DEFAULT --rsource -j DROP
iptables -A PPP0_FILTER -p tcp -m tcp --dport 22 -j ACCEPT
The first line tells the firewall to log all new incoming connections - if more than 2 new connections are attempted within 60 seconds, then all the remaining connections will be dropped until the 60 second period times out. Given my default policy of my firewall is to drop connections, the second line is included to explicitly ACCEPT the connection, if the first rule does not match (ie, no more than 2 connections are seen within the last 60 seconds).
Recipe #5 Fight Back Spammers By Tarpitting
A tarpit connection is one that delays incoming network
connections as long as possible. This technique causes spam connections
to slow down, limiting the amount of computers that it can spam. However
the iptables version of tarpit is a slightly more advanced variant: it
sets the TCP acknowledgement window of the network packet to 1, forcing
the sender to generate a full TCP packet per 1 byte of data it tries to
send, making it computationally costly for spammers as it saps the
computer’s CPU resources. If you like to fight back against spammers,
then this tip is for you.
To enable tarpitting, this requires you to patch and recompile your kernel, which is an entire post itself, so read my more detailed post on how to enable tarpitting.
Recipe #6 Making Your Firewall Changes
Permanent
After making all those nifty changes, it would be a shame if they
got lost the next time your computer rebooted. So here’s how you can
make these firewall settings permanent. Once you are satisfied with all
the changes you are making to your firewall, save it by invoking
iptables-save
:
iptables-save > /etc/iptables.rules
The above command pipes all the configuration into /etc/iptables.rules
file. Once you have that, you’ll want to restore the configuration every
single time your computer starts up. There are quite a few places where
you can start restoring the firewall, I do it in my /etc/rc.local
file, after my ppp connection is started, where I insert the following
line:
iptables-restore < /etc/iptables.rules
And you’re all done. Now you can sit back, relax and enjoy the security features of your firewall!