<?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>Extension Scripts and Default Actions</title>

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

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

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

    <copyright>
      <year>2001-2007</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 3.0 and
    later. If you are running a version of Shorewall earlier than Shorewall
    3.0.0 then please see the documentation for that
    release.</emphasis></para>
  </caution>

  <para>Extension scripts are user-provided scripts that are invoked at
  various points during firewall start, restart, stop and clear. The scripts
  are placed in /etc/shorewall and are processed using the Bourne shell
  <quote>source</quote> mechanism.</para>

  <caution>
    <orderedlist>
      <listitem>
        <para>Be sure that you actually need to use an extension script to do
        what you want. Shorewall has a wide range of features that cover most
        requirements.</para>
      </listitem>

      <listitem>
        <para>DO NOT SIMPLY COPY RULES THAT YOU FIND ON THE NET INTO AN
        EXTENSION SCRIPT AND EXPECT THEM TO WORK AND TO NOT BREAK SHOREWALL.
        TO USE SHOREWALL EXTENSION SCRIPTS YOU MUST KNOW WHAT YOU ARE DOING
        WITH RESPECT TO iptables/Netfilter AND SHOREWALL.</para>
      </listitem>
    </orderedlist>
  </caution>

  <para>The following scripts can be supplied:</para>

  <itemizedlist>
    <listitem>
      <para>init -- invoked early in <quote>shorewall start</quote> and
      <quote>shorewall restart</quote></para>
    </listitem>

    <listitem>
      <para>initdone -- invoked after Shorewall has flushed all existing rules
      but before any rules have been added to the builtin chains.</para>
    </listitem>

    <listitem>
      <para>start -- invoked after the firewall has been started or
      restarted.</para>
    </listitem>

    <listitem>
      <para>started -- invoked as a first step when the firewall is being
      started</para>
    </listitem>

    <listitem>
      <para>stop -- invoked as a first step when the firewall is being
      stopped.</para>
    </listitem>

    <listitem>
      <para>stopped -- invoked after the firewall has been stopped.</para>
    </listitem>

    <listitem>
      <para>clear -- invoked after the firewall has been cleared.</para>
    </listitem>

    <listitem>
      <para>refresh -- invoked while the firewall is being refreshed but
      before the blacklst chains have been rebuilt.</para>
    </listitem>

    <listitem>
      <para>continue -- invoked to allow you to insert special rules to allow
      traffic while Shorewall is [re]starting. Any rules added in this script
      should be deleted in your <emphasis>start</emphasis> script. This script
      is invoked earlier in the [re]start process than is the
      <emphasis>initdone</emphasis> script described above.</para>
    </listitem>

    <listitem>
      <para>maclog -- (Added in Shorewall version 3.2.5) invoked while mac
      filtering rules are being created. It is invoked once for each interface
      having 'maclist' specified and it is invoked just before the logging
      rule is added to the current chain (the name of that chain will be in
      $CHAIN).</para>
    </listitem>
  </itemizedlist>

  <para><emphasis role="bold">If your version of Shorewall doesn't have the
  file that you want to use from the above list, you can simply create the
  file yourself.</emphasis> You can also supply a script with the same name as
  any of the filter chains in the firewall and the script will be invoked
  after the /etc/shorewall/rules file has been processed but before the
  /etc/shorewall/policy file has been processed.</para>

  <para>There are a couple of special considerations for commands in extension
  scripts:</para>

  <itemizedlist>
    <listitem>
      <para>When you want to run <command>iptables</command>, use the command
      <command>run_iptables</command> instead. <command>run_iptables</command>
      will run the iptables utility passing the arguments to
      <command>run_iptables</command> and if the command fails, the firewall
      will be stopped (or restored from the last <command>save</command>
      command, if any).</para>
    </listitem>

    <listitem>
      <para>If you wish to generate a log message, use <emphasis
      role="bold">log_rule_limit</emphasis>. Parameters are:</para>

      <itemizedlist>
        <listitem>
          <para>Log Level</para>
        </listitem>

        <listitem>
          <para>Chain to insert the rule into</para>
        </listitem>

        <listitem>
          <para>Chain name to display in the message (this can be different
          from the preceding argument — see the <ulink
          url="PortKnocking.html">Port Knocking article</ulink> for an example
          of how to use this).</para>
        </listitem>

        <listitem>
          <para>Disposition to report in the message (ACCEPT, DROP,
          etc)</para>
        </listitem>

        <listitem>
          <para>Rate Limit (if passed as "" then $LOGLIMIT is assumed — see
          the LOGLIMIT option in <ulink
          url="Documentation.htm#Conf">/etc/shorewall/shorewall.conf</ulink>)</para>
        </listitem>

        <listitem>
          <para>Log Tag ("" if none)</para>
        </listitem>

        <listitem>
          <para>Command (-A or -I for append or insert).</para>
        </listitem>

        <listitem>
          <para>The remaining arguments are passed "as is" to iptables</para>
        </listitem>
      </itemizedlist>
    </listitem>

    <listitem>
      <para>Many of the extension scripts get executed for both the shorewall
      start and shorewall restart commands. You can determine which command is
      being executed using the contents of $COMMAND.</para>

      <programlisting>if [ $COMMAND = start ]; then
   ...</programlisting>
    </listitem>

    <listitem>
      <para><emphasis role="bold">Shorewall versions 3.0.x and earlier
      only.</emphasis> If you run commands other than
      <command>iptables</command> that must be re-run in order to restore the
      firewall to its current state then you must save the commands to the
      <firstterm>restore file</firstterm>. The restore file is a temporary
      file in <filename class="directory">/var/lib/shorewall</filename> that
      will be renamed <filename>/var/lib/shorewall/restore-base</filename> at
      the successful completion of the Shorewall command. The
      <command>shorewall save</command> command combines
      <filename>/var/lib/shorewall/restore-base</filename> with the output of
      <command>iptables-save</command> to produce the
      <filename>/var/lib/shorewall/restore</filename> script.</para>

      <para>Here are three functions that are useful when running commands
      other than <command>iptables</command>:</para>

      <orderedlist>
        <listitem>
          <para><emphasis role="bold">save_command() </emphasis>-- saves the
          passed command to the restore file.</para>

          <para>Example: <programlisting>save_command echo Operation Complete</programlisting></para>

          <para>That command would simply write "echo Operation Complete" to
          the restore file.</para>
        </listitem>

        <listitem>
          <para><emphasis role="bold">run_and_save_command()</emphasis> --
          saves the passed command to the restore file then executes it. The
          return value is the exit status of the command. Example:
          <programlisting>run_and_save_command "echo 1 &gt; /proc/sys/net/ipv4/icmp_echo_ignore_all"</programlisting></para>

          <para>Note that as in this example, when the command involves file
          redirection then the entire command must be enclosed in quotes. This
          applies to all of the functions described here.</para>
        </listitem>

        <listitem>
          <para><emphasis role="bold">ensure_and_save_command()</emphasis> --
          runs the passed command. If the command fails, the firewall is
          restored to its prior saved state and the operation is terminated.
          If the command succeeds, the command is written to the restore
          file</para>
        </listitem>
      </orderedlist>
    </listitem>

    <listitem>
      <para><emphasis role="bold">Shorewall version 3.2.0 - 3.2.8
      only.</emphasis> When compiling your firewall configuration, Shorewall
      copies most extension scripts directly into the "compiled" program where
      they are executed in-line during processing of the start, restart and
      restore commands. When copying a script, Shorewall indents the script to
      match the surrounding code; if you have 'awk' installed on the system
      where the configuration is being compiled, Shorewall can correctly
      handle line continuation in your script ("\" as the last character on a
      line). If you do not have awk, you may not use line continuation in your
      scripts. Also beware that quoted strings continued from one line to
      another will have extra whitespace inserted as a result of
      indentation.</para>

      <note>
        <para>The <filename>/etc/shorewall/params</filename> script is
        processed during compilation <emphasis role="bold">and</emphasis>
        copied into the compiled script as just described. So shell variables
        set during compilation may be used in Shorewall configuration files
        while those set at run-time are available to your other extension
        scripts. Note that if you assign dynamic values to variables, there is
        no guarantee that the value calculated at compile time will be the
        same as what is calculated at run time. This is particularly true if
        you use the <command>shorewall compile</command> command to compile a
        program then run that program at a later time.</para>
      </note>

      <note>
        <para>Extension scripts associated with a particular chain or action
        are not copied into the compiled script; they are rather processed
        directly by the compiler using the Bourne shell "." command. For
        example, if A is an action then if <filename
        class="directory">/etc/shorewall/A</filename> exists then it will be
        processed by the compiler rather than copied into the compiled
        script.</para>
      </note>
    </listitem>

    <listitem>
      <para><emphasis role="bold">Shorewall version 3.2.9 (3.4.0 RC2) and
      later.</emphasis> When compiling your firewall configuration, Shorewall
      copies most extension scripts directly into the "compiled" program where
      they are executed in-line during processing of the start, restart and
      restore commands. When copying a script, Shorewall indents the script to
      match the surrounding code; if you have 'awk' installed on the system
      where the configuration is being compiled, Shorewall can correctly
      handle line continuation in your script ("\" as the last character on a
      line). If you do not have awk, you may not use line continuation in your
      scripts. Also beware that quoted strings continued from one line to
      another will have extra whitespace inserted as a result of
      indentation.</para>

      <note>
        <para>The <filename>/etc/shorewall/params</filename> script is
        processed only during compilation if EXPORTPARAMS=No in
        <filename>shorewall.conf</filename>. So shell variables set in that
        file may be used in Shorewall configuration files only. Any variables
        that your extension scripts require at run-time on the firewall system
        should be set in the <filename>init</filename> extension script (if
        you need variable values in the <filename>stop</filename> or
        <filename>stopped</filename> scripts, you will need to set their value
        in <filename>stop</filename> since <filename>init</filename> is not
        invoked when processing the <command>stop</command> and
        <command>clear</command> commands).</para>

        <para>When EXPORTPARAMS=Yes (the default), the
        <filename>/etc/shorewall/params</filename> script is processed during
        compilation <emphasis role="bold">and</emphasis> copied into the
        compiled script as described above. So shell variables set during
        compilation may be used in Shorewall configuration files while those
        set at run-time are available to your other extension scripts.Note
        that if you assign dynamic values to variables, there is no guarantee
        that the value calculated at compile time will be the same as what is
        calculated at run time. This is particularly true if you use the
        <command>shorewall compile</command> command to compile a program then
        run that program at a later time or if you use Shorewall Lite.</para>
      </note>

      <note>
        <para>Extension scripts associated with a particular chain or action
        are not copied into the compiled script; they are rather processed
        directly by the compiler using the Bourne shell "." command. For
        example, if A is an action then if <filename
        class="directory">/etc/shorewall/A</filename> exists then it will be
        processed by the compiler rather than copied into the compiled
        script.</para>
      </note>
    </listitem>
  </itemizedlist>
</article>