Copyright © 2006, 2007 Thomas M. Eastep
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 “GNU Free Documentation License”.
2007/07/19
Table of Contents
The performance of the shorewall start and shorewall restart commands when using Shorewall-shell is a frequent topic of questions. This article attempts to explain the scalability issues involved and to offer some tips for reducing the time required to compile a Shorewall configuration and to execute the compiled script.
Ultimately, the solution to these performance problems is to migrate to the use of Shorewall-perl if at all possible.
In this article, we will use the term host group to refer to a set of IP addresses accessed through a particular interface. In a Shorewall configuration, there is one host group for:
Each entry in /etc/shorewall/interfaces
that contains the name of a zone in the first column.
Each entry in /etc/shorewall/hosts
.
As you can see, each host group is associated with a single zone.
For each host group, it is possible to attempt connections to every other host group; and if the host group has the routeback option, then it is possible for connections to be attempted from the host group to itself. So if there are H host groups defined in a Shorewall configuration, then the number of unique pairs of (source host group, destination host group) is H*H or H2. In other words, the number of combinations is the square of the number of host groups and increasing the number of groups from H to H+1 adds H + H + 1 = 2H + 1 additional combinations.
A similar scaling issue applies to Shorewall zones. If there are Z zones, then connections may be attempted from a given zone Zn to all of the other zones (including to Zn itself). Hence, the number of combinations is the square of the number of zones or Z2.
Shorewall is written entirely in Bourne Shell. While this allows Shorewall to run on a wide range of distributions (included embedded ones), the shell programming environment is not ideal for writing the compiler portion of Shorewall. As a consequence, the code must repeatedly perform sequential searches of lists. If a list has N elements and a sequential search is made for each of those elements, then the number of comparisons is 1 + 2 + 3 + .... + N = N * (N + 1 ) / 2. So again, we see order N2 scaling.
Achieving good performance boils down to three things:
Use a light-weight shell and fast hardware. Especially in the compiler, a light-weight shell such as ash or dash can provide considerable improvement over bash.
With all of the order N2 scaling that is implicit in the problem being solved, it is vital to keep N small.
If you have a large number of interfaces, use wild-cards
("+") in /etc/shorewall/interfaces
and
/etc/shorewall/hosts
to reduce the number of
host groups.
Combine host groups with similar firewall requirements into a single zone.
Use NONE policies whereever appropriate. This helps especially in the rules activation phase of both script compilation and execution.
So while it is tempting to create lots of zones through entries in
/etc/shorewall/hosts
, such configurations
always perform badly. In these cases, it is much
better to have more rules than more zones because the performance scales
linearly with the number of rules whereas it scales geometrically with the
number of zones.
Another tip worth noting has to do with the use of shell variables.
Suppose that the following appears in
/etc/shorewall/params
:
HOSTS=<ip1>,<ip2>,<ip3>,...<ipN>
and suppose that $HOSTS appears in the SOURCE column of M ACCEPT rules. That would generate a total of N * M iptables ACCEPT rules.
The number of rules can be reduced significantly by using an action. Consider the following:
/etc/shorewall/actions
:AcceptHosts
/etc/shorewall/action.AcceptHosts
:#TARGET SOURCE DEST PROTO DEST SOURCE ORIGINAL RATE # PORT PORT(S) DEST LIMIT ACCEPT $HOSTS
If the M ACCEPT rules are now replaced with M AcceptHosts rules, the total number of rules will be N + M.
Example (Accept net->fw SSH from $HOSTS):
#ACTION SOURCE DEST PROTO DEST SOURCE ORIGINAL RATE USER/ # PORT PORT(S) DEST LIMIT GROUP AcceptHosts net $FW tcp 22