Advanced Firewall Configurations with ipset
iptables is the user-space tool for configuring firewall rules in the Linux kernel. It is actually a part of the larger netfilter framework. Perhaps because iptables is the most visible part of the netfilter framework, the framework is commonly referred to collectively as iptables. iptables has been the Linux firewall solution since the 2.4 kernel.
ipset is an extension to iptables that allows you to create firewall rules that match entire "sets" of addresses at once. Unlike normal iptables chains, which are stored and traversed linearly, IP sets are stored in indexed data structures, making lookups very efficient, even when dealing with large sets.
Besides the obvious situations where you might imagine this would be useful, such as blocking long lists of "bad" hosts without worry of killing system resources or causing network congestion, IP sets also open up new ways of approaching certain aspects of firewall design and simplify many configuration scenarios.
In this article, after quickly discussing ipset's installation requirements, I spend a bit of time on iptables' core fundamentals and concepts. Then, I cover ipset usage and syntax and show how it integrates with iptables to accomplish various configurations. Finally, I provide some detailed and fairly advanced real-world examples of how ipsets can be used to solve all sorts of problems.
With significant performance gains and powerful extra features—like the ability to apply single firewall rules to entire groups of hosts and networks at once—ipset may be iptables' perfect match.
Because ipset is just an extension to iptables, this article is as much about iptables as it is about ipset, although the focus is those features relevant to understanding and using ipset.
ipset is a simple package option in many distributions, and since plenty of other installation resources are available, I don't spend a whole lot of time on that here.
The important thing to understand is that like iptables, ipset consists of both a user-space tool and a kernel module, so you need both for it to work properly. You also need an "ipset-aware" iptables binary to be able to add rules that match against sets.
Start by simply doing a search for "ipset" in your
distribution's package management tool.
There is a good chance you'll be able to find an easy
procedure to install ipset in a turn-key way. In Ubuntu (and
probably Debian), install the ipset and xtables-addons-source
packages. Then, run
ipset is ready to go in less than 30 seconds.
If your distro doesn't have built-in support, follow the manual installation procedure listed on the ipset home page (see Resources) to build from source and patch your kernel and iptables.
The versions used in this article are ipset v4.3 and iptables v1.4.9.
In a nutshell, an iptables firewall configuration consists of a set of built-in "chains" (grouped into four "tables") that each comprise a list of "rules". For every packet, and at each stage of processing, the kernel consults the appropriate chain to determine the fate of the packet.
Chains are consulted in order, based on the "direction" of the packet (remote-to-local, remote-to-remote or local-to-remote) and its current "stage" of processing (before or after "routing"). See Figure 1.
Figure 1. iptables Built-in Chains Traversal Order
When consulting a chain, the packet is compared to each and every one of the chain's rules, in order, until it matches a rule. Once the first match is found, the action specified in the rule's target is taken. If the end of the chain is reached without finding a match, the action of the chain's default target, or policy, is taken.
A chain is nothing more than an ordered list of rules, and a rule is nothing more than a match/target combination. A simple example of a match is "TCP destination port 80". A simple example of a target is "accept the packet". Targets also can redirect to other user-defined chains, which provide a mechanism for the grouping and subdividing of rules, and cascading through multiple matches and chains to arrive finally at an action to be taken on the packet.
Every iptables command for defining rules, from the very short to the very long, is composed of three basic parts that specify the table/chain (and order), the match and the target (Figure 2).
Figure 2. Anatomy of an iptables Command
To configure all these options and create a complete firewall configuration, you run a series of iptables commands in a specific order.
iptables is incredibly powerful and extensible. Besides its many built-in features, iptables also provides an API for custom "match extensions" (modules for classifying packets) and "target extensions" (modules for what actions to take when packets match).
ipset is a "match extension" for iptables. To use it, you create and populate uniquely named "sets" using the ipset command-line tool, and then separately reference those sets in the match specification of one or more iptables rules.
A set is simply a list of addresses stored efficiently for fast lookup.
Take the following normal iptables commands that would block inbound traffic from 22.214.171.124 and 126.96.36.199:
iptables -A INPUT -s 188.8.131.52 -j DROP iptables -A INPUT -s 184.108.40.206 -j DROP
The match specification syntax
-s 220.127.116.11 above
means "match packets
whose source address is 18.104.22.168". To block both 22.214.171.124 and 126.96.36.199,
two separate iptables rules with two separate match specifications
(one for 188.8.131.52 and one for 184.108.40.206) are defined above.
Alternatively, the following ipset/iptables commands achieve the same result:
ipset -N myset iphash ipset -A myset 220.127.116.11 ipset -A myset 18.104.22.168 iptables -A INPUT -m set --set myset src -j DROP
The ipset commands above create a new set (
with two addresses (22.214.171.124 and 126.96.36.199).
The iptables command then references the set with the match specification
-m set --set myset src, which means "match packets whose source header
matches (that is, is contained within) the set named myset".
src means match on "source".
dst would match on
"destination", and the flag
src,dst would match on both source and
In the second version above, only one iptables command is required, regardless of how many additional IP addresses are contained within the set. Although this example uses only two addresses, you could just as easily define 1,000 addresses, and the ipset-based config still would require only a single iptables rule, while the previous approach, without the benefit of ipset, would require 1,000 iptables rules.