shorewall_code/docs/shorewall_extension_scripts.xml
2007-08-27 20:03:39 +00:00

547 lines
22 KiB
XML

<?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</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>
<section id="Scripts">
<title>Extension Scripts</title>
<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 after the firewall has been marked as
'running'.</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>refreshed -- invoked after the firewall has been
refreshed.</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 (Not used by
Shorewall Perl).</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>
<listitem>
<para>isusable -- (Added in Shorewall-perl version 4.0.3) invoked when
Shorewall is trying to determine the usability of the network
interface associated with an optional entry in
<filename>/etc/shorewall/providers</filename>. $1 is the name of the
interface which will have been determined to be up and configured
before the script is invoked. The return value from the script
indicates whether or not the interface is usable (0 = usable, other =
unusable).</para>
<para>Example:<programlisting># Ping a gateway through the passed interface
case $1 in
eth0)
ping -c 4 -t 1 -I eth0 206.124.146.254 &gt; /dev/null 2&gt;&amp;1
return
;;
eth1)
ping -c 4 -t 1 -I eth1 192.168.12.254 &gt; /dev/null 2&gt;&amp;1
return
;;
*)
# No additional testing of other interfaces
return 0
;;
esac</programlisting><caution>
<para>We recommend that this script only be used with
ADMINISABSENTMINDED=Yes.</para>
<para>The firewall state when this script is invoked is
indeterminent. So if you have ADMINISABSENTMINDED=No in <ulink
url="manpages/shorewall.conf.html">shorewall.conf</ulink>(8) and
output on an interface is not allowed by <ulink
url="manpages/shorewall.conf.html">routestopped</ulink>(8) then
the isuasable script must blow it's own holes in the firewall
before probing. </para>
</caution></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>
</itemizedlist>
<para></para>
<section id="v3.0">
<title>Shorewall versions 3.0.x and earlier</title>
<para>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>
</section>
<section id="v3.2">
<title>Shorewall version 3.2.0 - 3.2.8</title>
<para>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>
</section>
<section id="v3.2.9">
<title>Shorewall version 3.2.9 (3.4.0 RC2) and later
(Shorewall-shell)</title>
<para>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>
</section>
<section id="Perl">
<title>Shorewall-perl (Version 4.0.0 and later)</title>
<para>Because the compiler is written in Perl, some of your extension
scripts from earlier versions will no longer work because Shorewall-perl
runs those extension scripts at compile-time rather than at
run-time.</para>
<para>The following table summarizes when the various extension scripts
are run:<informaltable frame="all">
<tgroup cols="3">
<tbody>
<row>
<entry><emphasis role="bold">Compile-time</emphasis></entry>
<entry><emphasis role="bold">Run-time</emphasis></entry>
<entry><emphasis role="bold">Eliminated</emphasis></entry>
</row>
<row>
<entry>initdone</entry>
<entry>clear</entry>
<entry>continue</entry>
</row>
<row>
<entry>maclog</entry>
<entry>isusable</entry>
<entry></entry>
</row>
<row>
<entry>Per-chain (including those associated with
actions)</entry>
<entry>start</entry>
<entry></entry>
</row>
<row>
<entry></entry>
<entry>started</entry>
<entry></entry>
</row>
<row>
<entry></entry>
<entry>stop</entry>
<entry></entry>
</row>
<row>
<entry></entry>
<entry>stopped</entry>
<entry></entry>
</row>
<row>
<entry></entry>
<entry>tcclear</entry>
</row>
<row>
<entry></entry>
<entry>refresh</entry>
</row>
<row>
<entry></entry>
<entry>refreshed</entry>
</row>
</tbody>
</tgroup>
</informaltable></para>
<para>Compile-time extension scripts are executed using the Perl 'eval
`cat &lt;<emphasis>file</emphasis>&gt;`' mechanism. Be sure that each
script returns a 'true' value; otherwise, the compiler will assume that
the script failed and will abort the compilation.</para>
<para>All scripts will need to begin with the following
line:<programlisting>use Shorewall::Chains;</programlisting>For more
complex scripts, you may need to 'use' other Shorewall Perl modules --
browse <filename
class="directory">/usr/share/shorewall-perl/Shorewall/</filename> to see
what's available.</para>
<para>When a script is invoked, the <emphasis
role="bold">$chainref</emphasis> scalar variable will hold a reference
to a chain table entry.<simplelist>
<member><emphasis role="bold">$chainref-&gt;{name}</emphasis>
contains the name of the chain</member>
<member><emphasis role="bold">$chainref-&gt;{table}</emphasis> holds
the table name</member>
</simplelist></para>
<para>To add a rule to the chain:<programlisting>add_rule( $chainref, &lt;<emphasis>the rule</emphasis>&gt; );</programlisting>Where<simplelist>
<member>&lt;<emphasis>the rule</emphasis>&gt; is a scalar argument
holding the rule text. Do not include "-A &lt;<emphasis>chain
name</emphasis>&gt;"</member>
</simplelist>Example:<programlisting>add_rule( $chainref, '-j ACCEPT' );</programlisting>To
insert a rule into the chain:<programlisting> insert_rule( $chainref, &lt;<emphasis>rulenum</emphasis>&gt;, &lt;<emphasis>the rule</emphasis>&gt; );</programlisting>The
<emphasis role="bold">log_rule_limit()</emphasis> function works like it
does in the shell compiler with three exceptions:<itemizedlist>
<listitem>
<para>You pass the chain reference rather than the name of the
chain.</para>
</listitem>
<listitem>
<para>The commands are 'add' and 'insert' rather than '-A' and
'-I'.</para>
</listitem>
<listitem>
<para>There is only a single "pass as-is to iptables" argument (so
you must quote that part).</para>
</listitem>
</itemizedlist>Example:<programlisting>log_rule_limit(
'info' ,
$chainref ,
$chainref-&gt;{name},
'DROP' ,
'', #Limit
'' , #Log tag
'add', #Command
'-p tcp' #Pass as-is
);</programlisting>Note that in the 'initdone' script, there is
no default chain (<emphasis role="bold">$chainref</emphasis>). You can
obtain a reference to a standard chain by:<programlisting>my $chainref = $chain_table{&lt;<emphasis>table</emphasis>&gt;}{&lt;<emphasis>chain name</emphasis>&gt;};</programlisting>Example:<programlisting>my $chainref = $chain_table{filter}{INPUT};</programlisting></para>
<para>You can also use the hash references <emphasis
role="bold">$filter_table</emphasis>, <emphasis
role="bold">$mangle_table</emphasis> and <emphasis
role="bold">$nat_table</emphasis> to access chain references in the
three main tables.</para>
<para>Example:</para>
<programlisting>my $chainref = $filter_table-&gt;{INPUT}; #Same as above with a few less keystrokes; runs faster too</programlisting>
<para>The 'continue' script has been eliminated because it no longer
make any sense under Shorewall-perl. That script was designed to allow
you to add special temporary rules during [re]start. Shorewall-perl
doesn't need such rules since the ruleset is instantianted atomically by
table.</para>
</section>
</section>
</article>