Shorewall and Ipsets

Tom Eastep

Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.2 or any later version published by the Free Software Foundation; with no Invariant Sections, with no Front-Cover, and with no Back-Cover Texts. A copy of the license is included in the section entitled “GNU Free Documentation License”.

2009/02/27


Table of Contents

What are Ipsets?
Shorewall Support for Ipsets
Defining Dynamic Zones using Ipsets

What are Ipsets?

Ipsets are an extension to Netfilter/iptables that are currently available in Patch-O-Matic-ng (http://www.netfilter.org). Using ipsets requires that you patch your kernel and iptables and that you build and install the ipset utility from http://ipset.netfilter.org/.

Ipset allows you to create one or more named sets of addresses then use those sets to define Netfilter/iptables rules. Possible uses of ipsets include:

  1. Blacklists. Ipsets provide an efficient way to represent large sets of addresses and you can maintain the lists without the need to restart or even refresh your Shorewall configuration.

  2. Zone definition. Using the /etc/shorewall/hosts file, you can define a zone based on the (dynamic) contents of an ipset. Again, you can then add or delete addresses to the ipset without restarting Shorewall.

See the ipsets site (URL above) for additional information about ipsets.

Shorewall Support for Ipsets

Support for ipsets was introduced in Shorewall version 2.3.0. In most places where a host or network address may be used, you may also use the name of an ipset prefaced by "+".

Example: "+Mirrors"

When using Shorewall-perl, the names of ipsets are restricted as follows:

  • They must begin with a letter (after the '+').

  • They must be composed of letters, digits or underscores ("_").

The name of the set may optionally followed by:

  1. a number from 1 to 6 enclosed in square brackets ([]) -- this number indicates the maximum number of ipset binding levels that are to be matched. Depending on the context where the ipset name is used, either all "src" or all "dst" matches will be used.

    Example: "+Mirrors[4]"

  2. a series of "src" and "dst" options separated by commas and enclosed in square brackets ([]). These will be passed directly to iptables in the generated --set clause. See the ipset documentation for details.

    Example: "+Mirrors[src,dst,src]"

    Note that "+Mirrors[4]" used in the SOURCE column of the rules file is equivalent to "+Mirrors[src,src,src,src]".

To generate a negative match, prefix the "+" with "!" as in "!+Mirrors".

Example 1: Blacklist all hosts in an ipset named "blacklist"

/etc/shorewall/blacklist

#ADDRESS/SUBNET         PROTOCOL        PORT
+blacklist

Example 2: Allow SSH from all hosts in an ipset named "sshok:

/etc/shorewall/rules

#ACTION      SOURCE      DEST     PROTO    DEST PORT(S)
ACCEPT       +sshok      $FW      tcp      22

If you are running Shorewall-shell:

Shorewall can automatically manage the contents of your ipsets for you. If you specify SAVE_IPSETS=Yes in /etc/shorewall/shorewall.conf then "shorewall save" will save the contents of your ipsets. The file where the sets are saved is formed by taking the name where the Shorewall configuration is stored and appending "-ipsets". So if you enter the command "shorewall save standard" then Shorewall will save the file as /var/lib/shorewall/standard-ipsets

Regardless of the setting of SAVE_IPSETS, the shorewall -f start and shorewall restore commands will restore the ipset contents corresponding to the Shorewall configuration restored provided that the saved Shorewall configuration specified exists.

For example, shorewall restore standard would restore the ipset contents from /var/lib/shorewall/standard-ipsets provided that /var/lib/shorewall/standard exists and is executable and that /var/lib/shorewall/standard-ipsets exists and is executable.

Also regardless of the setting of SAVE_IPSETS, the shorewall forget command will purge the saved ipset information (if any) associated with the saved shorewall configuration being removed.

You can also associate ipset contents with Shorewall configuration directories using the following command:

ipset -S > <config directory>/ipsets

Example:

ipset -S > /etc/shorewall/ipsets

When you start or restart Shorewall (including using the try command) from the configuration directory, your ipsets will be configured from the saved ipsets file. Once again, this behavior is independent of the setting of SAVE_IPSETS.

As mentioned above, ipsets are well suited for large blacklists. You can maintain your blacklist using the 'ipset' utility without ever having to restart or refresh Shorewall. If you use the SAVE_IPSETS=Yes feature just be sure to "shorewall save" after altering the blacklist ipset(s).

If you are running Shorewall-perl:

Shorewall is now out of the ipset load/reload business. With scripts generated by the Perl-based Compiler, the Netfilter rule set is never cleared. That means that there is no opportunity for Shorewall to load/reload your ipsets since that cannot be done while there are any current rules using ipsets.

So:

  1. Your ipsets must be loaded before Shorewall starts. You are free to try to do that with the following code in /etc/shorewall/init (it works for me; your mileage may vary):

    if [ "$COMMAND" = start ]; then
        ipset -U :all: :all:
        ipset -U :all: :default:
        ipset -F
        ipset -X
        ipset -R < /etc/shorewall/ipsets
    fi

    The file /etc/shorewall/ipsets will normally be produced using the ipset -S command.

    The above will work most of the time but will fail in a shorewall stop - shorewall start sequence if you use ipsets in your routestopped file (see below).

  2. Your ipsets may not be reloaded until Shorewall is stopped or cleared.

  3. If you specify ipsets in your routestopped file then Shorewall must be cleared in order to reload your ipsets.

As a consequence, scripts generated by the Perl-based compiler will ignore /etc/shorewall/ipsets and will issue a warning if you set SAVE_IPSETS=Yes in shorewall.conf.

Example (Note -- this example is applicable to ipset versions up to and including 2.4. In 2.5, the binding feature of ipsets is scheduled for removal in favor of different set types that include both IP addresses and port numbers. Check your ipset documentation):

/etc/shorewall/blacklist:

#ADDRESS/SUBNET         PROTOCOL        PORT
+Blacklist[src,dst]
+Blacklistnets[src,dst]

Create the blacklist ipsets using:

ipset -N Blacklist iphash
ipset -N Blacklistnets nethash

Add entries:

ipset -A Blacklist 206.124.146.177
ipset -A Blacklistnets 206.124.147.0/24

To allow entries for individual ports:

ipset -N SMTP portmap --from 1 --to 31
ipset -A SMTP 25

ipset -A Blacklist 206.124.146.177
ipset -B Blacklist 206.124.146.177 -b SMTP

Now only port 25 will be blocked from 206.124.146.177.

Defining Dynamic Zones using Ipsets

The use of ipsets provides a much better way to define dynamic zones than is provided by the native Shorewall implementation. To define a dynamic zone of hosts dyn that is a sub-zone of zone loc and that interfaces through interface eth3, use:

/etc/shorewall/zones:

#ZONE         TYPE         OPTIONS            IN OPTIONS        OUT OPTIONS
loc           ipv4
dyn:loc       ipv4

/etc/shorewall/interfaces:

#ZONE         INTERFACE     OPTIONS
loc           eth3          …

/etc/shorewall/hosts:

#ZONE         HOSTS         OPTIONS
dyn           eth3:+Dyn

Now create an ipmap named Dyn and you're all set. You can add and delete addresses from Dyn without having to touch Shorewall.