In most organizations, network security has become interwoven with standard network and system administration. Threats in the form of malicious hackers, self-propagating worms, denial of service attacks, and other nefarious security problems loom large for administrators. Of course, one of the building blocks of network security is a good firewall. Although many companies pay top dollar for commercial firewall solutions, Linux has long been a popular option for those who want to save some big money and who don't mind rolling up their sleeves and building the firewall configuration themselves.
Fortunately, the Linux firewall solution has continued to improve and the netfilter/iptables system now provides a robust and supremely flexible solution. netfilter/iptables (netfilter is the name of the project, and iptables is the name of the Linux software itself) is a system integrated into the Linux 2.4.x kernel for the handling of packet filtering. It is the successor to the ipchains and ipfwadm systems and is the first to be incorporated directly into the kernel. Here's a look at how you can build a strong Linux firewall with iptables.
Although there are many ways to design a firewall system, the basics remain the same. Set up a server with two network interface cards, one that connects to the Internet and one that connects to the private, internal network. (And if you want a DMZ for your hosted services, you set up a third NIC.) Then, you set up the firewall to filter packets to allow or deny certain traffic, creating a secured environment and freeing up bandwidth and processor cycles for more important work.
The main point of the firewall is to open up to the traffic that you need and close out everything else. The terms open and close refer to the actual ports, usually TCP, UDP, or ICMP, that allow connections to be established on a server. Communication between systems on the Internet can be looked at generally on a packet level. A packet contains information in its header such as source address, destination address, and protocol type, which iptables can then use to make filtering decisions.
Unlike ipchains and ipfwadm, iptables can be configured as a stateful firewall, rather than being stateless. Also known as connection tracking, being stateful means the firewall will remember previous decisions involving the handling of packets instead of treating each one as new event. Valid states include INVALID, ESTABLISHED, and NEW.
The netfilter/iptables system is part of the 2.4.x kernel, as mentioned above; however, the actual firewalling software, also called iptables, is not part of the kernel. Netfilter is often used to refer to the kernel portion, while the iptables tool is used to actually insert and delete rules in the kernel’s packet filtering table. While many distributions such as Red Hat include iptables as part of their standard install, you may need to download it separately from Netfilter.org. If installing from source, the following commands should get you up and running:
# bzip2 -d iptables-1.2.6a.tar.bz2
# tar -xpf iptables-1.2.6a.tar
# cd iptables-1.2.6a
# make <PATH_TO_KERNEL>
# make install <PATH_TO_KERNEL>
Support will most likely be preconfigured for the more recent kernels, but it may be necessary to compile it yourself. You'll need to do this if you receive an error such as “iptables is incompatible with your kernel.” First, verify that you're running a 2.4.x kernel (with uname –a, for instance) and compile a new kernel. Be sure to set the CONFIG_NETFILTER option to Y.
Configuring the firewall
Once iptables is running on your system, it’s time to look at configuring the firewall. The main commands you should be familiar with are listed in Table A.
|—append or –A||Append to chain|
|—delete or –D||Delete rule from chain|
|—list or –L [chain]||List rules in a chain or all chains|
|—flush or –F [chain]||Delete all rules in a chain or all chains|
The best way to set up your firewall so that the rules are saved and run each time your system boots is to create a script you can run manually and/or have the system run at startup. The firewall script shown in Listing A will get us started.
While this is a simple firewall, it covers many of the basic commands you will need to use. Our first step is to configure the variables used by the script. This is helpful in larger scripts, where it’s much easier to change a variable once than to modify every entry containing that variable, such as an IP address. After that, we flush the rules with the IPTABLES –F command, allowing us to start from a clean slate by wiping out any current iptables rules that are running. This is important when you consider rules are checked in sequential order. We don’t want a lingering filter to deny packets we now want to accept, or vice versa.
Next, we set the default rules for the three main chains—we deny incoming packets by default and we allow outgoing packets and forwarded (NAT) packets by default. As mentioned before, we want to open only what we need and make sure everything else is closed. We accomplish this by setting the default action on the INPUT chain (incoming packets) to DROP. Basically, all packets processed by the chain will be dropped unless explicitly allowed.
The OUTPUT and FORWARD chains are set to ACCEPT, as this traffic is coming from the internal network. If you plan on implementing policy with iptables, you should set this to DROP. It’s also important to note that if you are allowing all traffic sourced from the internal network, it might be a good idea to do some commonsense filtering. One example of this would be to set a rule that discards packets received on the external interface with an internal IP address (a sure sign of someone who is up to something).
To permit users to connect to the server via SSH or to allow inbound HTTP requests, we need to tell iptables to allow these packets. We do this by appending rules to a particular chain. This example from my script shows how to allow SSH (TCP port 22) on the external interface:
$IPTABLES -A INPUT -i $WAN_IFACE -p TCP —destination-port 22 \ -j ACCEPT
Let's break this down. The -A means append, or add, a particular rule. The -i refers to the interface that will be receiving the packets. The protocol is specified with the –p option, which can be TCP, UDP, ICMP, or ALL. The destination port is dependent upon the particular service that access is being granted. In the case of SSH, it operates on the well-known TCP port 22. And finally, we have the target of the rule, which in this case is ACCEPT. Other possibilities include DROP, REJECT, and user-defined actions. ACCEPT allows the packet through, and DROP means the packet is discarded. REJECT is the same as DROP, but it also sends back an error response to the sender of the packet.
In the above example, we have an entry that provides port forwarding. This is a means by which services can be forwarded by an external machine to an internal one. This is especially handy when you have just one routable IP address but would like to use multiple servers. This is accomplished with a form of network address translation (NAT). In this instance, we are forwarding SMTP traffic on port 25 from our WAN_IFACE to the internal address of 192.168.1.5. Thus, an SMTP server looks like it is sitting at 10.0.0.1. But in reality, that's the external address of the firewall, which is forwarding all requests on SMTP port 25 to the internal server at 192.168.1.5. The use of NAT provides for the return communication as well, making its use completely transparent to those connecting to it from the Internet.
For more information on iptables configuration, check out these resources:
- · Netfilter/iptables FAQ
- · Linux 2.4 Packet Filtering HOWTO
- · Oskar Andreasson's IPTables Tutorial 1.1.9
- · Iptables MAN page
- · MonMotha's IPTables Firewall
Linux can help administrators create a strong firewall with the powerful, kernel-based netfilter/iptables software. As I demonstrated, iptables can create general or specific packet filters to allow or deny traffic. This enables administrators to protect their servers from a wide variety of hazards, including service attacks and hack attempts. As always, the best way to learn is to get your hands dirty and experiment with iptables on a testing machine. This article introduced you to the basic concepts of building a strong iptables firewall. My next article will delve into some of the more advanced options that iptables has to offer.