First implementation of dynamic zones

git-svn-id: https://shorewall.svn.sourceforge.net/svnroot/shorewall/trunk@275 fbd18981-670d-0410-9b5c-8dc0c1a9a2bb
This commit is contained in:
teastep 2002-10-01 20:54:42 +00:00
parent 36fe894006
commit 129cedbe8f
3 changed files with 288 additions and 17 deletions

View File

@ -1142,7 +1142,7 @@ setup_tunnels() # $1 = name of tunnels file
local inchain
local outchain
setup_one_ipsec() # $1 = gateway $2 = gateway zone
setup_one_ipsec() # $1 = gateway $2 = gateway zones
{
options="-m state --state NEW -j ACCEPT"
addrule $inchain -p 50 -s $1 -j ACCEPT
@ -1152,14 +1152,14 @@ setup_tunnels() # $1 = name of tunnels file
run_iptables -A $inchain -p udp -s $1 --sport 500 --dport 500 $options
run_iptables -A $outchain -p udp -d $1 --dport 500 --sport 500 $options
if [ -n "$2" ]; then
if validate_zone $2; then
addrule ${FW}2${2} -p udp --sport 500 --dport 500 $options
for z in `separate_list $2`; do
if validate_zone $z; then
addrule ${FW}2${z} -p udp --sport 500 --dport 500 $options
else
error_message "Warning: Invalid gateway zone ($2)" \
error_message "Warning: Invalid gateway zone ($z)" \
" -- Tunnel \"$tunnel\" may encounter keying problems"
fi
fi
done
echo " IPSEC tunnel to $gateway defined."
}
@ -3183,23 +3183,34 @@ activate_rules()
multi_interfaces=`find_interfaces_by_option multi`
> ${STATEDIR}/chains
> ${STATEDIR}/zones
for zone in $zones; do
eval source_hosts=\$${zone}_hosts
echo $zone $source_hosts >> ${STATEDIR}/zones
chain1=`rules_chain $FW $zone`
chain2=`rules_chain $zone $FW`
echo "$FW $zone $chain1" >> ${STATEDIR}/chains
echo "$zone $FW $chain2" >> ${STATEDIR}/chains
for host in $source_hosts; do
interface=${host%:*}
subnet=${host#*:}
run_iptables -A OUTPUT -o \
$interface -d $subnet -j `rules_chain $FW $zone`
run_iptables -A OUTPUT -o $interface -d $subnet -j $chain1
#
# Add jumps from the builtin chains for DNAT and SNAT rules
#
addrulejump PREROUTING `dnat_chain $zone` -i $interface -s $subnet
addrulejump POSTROUTING `snat_chain $zone` -o $interface -d $subnet
run_iptables -A `input_chain $interface` -s $subnet \
-j `rules_chain $zone $FW`
run_iptables -A `input_chain $interface` -s $subnet -j $chain2
done
for zone1 in $zones; do
@ -3207,6 +3218,8 @@ activate_rules()
chain="`rules_chain $zone $zone1`"
echo "$zone $zone1 $chain" >> ${STATEDIR}/chains
if havechain ${zone}2${zone1} || havechain ${zone1}2${zone}; then
have_canonical=Yes
else
@ -3438,6 +3451,215 @@ refresh_firewall()
rm -rf $TMP_DIR
}
################################################################################
# Add a host or subnet to a zone #
################################################################################
add_to_zone() # $1 = <interface>[:<hosts>] $2 = zone
{
chain_exists() # $1 = chain name
{
qt iptables -L $1 -n
}
nat_chain_exists() # $1 = chain name
{
qt iptables -t nat -L $1 -n
}
do_iptables() # $@ = command
{
if ! iptables $@ ; then
startup_error "Error: can't add $1 to zone $2"
fi
}
output_rule_num() {
local num=`iptables -L OUTPUT -n --line-numbers | grep common | cut -d' ' -f1 | tail -n1`
[ -z "$num" ] && num=`iptables -L OUTPUT -n --line-numbers | grep ACCEPT | cut -d' ' -f1 | tail -n1`
echo $num
}
interface=${1%:*}
host=${1#*:}
[ -z "$host" ] && host="0.0.0.0/0"
determine_zones
zone=$2
validate_zone $zone || startup_error "Error: Unknown zone: $zone"
[ "$zone" = $FW ] && startup_error "Error: Can't add $1 to firewall zone"
[ -f ${STATEDIR}/chains ] || startup_error "Error: ${STATEDIR}/chains -- file not found"
[ -f ${STATEDIR}/zones ] || startup_error "Error: ${STATEDIR}/zones -- file not found"
if ! chain_exists `input_chain $interface` ; then
startup_error "Error: Unknown interface $interface"
fi
newhost="$interface:$host"
> ${STATEDIR}/zones_$$
while read z hosts; do
if [ "$z" = "$zone" ]; then
for h in $hosts; do
if [ "$h" = "$newhost" ]; then
rm -f ${STATEDIR}/zones_$$
startup_error "Error: $1 already in zone $zone"
fi
done
[ -z "$hosts" ] && hosts=$newhost || hosts="$hosts $newhost"
fi
eval ${z}_hosts=$hosts
echo "$z $hosts" >> ${STATEDIR}/zones_$$
done < ${STATEDIR}/zones
mv -f ${STATEDIR}/zones_$$ ${STATEDIR}/zones
chain=${zone}_dnat
if nat_chain_exists $chain; then
do_iptables -t nat -A PREROUTING -i $interface -s $host -j $chain
fi
while read z1 z2 chain; do
if [ "$z1" = "$zone" ]; then
if [ "$z2" = "$FW" ]; then
do_iptables -A `input_chain $interface` -i $interface -s $host -j $chain
else
source_chain=`forward_chain $interface`
eval dest_hosts=\$${z2}_hosts
for h in $dest_hosts; do
do_iptables -A $source_chain -s $host -o ${h%:*} -d ${h#*:} -j $chain
done
fi
elif [ "$z2" = "$zone" ]; then
if [ "$z1" = "$FW" ]; then
do_iptables -I OUTPUT `output_rule_num` $num -o $interface -d $host -j $chain
else
eval source_hosts=\$${z1}_hosts
for h in $source_hosts; do
iface=${h%:*}
hosts=${h#*:}
if [ "$iface" != "$interface" ]; then
do_iptables -A `forward_chain $iface` -s $hosts -o $interface -d $host -j $chain
fi
done
fi
fi
done < ${STATEDIR}/chains
echo "$1 added to zone $2"
}
################################################################################
# Delete a host or subnet from a zone #
################################################################################
delete_from_zone() # $1 = <interface>[:<hosts>] $2 = zone
{
chain_exists() # $1 = chain name
{
qt iptables -L $1 -n
}
delete_from_zones_file()
{
> ${STATEDIR}/zones_$$
while read z hosts; do
if [ "$z" = "$zone" ]; then
temp=$hosts
hosts=
for h in $temp; do
if [ "$h" = "$temp" ]; then
echo Yes
else
hosts="$hosts $h"
fi
done
fi
echo "$z $hosts" >> ${STATEDIR}/zones_$$
done < ${STATEDIR}/zones
mv -f ${STATEDIR}/zones_$$ ${STATEDIR}/zones
}
interface=${1%:*}
host=${1#*:}
[ -z "$host" ] && host="0.0.0.0/0"
determine_zones
zone=$2
validate_zone $zone || startup_error "Error: Unknown zone: $zone"
[ "$zone" = $FW ] && startup_error "Error: Can't remove $1 to firewall zone"
[ -f ${STATEDIR}/chains ] || startup_error "Error: ${STATEDIR}/chains -- file not found"
[ -f ${STATEDIR}/zones ] || startup_error "Error: ${STATEDIR}/zones -- file not found"
if ! chain_exists `input_chain $interface` ; then
startup_error "Error: Unknown interface $interface"
fi
newhost="$interface:$host"
[ -z "`delete_from_zones_file`" ] && startup_error "Error: $1 not in zone $2"
while read z hosts; do
eval ${z}_hosts=$hosts
done < ${STATEDIR}/zones
qt iptables -t nat -D PREROUTING -i $interface -s $host -j ${zone}_dnat
while read z1 z2 chain; do
if [ "$z1" = "$zone" ]; then
if [ "$z2" = "$FW" ]; then
qt iptables -D `input_chain $interface` -i $interface -s $host -j $chain
else
source_chain=`forward_chain $interface`
eval dest_hosts=\$${z2}_hosts
for h in $dest_hosts; do
qt iptables -D $source_chain -s $host -o ${h%:*} -d ${h#*:} -j $chain
done
fi
elif [ "$z2" = "$zone" ]; then
if [ "$z1" = "$FW" ]; then
qt iptables -D OUTPUT -o $interface -d $host -j $chain
else
eval source_hosts=\$${z1}_hosts
for h in $source_hosts; do
iface=${h%:*}
hosts=${h#*:}
if [ "$iface" != "$interface" ]; then
qt iptables -D `forward_chain $iface` -s $hosts -o $interface -d $host -j $chain
fi
done
fi
fi
done < ${STATEDIR}/chains
echo "$1 removed from zone $2"
}
################################################################################
# Determine the value for a parameter that defaults to Yes #
################################################################################
@ -3609,7 +3831,7 @@ do_initialize() {
# Give Usage Information #
################################################################################
usage() {
echo "Usage: $0 [debug] {start|stop|reset|restart|status|refresh|clear]}"
echo "Usage: $0 [debug] {start|stop|reset|restart|status|refresh|clear|{add|delete} <interface>[:hosts] zone}}"
exit 1
}
@ -3625,14 +3847,13 @@ nolock=
[ $# -gt 1 ] && [ "$1" = "nolock" ] && { nolock=Yes; shift ; }
[ $# -ne 1 ] && usage
trap "my_mutex_off; exit 2" 1 2 3 4 5 6 9
command="$1"
case "$command" in
stop)
[ $# -ne 1 ] && usage
do_initialize
my_mutex_on
echo -n "Stopping Shorewall..."
@ -3644,6 +3865,7 @@ case "$command" in
;;
start)
[ $# -ne 1 ] && usage
do_initialize
my_mutex_on
if qt iptables -L shorewall -n ; then
@ -3658,6 +3880,7 @@ case "$command" in
;;
restart)
[ $# -ne 1 ] && usage
do_initialize
my_mutex_on
if qt iptables -L shorewall -n ; then
@ -3672,17 +3895,20 @@ case "$command" in
;;
status)
[ $# -ne 1 ] && usage
echo -e "Shorewall-$version Status at $HOSTNAME - `date`\\n"
iptables -L -n -v
;;
reset)
[ $# -ne 1 ] && usage
iptables -L -n -Z -v
report "Shorewall Counters Reset"
date > $STATEDIR/restarted
;;
refresh)
[ $# -ne 1 ] && usage
do_initialize
my_mutex_on
if ! qt iptables -L shorewall -n ; then
@ -3696,6 +3922,7 @@ case "$command" in
;;
clear)
[ $# -ne 1 ] && usage
do_initialize
my_mutex_on
echo -n "Clearing Shorewall..."
@ -3707,10 +3934,36 @@ case "$command" in
;;
check)
[ $# -ne 1 ] && usage
do_initialize
check_config
;;
add)
[ $# -ne 3 ] && usage
do_initialize
my_mutex_on
if ! qt iptables -L shorewall -n ; then
echo "Shorewall Not Started"
[ -n "$TMP_DIR" ] && rm -rf $TMP_DIR
my_mutex_off
exit 2;
fi
add_to_zone $2 $3
my_mutex_off
;;
delete)
[ $# -ne 3 ] && usage
do_initialize
my_mutex_on
if ! qt iptables -L shorewall -n ; then
echo "Shorewall Not Started"
[ -n "$TMP_DIR" ] && rm -rf $TMP_DIR
my_mutex_off
exit 2;
fi
delete_from_zone $2 $3
my_mutex_off
;;
*)
usage
;;

View File

@ -32,6 +32,8 @@
#
# Commands are:
#
# shorewall add <iface>[:<host>] zone Adds a host or subnet to a zone
# shorewall delete <iface>[:<host>] zone Deletes a host or subnet from a zone
# shorewall start Starts the firewall
# shorewall restart Restarts the firewall
# shorewall stop Stops the firewall
@ -416,6 +418,8 @@ usage() # $1 = exit status
{
echo "Usage: `basename $0` [debug] [nolock] [-c <directory>] <command>"
echo "where <command> is one of:"
echo " add <interface>[:<host>] <zone>"
echo " delete <interface>[:<host>] <zone>"
echo " show [<chain>|connections|log|nat|tc|tos]"
echo " start"
echo " stop"
@ -537,6 +541,10 @@ case "$1" in
[ $# -ne 1 ] && usage 1
exec $firewall $debugging $nolock $1
;;
add|delete)
[ $# -ne 3 ] && usage 1
exec $firewall $debugging $nolock $1 $2 $3
;;
show)
[ $# -gt 2 ] && usage 1
case "$2" in

View File

@ -19,10 +19,10 @@
# remote getway has no fixed address (Road Warrior)
# then specify the gateway as 0.0.0.0/0.
#
# GATEWAY ZONE-- Optional. If the gateway system specified in the third
# GATEWAY ZONES -- Optional. If the gateway system specified in the third
# column is a standalone host then this column should
# contain the name of the zone that the host is in. This
# column only applies to IPSEC tunnels.
# contain a comma-separated list of the names of the zones that
# the host might be in. This column only applies to IPSEC tunnels.
#
# Example 1:
#
@ -47,5 +47,15 @@
#
# ipsec net 4.33.99.124 gw
#
# Example 4:
#
# Road Warriors that may belong to zones vpn1, vpn2 or
# vpn3. The FreeS/Wan _updown script will add the
# host to the appropriate zone using the "shorewall add"
# command on connect and will remove the host from the
# zone at disconnect time.
#
# ipsec net 0.0.0.0/0 vpn1,vpn2,vpn3
#
# TYPE ZONE GATEWAY GATEWAY ZONE
#LAST LINE -- ADD YOUR ENTRIES BEFORE THIS ONE -- DO NOT REMOVE