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

  <articleinfo>
    <title>User-defined Actions</title>

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

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

    <pubdate>2004-03-25</pubdate>

    <copyright>
      <year>2003</year>

      <year>2004</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>
    <title>Creating a New Action</title>

    <para>Prior to Shorewall version 1.4.9, rules in <filename>/etc/shorewall/rules</filename>
    were limited to those defined by Netfilter (ACCEPT, DROP, REJECT, etc.).
    Beginning with Shorewall version 1.4.9, users may use sequences of these
    elementary operations to define more complex actions.</para>

    <para>To define a new action:</para>

    <orderedlist>
      <listitem>
        <para>Add a line to <filename><filename>/etc/shorewall/actions</filename></filename>
        that names your new action. Action names must be valid shell variable
        names as well as valid Netfilter chain names. It is recommended that
        the name you select for a new action begins with with a capital
        letter; that way, the name won&#39;t conflict with a Shorewall-defined
        chain name.</para>

        <para>Beginning with Shorewall-2.0.0-Beta1, the name of the action may
        be optionally followed by a colon (<quote>:</quote>) and ACCEPT, DROP
        or REJECT. When this is done, the named action will become the
        <emphasis>common action </emphasis>for policies of type ACCEPT, DROP
        or REJECT respectively. The common action is applied immediately
        before the policy is enforced (before any logging is done under that
        policy) and is used mainly to suppress logging of uninteresting
        traffic which would otherwise clog your logs. The same policy name can
        appear in multiple actions; the last such action for each policy name
        is the one which Shorewall will use.</para>

        <para>Shorewall includes pre-defined actions for DROP and REJECT --
        see below.</para>
      </listitem>

      <listitem>
        <para>Once you have defined your new action name (ActionName), then
        copy /usr/share/shorewall/action.template to <filename>/etc/shorewall/action.ActionName</filename>
        (for example, if your new action name is <quote>Foo</quote> then copy
        <filename>/usr/share/shorewall/action.template</filename> to
        <filename>/etc/shorewall/action.Foo</filename>).</para>
      </listitem>

      <listitem>
        <para>Now modify the new file to define the new action.</para>
      </listitem>
    </orderedlist>

    <para>Columns in the action.template file are as follows:</para>

    <itemizedlist>
      <listitem>
        <para>TARGET - Must be ACCEPT, DROP, REJECT, LOG, CONTINUE, QUEUE or
        &#60;<emphasis>action</emphasis>&#62; where &#60;<emphasis>action</emphasis>&#62;
        is a previously-defined action (that is, it must precede the action
        being defined in this file in your <filename>/etc/shorewall/actions</filename>
        file). These actions have the same meaning as they do in the
        <filename>/etc/shorewall/rules</filename> file (CONTINUE terminates
        processing of the current action and returns to the point where that
        action was invoked). The TARGET may optionally be followed by a colon
        (<quote>:</quote>) and a syslog log level (e.g, REJECT:info or
        ACCEPT:debugging). This causes the packet to be logged at the
        specified level. You may also specify ULOG (must be in upper case) as
        a log level.This will log to the ULOG target for routing to a separate
        log through use of ulogd (<ulink
        url="http://www.gnumonks.org/projects/ulogd">http://www.gnumonks.org/projects/ulogd</ulink>).</para>
      </listitem>

      <listitem>
        <para>SOURCE - Source hosts to which the rule applies. A
        comma-separated list of subnets and/or hosts. Hosts may be specified
        by IP or MAC address; mac addresses must begin with <quote>~</quote>
        and must use <quote>-</quote> as a separator.</para>

        <para>Alternatively, clients may be specified by interface name. For
        example, eth1 specifies a client that communicates with the firewall
        system through eth1. This may be optionally followed by another colon
        (<quote>:</quote>) and an IP/MAC/subnet address as described above
        (e.g., eth1:192.168.1.5).</para>
      </listitem>

      <listitem>
        <para>DEST - Location of Server. Same as above with the exception that
        MAC addresses are not allowed.</para>

        <para>Unlike in the SOURCE column, you may specify a range of up to
        256 IP addresses using the syntax &#60;<emphasis>first ip</emphasis>&#62;-&#60;<emphasis>last
        ip</emphasis>&#62;.</para>
      </listitem>

      <listitem>
        <para>PROTO - Protocol - Must be <quote>tcp</quote>, <quote>udp</quote>,
        <quote>icmp</quote>, a number, or <quote>all</quote>.</para>
      </listitem>

      <listitem>
        <para>DEST PORT(S) - Destination Ports. A comma-separated list of Port
        names (from <filename>/etc/services</filename>), port numbers or port
        ranges; if the protocol is <quote>icmp</quote>, this column is
        interpreted as the destination icmp-type(s).</para>

        <para>A port range is expressed as &#60;<emphasis>low port</emphasis>&#62;:&#60;<emphasis>high
        port</emphasis>&#62;.</para>

        <para>This column is ignored if PROTOCOL = all but must be entered if
        any of the following ields are supplied. In that case, it is suggested
        that this field contain <quote>-</quote>.</para>

        <para>If your kernel contains multi-port match support, then only a
        single Netfilter rule will be generated if in this list and in the
        CLIENT PORT(S) list below:</para>

        <orderedlist>
          <listitem>
            <para>There are 15 or less ports listed.</para>
          </listitem>

          <listitem>
            <para>No port ranges are included.</para>
          </listitem>
        </orderedlist>

        <para>Otherwise, a separate rule will be generated for each port.</para>
      </listitem>

      <listitem>
        <para>SOURCE PORT(S) - Port(s) used by the client. If omitted, any
        source port is acceptable. Specified as a comma-separated list of port
        names, port numbers or port ranges.</para>

        <para>If you don&#39;t want to restrict client ports but need to
        specify an ADDRESS in the next column, then place &#34;-&#34; in this
        column.</para>

        <para>If your kernel contains multi-port match support, then only a
        single Netfilter rule will be generated if in this list and in the
        DEST PORT(S) list above:</para>

        <orderedlist>
          <listitem>
            <para>There are 15 or less ports listed.</para>
          </listitem>

          <listitem>
            <para>No port ranges are included.</para>
          </listitem>
        </orderedlist>

        <para>Otherwise, a separate rule will be generated for each port.</para>
      </listitem>

      <listitem>
        <para>RATE LIMIT - You may rate-limit the rule by placing a value in
        this column:</para>

        <para><programlisting>     &#60;<emphasis>rate</emphasis>&#62;/&#60;<emphasis>interval</emphasis>&#62;[:&#60;<emphasis>burst</emphasis>&#62;]</programlisting>where
        &#60;<emphasis>rate</emphasis>&#62; is the number of connections per
        &#60;<emphasis>interval</emphasis>&#62; (<quote>sec</quote> or
        <quote>min</quote>) and &#60;<emphasis>burst</emphasis>&#62; is the
        largest burst permitted. If no &#60;<emphasis>burst</emphasis>&#62; is
        given, a value of 5 is assumed. There may be no whitespace embedded in
        the specification.</para>

        <para><programlisting>     Example: 10/sec:20</programlisting></para>
      </listitem>

      <listitem>
        <para>USER/GROUP - For output rules (those with the firewall as their
        source), you may control connections based on the effective UID and/or
        GID of the process requesting the connection. This column can contain
        any of the following:</para>

        <simplelist>
          <member>[!]&#60;<emphasis>user number</emphasis>&#62;[:]</member>

          <member>[!]&#60;<emphasis>user name</emphasis>&#62;[:]</member>

          <member>[!]:&#60;<emphasis>group number</emphasis>&#62;</member>

          <member>[!]:&#60;<emphasis>group name</emphasis>&#62;</member>

          <member>[!]&#60;<emphasis>user number</emphasis>&#62;:&#60;<emphasis>group
          number</emphasis>&#62;</member>

          <member>[!]&#60;<emphasis>user name</emphasis>&#62;:&#60;<emphasis>group
          number</emphasis>&#62;</member>

          <member>[!]&#60;<emphasis>user inumber</emphasis>&#62;:&#60;<emphasis>group
          name</emphasis>&#62;</member>

          <member>[!]&#60;<emphasis>user name</emphasis>&#62;:&#60;<emphasis>group
          name</emphasis>&#62;</member>
        </simplelist>
      </listitem>
    </itemizedlist>

    <para>Omitted column entries should be entered using a dash (&#34;-:).</para>

    <para>Example:</para>

    <para><filename>/etc/shorewall/actions</filename>:</para>

    <para><programlisting>     LogAndAccept</programlisting><phrase><filename>/etc/shorewall/action.LogAndAccept</filename></phrase><programlisting>     LOG:info
     ACCEPT</programlisting></para>

    <para>To use your action, in <filename>/etc/shorewall/rules</filename> you
    might do something like:</para>

    <programlisting>#ACTION      SOURCE      DEST        PROTO    DEST PORT(S)
LogAndAccept loc         fw          tcp      22</programlisting>
  </section>

  <section>
    <title>Standard Actions In Shorewall 2.0</title>

    <para>Beginning with Shorewall 2.0.0-Beta1, Shorewall includes a number of
    defined actions. These defined actions are listed in <filename>/usr/share/shorewall/actions.std</filename>.</para>

    <para>The <filename>/usr/share/shorewall/actions.std</filename> file
    includes the common actions <quote>Drop</quote> for DROP policies and
    <quote>Reject</quote> for REJECT policies.</para>

    <example>
      <title>Example of Using a Standard Action</title>

      <para>Suppose that you wish to enable ftp from your local network to
      your firewall. In <filename>/etc/shorewall/rules</filename>:</para>

      <programlisting>#ACTION   SOURCE      DEST        PROTO    ...
AllowFTP  loc         fw</programlisting>
    </example>

    <para><filename>/usr/share/shorewall/actions.std</filename> is processed
    before <filename>/etc/shorewall/actions</filename> and if you have any
    actions defined with the same name as one in <filename>/usr/share/shorewall/actions.std</filename>,
    your version in <filename class="directory">/etc/shorewall</filename> will
    be the one used. So if you wish to modify a standard action, simply copy
    the associated action file from <filename class="directory">/usr/share/shorewall
    </filename>to <filename class="directory">/etc/shorewall and modify</filename>
    it to suit your needs. The next <command>shorewall restart</command> will
    cause your action to be installed in place of the standard one. In
    particular, if you want to modify the common actions <quote>Drop</quote>
    or <quote>Reject</quote>, simply copy <filename>action.Drop</filename> or
    <filename>Action.Reject</filename> to <filename class="directory">/etc/shorewall</filename>
    and modify that copy as desired.</para>
  </section>

  <section>
    <title>Creating an Action using an Extension Script</title>

    <para>There may be cases where you wish to create a chain with rules that
    can&#39;t be constructed using the tools defined in the action.template.
    In that case, you can use an extension script.<note><para>If you actually
    need an action to drop broadcast packets, use the <command>dropBcast</command>
    standard action rather than create one like this.</para></note></para>

    <example>
      <title>An action to drop all broadcast packets</title>

      <para>/etc/shorewall/actions<programlisting>DropBcasts</programlisting></para>

      <para>/etc/shorewall/action.DropBcasts<programlisting># This file is empty</programlisting></para>

      <para>/etc/shorewall/DropBcasts<programlisting>run_iptables -A DropBcasts -m pkttype --pkttype broadcast -j DROP</programlisting></para>
    </example>
  </section>
</article>