Add/Delete multiple hosts in one command; fix Add/Delete IPSEC problems

git-svn-id: https://shorewall.svn.sourceforge.net/svnroot/shorewall/trunk@1811 fbd18981-670d-0410-9b5c-8dc0c1a9a2bb
This commit is contained in:
teastep 2004-12-08 20:00:03 +00:00
parent bb4652cdf7
commit ed809afe96
5 changed files with 298 additions and 256 deletions

View File

@ -175,4 +175,7 @@ Changes since 2.0.3
86) Corrected typo in interfaces file. 86) Corrected typo in interfaces file.
97) Add DROPINVALID option. 87) Add DROPINVALID option.
88) Allow list of hosts in add and delete commands. Fix ipsec problem
with "add" and "delete"

View File

@ -6637,11 +6637,11 @@ refresh_firewall()
# #
# Add a host or networks to a zone # Add a host or networks to a zone
# #
add_to_zone() # $1 = <interface>[:<hosts>] $2 = zone add_to_zone() # $1...${n-1} = <interface>[:<hosts>] $n = zone
{ {
local base interface host newhost zone z h z1 z2 chain terminator local interface host zone z h z1 z2 chain
local dhcp_interfaces blacklist_interfaces maclist_interfaces tcpflags_interfaces local dhcp_interfaces blacklist_interfaces maclist_interfaces tcpflags_interfaces
local rulenum source_chain dest_hosts iface hosts is_ipsec policyin= policyout= local rulenum source_chain dest_hosts iface hosts hostlist=
nat_chain_exists() # $1 = chain name nat_chain_exists() # $1 = chain name
{ {
@ -6654,17 +6654,10 @@ add_to_zone() # $1 = <interface>[:<hosts>] $2 = zone
[ -n "$IPRANGE_MATCH" ] && [ -f $TMP_DIR/iprange ] && rm -f $TMP_DIR/iprange [ -n "$IPRANGE_MATCH" ] && [ -f $TMP_DIR/iprange ] && rm -f $TMP_DIR/iprange
if ! $IPTABLES $@ ; then if ! $IPTABLES $@ ; then
startup_error "Can't add $1 to zone $2" error_message "Can't add $newhost to zone $zone"
fi fi
} }
#
# Isolate interface and host parts
#
interface=${1%%:*}
host=${1#*:}
[ -z "$host" ] && host="0.0.0.0/0"
# #
# Load $zones # Load $zones
# #
@ -6674,41 +6667,21 @@ add_to_zone() # $1 = <interface>[:<hosts>] $2 = zone
# #
validate_interfaces_file validate_interfaces_file
# #
# Validate Hosts File
#
validate_hosts_file
#
# Validate IPSec File # Validate IPSec File
# #
f=$(find_file ipsec) f=$(find_file ipsec)
if [ -f $f ]; then [ -f $f ] && setup_ipsec $f
progress_message "Processing $f..."
setup_ipsec $f
fi
# #
# Validate Zone # Normalize host list
# #
zone=$2 while [ $# -gt 1 ]; do
interface=${1%%:*}
validate_zone $zone || startup_error "Unknown zone: $zone" host=${1#*:}
[ "$zone" = $FW ] && startup_error "Can't add $1 to firewall zone"
eval is_ipsec=\$${zone}_is_ipsec
eval options=\"\$${zone}_ipsec_options\"
eval in_options=\"\$${zone}_ipsec_in_options\"
eval out_options=\"\$${zone}_ipsec_out_options\"
if [ -n "$is_ipsec" ]; then
[ -n "$POLICY_MATCH" ] || startup_error "Your kernel and/or iptables lacks policy match support"
policyin="-m policy --pol ipsec --dir in $options $in_options"
policyout="-m policy --pol ipsec --dir out $options $out_options"
elif [ -n "$POLICY_MATCH" ]; then
policyin="-m policy --pol none --dir in"
policyout="-m policy --pol none --dir out"
fi
#
# Be sure that Shorewall has been restarted using a DZ-aware version of the code
#
[ -f ${STATEDIR}/chains ] || startup_error "${STATEDIR}/chains -- file not found"
[ -f ${STATEDIR}/zones ] || startup_error "${STATEDIR}/zones -- file not found"
# #
# Be sure that the interface was dynamic at last [re]start # Be sure that the interface was dynamic at last [re]start
# #
@ -6719,29 +6692,48 @@ add_to_zone() # $1 = <interface>[:<hosts>] $2 = zone
if ! chain_exists $(dynamic_in $interface) ; then if ! chain_exists $(dynamic_in $interface) ; then
startup_error "At last Shorewall [re]start, DYNAMIC_ZONES=No in shorewall.conf" startup_error "At last Shorewall [re]start, DYNAMIC_ZONES=No in shorewall.conf"
fi fi
#
# Normalize the first argument to this function
#
newhost="$interface:$host"
terminator=fatal_error if [ -z "$host" ]; then
hostlist="$hostlist $interface:0.0.0.0/0"
else
for h in $(separate_list $host); do
hostlist="$hostlist $interface:$h"
done
fi
shift
done
# #
# Create a new Zone state file # Validate Zone
#
zone=$1
validate_zone $zone || startup_error "Unknown zone: $zone"
[ "$zone" = $FW ] && startup_error "Can't add $1 to firewall zone"
#
# Be sure that Shorewall has been restarted using a DZ-aware version of the code
#
[ -f ${STATEDIR}/chains ] || startup_error "${STATEDIR}/chains -- file not found"
[ -f ${STATEDIR}/zones ] || startup_error "${STATEDIR}/zones -- file not found"
#
# Check for duplicates and create a new zone state file
# #
> ${STATEDIR}/zones_$$ > ${STATEDIR}/zones_$$
#
# Add $1 to the Zone state file
#
while read z hosts; do while read z hosts; do
if [ "$z" = "$zone" ]; then if [ "$z" = "$zone" ]; then
for h in $hosts; do for h in $hosts; do
if [ "$h" = "$newhost" ]; then for host in $hostlist; do
if [ "$h" = "$host" ]; then
rm -f ${STATEDIR}/zones_$$ rm -f ${STATEDIR}/zones_$$
startup_error "$1 already in zone $zone" startup_error "$host already in zone $zone"
fi fi
done done
done
[ -z "$hosts" ] && hosts=$newhost || hosts="$hosts $newhost" [ -z "$hosts" ] && hosts=$hostlist || hosts="$hosts $hostlist"
fi fi
eval ${z}_hosts=\"$hosts\" eval ${z}_hosts=\"$hosts\"
@ -6750,6 +6742,17 @@ add_to_zone() # $1 = <interface>[:<hosts>] $2 = zone
done < ${STATEDIR}/zones done < ${STATEDIR}/zones
mv -f ${STATEDIR}/zones_$$ ${STATEDIR}/zones mv -f ${STATEDIR}/zones_$$ ${STATEDIR}/zones
terminator=fatal_error
#
# Create a new Zone state file
#
for newhost in $hostlist; do
#
# Isolate interface and host parts
#
interface=${newhost%%:*}
host=${newhost#*:}
# #
# If the zone passed in the command has a dnat chain then insert a rule in # If the zone passed in the command has a dnat chain then insert a rule in
# the nat table PREROUTING chain to jump to that chain when the source # the nat table PREROUTING chain to jump to that chain when the source
@ -6758,7 +6761,7 @@ add_to_zone() # $1 = <interface>[:<hosts>] $2 = zone
chain=${zone}_dnat chain=${zone}_dnat
if nat_chain_exists $chain; then if nat_chain_exists $chain; then
do_iptables -t nat -A $(dynamic_in $interface) $(source_ip_range $host) $policyin -j $chain do_iptables -t nat -A $(dynamic_in $interface) $(source_ip_range $host) $(match_ipsec_in $zone $newhost) -j $chain
fi fi
# #
# Insert new rules into the filter table for the passed interface # Insert new rules into the filter table for the passed interface
@ -6766,7 +6769,7 @@ add_to_zone() # $1 = <interface>[:<hosts>] $2 = zone
while read z1 z2 chain; do while read z1 z2 chain; do
if [ "$z1" = "$zone" ]; then if [ "$z1" = "$zone" ]; then
if [ "$z2" = "$FW" ]; then if [ "$z2" = "$FW" ]; then
do_iptables -A $(dynamic_in $interface) $(match_source_hosts $host) $policyin -j $chain do_iptables -A $(dynamic_in $interface) $(match_source_hosts $host) $(match_ipsec_in $z1 $newhost) -j $chain
else else
source_chain=$(dynamic_fwd $interface) source_chain=$(dynamic_fwd $interface)
eval dest_hosts=\"\$${z2}_hosts\" eval dest_hosts=\"\$${z2}_hosts\"
@ -6776,7 +6779,7 @@ add_to_zone() # $1 = <interface>[:<hosts>] $2 = zone
hosts=${h#*:} hosts=${h#*:}
if [ "$iface" != "$interface" -o "$hosts" != "$host" ]; then if [ "$iface" != "$interface" -o "$hosts" != "$host" ]; then
do_iptables -A $source_chain $(match_source_hosts $host) -o $iface $(match_dest_hosts $hosts) $policyout -j $chain do_iptables -A $source_chain $(match_source_hosts $host) -o $iface $(match_dest_hosts $hosts) $(match_ipsec_out $z2 $h) -j $chain
fi fi
done done
fi fi
@ -6785,7 +6788,7 @@ add_to_zone() # $1 = <interface>[:<hosts>] $2 = zone
# #
# Add a rule to the dynamic out chain for the interface # Add a rule to the dynamic out chain for the interface
# #
do_iptables -A $(dynamic_out $interface) $(match_dest_hosts $host) $policyout -j $chain do_iptables -A $(dynamic_out $interface) $(match_dest_hosts $host) $(match_ipsec_out $z2 $newhost) -j $chain
else else
eval source_hosts=\"\$${z1}_hosts\" eval source_hosts=\"\$${z1}_hosts\"
@ -6794,16 +6797,18 @@ add_to_zone() # $1 = <interface>[:<hosts>] $2 = zone
hosts=${h#*:} hosts=${h#*:}
if [ "$iface" != "$interface" -o "$hosts" != "$host" ]; then if [ "$iface" != "$interface" -o "$hosts" != "$host" ]; then
do_iptables -A $(dynamic_fwd $iface) $rulenum $(match_source_hosts $hosts) -o $interface $(match_dest_hosts $host) $policyout -j $chain do_iptables -A $(dynamic_fwd $iface) $rulenum $(match_source_hosts $hosts) -o $interface $(match_dest_hosts $host) $(match_ipsec_out $z2 $newhost) -j $chain
fi fi
done done
fi fi
fi fi
done < ${STATEDIR}/chains done < ${STATEDIR}/chains
rm -rf $TMP_DIR progress_message "$newhost added to zone $zone"
progress_message "$1 added to zone $2" done
rm -rf $TMP_DIR
} }
# #
@ -6811,11 +6816,73 @@ add_to_zone() # $1 = <interface>[:<hosts>] $2 = zone
# #
delete_from_zone() # $1 = <interface>[:<hosts>] $2 = zone delete_from_zone() # $1 = <interface>[:<hosts>] $2 = zone
{ {
local interface host zone z h z1 z2 chain delhost
local dhcp_interfaces blacklist_interfaces maclist_interfaces tcpflags_interfaces
local rulenum source_chain dest_hosts iface hosts hostlist=
# #
# Delete the subject host(s) from the zone state file # Load $zones
#
determine_zones
#
# Validate Interfaces File
#
validate_interfaces_file
#
# Validate Hosts File
#
validate_hosts_file
#
# Validate IPSec File
#
f=$(find_file ipsec)
[ -f $f ] && setup_ipsec $f
#
# Normalize host list
#
while [ $# -gt 1 ]; do
interface=${1%%:*}
host=${1#*:}
#
# Be sure that the interface was dynamic at last [re]start
#
if ! chain_exists $(input_chain $interface) ; then
startup_error "Unknown interface $interface"
fi
if ! chain_exists $(dynamic_in $interface) ; then
startup_error "At last Shorewall [re]start, DYNAMIC_ZONES=No in shorewall.conf"
fi
if [ -z "$host" ]; then
hostlist="$hostlist $interface:0.0.0.0/0"
else
for h in $(separate_list $host); do
hostlist="$hostlist $interface:$h"
done
fi
shift
done
#
# Validate Zone
#
zone=$1
validate_zone $zone || startup_error "Unknown zone: $zone"
[ "$zone" = $FW ] && startup_error "Can't delete from the firewall zone"
#
# Be sure that Shorewall has been restarted using a DZ-aware version of the code
#
[ -f ${STATEDIR}/chains ] || startup_error "${STATEDIR}/chains -- file not found"
[ -f ${STATEDIR}/zones ] || startup_error "${STATEDIR}/zones -- file not found"
#
# Delete the passed hosts from the zone state file
# #
delete_from_zones_file()
{
> ${STATEDIR}/zones_$$ > ${STATEDIR}/zones_$$
while read z hosts; do while read z hosts; do
@ -6823,116 +6890,72 @@ delete_from_zone() # $1 = <interface>[:<hosts>] $2 = zone
temp=$hosts temp=$hosts
hosts= hosts=
for host in $hostlist; do
found=
for h in $temp; do for h in $temp; do
if [ "$h" = "$delhost" ]; then if [ "$h" = "$host" ]; then
echo Yes found=Yes
else break
hosts="$hosts $h"
fi fi
done done
[ -n "$found" ] || error_message "Warning: $1 does not appear to be in zone $2"
done
for h in $temp; do
found=
for host in $hostlist; do
if [ "$h" = "$host" ]; then
found=Yes
break
fi fi
done
[ -n "$found" ] || hosts="$hosts $h"
done
fi
eval ${z}_hosts=\"$hosts\"
echo "$z $hosts" >> ${STATEDIR}/zones_$$ echo "$z $hosts" >> ${STATEDIR}/zones_$$
done < ${STATEDIR}/zones done < ${STATEDIR}/zones
mv -f ${STATEDIR}/zones_$$ ${STATEDIR}/zones mv -f ${STATEDIR}/zones_$$ ${STATEDIR}/zones
}
#
# Isolate interface and host parts
#
interface=${1%%:*}
host=${1#*:}
[ -z "$host" ] && host="0.0.0.0/0"
#
# Load $zones
#
determine_zones
f=$(find_file ipsec)
if [ -f $f ]; then
progress_message "Processing $f..."
setup_ipsec $f
fi
zone=$2
validate_zone $zone || startup_error "Unknown zone: $zone"
[ "$zone" = $FW ] && startup_error "Can't remove $1 from firewall zone"
eval is_ipsec=\$${zone}_is_ipsec
eval options=\"\$${zone}_ipsec_options\"
eval in_options=\"\$${zone}_ipsec_in_options\"
eval out_options=\"\$${zone}_ipsec_out_options\"
if [ -n "$is_ipsec" ]; then
[ -n "$POLICY_MATCH" ] || startup_error "Your kernel and/or iptables lacks policy match support"
policyin="-m policy --pol ipsec --dir in $options $in_options"
policyout="-m policy --pol ipsec --dir out $options $out_options"
elif [ -n "$POLICY_MATCH" ]; then
policyin="-m policy --pol none --dir in"
policyout="-m policy --pol none --dir out"
fi
#
# Be sure that Shorewall has been restarted using a DZ-aware version of the code
#
[ -f ${STATEDIR}/chains ] || startup_error "${STATEDIR}/chains -- file not found"
[ -f ${STATEDIR}/zones ] || startup_error "${STATEDIR}/zones -- file not found"
#
# Be sure that the interface was present at last [re]start
#
if ! chain_exists $(input_chain $interface) ; then
startup_error "Unknown interface $interface"
fi
if ! chain_exists $(dynamic_in $interface) ; then
startup_error "Interface $interface is not dynamic"
fi
#
# Normalize the first argument to this function
#
delhost="$interface:$host"
#
# Delete the passed hosts from the zone state file
#
[ -z "$(delete_from_zones_file)" ] && \
error_message "Warning: $1 does not appear to be in zone $2"
#
# Construct the zone host maps
#
while read z hosts; do
eval ${z}_hosts=\"$hosts\"
done < ${STATEDIR}/zones
terminator=fatal_error terminator=fatal_error
for delhost in $hostlist; do
interface=${delhost%%:*}
host=${delhost#*:}
# #
# Delete any nat table entries for the host(s) # Delete any nat table entries for the host(s)
# #
qt_iptables -t nat -D $(dynamic_in $interface) $(match_source_hosts $host) $policyin -j ${zone}_dnat qt_iptables -t nat -D $(dynamic_in $interface) $(match_source_hosts $host) $(match_ipsec_in $zone $newhost) -j ${zone}_dnat
# #
# Delete rules rules the input chains for the passed interface # Delete rules rules the input chains for the passed interface
# #
while read z1 z2 chain; do while read z1 z2 chain; do
if [ "$z1" = "$zone" ]; then if [ "$z1" = "$zone" ]; then
if [ "$z2" = "$FW" ]; then if [ "$z2" = "$FW" ]; then
qt_iptables -D $(dynamic_in $interface) $(match_source_hosts $host) $policyin -j $chain qt_iptables -D $(dynamic_in $interface) $(match_source_hosts $host) $(match_ipsec_in $z1 $newhost) -j $chain
else else
source_chain=$(dynamic_fwd $interface) source_chain=$(dynamic_fwd $interface)
eval dest_hosts=\"\$${z2}_hosts\" eval dest_hosts=\"\$${z2}_hosts\"
for h in $dest_hosts $delhost; do [ "$z2" = "$zone" ] && dest_hosts="$dest_hosts $hostlist"
for h in $dest_hosts; do
iface=${h%%:*} iface=${h%%:*}
hosts=${h#*:} hosts=${h#*:}
if [ "$iface" != "$interface" -o "$hosts" != "$host" ]; then if [ "$iface" != "$interface" -o "$hosts" != "$host" ]; then
qt_iptables -D $source_chain $(match_source_hosts $host) -o $iface $(match_dest_hosts $hosts) $policyout -j $chain qt_iptables -D $source_chain $(match_source_hosts $host) -o $iface $(match_dest_hosts $hosts) $(match_ipsec_out $z2 $h) -j $chain
fi fi
done done
fi fi
elif [ "$z2" = "$zone" ]; then elif [ "$z2" = "$zone" ]; then
if [ "$z1" = "$FW" ]; then if [ "$z1" = "$FW" ]; then
qt_iptables -D $(dynamic_out $interface) $(match_dest_hosts $host) $policyout -j $chain qt_iptables -D $(dynamic_out $interface) $(match_dest_hosts $host) $(match_ipsec_out $z2 $delhost) -j $chain
else else
eval source_hosts=\"\$${z1}_hosts\" eval source_hosts=\"\$${z1}_hosts\"
@ -6941,16 +6964,18 @@ delete_from_zone() # $1 = <interface>[:<hosts>] $2 = zone
hosts=${h#*:} hosts=${h#*:}
if [ "$iface" != "$interface" -o "$hosts" != "$host" ]; then if [ "$iface" != "$interface" -o "$hosts" != "$host" ]; then
qt_iptables -D $(dynamic_fwd $iface) $(match_source_hosts $hosts) -o $interface $(match_dest_hosts $host) $policyout -j $chain qt_iptables -D $(dynamic_fwd $iface) $(match_source_hosts $hosts) -o $interface $(match_dest_hosts $host) $(match_ipsec_out $z2 $delhost) -j $chain
fi fi
done done
fi fi
fi fi
done < ${STATEDIR}/chains done < ${STATEDIR}/chains
rm -rf $TMP_DIR progress_message "$delhost removed from zone $zone"
progress_message "$1 removed from zone $2" done
rm -rf $TMP_DIR
} }
# #
@ -7123,7 +7148,7 @@ do_initialize() {
ensure_config_path ensure_config_path
# #
# Determine the capabilities of the installed iptables/netfilter # Determine the capabilities of the installed iptables/netfilter
# We load the kernel modules here to acurately determine # We load the kernel modules here to acuray determine
# capabilities when module autoloading isn't enabled. # capabilities when module autoloading isn't enabled.
# #
@ -7409,7 +7434,7 @@ case "$COMMAND" in
;; ;;
add) add)
[ $# -ne 3 ] && usage [ $# -lt 3 ] && 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
@ -7418,12 +7443,13 @@ case "$COMMAND" in
my_mutex_off my_mutex_off
exit 2; exit 2;
fi fi
add_to_zone $2 $3 shift
add_to_zone $@
my_mutex_off my_mutex_off
;; ;;
delete) delete)
[ $# -ne 3 ] && usage [ $# -lt 3 ] && 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
@ -7432,7 +7458,8 @@ case "$COMMAND" in
my_mutex_off my_mutex_off
exit 2; exit 2;
fi fi
delete_from_zone $2 $3 shift
delete_from_zone $@
my_mutex_off my_mutex_off
;; ;;

View File

@ -29,10 +29,10 @@
case $1 in case $1 in
add) add)
echo "add: add <interface>[:<bridge-port>][:<host>] <zone> echo "add: add <interface>[:<bridge-port>][:<host-list>] ... <zone>
Adds a host or subnet to a dynamic zone usually used with VPN's. Adds a list of hosts or subnets to a dynamic zone usually used with VPN's.
shorewall add interface[:host] zone - Adds the specified interface shorewall add interface[:<port>][:host-list] ... zone - Adds the specified interface
(and bridge port/host if included) to the specified zone. (and bridge port/host if included) to the specified zone.
Example: Example:
@ -95,11 +95,11 @@ debug)
;; ;;
delete) delete)
echo "delete: delete <interface>[:<bridge-port>][:<host>] <zone> echo "delete: delete <interface>[:<bridge-port>][:<host-list>] ... <zone>
Deletes a host or subnet from a dynamic zone usually used with VPN's. Deletes a host or subnet from a dynamic zone usually used with VPN's.
shorewall delete interface[:port][:host] zone - Deletes the specified shorewall delete interface[:port][:host-list] ... zone - Deletes the specified
interface (and bridge port/host if included) from the specified zone. interfaces (and bridge ports/hosts if included) from the specified zone.
Example: Example:

View File

@ -184,6 +184,9 @@ Problems corrected since 2.2.0 Beta 7:
1) A typo in the /etc/shorewall/interfaces file has been corrected. 1) A typo in the /etc/shorewall/interfaces file has been corrected.
2) The "add" and "delete" commands were generating incorrect policy
matches when policy match support was available.
----------------------------------------------------------------------- -----------------------------------------------------------------------
Issues when migrating from Shorewall 2.0 to Shorewall 2.1: Issues when migrating from Shorewall 2.0 to Shorewall 2.1:
@ -806,3 +809,12 @@ New Features:
If not specified or if specified as empty (e.g., DROPINVALID="") If not specified or if specified as empty (e.g., DROPINVALID="")
then DROPINVALID=Yes is assumed. then DROPINVALID=Yes is assumed.
36) The "shorewall add" and "shorewall delete" commands now accept a
list of hosts to add or delete.
Examples:
shorewall add eth1:1.2.3.4 eth1:2.3.4.5 z12
shorewall delete eth1:1.2.3.4 eth1:2.3.4.5 z12

View File

@ -867,8 +867,8 @@ case "$1" in
exec $SHOREWALL_SHELL $FIREWALL $debugging $nolock $1 exec $SHOREWALL_SHELL $FIREWALL $debugging $nolock $1
;; ;;
add|delete) add|delete)
[ $# -ne 3 ] && usage 1 [ $# -lt 3 ] && usage 1
exec $SHOREWALL_SHELL $FIREWALL $debugging $nolock $1 $2 $3 exec $SHOREWALL_SHELL $FIREWALL $debugging $nolock $@
;; ;;
show|list) show|list)
[ -n "$debugging" ] && set -x [ -n "$debugging" ] && set -x