Allow policy-level specification of default action or macro

git-svn-id: https://shorewall.svn.sourceforge.net/svnroot/shorewall/trunk@4481 fbd18981-670d-0410-9b5c-8dc0c1a9a2bb
This commit is contained in:
teastep 2006-08-30 17:06:23 +00:00
parent 1ec8b73540
commit 8c4eef48c4
4 changed files with 555 additions and 474 deletions

View File

@ -2,4 +2,7 @@ Changes in 3.3.1
1) Load the proxyarp lib when 'proxyarp' option is specified.
2) Implement default action/macros at the individual policy level.

View File

@ -426,6 +426,7 @@ validate_policy()
local loglevel
local synparams
local parents
local default
print_policy() # $1 = source zone, $2 = destination zone
{
@ -494,16 +495,24 @@ validate_policy()
fi
esac
default=
case $policy in
*:None|*:none)
default=none
;;
*:*)
macro=${policy#*:}
if ! list_search $macro $DEFAULT_MACROS;
[ -f find_file macro.${macro} ] || fatal_error "$client $server $policy $loglevel $synparams: Default Macro $macro not found"
DEFAULT_MACROS="$DEFAULT_MACROS $macro"
default=${policy#*:}
if list_search $default $ACTIONS; then
if ! list_search $default $USEDACTIONS; then
USEDACTIONS="$USEDACTIONS $default"
fi
elif ! list_search $default $DEFAULT_MACROS; then
[ -f $(find_file macro.${default}) ] || fatal_error "$client $server $policy $loglevel $synparams: Default Macro $default not found"
DEFAULT_MACROS="$DEFAULT_MACROS $default"
fi
;;
*)
macro=
;;
esac
@ -543,7 +552,7 @@ validate_policy()
eval ${chain}_policy=$policy
eval ${chain}_loglevel=$loglevel
eval ${chain}_synparams=$synparams
eval ${chain}_macro=$macro
eval ${chain}_default=$default
if [ -n "${clientwild}" ]; then
if [ -n "${serverwild}" ]; then
@ -1300,8 +1309,8 @@ substitute_action() # $1 = parameter, $2 = action
esac
}
process_actions3() {
process_actions3()
{
for xaction in $USEDACTIONS; do
#
# Find the chain associated with this action:level:tag
@ -1664,54 +1673,27 @@ __EOF__
}
#
# Process a record from the rules file
# Add one Filter Rule
#
process_rule() # $1 = target
# $2 = clients
# $3 = servers
# $4 = protocol
# $5 = ports
# $6 = cports
# $7 = address
# $8 = ratelimit
# $9 = userspec
{
local target="$1"
local clients="$2"
local servers="$3"
local protocol="$4"
local ports="$5"
local cports="$6"
local address="$7"
local ratelimit="$8"
local userspec="$9"
local userandgroup=
local logtag=
local nonat=
#
# Add one Filter Rule
#
# The caller has established the following variables:
# COMMAND = current command.
# which only goes through the motions.
# client = SOURCE IP or MAC
# server = DESTINATION IP or interface
# protocol = Protocol
# address = Original Destination Address
# port = Destination Port
# cport = Source Port
# multioption = String to invoke multiport match if appropriate
# servport = Port the server listens on
# chain = The canonical chain for this rule
# logchain = The chain that should be mentioned in log messages
# ratelimit = Optional rate limiting clause
# userandgroup = -m owner clause
# userspec = User name
# logtag = Log tag
# policy = Applicable Policy
#
add_a_rule()
{
# The caller has established the following variables:
# COMMAND = current command.
# client = SOURCE IP or MAC
# server = DESTINATION IP or interface
# protocol = Protocol
# address = Original Destination Address
# port = Destination Port
# cport = Source Port
# multioption = String to invoke multiport match if appropriate
# servport = Port the server listens on
# chain = The canonical chain for this rule
# logchain = The chain that should be mentioned in log messages
# ratelimit = Optional rate limiting clause
# userandgroup = -m owner clause
# userspec = User name
# logtag = Log tag
# policy = Applicable Policy
#
add_a_rule() {
local natrule=
do_ports() {
@ -1754,7 +1736,7 @@ process_rule() # $1 = target
done
addr=
else
run_iptables -A $state $logchain $(fix_bang $cli $proto $sports $multiport $dports) $user -j $chain
run_iptables -A $logchain $state $(fix_bang $cli $proto $sports $multiport $dports) $user -j $chain
fi
cli=
@ -1891,10 +1873,12 @@ process_rule() # $1 = target
case "$logtarget" in
ACCEPT|DROP|REJECT|CONTINUE)
if [ "$SECTION" != DONE ]; then
if [ -z "$proto" -a -z "$cli" -a -z "$serv" -a -z "$servport" -a -z "$user" -a -z "$excludesource" -a -z "$excludedest" ] ; then
error_message "WARNING -- Rule \"$rule\" is a POLICY"
error_message " -- and should be moved to the policy file"
fi
fi
;;
REDIRECT)
[ -n "$excludedest" ] && fatal_error "Invalid DEST for this ACTION; rule \"$rule\""
@ -2043,7 +2027,32 @@ __EOF__
fi
fi
fi
}
}
#
# Process a record from the rules file
#
process_rule() # $1 = target
# $2 = clients
# $3 = servers
# $4 = protocol
# $5 = ports
# $6 = cports
# $7 = address
# $8 = ratelimit
# $9 = userspec
{
local target="$1"
local clients="$2"
local servers="$3"
local protocol="$4"
local ports="$5"
local cports="$6"
local address="$7"
local ratelimit="$8"
local userspec="$9"
local userandgroup=
local logtag=
local nonat=
# # # # # F u n c t i o n B o d y # # # # #
@ -2722,115 +2731,142 @@ process_rules()
SECTION=DONE
}
#
# Expand an entry in a default macro
#
expand_macro() {
local chain=$1
local target=$2
local protocol=$3
local port=$4
local cport=$5
local rule=
if [ "x$protocol" != x- -a -n "$protocol" ]; then
rule="-p $protocol"
case $protocol in
6|tcp|TCP|17|udp|UDP)
if [ "x$port" != x- -a -n "$port" ]; then
rule="$rule -m multiport --dports $port"
[ "x$cport" != x- -a -n "$cport" ] && rule="$rule --sports $cport"
else
[ "x$cport" != x- -a -n "$cport" ] && rule="$rule -m multiport --sports $cport"
fi
;;
icmp|ICMP|0)
[ "x$port" != x- -a -n "$port" ] && rule="$rule --icmp-type $port"
;;
;;
*)
[ "x$port" != x- -a -n "$port" ] && fatal_error "DEST PORT(S) not allowed with protocol $protocol"
[ "x$cport" != x- -a -n "$cport" ] && fatal_error "SOURCE PORT(S) not allowed with protocol $protocol"
;;
esac
fi
run_iptables -A $chain $rule -j $target
}
#
# Process a default macro
#
process_default_macro() # $1 = macro name
{
local macro=$1
local address=
local multioption=
local servport=
local chain=$1
local logchain=$1
local userandgroup=
local logtag=
local excludesource=
local target client server protocol port cport ratelimit userspec rule
havechain $macro && fatal_error "Illegal duplicate default macro name: $macro"
createchain $macro
strip_file macro.${macro}
progress_message "..Expanding Macro $(find_file macro.${macro})..."
createchain $macro no
strip_file macro.$macro
progress_message "..Expanding Default Macro $(find_file macro.${macro}) into chain $macro..."
while read mtarget mclients mservers mprotocol mports mcports mratelimit muserspec; do
expandv mtarget mclients mservers mprotocol mports mcports mratelimit muserspec
while read target client server protocol port cport ratelimit userspec; do
expandv target client server protocol port cport ratelimit userspec
rule="$target ${client:--} ${server:--} ${protocol:--} ${port:--} ${cport:--} ${ratelimit:--} ${userspec:--}"
case $mtarget in
case $target in
PARAM|PARAM:*)
fatal_error "Invalid target ($mtarget) in default macro $macro"
fatal_error "Invalid target ($target) in default macro $macro"
;;
esac
case ${mtarget} in
case ${target} in
ACCEPT|DROP|REJECT)
;;
*)
if list_search ${mtarget%%:*} $ACTIONS; then
if ! list_search $mtarget $USEDACTIONS; then
createactionchain $mtarget
USEDACTIONS="$USEDACTIONS $mtarget"
if list_search $target $ACTIONS; then
if ! list_search $target $USEDACTIONS; then
createactionchain $target
USEDACTIONS="$USEDACTIONS $target"
fi
mtarget=$(find_logactionchain $mtarget)
else
fatal_error "Invalid Action in rule \"$mtarget ${mclients:--} ${mservers:--} ${mprotocol:--} ${mports:--} ${mcports:--} ${xaddress:--} ${mratelimit:--} ${muserspec:--}\""
fatal_error "Invalid target ($target) in default macro $macro"
fi
;;
esac
if [ -n "$mclients" ]; then
case $mclients in
if [ $(list_count ${port}${cport}) -gt 1 ]; then
multioption="-m multiport"
fi
if [ -n "$client" ]; then
case $client in
-|SOURCE)
;;
*)
fatal_error "Invalid SOURCE ($mclients) in default macro $macro"
client=
;;
esac
fi
if [ -n "$mservers" ]; then
case $mservers in
if [ -n "$server" ]; then
case $server in
-|DEST)
server=
;;
*)
fatal_error "Invalid DEST ($mservers) in default macro $macro"
;;
esac
fi
case ${mports}${mcports} in
*,*)
fatal_error "Port lists not allowed in default macro"
[ "x$userspec" = "x-" ] && userspec=
if [ -n "$userspec" ]; then
userandgroup="-m owner"
case "$userspec" in
!*+*)
if [ -n "${userspec#*+}" ]; then
userandgroup="$userandgroup ! --cmd-owner ${userspec#*+}"
fi
userspec=${userspec%+*}
;;
*+*)
if [ -n "${userspec#*+}" ]; then
userandgroup="$userandgroup --cmd-owner ${userspec#*+}"
fi
userspec=${userspec%+*}
;;
esac
[ "x$mratelimit" != "x-" -a -n "$mratelimit" ] && fatal_error "Invalid Rate Limit ($mratelimit) in default macro $macro"
[ "x$muserspec" != "x-" -a -n "$muserspec" ] && fatal_error "Invalid USER/GROUP ($muserspec) in default macro $macro"
case "$userspec" in
!*:*)
if [ "$userspec" != "!:" ]; then
temp="${userspec#!}"
temp="${temp%:*}"
[ -n "$temp" ] && userandgroup="$userandgroup ! --uid-owner $temp"
temp="${userspec#*:}"
[ -n "$temp" ] && userandgroup="$userandgroup ! --gid-owner $temp"
fi
;;
*:*)
if [ "$userspec" != ":" ]; then
temp="${userspec%:*}"
[ -n "$temp" ] && userandgroup="$userandgroup --uid-owner $temp"
temp="${userspec#*:}"
[ -n "$temp" ] && userandgroup="$userandgroup --gid-owner $temp"
fi
;;
!*)
[ "$userspec" != "!" ] && userandgroup="$userandgroup ! --uid-owner ${userspec#!}"
;;
*)
[ -n "$userspec" ] && userandgroup="$userandgroup --uid-owner $userspec"
;;
esac
expand_macro $1 $target $mprotocol $mports $mcports $mratelimit $muserspec
progress_message "Rule \"$target $mprotocol $mports $mcports $mratelimit $muserspec\" $DONE"
[ "$userandgroup" = "-m owner" ] && userandgroup=
fi
done < $TMP_DIR/macro.${itarget%%:*}
[ "x$ratelimit" = "x-" ] && ratelimit=
if [ -n "$ratelimit" ]; then
case $ratelimit in
*:*)
ratelimit="-m limit --limit ${ratelimit%:*} --limit-burst ${ratelimit#*:}"
;;
*)
ratelimit="-m limit --limit $ratelimit"
;;
esac
fi
add_a_rule
progress_message "Rule \"$target $protocol $port $cport $ratelimit $userspec\" $DONE"
done < $TMP_DIR/macro.$macro
progress_message "..End Macro"
@ -3043,12 +3079,12 @@ policy_rules() # $1 = chain to add rules to
# $3 = loglevel
{
local target="$2"
local macro
local default
eval macro=\$${1}_macro
eval default=\$${1}_default
if [ -n "$macro" ]; then
run_iptables -A $1 -j $macro
if [ -n "$default" ]; then
[ "$default" = none ] || run_iptables -A $1 -j $default
else
case "$target" in
ACCEPT)
@ -3484,6 +3520,13 @@ initialize_netfilter () {
validate_hosts_file
define_builtin_actions
if [ -n "$USE_ACTIONS" ]; then
progress_message2 "Pre-processing Actions..."
process_actions1
fi
progress_message2 "Validating Policy file..."
validate_policy
@ -3495,22 +3538,9 @@ initialize_netfilter () {
append_file init
#
# Some files might be large so strip them while the firewall is still running
# (restart command). This reduces the length of time that the firewall isn't
# accepting new connections.
#
strip_file rules
strip_file maclist
define_builtin_actions
if [ -n "$USE_ACTIONS" ]; then
progress_message2 "Pre-processing Actions..."
process_actions1
fi
TERMINATOR=fatal_error
deletechain shorewall
@ -5174,6 +5204,7 @@ __EOF__
if [ -n "$DEFAULT_MACROS" ]; then
progress_message2 "$DOING default macros..."
save_progress_message "Creating default macro chains..."
for macro in $DEFAULT_MACROS; do
process_default_macro $macro
done

View File

@ -59,19 +59,20 @@
# contain the firewall zone ($FW) or
# "all".
#
# If USE_ACTIONS=Yes in shorewall.conf (or if that
# option is not set) then if this column contains ACCEPT,
# DROP, or REJECT and a corresponding default action
# is defined in /etc/shorewall/actions (or
# /usr/share/shorewall/actions.std) then that action
# will be invoked before the policy named in this column
# is enforced.
# If the policy is ACCEPT, DROP, REJECT or QUEUE then
# the policy may be followed by ":" and one of the
# following:
#
# If USE_ACTIONS=No in shorewall.conf then ACCEPT,DROP
# REJECT may be optionally followed by ":" and the name
# of a macro. The rules in the macro will be expanded
# and packets will pass through the rules prior to
# the policy being applied.
# a) The word "None" or "none". This causes any default
# action define in /etc/shorewall/actions.std or
# /etc/shorewall/actions to be omitted for this
# policy.
# b) The name of an action (requires that USE_ACTIONS=Yes
# in shorewall.conf). That action will be invoked
# before the policy is enforced.
# c) The name of a macro. The rules in that macro will
# be applied before the policy is enforced. This
# does not require USE_ACTIONS=Yes.
#
# LOG LEVEL If supplied, each connection handled under the default
# POLICY is logged at that level. If not supplied, no

View File

@ -112,4 +112,50 @@ New Features:
The macros macro.Drop and macro.Reject are supplied to help you do
that.
3) Prior to Shorewall 3.3, default actions were specified in
/usr/share/shorewall/actions.std or in /etc/shorewall/actions.
This approach has two drawbacks:
a) All DROP policies must use the same default action and all
REJECT policies must use the same default action.
b) Now that we have modularized action processing, we need a way to
define default rules for a policy.
The solution is to extend the POLICY column in
/etc/shorewall/policy.
When the POLICY is ACCEPT, DROP, REJECT or QUEUE then the policy
may be followed by ":" and one of the following:
a) The word "None" or "none". This causes any default
action define in /etc/shorewall/actions.std or
/etc/shorewall/actions to be omitted for this
policy.
b) The name of an action (requires that USE_ACTIONS=Yes
in shorewall.conf). That action will be invoked
before the policy is enforced.
c) The name of a macro. The rules in that macro will
be applied before the policy is enforced. This
does not require USE_ACTIONS=Yes.
Example:
#SOURCE DEST POLICY LOG
# LEVEL
loc net ACCEPT
net all DROP:Drop info
#
# THE FOLLOWING POLICY MUST BE LAST
#
all all REJECT:Reject info
With USE_ACTIONS=Yes, the above will work the same way that the
pre-3.3 setup did. The 'Drop' and 'Reject' actions will be invoked
before the DROP and REJECT policies are enforced.
With USE_ACTION=No, there will be no Drop or Reject actions so
Shorewall will look for macros by that name; as described in item
2) above, these macros are provided as part of the Shorewall 3.3
release.