<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE article PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN"
"http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd">
<article>
  <!--$Id$-->

  <articleinfo>
    <title>Shorewall and Ipsets</title>

    <authorgroup>
      <author>
        <firstname>Tom</firstname>

        <surname>Eastep</surname>
      </author>
    </authorgroup>

    <pubdate><?dbtimestamp format="Y/m/d"?></pubdate>

    <copyright>
      <year>2005</year>

      <year>2008</year>

      <holder>Thomas M. Eastep</holder>
    </copyright>

    <legalnotice>
      <para>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
      <quote><ulink url="GnuCopyright.htm">GNU Free Documentation
      License</ulink></quote>.</para>
    </legalnotice>
  </articleinfo>

  <section id="Ipsets">
    <title>What are Ipsets?</title>

    <para>Ipsets are an extension to Netfilter/iptables that are currently
    available in <ulink
    url="http://xtables-addons.sourceforge.net/">xtables-addons</ulink>.
    Instructions for installing xtables-addons may be found in the <ulink
    url="Dynamic.html">Dynamic Zones article</ulink>.</para>

    <para>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:</para>

    <orderedlist>
      <listitem>
        <para>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.</para>
      </listitem>

      <listitem>
        <para>Zone definition. Using the /etc/shorewall/hosts file, you can
        <ulink url="Dynamic.html">define a zone based on the (dynamic)
        contents of an ipset</ulink>. Again, you can then add or delete
        addresses to the ipset without restarting Shorewall.</para>
      </listitem>
    </orderedlist>

    <para>See the ipsets site (URL above) for additional information about
    ipsets.</para>
  </section>

  <section id="Support">
    <title>Shorewall Support for Ipsets</title>

    <para>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 "+".</para>

    <para>Example: "+Mirrors"</para>

    <para>When using Shorewall, the names of ipsets are restricted as
    follows:</para>

    <itemizedlist>
      <listitem>
        <para>They must begin with a letter (after the '+').</para>
      </listitem>

      <listitem>
        <para>They must be composed of letters, digits or underscores
        ("_").</para>
      </listitem>
    </itemizedlist>

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

    <para>Example 1: Blacklist all hosts in an ipset named "blacklist"</para>

    <para><filename>/etc/shorewall/blacklist</filename><programlisting>#ADDRESS/SUBNET         PROTOCOL        PORT
+blacklist</programlisting></para>

    <para>Example 2: Allow SSH from all hosts in an ipset named "sshok:</para>

    <para><filename>/etc/shorewall/rules</filename><programlisting>#ACTION      SOURCE      DEST     PROTO    DEST PORT(S)
ACCEPT       net:+sshok  $FW      tcp      22</programlisting></para>

    <para>Shorewall is not in the ipset load/reload business because 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.</para>

    <para>So:</para>

    <orderedlist numeration="upperroman">
      <listitem>
        <para>Your ipsets must be loaded before Shorewall starts. You are free
        to try to do that with the following code in
        <filename>/etc/shorewall/init (it works for me; your mileage may
        vary)</filename>:</para>

        <programlisting>if [ "$COMMAND" = start ]; then
    ipset -F
    ipset -X
    ipset -R &lt; /etc/shorewall/ipsets
fi</programlisting>

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

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

      <listitem>
        <para>Your ipsets may not be reloaded until Shorewall is stopped or
        cleared.</para>
      </listitem>

      <listitem>
        <para>If you specify ipsets in your routestopped file then Shorewall
        must be cleared in order to reload your ipsets.</para>
      </listitem>
    </orderedlist>

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