Building Firewalls with iptables, Part 1
Exposing any system, no matter how briefly, to an untrusted network is suicidal. A firewall, while not a 100% secure solution, is absolutely vital. The Linux world gives us an excellent firewall utility in netfilter/iptables. It is free and runs nicely on feeble old PCs. Netfilter/iptables is flexible, powerful, and enables fine-grained control of incoming and outgoing traffic. The two main functions this series will address are building firewalls and sharing Internet connections, which commonly go hand-in-hand. In Part 1 we'll cover basic concepts; Part 2 will offer examples of rulesets for various uses.
Netfilter/iptables is included with the 2.4/2.5 Linux kernel for firewall, network address translation (NAT), and packet mangling functions. Netfilter works inside the kernel, while iptables is the table structure for the user-defined rulesets. Netfilter/iptables is the descendant of our old friends ipchains and ipwadfm (IP firewall administration); for simplicity, let's call it iptables from this point forward.
Some other excellent uses for iptables are for building firewalls for individual Unix/Linux/BSD workstations and also for building firewalls for subnets to protect other platforms. It's free, so why not construct layers of defenses? Depending solely on a gateway firewall is not enough.
iptables reads only packet headers, and as a result does not inspect payload. It also does not perform authentication. For extra security, combine it with a proxy server such as squid. For Windows users, AnalogX is a popular proxy server noted for its ease of use. (Beware that the default configuration is completely insecure. Do not "set it and forget it," as it installs wide open.)
What It Does
The typical setup is to have two network interfaces -- one "outward" and one "inward" (or call them public and private). iptables reads incoming (and outgoing -- don't forget egress filtering!) packet headers and compares them to the rulesets, then forwards the acceptable packets from one interface to the other. Rejected packets are dropped on the spot -- boom splat -- or are directed in other ways, as you prefer.
Packets must traverse tables and chains. iptables has three built-in tables: filter, NAT, and mangle. (The mangle table is for specialized packet alterations, which we will not cover in this series.) Chains are the lists of rules in each table that match packets and then tell what to do with them. Target is any rule that applies to a matching packet. You'll see these terms a lot.
Unlike ipchains and ipfwadm, iptables uses stateful packet inspection. iptables inspects the source and destination IP addresses, the source and destination ports, and the sequence numbers of incoming packets. In a sense, iptables "remembers" which packets are already permitted on an existing connection. This provides a significant gain in security -- ephemeral ports are open only for as long as they are needed, as opposed to requiring all manner of permanent holes in the firewall to accomodate the various protocols. Malicious packets with altered headers are detected and dropped, even when they contain an allowed destination address and port.
Starting and Stopping iptables
This depends on your individual flavor of Linux; a nice rc script does the job, or you can run it manually from the command line. Please consult the docs for your distribution. Part 2 in this series will have sample scripts.
As always, the more you understand about TCP/IP, the more this stuff makes sense. iptables rules filter and match on packet headers and TCP/IP protocols -- any of them.
iptables is commonly included in Linux distributions; it would be very unusual to not have it. Run iptables --version to see what's on your system. If for some inexplicable reason you do not have it, see Resources at the end of this article.
man iptables is a complete reference for all the commands and options, or run iptables --help for a quick reference. To view your existing iptables rules, run:
# iptables --list
This is what iptables looks like with no rules defined:
Chain INPUT (policy ACCEPT) target prot opt source destination Chain FORWARD (policy ACCEPT) target prot opt source destination Chain OUTPUT (policy ACCEPT) target prot opt source destination
As shown in the above example, every packet must first traverse one of three built-in chains: INPUT, OUTPUT, or FORWARD.
Filter is the most commonly used table. Here is the basic syntax for all iptables rules:
iptables [-t table] command [match] [target/jump]
Not every piece of this is required, nor does it need to be in this order; however, this is the usual method, and as always, I encourage verbosity for the sake of clarity.
The filter table is the default if none is specified. The three most common targets in the filter table are ACCEPT, DROP, and REJECT. DROP drops packets dead, with no further processing. No messages are sent at all to anyone. REJECT sends back an error message to the sending host. DROP is very useful, although at times it may have undesirable side effects, such as leaving a messy trail of dead sockets.
This example rule blocks traffic from a specific IP range because it belongs to a notoriously noxious spammer, and we don't want the spammer's spew polluting our nice systems:
# iptables -t filter -A INPUT -s 123.456.789.0/24 -j DROP
See how it follows the syntax described above. (See man iptables for definitions of the various switches and commands.) Now let's say your users are becoming increasingly vindictive and resentful towards spammers, which is understandable, but certain retaliatory tactics are simply not permissible, at least not from your network. We can also block all outgoing packets directed to the spammer's IPs easily enough with this slightly different syntax:
# iptables -t filter -A OUTPUT -d 123.456.789.0/24 -j DROP
Notice the -A switch. Use this to append rules to existing chains.
Spammers are shifty, experts at playing whack-a-mole (in the role of the mole) by continually changing IPs and DNS. Suppose our ignominious spammer moves to a new IP range, and the old IP address is then reassigned to some saintly nuns, whose bits are worthy to traverse your network. Simply delete the rule with the -D switch:
# iptables -t filter -D OUTPUT -d 123.456.789.0/24 -j DROP
Crafting rules to cover every contingency is a nice way to consume mass quantities of time. For those who would rather not, the basic principle is "deny all, allow only as needed." Let's set up the default rules for each chain:
# iptables -P INPUT DROP
# iptables -P FORWARD DROP
# iptables -P OUTPUT ACCEPT
-P sets the policy for the chain. Only the three built-in chains can have policies. These policies permit unfettered outgoing traffic, but no incoming traffic. At the very least, we want to hear from the nuns:
# iptables -t filter -A INPUT -s 123.456.789.0/24 -j ACCEPT
Stay tuned for Part 2, which will offer more sample rules and scripts.