Linux Penguin

Linux Security – Firewall Management With IPTABLES

We have talked about security in this space before, in more abstract terms. More specifically, we are going to review the basic setup and some simple access rules using the venerable and ever popular ‘iptables’ firewall available for every Linux distribution around.

Firewall Service Management
Depending on the distribution, you are able to manage your firewall service a number of ways. With the RPM based distributions (Red Hat, CentOS, Fedora), you can start the firewall as follows:
sudo service iptables start
and you can set it to autostart thereafter by executing:
sudo chkconfig iptables on

With Debian based distributions (Debian, Ubuntu and its variants and Mint), you manage both the start and autostart using a script called ‘ufw’ as follows:
sudo ufw enable

This will both start the firewall with default chain rulesets in place as well as configure the firewall to autostart on system boot. The valid states for ‘ufw’ are [enable/disable/status], status will let you know whether the firewall is started and configured to start on boot.

The Chain Gang
So, regardless of your distribution and the management of the service, the underlying application is ‘iptables’ which we will be using directly at this time. Now would be a good time for me to mention that, in addition to many other security topics that are specific to the Linux Certification Exam, there is a video that details all of the following steps at our sister site Linux Academy. The video on ‘iptables’ was created to demonstrate everything we are talking about here, although in a bit more detail.

Now that we have started our firewall (and be sure to be logged on to the system directly and not over SSH, the act of enabling the firewall may very well kill your SSH connection), we need to review our default chain rulesets. The three main chains that we will concern ourselves with for the purposes of this article are INPUT, OUTPUT and FORWARD. These chains control most of what we care about in a firewall. So, execute the following:
sudo iptables -L ... [or] sudo iptables --list

That command will list all current rules in our active firewall, in particular, the three chains at the top are what we are interested in. In Ubuntu Linux 12.10, the default chain rules appear as follows:

Chain INPUT (policy DROP)
target prot opt source destination
ufw-before-logging-input all — anywhere anywhere
ufw-before-input all — anywhere anywhere
ufw-after-input all — anywhere anywhere
ufw-after-logging-input all — anywhere anywhere
ufw-reject-input all — anywhere anywhere
ufw-track-input all — anywhere anywhere

Chain FORWARD (policy DROP)
target prot opt source destination
ufw-before-logging-forward all — anywhere anywhere
ufw-before-forward all — anywhere anywhere
ufw-after-forward all — anywhere anywhere
ufw-after-logging-forward all — anywhere anywhere
ufw-reject-forward all — anywhere anywhere

Chain OUTPUT (policy ACCEPT)
target prot opt source destination
ufw-before-logging-output all — anywhere anywhere
ufw-before-output all — anywhere anywhere
ufw-after-output all — anywhere anywhere
ufw-after-logging-output all — anywhere anywhere
ufw-reject-output all — anywhere anywhere
ufw-track-output all — anywhere anywhere

At this point, our default rules will DROP all INPUT connections, DROP all FORWARD and ACCEPT all OUTPUT connections. This means that we can still browse using this system as well as make outgoing SSH connections, but nothing will be able to connect to us, whether that service is listening for connections or not.

Lock It Down
So, in my opinion, the best security policy can be stated as follows – “No one gets access to anything ever, everything else is an exception”. Paranoid? Maybe, but given the online world in which we live, it pays to be cautious. So, we are going to lock this firewall down so that nothing can come in or go out and then manage all connectivity as an exception to those default rules. Regardless of the initial state you find your firewall when you start it up, you can lock it down as follows:
sudo iptables -P INPUT DROP && sudo iptables OUTPUT DROP && sudo iptables FORWARD DROP

This will leave us with a firewall whose default state is to say ‘no’ to anything coming or going. Next, let’s open a few things so the system is usable.

Follow The Rules
We are going to use our desktop for outgoing web browsing. At this point, opening a web browser on the system would fail to bring up any website despite the network being available. So, we have to tell the firewall to ALLOW HTTP connections going out, using the appropriate protocol and port. That rule would look like this:
sudo iptables -A OUTPUT -p tcp --sport 80 -j ACCEPT

That simple rule literally translates as “append to the OUTPUT chain a new rule that allows outgoing TCP connections from the source port of 80”. This becomes ‘live’ as soon as you press enter. Again, being connected locally to your system is the best way to be sure that an errant rule entry will not disconnect you. Note here, each time your system reboots, your rules are empty. In a later article (and demonstrated during the video at Linux Academy), we will go over how to create a script that executes on boot to restore all your access rules.

If you bring up a web browser, you should now be able to browse the internet in general. If you list your firewall rules at this point, you should see something like this:

Chain OUTPUT (policy ACCEPT)
target prot opt source destination
ufw-before-logging-output all — anywhere anywhere
ufw-before-output all — anywhere anywhere
ufw-after-output all — anywhere anywhere
ufw-after-logging-output all — anywhere anywhere
ufw-reject-output all — anywhere anywhere
ufw-track-output all — anywhere anywhere
ACCEPT tcp — anywhere anywhere tcp spt:http

So now we can get out to browse, we can add a rule that allows us to make an outgoing SSH connection in exactly the same way. But what if we need to allow an incoming connection over SSH? It is handled very much the same, execute the following:
sudo iptables -A INPUT -p tcp --dport 22 -j ACCEPT

Do note that in all the examples, case does matter. The chain references and the actions must be capitalized or you will simply create problems. In the case of our rule above, the literal translation to our firewall is “append a new rule to the INPUT chain to allow incoming tcp connection to the destination port of 22”. You can test from another system by trying to SSH into the system your firewall is on. Strangely enough, if you try to execute an ‘ssh localhost’, it will fail to connect. Why would that be? We do not have a corresponding ‘OUTPUT’ rule that allows the system to make an outgoing connection over SSH, even though we are now listening for it. As an exercise, using the HTTP rule from above, write your ssh OUTPUT rule and make an outgoing connection to test.

Final Thoughts
We have only scratched the surface in exploring the power and flexibility of our firewall setup here. In fact, if you want to see a much deeper dive into the ‘iptables’ application, please visit Linux Academy and sign up. One of the benefits of membership is that we allow our members to vote on what they would like to see us create tutorials on, you drive the content that is most useful to you.

Leave a comment below with any questions you have on your firewall setup or particular rules you may be struggling with and I will do my best to help.

Terrence T. Cox

A veteran of twenty years in Information Technology in a variety of roles. He has worked in development, security and infrastructure well before they merged into what we now call DevOps. He provides training in Linux, VMWare, DevOps (Ansible, Jenkins, etc) as well as containers and AWS topics.

Leave a Reply

Your email address will not be published. Required fields are marked *