Multiple set matches with Linux's iptables 'ipset' extension

June 25, 2015

Recently, Luke Atchew approached me on Twitter to ask if I had any ideas for solving an ipset challenge. Suppose that you have a set of origin hosts, a set of destination servers, and you want to allow traffic from the origin hosts to the destination servers while blocking all other traffic. As Luke noted, most ipset examples, including mine, are about blocking access to or from a set of hosts; they don't have a matrix setup like Luke's.

One obvious option is a complex multi-rule setup, where you have a series of rules that try to block and accept more and more of the traffic that you want; for example, you can start out by blocking all traffic to '! -match-set Destinations dst'. This gets complex if you have other rules involved, though. Another option is one of ipset's more complicated set types, such as hash:net,net, but then you get into hassles populating and maintaining the set (since it's basically the cross product of your allowed source and destination hosts).

As Luke Atchew discovered while working on this, all of this complexity is unnecessary because you can match against multiple ipset sets in the same iptables rule. It is perfectly legitimate to write rules like:

iptables -A FORWARD -m set --match-set Locals src -m set --match-set Remotes dst -j ACCEPT
iptables -A FORWARD -m set ! --match-set Locals src -m set --match-set Remotes dst -j DROP

(These rules use different keys, here the source and destination IPs, but it's probably legitimate to have several --match-set's that reuse the same key. You might need a source IP to be in an 'allowed' set and not in a 'temporarily blocked' set, for example.)

An important note here is that you absolutely have to use two '-m set' arguments, one before each --match-set. If you leave the second one out you will get the somewhat obscure error message 'iptables v1.4.21: --match-set can be specified only once', which may mislead you into believing that this isn't supported at all. This is a really easy mistake to make because it sure smells like the second -m set is surplus; after all, you already told iptables you wanted to use the ipset extension here.

(I assume that the second '-m set' is causing the parser to start setting up a new internal ipset matching operation instead of accumulating more options for the first one.)

Written on 25 June 2015.
« I've finally turned SELinux fully off even on my laptop
The status of our problems with overloaded OmniOS NFS servers »

Page tools: View Source, Add Comment.
Login: Password:
Atom Syndication: Recent Comments.

Last modified: Thu Jun 25 02:03:13 2015
This dinky wiki is brought to you by the Insane Hackers Guild, Python sub-branch.