Sometimes there isn’t a clear line between perimeter and host-based security, and this is especially the case with iptables. This is a really low-level system of packet filtering that enables a UNIX/Linux box to function as an advanced perimeter firewall with capabilities that are comparable to, if not better than, expensive commercial equipment.
Since this relates to the operating system’s ability to interact with the network interface at the kernel level, it’s certainly important to understand what iptables is and how it works before doing anything with it related to production systems and perimeter security.
The basic description of iptables is a ‘kernel firewall’ that uses netfilter modules to implement packet filtering policies. In other words, the netfilter modules provide the kernel packet filtering services, and iptables provides the method of controlling this in user-space, through the /sbin/iptables executable.
What this should mean is the operating system ignores packets completely if they’re dropped/rejected by netfilter.
Packet filtering is defined by firewall rules that are grouped into ‘chains’ – this is basically what iptables consists of. Each table should have the following chains by default:
* INPUT: Packets to be delivered somewhere on the local system, and independently of any network socket.
* FORWARD: All packets that are routed non-locally.
* OUTPUT: Packets sent from the local host.
* PREROUTING: Used for NAT.
* POSTROUTING: Used for NAT.
Each chain is going to define how netfilter handles packets as they pass through the networking components of the kernel, as the following diagram, which I’ve borrowed from Linux Firewalls (Michael Rash, 2007), shows:
(Update: Even better, I’ve found a more detailed chart here.)
Here’s the bit that’s caused some confusion: iptables isn’t just a firewall. There’s another table for Network Address Translation (nat), a third table for modifying packets as they passes through netfilter (mangle), and a fourth table that allows packets through without interference or alteration (raw).
So now an iptables setup encompasses the following tables:
Much more complicated than our typical GUI-based firewall application, innit? But it’s necessary because although it’s host-based, a host might itself be deployed as a perimeter firewall.
Also on a UNIX/Linux system, we have (or should have) ip6tables. This is very important, because IPv6 and IPv4 headers are both different and have definite field lengths, which is how a firewall knows what it’s reading. Unless we set up IPv6 packet filtering as well, netfilter could potentially ignore and allow all incoming IPv6 traffic.
With Ubuntu and Linux Mint (and probably most mainstream distros) the netfilter modules are compiled into the kernel, but the hardcore techies who compile their own kernels get the option of having netfilter as loadable modules that could be added or removed during runtime. It’s hard to see which is better, but I should imagine there’s more latency with loadable modules, and the small possibility of an attacker unloading them if the host is compromised.
Administrating iptables and Packet Filtering
As I’ve already mentioned, filtering policies can be administrated using /sbin/iptables, but this is the cumbersome and rather complicated method until we develop a BASH script for our own needs. What I didn’t know, until looking into this, is that the Uncomplicated Firewall and its GUI (gufw) are also front-ends for iptables, and we can configure the firewall using those instead.
I’ll post some of the basic iptables rules here, in the hope of getting a feel for the syntax and general format. The first one flushes/wipes all the existing iptables entries:
Send all incoming packets to the DROP chain, if present:
$iptables -A INPUT -j DROP
The ‘-A‘ option tells iptables to append the rule to the existing INPUT chain.
The following allows all HTTP and HTTPS traffic:
$iptables -I INPUT 1 -p tcp --dport 80 -j ACCEPT
$iptables -I INPUT 1 -p tcp --dport 443 -j ACCEPT
So far so good. The simpler rules share pretty much the same format of other command line stuff. In the above rule, the packets are directed to the INPUT chain, they are sifted for TCP packets going through port 80 or 443, and they are ‘jumped’ to the ACCEPT chain.
Another example, from The Geek Stuff tutorial, allows all incoming SSH, HTTP and HTTPS traffic over TCP by chaining three policies within a single iptables entry:
$iptables -A INPUT -i eth0 -p tcp -m multiport --dports 22,80,443 -m state --state NEW,ESTABLISHED -j ACCEPT iptables -A OUTPUT -o eth0 -p tcp -m multiport --sports 22,80,443 -m state --state ESTABLISHED -j ACCEPT
Here we’ll notice there’s the state option, because iptables/netfilter can provide stateful filtering, that’s to say it can look at a packet in the context of whatever stream, and not as an isolated bit of data. In the above entry, I’m guessing that netfilter is being configured to accept only packets that are either establishing a connection or are part of an established connection, and therefore ignore anything that might be associated with a Denial of Service attack or stealth scan. We also have two network interfaces: input and output (both eth0). In the case of a perimeter firewall, both will be needed as the host will bridge the local network and the outside world.
Some people have reported problems in trying to make the firewall rules persistent. That’s because the rules are lost if they aren’t explicitly saved before the system is rebooted. The core problem here seems to be that iptables is intended for production systems that aren’t rebooted as often as PCs, and therefore the tables must be saved to file and manually restored unless the system is configured otherwise. As always, this is done in the command line:
$iptables-restore: Restore tables from file.
$iptables-save: Dump tables to file.
$iptables-xml: Convert output of iptables-save to XML format.
I believe the Red Hat distro also comes with a script/exectutable that automates this further:
This does the same as running iptables-save. The /etc/sysconfig/iptables file is then saved as /etc/sysconfig/iptables.save. The system should then run iptables-restore when the system reboots.
FEDORA DOCUMENTATION. 2013. Fedora Documentation: Saving IPTables Rules. [WWW]. http://docs.fedoraproject.org/en-US/fedora/17/html/Security_Guide/sect-Security_Guide-IPTables-Saving_IPTables_Rules.html. (17th August 2013).
NATARAJAN, R. 2011. The Geek Stuff: 25 Most Frequently Used Linux IPTables Rules Examples. [WWW]. http://www.thegeekstuff.com/2011/06/iptables-rules-examples/. (17th August 2013).
NATARAJAN, R. 2011.The Geek Stuff: Linux IPTables: How to Add Firewall Rules (With Allow SSH Example). [WWW]. http://www.thegeekstuff.com/2011/02/iptables-add-rule/. (17th August 2013).
NIXCRAFT. 2013. Linux Iptables Setup Firewall for a Web Server. [WWW]. http://www.cyberciti.biz/faq/linux-web-server-firewall-tutorial/. (17th August 2013).
RACKSPACE US, INC. 2013. Knowledge Center: Introduction to iptables. [WWW]. http://www.rackspace.com/knowledge_center/article/introduction-to-iptables. (17th August 2013).
RUSSEL, R. WELTE, H. 2002. Linux netfilter Hacking HOWTO: Netfilter Architecture. [WWW]. http://www.netfilter.org/documentation/HOWTO/netfilter-hacking-HOWTO-3.html. (24th August 2013).