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. 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 loglevel
local synparams local synparams
local parents local parents
local default
print_policy() # $1 = source zone, $2 = destination zone print_policy() # $1 = source zone, $2 = destination zone
{ {
@ -494,16 +495,24 @@ validate_policy()
fi fi
esac esac
default=
case $policy in case $policy in
*:None|*:none)
default=none
;;
*:*) *:*)
macro=${policy#*:} default=${policy#*:}
if ! list_search $macro $DEFAULT_MACROS; if list_search $default $ACTIONS; then
[ -f find_file macro.${macro} ] || fatal_error "$client $server $policy $loglevel $synparams: Default Macro $macro not found" if ! list_search $default $USEDACTIONS; then
DEFAULT_MACROS="$DEFAULT_MACROS $macro" 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 fi
;; ;;
*) *)
macro=
;; ;;
esac esac
@ -543,7 +552,7 @@ validate_policy()
eval ${chain}_policy=$policy eval ${chain}_policy=$policy
eval ${chain}_loglevel=$loglevel eval ${chain}_loglevel=$loglevel
eval ${chain}_synparams=$synparams eval ${chain}_synparams=$synparams
eval ${chain}_macro=$macro eval ${chain}_default=$default
if [ -n "${clientwild}" ]; then if [ -n "${clientwild}" ]; then
if [ -n "${serverwild}" ]; then if [ -n "${serverwild}" ]; then
@ -1300,8 +1309,8 @@ substitute_action() # $1 = parameter, $2 = action
esac esac
} }
process_actions3() { process_actions3()
{
for xaction in $USEDACTIONS; do for xaction in $USEDACTIONS; do
# #
# Find the chain associated with this action:level:tag # 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 # The caller has established the following variables:
# $2 = clients # COMMAND = current command.
# $3 = servers # client = SOURCE IP or MAC
# $4 = protocol # server = DESTINATION IP or interface
# $5 = ports # protocol = Protocol
# $6 = cports # address = Original Destination Address
# $7 = address # port = Destination Port
# $8 = ratelimit # cport = Source Port
# $9 = userspec # multioption = String to invoke multiport match if appropriate
{ # servport = Port the server listens on
local target="$1" # chain = The canonical chain for this rule
local clients="$2" # logchain = The chain that should be mentioned in log messages
local servers="$3" # ratelimit = Optional rate limiting clause
local protocol="$4" # userandgroup = -m owner clause
local ports="$5" # userspec = User name
local cports="$6" # logtag = Log tag
local address="$7" # policy = Applicable Policy
local ratelimit="$8" #
local userspec="$9" add_a_rule() {
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()
{
local natrule= local natrule=
do_ports() { do_ports() {
@ -1754,7 +1736,7 @@ process_rule() # $1 = target
done done
addr= addr=
else 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 fi
cli= cli=
@ -1891,10 +1873,12 @@ process_rule() # $1 = target
case "$logtarget" in case "$logtarget" in
ACCEPT|DROP|REJECT|CONTINUE) 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 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 "WARNING -- Rule \"$rule\" is a POLICY"
error_message " -- and should be moved to the policy file" error_message " -- and should be moved to the policy file"
fi fi
fi
;; ;;
REDIRECT) REDIRECT)
[ -n "$excludedest" ] && fatal_error "Invalid DEST for this ACTION; rule \"$rule\"" [ -n "$excludedest" ] && fatal_error "Invalid DEST for this ACTION; rule \"$rule\""
@ -2043,7 +2027,32 @@ __EOF__
fi fi
fi 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 # # # # # # # # # # F u n c t i o n B o d y # # # # #
@ -2722,115 +2731,142 @@ process_rules()
SECTION=DONE 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 a default macro
# #
process_default_macro() # $1 = macro name process_default_macro() # $1 = macro name
{ {
local macro=$1 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" havechain $macro && fatal_error "Illegal duplicate default macro name: $macro"
createchain $macro createchain $macro no
strip_file macro.${macro} strip_file macro.$macro
progress_message "..Expanding Macro $(find_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 while read target client server protocol port cport ratelimit userspec; do
expandv mtarget mclients mservers mprotocol mports mcports mratelimit muserspec 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:*) PARAM|PARAM:*)
fatal_error "Invalid target ($mtarget) in default macro $macro" fatal_error "Invalid target ($target) in default macro $macro"
;; ;;
esac esac
case ${mtarget} in case ${target} in
ACCEPT|DROP|REJECT) ACCEPT|DROP|REJECT)
;; ;;
*) *)
if list_search ${mtarget%%:*} $ACTIONS; then if list_search $target $ACTIONS; then
if ! list_search $mtarget $USEDACTIONS; then if ! list_search $target $USEDACTIONS; then
createactionchain $mtarget createactionchain $target
USEDACTIONS="$USEDACTIONS $mtarget" USEDACTIONS="$USEDACTIONS $target"
fi fi
mtarget=$(find_logactionchain $mtarget)
else 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 fi
;; ;;
esac esac
if [ -n "$mclients" ]; then if [ $(list_count ${port}${cport}) -gt 1 ]; then
case $mclients in multioption="-m multiport"
fi
if [ -n "$client" ]; then
case $client in
-|SOURCE) -|SOURCE)
;; client=
*)
fatal_error "Invalid SOURCE ($mclients) in default macro $macro"
;; ;;
esac esac
fi fi
if [ -n "$mservers" ]; then if [ -n "$server" ]; then
case $mservers in case $server in
-|DEST) -|DEST)
server=
;; ;;
*) *)
fatal_error "Invalid DEST ($mservers) in default macro $macro"
;; ;;
esac esac
fi fi
case ${mports}${mcports} in [ "x$userspec" = "x-" ] && userspec=
*,*)
fatal_error "Port lists not allowed in default macro" 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 esac
[ "x$mratelimit" != "x-" -a -n "$mratelimit" ] && fatal_error "Invalid Rate Limit ($mratelimit) in default macro $macro" case "$userspec" in
[ "x$muserspec" != "x-" -a -n "$muserspec" ] && fatal_error "Invalid USER/GROUP ($muserspec) in default macro $macro" !*:*)
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 [ "$userandgroup" = "-m owner" ] && userandgroup=
progress_message "Rule \"$target $mprotocol $mports $mcports $mratelimit $muserspec\" $DONE" 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" progress_message "..End Macro"
@ -3043,12 +3079,12 @@ policy_rules() # $1 = chain to add rules to
# $3 = loglevel # $3 = loglevel
{ {
local target="$2" local target="$2"
local macro local default
eval macro=\$${1}_macro eval default=\$${1}_default
if [ -n "$macro" ]; then if [ -n "$default" ]; then
run_iptables -A $1 -j $macro [ "$default" = none ] || run_iptables -A $1 -j $default
else else
case "$target" in case "$target" in
ACCEPT) ACCEPT)
@ -3484,6 +3520,13 @@ initialize_netfilter () {
validate_hosts_file validate_hosts_file
define_builtin_actions
if [ -n "$USE_ACTIONS" ]; then
progress_message2 "Pre-processing Actions..."
process_actions1
fi
progress_message2 "Validating Policy file..." progress_message2 "Validating Policy file..."
validate_policy validate_policy
@ -3495,22 +3538,9 @@ initialize_netfilter () {
append_file init 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 rules
strip_file maclist strip_file maclist
define_builtin_actions
if [ -n "$USE_ACTIONS" ]; then
progress_message2 "Pre-processing Actions..."
process_actions1
fi
TERMINATOR=fatal_error TERMINATOR=fatal_error
deletechain shorewall deletechain shorewall
@ -5174,6 +5204,7 @@ __EOF__
if [ -n "$DEFAULT_MACROS" ]; then if [ -n "$DEFAULT_MACROS" ]; then
progress_message2 "$DOING default macros..." progress_message2 "$DOING default macros..."
save_progress_message "Creating default macro chains..."
for macro in $DEFAULT_MACROS; do for macro in $DEFAULT_MACROS; do
process_default_macro $macro process_default_macro $macro
done done

View File

@ -59,19 +59,20 @@
# contain the firewall zone ($FW) or # contain the firewall zone ($FW) or
# "all". # "all".
# #
# If USE_ACTIONS=Yes in shorewall.conf (or if that # If the policy is ACCEPT, DROP, REJECT or QUEUE then
# option is not set) then if this column contains ACCEPT, # the policy may be followed by ":" and one of the
# DROP, or REJECT and a corresponding default action # following:
# 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 USE_ACTIONS=No in shorewall.conf then ACCEPT,DROP # a) The word "None" or "none". This causes any default
# REJECT may be optionally followed by ":" and the name # action define in /etc/shorewall/actions.std or
# of a macro. The rules in the macro will be expanded # /etc/shorewall/actions to be omitted for this
# and packets will pass through the rules prior to # policy.
# the policy being applied. # 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 # LOG LEVEL If supplied, each connection handled under the default
# POLICY is logged at that level. If not supplied, no # 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 The macros macro.Drop and macro.Reject are supplied to help you do
that. 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.