<?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>Actions</title>

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

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

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

    <copyright>
      <year>2005</year>

      <year>2007</year>

      <year>2008</year>

      <year>2009</year>

      <year>2010</year>

      <year>2012</year>

      <year>2013</year>

      <year>2015-2016</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>

  <caution>
    <para><emphasis role="bold">This article applies to Shorewall 4.3 and
    later. If you are running a version of Shorewall earlier than Shorewall
    4.3.5 then please see the documentation for that
    release.</emphasis></para>
  </caution>

  <section id="Intro">
    <title>What are Shorewall Actions?</title>

    <para>Shorewall actions allow a symbolic name to be associated with a
    series of one or more iptables rules. The symbolic name may appear in the
    ACTION column of an <filename><ulink
    url="manpages/shorewall-rules.html">/etc/shorewall/rules</ulink></filename>
    entry, in a <ulink url="Macros.html">macro</ulink> body and within another
    action, in which case the traffic matching that rules file entry will be
    passed to the series of iptables rules named by the action.</para>

    <para>Actions can be thought of as templates. When an action is invoked in
    an <filename>/etc/shorewall/rules</filename> entry, it may be qualified by
    a logging specification (log level and optionally a log tag). The presence
    of the log level/tag causes a modified series of rules to be generated in
    which each packet/rule match within the action causes a log message to be
    generated.</para>

    <para>For readers familiar with iptables, actions are the way in which you
    can create your own filter-table chains.</para>

    <para>There are three types of Shorewall actions:</para>

    <orderedlist>
      <listitem>
        <para>Built-in Actions. These actions are known by the Shorewall code
        itself. They were formerly listed in the comments at the top of the
        file <filename>/usr/share/shorewall/actions.std</filename>. They have
        now been replaced by Standard Actions.</para>
      </listitem>

      <listitem>
        <para>Standard Actions. These actions are released as part of
        Shorewall. They are listed in the file
        <filename>/usr/share/shorewall/actions.std</filename> and are defined
        in the corresponding action.* files in <filename
        class="directory">/usr/share/shorewall</filename>. Each
        <filename>action.*</filename> file has a comment at the beginning of
        the file that describes what the action does. As an example, here is
        the definition of the <firstterm>AllowSMB</firstterm> standard action
        from Shorewall version 2.2.</para>

        <programlisting>#
# Shorewall 2.2 /usr/share/shorewall/action.AllowSMB
#
#       Allow Microsoft SMB traffic. You need to invoke this action in
#       both directions.
#
######################################################################################
#TARGET  SOURCE         DEST            PROTO   DPORT   SPORT           RATE    USER
ACCEPT   -              -               udp     135,445
ACCEPT   -              -               udp     137:139
ACCEPT   -              -               udp     1024:   137
ACCEPT   -              -               tcp     135,139,445</programlisting>

        <para>If you wish to modify one of the standard actions, do not modify
        the definition in <filename
        class="directory">/usr/share/shorewall</filename>. Rather, copy the
        file to <filename class="directory">/etc/shorewall</filename> (or
        somewhere else on your CONFIG_PATH) and modify the copy.</para>

        <para>You can see a list of the standard actions with a short
        description of each action using the <command>shorewall show
        actions</command> command. You can display the contents of
        action.<replaceable>name </replaceable>by typing s<command>horewall
        show action <replaceable>name</replaceable></command>.</para>
      </listitem>

      <listitem>
        <para>User-defined Actions. These actions are created by end-users.
        They are listed in the file
        <filename>/etc/shorewall/actions</filename> and are defined in
        <filename>action.*</filename> files in <filename
        class="directory">/etc/shorewall</filename> or in another directory
        listed in your CONFIG_PATH (defined in <filename><ulink
        url="manpages/shorewall.conf.html">/etc/shorewall/shorewall.conf</ulink></filename>).</para>
      </listitem>
    </orderedlist>
  </section>

  <section id="Default">
    <title>Policy Actions (Formerly Default Actions)</title>

    <para>Shorewall allows the association of a <firstterm>policy
    action</firstterm> with policies. A separate policy action may be
    associated with ACCEPT, DROP, REJECT, QUEUE, NFQUEUE and BLACKLIST
    policies. Policy actions provide a way to invoke a set of common rules
    just before the policy is enforced. Policy actions accomplish two
    goals:</para>

    <orderedlist>
      <listitem>
        <para>Relieve log congestion. Default actions typically include rules
        to silently drop or reject traffic that would otherwise be logged when
        the policy is enforced.</para>
      </listitem>

      <listitem>
        <para>Ensure correct operation.</para>
      </listitem>
    </orderedlist>

    <para>Shorewall supports policy actions for the ACCEPT, REJECT, DROP,
    QUEUE, NFQUEUE and BLACKLIST policies. These default actions are specified
    in the <filename>/etc/shorewall/shorewall.conf</filename> file using the
    ACCEPT_DEFAULT, REJECT_DEFAULT, DROP_DEFAULT, QUEUE_DEFAULT and
    NFQUEUE_DEFAULT options respectively. Policies whose default is set to a
    value of <quote>none</quote> have no default action.</para>

    <para>In addition, the default specified in
    <filename>/etc/shorewall/shorewall.conf</filename> may be overridden by
    specifying a different action in the POLICY column of <filename><ulink
    url="manpages/shorewall-policy.html">/etc/shorewall/policy</ulink></filename>.</para>

    <important>
      <para>Entries in the DROP, REJECT and BLACKLIST policy actions <emphasis
      role="bold">ARE NOT THE CAUSE OF CONNECTION PROBLEMS</emphasis>.
      Remember — policy actions are only invoked immediately before the packet
      is going to be dropped or rejected anyway!!!</para>
    </important>

    <para>Prior to Shorewall 5.1.2, the Drop and Reject actions were the
    default policy actions for DROP and REJECT policies respectively. Those
    actions are parameterized; each has five parameters as follows:</para>

    <informaltable>
      <tgroup cols="4">
        <tbody>
          <row>
            <entry>ACTION</entry>

            <entry>PARAMETER</entry>

            <entry>VALUE</entry>

            <entry>DEFAULT</entry>
          </row>

          <row>
            <entry>Drop</entry>

            <entry>1</entry>

            <entry>Either '-' or 'audit'. 'audit' causes auditing by the
            builtin actions invoked by Drop</entry>

            <entry>-</entry>
          </row>

          <row>
            <entry>Drop</entry>

            <entry>2</entry>

            <entry>Determines what to do with Auth requests</entry>

            <entry>-</entry>
          </row>

          <row>
            <entry>Drop</entry>

            <entry>3</entry>

            <entry>Determines what to do with SMB</entry>

            <entry>DROP or A_DROP depending on the setting of parameter
            1</entry>
          </row>

          <row>
            <entry>Reject</entry>

            <entry>1</entry>

            <entry>Either '-' or 'audit'. 'audit' causes auditing by the
            builtin actions invoked by Drop</entry>

            <entry>-</entry>
          </row>

          <row>
            <entry>Reject</entry>

            <entry>2</entry>

            <entry>Determines what to do with Auth requests</entry>

            <entry>-</entry>
          </row>

          <row>
            <entry>Reject</entry>

            <entry>3</entry>

            <entry>Determines what to do with SMB</entry>

            <entry>REJECT or A_REJECT depending on the setting of parameter
            1</entry>
          </row>

          <row>
            <entry>Both</entry>

            <entry>4</entry>

            <entry>Determines what to do with accepted critical ICMP
            packets.</entry>

            <entry>ACCEPT or A_ACCEPT depending on the setting of parameter
            1</entry>
          </row>

          <row>
            <entry>Both</entry>

            <entry>5</entry>

            <entry>Determines what to do with late-arriving DNS replies
            (source port 53) or UPnP (udp port 1900).</entry>

            <entry>DROP or A_DROP depending on the setting of parameter
            1.</entry>
          </row>
        </tbody>
      </tgroup>
    </informaltable>

    <para>The parameters may be specified in either shorewall.conf (e.g.,
    DROP_DEFAULT=<emphasis role="bold">Drop(-,DROP)</emphasis> or in the
    POLICY column of <ulink
    url="manpages/shorewall-policy.html">shorewall-policy</ulink>(5) (e.g.,
    DROP:<emphasis role="bold">Drop(audit)</emphasis>:audit).</para>

    <para>Beginning with Shorewall 5.1.2, Drop and Reject are deprecated. In
    5.1.2, a list of policy actions is accepted in both shorewall.conf and the
    policy file. This allows logging to be specified on some actions and not
    on others and eliminates the need for a large number of policy-action
    parameters.</para>

    <para>Actions commonly included in policy-action lists are:</para>

    <variablelist>
      <varlistentry>
        <term>Broadcast[(<replaceable>disposition</replaceable>)]</term>

        <listitem>
          <para>Handles broadcasts based on the
          <replaceable>disposition</replaceable>. The default
          <replaceable>disposition</replaceable> is DROP.</para>
        </listitem>
      </varlistentry>

      <varlistentry>
        <term>Multicast[(<replaceable>disposition</replaceable>)]</term>

        <listitem>
          <para>Handles multicasts based on the
          <replaceable>disposition</replaceable>. The default
          <replaceable>disposition</replaceable> is DROP.</para>
        </listitem>
      </varlistentry>

      <varlistentry>
        <term>dropNotSyn[:<replaceable>level</replaceable>]</term>

        <listitem>
          <para>Drops TCP packets that are not part of an existing connection
          but that don't have the SYN flag set or that have additional flags
          set. We recommend that these be logged by specifying an approproate
          <replaceable>level</replaceable>. This action is particularly
          appropriate packets received from the Internet. Recommended when the
          policy is BLACKLIST to avoid late-arriving FIN packets from
          blacklisting the remote system.</para>
        </listitem>
      </varlistentry>

      <varlistentry>
        <term>DropDNSrep[:<replaceable>level</replaceable>]</term>

        <listitem>
          <para>Drops UDP packets with source port 53. We recommend that these
          be logged by specifying an approproate
          <replaceable>level</replaceable>. This action is recommended when
          the policy is BLACKLIST to avoid blacklisting uplevel DNS
          servers.</para>
        </listitem>
      </varlistentry>

      <varlistentry>
        <term>AllowICMPs (IPv6 only)</term>

        <listitem>
          <para>Allows ICMP packets mandated by RFC 4890. In particular, this
          ensures that Neighbor Discovery won't be broken</para>
        </listitem>
      </varlistentry>
    </variablelist>

    <para>The recommended settings for the 6 policy actions for IPv4
    are:</para>

    <programlisting>        ACCEPT_DEFAULT=none
        BLACKLIST_DEFAULT="Broadcast(DROP),Multicast(DROP),dropNotSyn:$LOG_LEVEL,dropInvalid:$LOG_LEVEL,DropDNSrep:$LOG_LEVEL"
        DROP_DEFAULT="Broadcast(DROP),Multicast(DROP)"
        NFQUEUE_DEFAULT=none
        QUEUE_DEFAULT=none
        REJECT_DEFAULT="Broadcast(DROP),Multicast(DROP)"
</programlisting>

    <para>The recommended settings for IPv6 are:</para>

    <programlisting>        ACCEPT_DEFAULT=none
        BLACKLIST_DEFAULT="AllowICMPs,Broadcast(DROP),Multicast(DROP),dropNotSyn:$LOG_LEVEL,dropInvalid:$LOG_LEVEL,DropDNSrep:$LOG_LEVEL"
        DROP_DEFAULT="AllowICMPs,Broadcast(DROP),Multicast(DROP)"
        NFQUEUE_DEFAULT=none
        QUEUE_DEFAULT=none
        REJECT_DEFAULT="AllowICMPs,Broadcast(DROP),Multicast(DROP)"
</programlisting>

    <para>Note that in both cases, logging occurs based on the setting of
    LOG_LEVEL in shorewall[6].conf.</para>
  </section>

  <section id="Defining">
    <title>Defining your own Actions</title>

    <para>Before defining a new action, you should evaluate whether your goal
    can be best accomplished using an action or a
    <firstterm>macro</firstterm>. See <ulink url="Macros.html">this
    article</ulink> for details.</para>

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

    <orderedlist>
      <listitem>
        <para>Add a line to <filename>/etc/shorewall/actions</filename> that
        names your new action. Action names must be valid shell variable names
        (must begin with a letter and be composed of letters, digits and
        underscore characters) as well as valid Netfilter chain names. If you
        intend to log from the action, the name must have a maximum of 11
        characters. It is recommended that the name you select for a new
        action begins with a capital letter; that way, the name won't conflict
        with a Shorewall-defined chain name.</para>

        <para>Normally. the rules in an action are placed in a separate chain.
        Beginning with Shorewall 4.5.10, the action rules can be expanded
        inline in a manner similar to a macro by specifying
        <option>inline</option> in the OPTIONS column of
        <filename>/etc/shorewall/actions</filename>.</para>

        <para>Beginning in Shorewall 4.5.11, the <option>nolog</option> option
        may be specified; see the <link linkend="Logging">logging
        section</link> below for details.</para>

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

      <listitem>
        <para>Once you have defined your new action name (ActionName), then
        copy <filename>/usr/share/shorewall/action.template</filename> 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>

    <section>
      <title>Shorewall 5.0.0 and Later.</title>

      <para>In Shorewall 5.0, the columns in action.template are the same as
      those in shorewall-rules (5). There are no restrictions regarding which
      targets can be used within your action.</para>

      <para>The SOURCE and DEST columns in the action file may not include
      zone names; those are given when the action is invoked.</para>

      <para>Additionally, it is possible to pass parameters to an action, when
      it is invoked in the rules file or in another action.</para>

      <para>Here's a trivial example:</para>

      <para>/etc/shorewall/action.A:</para>

      <programlisting>#TARGET        SOURCE  DEST    PROTO   Dport   SPORT   ORIGDEST
$1             -       -       tcp     80      -       1.2.3.4</programlisting>

      <para>/etc/shorewall/rules:</para>

      <programlisting>#TARGET        SOURCE  DEST    PROTO   DPORT   SPORT   ORIGDEST

A(REDIRECT)    net     fw</programlisting>

      <para>The above is equivalent to this rule:</para>

      <programlisting>#TARGET        SOURCE  DEST    PROTO   DPORT   SPORT   ORIGDEST
REDIRECT       net     -       tcp     80      -       1.2.3.4</programlisting>

      <para>You can 'omit' parameters by using '-'.</para>

      <para>Example: ACTION(REDIRECT,-,info)</para>

      <para>In the above example, $2 would expand to nothing.</para>

      <para>Beginning with Shorewall 4.5.13, completely omitting a arameter is
      equivalent to passing '-'.</para>

      <para>Example: ACTION(REDIRECT,,info)</para>

      <para>This example behaves the same as the one shown above.</para>

      <para>If you refer to a parameter $n in the body of the action, then the
      nth paramer must either be passed to all action invocations or it's
      default value must be established via a DEFAULTS line.</para>

      <para>If you want to make '-' a parameter value, use '--' (e.g.,
      ACTION(REDIRECT,--.info)).</para>

      <para>Beginning with Shorewall 4.4.21, you can specify the default
      values of your FORMAT-2 actions:</para>

      <programlisting>DEFAULTS <replaceable>def1</replaceable>,<replaceable>def2</replaceable>,...</programlisting>

      <para>where <replaceable>def1</replaceable> is the default value for the
      first parameter, <replaceable>def2</replaceable> is the default value
      for the second parameter and so on. You can specify an empty default
      using '-' (e.g. DEFAULTS DROP,-,audit).</para>

      <para>For additional information about actions, see the <ulink
      url="configuration_file_basics.htm#ActionVariables">Action Variables
      section</ulink> of the Configuration Basics article.</para>
    </section>

    <section>
      <title>Mangle Actions</title>

      <para>Beginning with Shorewall 5.0.7, actions may be used in <ulink
      url="manpages/shorewall-mangle.html">shorewall-mangle(5)</ulink>.
      Because the rules and mangle files have different column layouts,
      actions can be defined to be used in one file or the other but not in
      both. To designate an action to be used in the mangle file, specify the
      <option>mangle</option> option in the action's entry in <ulink
      url="manpages/shorewall-actions.html">shorewall-actions</ulink>(5).</para>

      <para>To create a mangle action, follow the steps in the preceding
      section, but use the
      <filename>/usr/share/shorewall/action.mangletemplate</filename>
      file.</para>
    </section>
  </section>

  <section id="Logging">
    <title>Actions and Logging</title>

    <para>Specifying a log level in a rule that specifies a user-defined or
    Shorewall-defined action will cause each rule in the action to be logged
    with the specified level (and tag), unless the <option>nolog</option>
    option is specified in the action's entry in
    <filename>/etc/shorewall/actions</filename>.</para>

    <para>The extent to which logging of action rules occur is governed by the
    following:</para>

    <orderedlist>
      <listitem>
        <para>When you invoke an action and specify a log level, only those
        rules in the action that have no log level will be changed to log at
        the level specified at the action invocation.</para>

        <para>Example:</para>

        <para>/etc/shorewall/action.foo</para>

        <programlisting>#TARGET      SOURCE     DEST     PROTO    DPORT
ACCEPT       -          -        tcp      22
bar:info</programlisting>

        <para>/etc/shorewall/rules:</para>

        <programlisting>#ACTION      SOURCE     DEST     PROTO    DPORT
foo:debug    $FW         net</programlisting>

        <para>Logging in the invoke <quote>foo</quote> action will be as if
        foo had been defined as:</para>

        <programlisting>#TARGET      SOURCE     DEST     PROTO    DPORT
ACCEPT:debug -          -        tcp      22
bar:info</programlisting>
      </listitem>

      <listitem>
        <para>If you follow the log level with <quote>!</quote> then logging
        will be set at that level for all rules recursively invoked by the
        action.</para>

        <para>Example:</para>

        <para>/etc/shorewall/action.foo</para>

        <programlisting>#TARGET      SOURCE     DEST     PROTO    DPORT
ACCEPT       -          -        tcp      22
bar:info</programlisting>

        <para>/etc/shorewall/rules:</para>

        <programlisting>#ACTION      SOURCE     DEST     PROTO    DPORT
foo:debug!   $FW        net</programlisting>

        <para>Logging in the invoke <quote>foo</quote> action will be as if
        foo had been defined as:</para>

        <programlisting>#TARGET      SOURCE     DEST     PROTO    DPORT
ACCEPT:debug -          -        tcp      22
bar:debug</programlisting>
      </listitem>
    </orderedlist>
  </section>

  <section id="Embedded">
    <title>Using Embedded Perl in an Action</title>

    <para>There may be cases where you wish to create a chain with rules that
    can't be constructed using the tools defined in the
    <filename>action.template</filename>. Such rules can be constructed using
    <ulink url="configuration_file_basics.htm#Embedded">Embedded Perl.</ulink>
    For those who are comfortable using Perl, embedded Perl is more efficient
    that using complicated conditional entries. The Perl compiler is invoked
    only once for a BEGIN PERL...END PERL block; it is invoked most times that
    an expression is evaluated in an ?IF, ?ELSEIF or ?SET directive.</para>

    <para>The Shorewall compiler provides a set of services that are available
    to Perl code embedded in an action file. These services are not available
    in in-line actions when running Shorewall 4.5.12 or earlier.</para>

    <variablelist>
      <varlistentry>
        <term>Shorewall::Config::get_action_params(
        <replaceable>$howmany</replaceable> )</term>

        <listitem>
          <para>This function returns an array containing the functions
          parameters. The scalar argument <replaceable>$howmany</replaceable>
          is the number of parameters that you expect to be passed. You can
          ensure that at least this many parameters are passed by including a
          DEFAULTS line prior to the embedded Perl.</para>
        </listitem>
      </varlistentry>

      <varlistentry>
        <term>Shorewall::Config::set_action_param(
        <replaceable>$ordinal</replaceable>, <replaceable>$value</replaceable>
        )</term>

        <listitem>
          <para>Set the value of parameter <replaceable>$ordinal</replaceable>
          to <replaceable>$value</replaceable>. Care must be take when using
          this function such that for a given set of parameters actually
          passed to the action, the same rules are created. That is because
          the compiler assumes that all invocations of an action with the same
          parameters, log level and log tag can share the same action
          chain.</para>
        </listitem>
      </varlistentry>

      <varlistentry>
        <term>Shorewall::Config::get_action_chain()</term>

        <listitem>
          <para>This function returns a reference to the chain table entry for
          the current action chain.</para>
        </listitem>
      </varlistentry>

      <varlistentry>
        <term>Shorewall::Config::get_action_logging()</term>

        <listitem>
          <para>Returns a two-element list containing the the log level and
          log tag specified when the action was invoked. Note that you must
          use this function rather than @loglevel and @logtag within embedded
          Perl, as the compiler does not expand <ulink
          url="configuration_file_basics.htm#ShorewallVariables">Shorewall
          Variables</ulink> within embedded Perl (or embedded shell).</para>
        </listitem>
      </varlistentry>

      <varlistentry>
        <term>Shorewall::Config::push_comment()</term>

        <listitem>
          <para>Prior to Shorewall 4.5.21, this required:</para>

          <programlisting>use Shorewall::Config (:DEFAULT :internal);</programlisting>

          <para>Returns the current rule comment to the caller and clears the
          comment. The returned comment may be restored by calling either
          pop_comment() or set_comment().</para>
        </listitem>
      </varlistentry>

      <varlistentry>
        <term>Shorewall::Config::pop_comment($comment) and
        Shorewall::Config::set_comment($comment).</term>

        <listitem>
          <para>The set_comment() function was added in Shorewall 4.5.21.
          Prior to that release, accessing pop_comment() required:</para>

          <programlisting>use Shorewall::Config (:DEFAULT :internal);</programlisting>

          <para>These functions are identical and set the current rule comment
          to the contents of the passed simple variable.</para>
        </listitem>
      </varlistentry>

      <varlistentry>
        <term>Shorewall::Chains::add_rule(
        <replaceable>$chainre</replaceable>f, <replaceable>$rule</replaceable>
        [, <replaceable>$expandports</replaceable> ] )</term>

        <listitem>
          <para>This function adds a rule to a chain. As of Shoreall 4.5.13,
          it is deprecated in favor of Shorewall::Rules::perl_action_helper().
          Arguments are:</para>

          <variablelist>
            <varlistentry>
              <term><replaceable>$chainref</replaceable></term>

              <listitem>
                <para>Normally, you get this from get_action_chain() described
                above.</para>
              </listitem>
            </varlistentry>

            <varlistentry>
              <term><replaceable>$rule</replaceable></term>

              <listitem>
                <para>The matches and target for the rule that you want
                added.</para>
              </listitem>
            </varlistentry>

            <varlistentry>
              <term><replaceable>$expandports</replaceable> (optional)</term>

              <listitem>
                <para>This optional argument is for compiler-internal use
                only. Either omit it or pass a false value.</para>
              </listitem>
            </varlistentry>
          </variablelist>

          <warning>
            <para>Do not call this function in a inline action. Use
            perl_action_helper() instead (see below).</para>
          </warning>
        </listitem>
      </varlistentry>

      <varlistentry>
        <term>Shorewall::Chains::log_rule_limit(
        <replaceable>$level</replaceable>,
        $<replaceable>chainref</replaceable>,
        <replaceable>$chain</replaceable>,
        <replaceable>$disposition</replaceable>,
        <replaceable>$limit</replaceable>, <replaceable>$tag</replaceable>,
        <replaceable>$command</replaceable>,
        <replaceable>$matches</replaceable> )</term>

        <listitem>
          <para>This function adds a logging rule to a chain. As of Shoreall
          4.5.13, it is deprecated in favor of
          Shorewall::Rules::perl_action_helper(). Arguments are:</para>

          <variablelist>
            <varlistentry>
              <term><replaceable>$level</replaceable></term>

              <listitem>
                <para>Either a syslog level or a ULOG or NFLOG target
                expression (e.g., "NFLOG(1,0,1)"). Specifies how you want the
                logging done.</para>
              </listitem>
            </varlistentry>

            <varlistentry>
              <term><replaceable>$chainref</replaceable></term>

              <listitem>
                <para>Normally, you get this from get_action_chain() described
                above.</para>
              </listitem>
            </varlistentry>

            <varlistentry>
              <term><replaceable>$chain</replaceable></term>

              <listitem>
                <para>The value you want substituted for the first %s
                formatting directive in the LOGFORMAT setting in
                <filename>/etc/shorewall/shorewall.conf</filename>.</para>
              </listitem>
            </varlistentry>

            <varlistentry>
              <term><replaceable>$disposition</replaceable></term>

              <listitem>
                <para>This is the value substituted for the second '%s'
                formatting directive in the LOGFORMAT setting in
                <filename>/etc/shorewall/shorewall.conf</filename>.</para>
              </listitem>
            </varlistentry>

            <varlistentry>
              <term><replaceable>$limit</replaceable></term>

              <listitem>
                <para>If you want to use the default limit set in LOGLIMIT
                (<filename>/etc/shorewall/shorewall.conf</filename>), you can
                specify your own '-limit' match. Otherwise, if you want to use
                the default, pass 0 or "". If you want the rule to be
                unlimited, pass '-'.</para>
              </listitem>
            </varlistentry>

            <varlistentry>
              <term><replaceable>$tag</replaceable></term>

              <listitem>
                <para>Log tag.</para>
              </listitem>
            </varlistentry>

            <varlistentry>
              <term><replaceable>$command</replaceable></term>

              <listitem>
                <para>Pass 'add' here, unless you want the rule to be inserted
                at the front of the chain.</para>
              </listitem>
            </varlistentry>

            <varlistentry>
              <term><firstterm>$matches</firstterm></term>

              <listitem>
                <para>Zero or more iptables matches that limit when logging
                will occur. If this parameter is other than the empty string,
                the last character must be a space.</para>
              </listitem>
            </varlistentry>
          </variablelist>
        </listitem>
      </varlistentry>

      <varlistentry>
        <term>Shorewall::Chains::allow::optimize(
        <replaceable>$chainref</replaceable> )</term>

        <listitem>
          <para>This allows the passed action chain to be optimized away
          (jumps to the chain are replaced by the chain's rule(s)). The
          <replaceable>chainref</replaceable> argument is usually obtained
          from get_action_chain() described above.</para>
        </listitem>
      </varlistentry>

      <varlistentry>
        <term>Shorewall::Rules::perl_action_helper( $target, $matches )</term>

        <listitem>
          <para>This function adds a rule to the current chain. For a regular
          action, the chain will be an action chain; for an inline action, the
          chain is determined by the invoking rule.</para>

          <para>To use this function, you must include:</para>

          <simplelist>
            <member><emphasis role="bold">use
            Shorewall::Rules;</emphasis></member>
          </simplelist>

          <para>Arguments are:</para>

          <variablelist>
            <varlistentry>
              <term>$target</term>

              <listitem>
                <para>The target of the rule. Legal values are anything that
                can appear in the TARGET column of in an action body and may
                include log level, tag, and parameters.</para>
              </listitem>
            </varlistentry>

            <varlistentry>
              <term>$matches</term>

              <listitem>
                <para>ip[6]tables matches to be included in the rule. When
                called in an inline action, these matches are augmented by
                matches generated by the invoking rule.</para>
              </listitem>
            </varlistentry>
          </variablelist>

          <note>
            <para>This function has additional optional arguments which are
            used internally by Shorewall standard actions. Their number and
            behavior is likely to change in future Shorewall releases.</para>
          </note>
        </listitem>
      </varlistentry>

      <varlistentry>
        <term>Shorewall::Rules::perl_action_tcp_helper( $target, $proto
        )</term>

        <listitem>
          <para>This function is similar to
          Shorewall::Rules::perl_action_helper but is taylored for specifying
          options to "-p tcp".</para>

          <para>To use this function, you must include:</para>

          <simplelist>
            <member><emphasis role="bold">use
            Shorewall::Rules;</emphasis></member>
          </simplelist>

          <para>Arguments are:</para>

          <variablelist>
            <varlistentry>
              <term>$target</term>

              <listitem>
                <para>The target of the rule. Legal values are anything that
                can appear in the TARGET column of in an action body and may
                include log level, tag, and parameters.</para>
              </listitem>
            </varlistentry>

            <varlistentry>
              <term>$proto</term>

              <listitem>
                <para>The '-p' part of the rule to be generated (e.g., "-p tcp
                --tcp-flags RST RST").</para>
              </listitem>
            </varlistentry>
          </variablelist>
        </listitem>
      </varlistentry>
    </variablelist>

    <para>For examples of using these services, look at the standard actions
    in <filename>/usr/share/shorewall/action.*</filename>.</para>
  </section>

  <section id="Extension">
    <title>Creating an Action using an Extension Script (deprecated in favor
    of BEGIN PERL ... END PERL)</title>

    <para>There may be cases where you wish to create a chain with rules that
    can't be constructed using the tools defined in the
    <filename>action.template</filename>. In that case, you can use an <ulink
    url="shorewall_extension_scripts.htm">extension script</ulink>. Beginning
    with Shorewall 4.5.16, such scripts require CHAIN_SCRIPTS=Yes in <ulink
    url="manpages/shorewall.conf.html">shorewall.conf</ulink> (5)<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 id="Example">
      <title>An action to drop all broadcast packets</title>

      <para>If you define an action <quote>acton</quote> and you have an
      <filename>/etc/shorewall/acton</filename> script, the rules compiler
      sets lexical variables as follows:</para>

      <itemizedlist>
        <listitem>
          <para><emphasis role="bold">$chainref</emphasis> is a reference to
          the chain-table entry for the chain where your rules are to be
          placed.</para>
        </listitem>

        <listitem>
          <para><emphasis role="bold">$level</emphasis> is the log level. If
          false, no logging was specified.</para>
        </listitem>

        <listitem>
          <para><emphasis role="bold">$tag</emphasis> is the log tag.</para>
        </listitem>

        <listitem>
          <para><emphasis role="bold">@params</emphasis> is the list of
          parameter values (Shorewall 4.4.16 and later). 'Omitted' parameters
          contain '-'.</para>
        </listitem>
      </itemizedlist>

      <para>Example:</para>

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

      <para>/etc/shorewall/action.DropBcasts<programlisting># This file is empty</programlisting>/etc/shorewall/DropBcasts<programlisting>use Shorewall::Chains;

if ( $level ne '' ) {
    log_rule_limit $level, $chainref, 'dropBcast' , 'DROP', '', $tag, 'add', ' -m addrtype --dst-type BROADCAST ';
    log_rule_limit $level, $chainref, 'dropBcast' , 'DROP', '', $tag, 'add', ' -d 224.0.0.0/4 ';
}

add_rule $chainref, '-m addrtype --dst-type BROADCAST -j DROP';
add_rule $chainref, '-d 224.0.0.0/4 -j DROP';

1;</programlisting></para>
    </example>

    <para>For a richer example, see the next section.</para>
  </section>

  <section id="Limit">
    <title>Limiting Per-IP Connection Rate using the Limit Action</title>

    <para>Shorewall supports a <quote>Limit</quote> built-in action. Prior to
    Shorewall 4.4.16, Limit is invoked with a comma-separated list in place of
    a logging tag. Beginning in Shorewall 4.4.16, it may also be invoked with
    a list of three parameters enclosed in parentheses. The list has three
    elements:</para>

    <orderedlist>
      <listitem>
        <para>The name of a <quote>recent</quote> list. You select the list
        name which must conform to the rules for a valid chain name. Different
        rules that specify the same list name will use the same set of
        counters.</para>
      </listitem>

      <listitem>
        <para>The number of connections permitted in a specified time
        period.</para>
      </listitem>

      <listitem>
        <para>The time period, expressed in seconds.</para>
      </listitem>
    </orderedlist>

    <para>Connections that exceed the specified rate are dropped.</para>

    <para>For example, to use a recent list name of <emphasis
    role="bold">SSHA</emphasis>, and to limit SSH connections to 3 per minute,
    use this entry in <filename>/etc/shorewall/rules</filename>:</para>

    <programlisting>#ACTION                SOURCE            DEST           PROTO       DPORT
Limit:none:SSHA,3,60   net               $FW            tcp         22</programlisting>

    <para>Using Shorewall 4.4.16 or later, you can also invoke the action this
    way:</para>

    <programlisting>#ACTION                SOURCE            DEST           PROTO       DPORT
Limit(SSHA,3,60):none  net               $FW            tcp         22</programlisting>

    <para>If you want dropped connections to be logged at the info level, use
    this rule instead:</para>

    <programlisting>#ACTION                SOURCE            DEST           PROTO       DPORT
Limit:info:SSHA,3,60   net               $FW            tcp         22</programlisting>

    <para>Shorewall 4.4.16 and later:<programlisting>#ACTION                SOURCE            DEST           PROTO       DPORT
Limit(SSH,3,60):info   net               $FW            tcp         22</programlisting></para>

    <para>To summarize, you pass four pieces of information to the Limit
    action:</para>

    <itemizedlist>
      <listitem>
        <para>The log level. If you don't want to log, specify
        <quote>none</quote>.</para>
      </listitem>

      <listitem>
        <para>The name of the recent list that you want to use
        (<quote>SSHA</quote> in this example).</para>
      </listitem>

      <listitem>
        <para>The maximum number of connections to accept (3 in this
        example).</para>
      </listitem>

      <listitem>
        <para>The number of seconds over which you are willing to accept that
        many connections (60 in this example).</para>
      </listitem>
    </itemizedlist>

    <section id="LimitImp">
      <title>How Limit is Implemented</title>

      <para>For those who are curious, the Limit action in Shorewall 4.4.16 is
      implemented as follows:</para>

      <programlisting>use Shorewall::Chains;

@params = split( /,/, $tag ), $tag='' unless @params;

fatal_error 'Limit rules must include &lt;list name&gt;,&lt;max connections&gt;,&lt;interval&gt; as the log tag or params' unless @params == 3;

my $list = $params[0];

for ( @params[1,2] ) {
    fatal_error 'Max connections and interval in Limit rules must be numeric (' . $_ . ')' unless /^\d+$/
}

my $count = $params[1] + 1;

add_rule $chainref, "-m recent --name $list --set";

if ( $level ) {
    my $xchainref = new_chain 'filter' , "$chainref-&gt;{name}%";
    log_rule_limit $level, $xchainref, $params[0], 'DROP', $tag, '', 'add', '';
    add_rule $xchainref, '-j DROP';
    add_rule $chainref,  "-m recent --name $list --update --seconds $params[2] --hitcount $count -j $xchainref-&gt;{name}";
} else {
    add_rule $chainref, "-m recent --update --name $list --seconds $params[2] --hitcount $count -j DROP";
}

add_rule $chainref, '-j ACCEPT';

1; </programlisting>
    </section>
  </section>

  <section>
    <title>Mangle Actions</title>

    <para>Beginning with Shorewall 5.0.7, actions are supported in <ulink
    url="manpages/shorewall-mangle.html">shorewall-mangle(5)</ulink>. Like
    actions used out of <ulink
    url="manpages/shorewall-rules.html">shorewall-rules(5)</ulink>, they must
    be declared in <ulink
    url="manpages/shorewall-actions.html">shorewall-actions(5)</ulink>. These
    <firstterm>mangle actions</firstterm> must have the
    <option>mangle</option> option specified on <ulink
    url="manpages/shorewall-actions.html">shorewall-actions(5)</ulink>. Like
    the actions described in the preceding sections, mangle actions are
    defined in a files with names of the form
    action.<replaceable>action</replaceable>. Rules in those files have the
    same format as those in <ulink
    url="manpages/shorewall-mangle.html">shorewall-mangle(5)</ulink> with the
    restriction that chain designators (:P, :F, etc.) are not permitted in the
    ACTION column. Both regular and inline actions are supported.</para>

    <para>Inline Example</para>

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

    <programlisting>#ACTION     OPTIONS
Divert	     inline,mangle      # TProxy Rules
</programlisting>

    <para><filename>/etc/shorewall/action.Divert</filename>:</para>

    <programlisting>#ACTION         SOURCE          DEST            PROTO   DPORT   SPORT
DIVERT          COMB_IF         -               tcp     -       80
DIVERT          COMC_IF         -               tcp     -       80
DIVERT          DMZ_IF          172.20.1.0/24   tcp     -       80
</programlisting>

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

    <programlisting>#ACTION         SOURCE          DEST            PROTO   DPORT   SPORT
Divert</programlisting>

    <para>More efficient way to do this:</para>

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

    <programlisting>#ACTION     OPTIONS
Divert	     inline             # TProxy Rules
</programlisting>

    <para><filename>/etc/shorewall/action.Divert</filename>:</para>

    <programlisting>#ACTION         SOURCE          DEST            PROTO   DPORT   SPORT
DIVERT          COMB_IF         -               
DIVERT          COMC_IF         -               
DIVERT          DMZ_IF          172.20.1.0/24
</programlisting>

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

    <programlisting>#ACTION         SOURCE          DEST            PROTO   DPORT   SPORT
Divert          -               -               tcp     -       80</programlisting>
  </section>

  <section>
    <title>SNAT Actions</title>

    <para>Beginning with Shorewall 5.0.14, actions are supported in <ulink
    url="manpages/shorewall-snat.html">shorewall-snat(5</ulink>); that file
    supercedes <ulink
    url="manpages/shorewall-masq.html">shorewall-masq(5)</ulink> which is
    still supported. The shorewall update command will convert a
    <filename>masq</filename> file into the equivalent
    <filename>snat</filename> file. Like actions used out of <ulink
    url="manpages/shorewall-rules.html">shorewall-rules(5)</ulink>,
    <firstterm>SNAT actions</firstterm> must be declared in <ulink
    url="manpages/shorewall-actions.html">shorewall-actions(5)</ulink>. These
    <firstterm>mangle actions</firstterm> must have the <option>nat</option>
    option specified on <ulink
    url="manpages/shorewall-actions.html">shorewall-actions(5)</ulink>. Like
    the actions described in the preceding sections, SNAT actions are defined
    in a files with names of the form
    action.<replaceable>action</replaceable>. Rules in those files have the
    same format as those in <ulink
    url="manpages/shorewall-snat.html">shorewall-snat(5)</ulink> with two
    restrictions:</para>

    <orderedlist>
      <listitem>
        <para>The plus sign ("+") is not allowed in the ACTION column, so all
        rules in the action will either be pre-nat or post-nat depending on
        whether '+' was present in the action's invocation.</para>
      </listitem>

      <listitem>
        <para>Interface names are not allowed in the DEST column, so all rules
        in the action will apply to the interface specified in the action's
        invocation.</para>
      </listitem>
    </orderedlist>

    <para>Both regular and inline actions are supported.</para>

    <para>Example:</para>

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

    <programlisting>#ACTION     OPTIONS
custEPTs    nat,inline</programlisting>

    <para><filename>/etc/shorewall/action.custEPTs</filename>:</para>

    <programlisting>#ACTION         SOURCE          DEST            PROTO   PORT
SNAT($GW_IP)    { proto=udp port=1146 }
SNAT($GW_IP)    { proto=tcp port=1156,7221,21000 }
</programlisting>

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

    <programlisting>ACTION          SOURCE          DEST            PROTO   PORT
custEPTs  { source=$EPT_LIST dest=$IF_NET:$EPT_SERVERS }</programlisting>

    <para>More effeciently:</para>

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

    <programlisting>#ACTION     OPTIONS
custEPTs    nat</programlisting>

    <para><filename>/etc/shorewall/action.custEPTs</filename>:</para>

    <programlisting>#ACTION         SOURCE          DEST            PROTO   PORT
SNAT($GW_IP)    { proto=udp port=1146 }
SNAT($GW_IP)    { proto=tcp port=1156,7221,21000 }
</programlisting>

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

    <programlisting>ACTION          SOURCE          DEST            PROTO   PORT
custEPT  { source=$EPT_LIST dest=$IF_NET:$EPT_SERVERS }</programlisting>
  </section>
</article>