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 inchain
local outchain 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" options="-m state --state NEW -j ACCEPT"
addrule $inchain -p 50 -s $1 -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 $inchain -p udp -s $1 --sport 500 --dport 500 $options
run_iptables -A $outchain -p udp -d $1 --dport 500 --sport 500 $options run_iptables -A $outchain -p udp -d $1 --dport 500 --sport 500 $options
if [ -n "$2" ]; then for z in `separate_list $2`; do
if validate_zone $2; then if validate_zone $z; then
addrule ${FW}2${2} -p udp --sport 500 --dport 500 $options addrule ${FW}2${z} -p udp --sport 500 --dport 500 $options
else else
error_message "Warning: Invalid gateway zone ($2)" \ error_message "Warning: Invalid gateway zone ($z)" \
" -- Tunnel \"$tunnel\" may encounter keying problems" " -- Tunnel \"$tunnel\" may encounter keying problems"
fi fi
fi done
echo " IPSEC tunnel to $gateway defined." echo " IPSEC tunnel to $gateway defined."
} }
@ -3183,23 +3183,34 @@ activate_rules()
multi_interfaces=`find_interfaces_by_option multi` multi_interfaces=`find_interfaces_by_option multi`
> ${STATEDIR}/chains
> ${STATEDIR}/zones
for zone in $zones; do for zone in $zones; do
eval source_hosts=\$${zone}_hosts 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 for host in $source_hosts; do
interface=${host%:*} interface=${host%:*}
subnet=${host#*:} subnet=${host#*:}
run_iptables -A OUTPUT -o \ run_iptables -A OUTPUT -o $interface -d $subnet -j $chain1
$interface -d $subnet -j `rules_chain $FW $zone`
# #
# Add jumps from the builtin chains for DNAT and SNAT rules # Add jumps from the builtin chains for DNAT and SNAT rules
# #
addrulejump PREROUTING `dnat_chain $zone` -i $interface -s $subnet addrulejump PREROUTING `dnat_chain $zone` -i $interface -s $subnet
addrulejump POSTROUTING `snat_chain $zone` -o $interface -d $subnet addrulejump POSTROUTING `snat_chain $zone` -o $interface -d $subnet
run_iptables -A `input_chain $interface` -s $subnet \ run_iptables -A `input_chain $interface` -s $subnet -j $chain2
-j `rules_chain $zone $FW`
done done
for zone1 in $zones; do for zone1 in $zones; do
@ -3207,6 +3218,8 @@ activate_rules()
chain="`rules_chain $zone $zone1`" chain="`rules_chain $zone $zone1`"
echo "$zone $zone1 $chain" >> ${STATEDIR}/chains
if havechain ${zone}2${zone1} || havechain ${zone1}2${zone}; then if havechain ${zone}2${zone1} || havechain ${zone1}2${zone}; then
have_canonical=Yes have_canonical=Yes
else else
@ -3438,6 +3451,215 @@ refresh_firewall()
rm -rf $TMP_DIR 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 # # Determine the value for a parameter that defaults to Yes #
################################################################################ ################################################################################
@ -3609,7 +3831,7 @@ do_initialize() {
# Give Usage Information # # Give Usage Information #
################################################################################ ################################################################################
usage() { 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 exit 1
} }
@ -3625,14 +3847,13 @@ nolock=
[ $# -gt 1 ] && [ "$1" = "nolock" ] && { nolock=Yes; shift ; } [ $# -gt 1 ] && [ "$1" = "nolock" ] && { nolock=Yes; shift ; }
[ $# -ne 1 ] && usage
trap "my_mutex_off; exit 2" 1 2 3 4 5 6 9 trap "my_mutex_off; exit 2" 1 2 3 4 5 6 9
command="$1" command="$1"
case "$command" in case "$command" in
stop) stop)
[ $# -ne 1 ] && usage
do_initialize do_initialize
my_mutex_on my_mutex_on
echo -n "Stopping Shorewall..." echo -n "Stopping Shorewall..."
@ -3644,6 +3865,7 @@ case "$command" in
;; ;;
start) start)
[ $# -ne 1 ] && usage
do_initialize do_initialize
my_mutex_on my_mutex_on
if qt iptables -L shorewall -n ; then if qt iptables -L shorewall -n ; then
@ -3658,6 +3880,7 @@ case "$command" in
;; ;;
restart) restart)
[ $# -ne 1 ] && usage
do_initialize do_initialize
my_mutex_on my_mutex_on
if qt iptables -L shorewall -n ; then if qt iptables -L shorewall -n ; then
@ -3672,17 +3895,20 @@ case "$command" in
;; ;;
status) status)
[ $# -ne 1 ] && usage
echo -e "Shorewall-$version Status at $HOSTNAME - `date`\\n" echo -e "Shorewall-$version Status at $HOSTNAME - `date`\\n"
iptables -L -n -v iptables -L -n -v
;; ;;
reset) reset)
[ $# -ne 1 ] && usage
iptables -L -n -Z -v iptables -L -n -Z -v
report "Shorewall Counters Reset" report "Shorewall Counters Reset"
date > $STATEDIR/restarted date > $STATEDIR/restarted
;; ;;
refresh) refresh)
[ $# -ne 1 ] && usage
do_initialize do_initialize
my_mutex_on my_mutex_on
if ! qt iptables -L shorewall -n ; then if ! qt iptables -L shorewall -n ; then
@ -3696,6 +3922,7 @@ case "$command" in
;; ;;
clear) clear)
[ $# -ne 1 ] && usage
do_initialize do_initialize
my_mutex_on my_mutex_on
echo -n "Clearing Shorewall..." echo -n "Clearing Shorewall..."
@ -3707,10 +3934,36 @@ case "$command" in
;; ;;
check) check)
[ $# -ne 1 ] && usage
do_initialize do_initialize
check_config 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 usage
;; ;;

View File

@ -32,6 +32,8 @@
# #
# Commands are: # 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 start Starts the firewall
# shorewall restart Restarts the firewall # shorewall restart Restarts the firewall
# shorewall stop Stops 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 "Usage: `basename $0` [debug] [nolock] [-c <directory>] <command>"
echo "where <command> is one of:" 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 " show [<chain>|connections|log|nat|tc|tos]"
echo " start" echo " start"
echo " stop" echo " stop"
@ -537,6 +541,10 @@ case "$1" in
[ $# -ne 1 ] && usage 1 [ $# -ne 1 ] && usage 1
exec $firewall $debugging $nolock $1 exec $firewall $debugging $nolock $1
;; ;;
add|delete)
[ $# -ne 3 ] && usage 1
exec $firewall $debugging $nolock $1 $2 $3
;;
show) show)
[ $# -gt 2 ] && usage 1 [ $# -gt 2 ] && usage 1
case "$2" in case "$2" in

View File

@ -19,10 +19,10 @@
# remote getway has no fixed address (Road Warrior) # remote getway has no fixed address (Road Warrior)
# then specify the gateway as 0.0.0.0/0. # 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 # column is a standalone host then this column should
# contain the name of the zone that the host is in. This # contain a comma-separated list of the names of the zones that
# column only applies to IPSEC tunnels. # the host might be in. This column only applies to IPSEC tunnels.
# #
# Example 1: # Example 1:
# #
@ -47,5 +47,15 @@
# #
# ipsec net 4.33.99.124 gw # 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 # TYPE ZONE GATEWAY GATEWAY ZONE
#LAST LINE -- ADD YOUR ENTRIES BEFORE THIS ONE -- DO NOT REMOVE #LAST LINE -- ADD YOUR ENTRIES BEFORE THIS ONE -- DO NOT REMOVE