A Simple Linux Firewall – A brief tutorial in iptables.
‘Firestarter‘ is one of the firewall options available to a Linux user. To install Firestarter in Ubuntu, open up a terminal window and type:
$ sudo apt-get install firestarter
You have now installed a firewall. For most people this is sufficient, and they need not read any further. People with a genuine interest in computing may wish to investigate a little more deeply…
Actually, Firestarter is one of several graphical front ends for the firewall tool called ‘iptables‘. Iptables is a command line tool that allows the administrator to define a set of packet filtering rules, and these rules are enforced using a kernel framework called ‘netfilter’. Let’s take a look at iptables. Login as root/super-user and type in the following command to display your current iptables configuration:
$ iptables -L
If you have never configured iptables, you should see something like the following displayed on your terminal:
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 have installed Firestarter, you will see a complicated set of firewall rules displayed. I also suspect that some distributions are pre-configured with an iptables firewall. This artical is written on the assumption that you can see the above.
In the above example taken from my laptop after I have cleared the firewall, you can see three ‘chains’ – the INPUT chain (for incoming traffic), the FORWARD chain (used for packet routing) and the OUTPUT chain (take a guess!).
We’re going to be focusing on protecting our computer from external attack, so we will be putting all of our effort into creating a set of rules in the INPUT chain. You will notice that the policy for the INPUT chain is ACCEPT – this is the default action to take when a packet arrives. This is not the setting we want, it would be preferable if we rejected (dropped) incoming traffic (that is the best way to fend off attack). To change the INPUT chain policy to DROP we would type:
$ iptables -P INPUT DROP
(remember, you need to be doing this as root/super-user)
You can then confirm this change by listing the iptables configuration, again with the command:
$ iptables -L
I bet you feel better already.
Unfortunately, our new firewall is far too powerful. Many processes on your computer communicate by sending network packets, but they stay inside your computer instead of being broadcasted across the net. We need to make sure that these processes can signal each other. We can do this by typing the following command:
$ iptables -A INPUT -j ACCEPT -s localhost -d localhost
As a packet is generated, iptables checks to see if the packet matches any rules, and if it does the rule is applied to that packet. Here, we are saying that packets made locally (the source, -s), that are destined to stay local (the desination, -d), can be allowed to go about their business without interference. Any other packets received that do not match this rule have the policy applied (they are dropped)
Things are still not quite right. Pull up your web browser and visit your favourite website. You’ll find that you can’t use the net. If you check your policy on the OUPUT chain you will find that this traffic is ACCEPTED.
$ iptables -A INPUT -j ACCEPT -m state –state RELATED,ESTABLISHED
Here we tell iptables that if a packet arrives that is part of a connection that already exists, it should be allowed to pass. This way, if you throw a packet out into the lawless wilderness of the internet, any returning data is accepted. Now try browsing the internet, it should work fine now…
It is good practice to add a final rule to a chain to reject any remaining un-matched packets. This prevents the POLICY from having to be applied. This is useful if you decide to implement some sort of clever logging rule set. Enter the command:
$ iptables -A INPUT -j DROP
Iptables starts with the first rule in the chain and works down. As soon as a rule match is identified, the specified action is performed and no further inspection occours. Therefore, you must make sure that this is the last rule in your INPUT chain (so enter this command last). If, for instance, this was the first rule in the input chain, all traffic would be rejected.
Just a few more loose ends.
Let’s take a look at the FORWARD chain. This is useful for things such as network routing. We won’t be using these types of network packets for a simple workstation, nor should we have any of these packets floating around. To block traffic of this type we will apply a global policy:
$ iptables -P FORWARD DROP
Now we have to consider outgoing traffic. Filtering outgoing traffic is a complex task. Here, I will suggest a simple ACCEPT policy, as most sensible Linux users are not likely to have installed any malware.
$ iptables -P OUTPUT ACCEPT
We have now built a simple and effective firewall policy. If you display you firewall tables (using ‘iptables -L’) you should see:
Chain INPUT (policy DROP)
target prot opt source destination
ACCEPT all — localhost localhost
ACCEPT all — anywhere anywhere state RELATED,ESTABLISHED
DROP all — anywhere anywhereChain FORWARD (policy DROP)
target prot opt source destinationChain OUTPUT (policy ACCEPT)
target prot opt source destination
Rules in iptables can be inserted in any point in the chain (see the online manual) but at this stage it is easiest to just work top to bottom. If you screw up and need to start again, use the command ‘iptables -F’ to flush all rules from your chains and start again. It is useful to construct shell scripts instead of working directly with the terminal, as these can be edited and then re-applied quickly.
You can save the iptables configuration to a textfile with the command:
$ iptables-save > filename
and this file can be used to configure iptables with the command:
$ iptables-restore < filename
If you restart your computer you will lose you firewall configuration. The restore command (or the line by line instructions you have just entered) could be placed in a shell script, and your computer can be instructed to run this script when it starts (check the documentation for your linux distribution).
For a slightly more advanced solution, in Ubuntu (and probably most other distributions) browse to the directory ‘/etc/network’ and list the directories contents. You will see the following directories:
if-down.d if-post-down.d if-pre-up.d if-up.d
Just before the network adaptor comes ‘on-line’, all of the shell scripts inside the directory ‘if-pre-up.d’ are executed (the other directories are similarly self explanatory). So, either a shell script containing the steps to build your firewall, or a short shell script that executes the ‘iptables-restore’ command can be placed in this directory. As soon as the network adaptor comes on-line the firewall will be automatically restored. Make sure the resore file is somewhere safe with a sensible name, such as /etc/iptables.bak. You will need to make sure that your script is owned by root and has execute permissions,use the’chown’ and ‘chmod’ commands respectively.
Good stuff!
[Translate]
Thanks Dan
[Translate]
Hi, thanks for the tutorial. I'd like to ask a question about the INPUT chain described above. As we already have 'Chain INPUT (policy DROP)', is it necessary to have 'DROP all — anywhere anywhere' at the end? I can see it might be good practice to do so as a belt and braces approach.
[Translate]
Hi Mark,
You are quite right. 'DROP all — anywhere anywhere' is not strictly needed, but I prefer to add this rule in case I inadvertently change the default policy.
Whilst you would need to make a deliberate effort to change this at the command line, I am paranoid that the policy might get changed when I am playing with various GUI front-ends. As you suggest, it is probably better practice to include this rule.
Regards,
Rich
[Translate]
i get an error :
sudo iptables -A INPUT -j ACCEPT -m state –state RELATED,ESTABLISHED
Bad argument `–state'
Try `iptables -h' or 'iptables –help' for more information.
[Translate]
Hi Sam,
I have just checked my article. My wordpress theme has turned a double-dash into a single. Use two hyphens instead of one.
Rich
[Translate]
this helped me a lot!
[Translate]
Glad it helped. Took me a long time to figure this out.
[Translate]
Really its excellent article for beginners
[Translate]