shorewall_code/docs/Actions.xml
Tom Eastep 81a5723009 Add appropriate 'use' statement to Limit code
Signed-off-by: Tom Eastep <teastep@shorewall.net>
2010-01-14 08:04:08 -08:00

656 lines
26 KiB
XML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?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>
<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>
file entry, 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 are listed in the comments at the top of the file
<filename>/usr/share/shorewall/actions.std</filename>.</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 DEST SOURCE RATE USER/
# PORT PORT(S) LIMIT GROUP
ACCEPT - - udp 135,445
ACCEPT - - udp 137:139
ACCEPT - - udp 1024: 137
ACCEPT - - tcp 135,139,445
#LAST LINE -- ADD YOUR ENTRIES BEFORE THIS ONE -- DO NOT REMOVE</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>Standard Actions have been largely replaced by <ulink
url="Macros.html">macros</ulink> .</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>Default Actions (Formerly Common Actions)</title>
<para>Shorewall allows the association of a <firstterm>default
action</firstterm> with policies. A separate default action may be
associated with ACCEPT, DROP and REJECT policies. Default actions provide
a way to invoke a set of common rules just before the policy is enforced.
Default 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. Default actions can also avoid common
pitfalls like dropping connection requests on port TCP port 113. If
these connections are dropped (rather than rejected) then you may
encounter problems connecting to Internet services that utilize the
AUTH protocol of client authentication<footnote>
<para>AUTH is actually pretty silly on today's Internet but it's
amazing how many servers still employ it.</para>
</footnote>.</para>
</listitem>
</orderedlist>
<para>Shorewall supports default actions for the ACCEPT, REJECT, DROP,
QUEUE and NFQUEUE 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>
<warning>
<para>Entries in the DROP and REJECT default actions <emphasis
role="bold">ARE NOT THE CAUSE OF CONNECTION PROBLEMS</emphasis>.
Remember — default actions are only invoked immediately before the
packet is going to be dropped or rejected anyway!!!</para>
</warning>
</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>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>
<para>Columns in the <filename>action.template</filename> file are as
follows:</para>
<itemizedlist>
<listitem>
<para>TARGET - Must be ACCEPT, DROP, REJECT, LOG, CONTINUE, QUEUE or
&lt;<emphasis>action</emphasis>&gt; where
&lt;<emphasis>action</emphasis>&gt; 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.netfilter.org/projects/ulogd/index.html">http://www.netfilter.org/projects/ulogd/index.html</ulink>).</para>
<para>You may also use a <ulink url="Macros.html">macro</ulink> in
your action provided that the macro's expansion only results in the
ACTIONs ACCEPT, DROP, REJECT, LOG, CONTINUE, or QUEUE. See
<filename>/usr/share/shorewall/action.Drop</filename> for an example
of an action that users macros extensively.</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 &lt;<emphasis>first
ip</emphasis>&gt;-&lt;<emphasis>last ip</emphasis>&gt;.</para>
</listitem>
<listitem>
<para>PROTO - Protocol - Must be <quote>tcp</quote>,
<quote>udp</quote>, <quote>icmp</quote>, a protocol 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 &lt;<emphasis>low
port</emphasis>&gt;:&lt;<emphasis>high port</emphasis>&gt;.</para>
<para>This column is ignored if PROTO = <quote>all</quote>, but must
be entered if any of the following fields 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't want to restrict client ports but need to specify
any of the subsequent fields, then place <quote>-</quote> 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> &lt;<emphasis>rate</emphasis>&gt;/&lt;<emphasis>interval</emphasis>&gt;[:&lt;<emphasis>burst</emphasis>&gt;]</programlisting>where
&lt;<emphasis>rate</emphasis>&gt; is the number of connections per
&lt;<emphasis>interval</emphasis>&gt; (<quote>sec</quote> or
<quote>min</quote>) and &lt;<emphasis>burst</emphasis>&gt; is the
largest burst permitted. If no &lt;<emphasis>burst</emphasis>&gt; 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>[!]&lt;<emphasis>user number</emphasis>&gt;[:]</member>
<member>[!]&lt;<emphasis>user name</emphasis>&gt;[:]</member>
<member>[!]:&lt;<emphasis>group number</emphasis>&gt;</member>
<member>[!]:&lt;<emphasis>group name</emphasis>&gt;</member>
<member>[!]&lt;<emphasis>user
number</emphasis>&gt;:&lt;<emphasis>group
number</emphasis>&gt;</member>
<member>[!]&lt;<emphasis>user
name</emphasis>&gt;:&lt;<emphasis>group
number</emphasis>&gt;</member>
<member>[!]&lt;<emphasis>user
inumber</emphasis>&gt;:&lt;<emphasis>group
name</emphasis>&gt;</member>
<member>[!]&lt;<emphasis>user
name</emphasis>&gt;:&lt;<emphasis>group name</emphasis>&gt;</member>
<member>[!]+&lt;<emphasis>program name</emphasis>&gt; (Note: support
for this form was removed from Netfilter in kernel version
2.6.14).</member>
</simplelist>
</listitem>
<listitem>
<para>MARK</para>
<para><simplelist>
<member>[!]&lt;<emphasis>value</emphasis>&gt;[/&lt;<emphasis>mask</emphasis>&gt;][:C]</member>
</simplelist></para>
<para>Defines a test on the existing packet or connection mark. The
rule will match only if the test returns true.</para>
<para>If you dont want to define a test but need to specify anything
in the subsequent columns, place a <quote>-</quote> in this
field.<simplelist>
<member>! — Inverts the test (not equal)</member>
<member>&lt;<emphasis>value</emphasis>&gt; — Value of the packet
or connection mark.</member>
<member>&lt;<emphasis>mask</emphasis>&gt; —A mask to be applied to
the mark before testing.</member>
<member>:C — Designates a connection mark. If omitted, the packet
marks value is tested. This option is only supported by
Shorewall-perl</member>
</simplelist></para>
</listitem>
</itemizedlist>
<para>Omitted column entries should be entered using a dash
(<quote>-</quote>).</para>
<para>Example:</para>
<para><filename>/etc/shorewall/actions</filename>:</para>
<para><programlisting> #ACTION COMMENT (place '# ' below the 'C' in comment followed by
# v a comment describing the action)
LogAndAccept # LOG and ACCEPT a connection</programlisting><emphasis
role="bold">Note:</emphasis> If your
<filename>/etc/shorewall/actions</filename> file doesn't have an
indication where to place the comment, put the <quote>#</quote> in column
21.</para>
<para><phrase><filename>/etc/shorewall/action.LogAndAccept</filename></phrase><programlisting> LOG:info
ACCEPT</programlisting></para>
<para>Placing a comment on the line causes the comment to appear in the
output of the <command>shorewall show actions</command> command.</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 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).</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 DEST PORT(S)
ACCEPT - - tcp 22
bar:info</programlisting>
<para>/etc/shorewall/rules:</para>
<programlisting>#ACTION SOURCE DEST PROTO DEST PORT(S)
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 DEST PORT(S)
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 DEST PORT(S)
ACCEPT - - tcp 22
bar:info</programlisting>
<para>/etc/shorewall/rules:</para>
<programlisting>#ACTION SOURCE DEST PROTO DEST PORT(S)
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 DEST PORT(S)
ACCEPT:debug - - tcp 22
bar:debug</programlisting>
</listitem>
</orderedlist>
</section>
<section id="Extension">
<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'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>.<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>
</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;
log_rule_limit( $level, $chainref, 'DropBcasts', 'DROP', '', $tag, 'add', '' ) if $level ne '';
add_rule( $chainref, '-m pkttype --pkttype broadcast -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. Limit is
invoked with a comma-separated list in place of a logging tag. 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 DEST PORT(S)
Limit:none:SSHA,3,60 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 DEST PORT(S)
Limit:info:SSHA,3,60 net $FW tcp 22</programlisting>
<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 is implemented as
follows:</para>
<programlisting>use Shorewall::Chains;
my @tag = split /,/, $tag;
fatal_error 'Limit rules must include &lt;list name&gt;,&lt;max connections&gt;,&lt;interval&gt; as the log tag (' . join( ':', 'Limit', $level eq '' ? 'none' : $level , $tag ) . ')'
unless @tag == 3;
my $list = $tag[0];
for ( @tag[1,2] ) {
fatal_error 'Max connections and interval in Limit rules must be numeric (' . join( ':', 'Limit', $level eq '' ? 'none' : $level, $tag ) . ')' unless /^\d+$/
}
my $count = $tag[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, $tag[0], 'DROP', '', '', 'add', '';
add_rule $xchainref, '-j DROP';
add_rule $chainref, "-m recent --name $list --update --seconds $tag[2] --hitcount $count -j $xchainref-&gt;{name}";
} else {
add_rule $chainref, "-m recent --update --name $list --seconds $tag[2] --hitcount $count -j DROP";
}
add_rule $chainref, '-j ACCEPT';
1; </programlisting>
</section>
</section>
</article>