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.
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_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 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
{
@ -6654,17 +6654,10 @@ add_to_zone() # $1 = <interface>[:<hosts>] $2 = zone
[ -n "$IPRANGE_MATCH" ] && [ -f $TMP_DIR/iprange ] && rm -f $TMP_DIR/iprange
if ! $IPTABLES $@ ; then
startup_error "Can't add $1 to zone $2"
error_message "Can't add $newhost to zone $zone"
fi
}
#
# Isolate interface and host parts
#
interface=${1%%:*}
host=${1#*:}
[ -z "$host" ] && host="0.0.0.0/0"
#
# Load $zones
#
@ -6674,74 +6667,73 @@ add_to_zone() # $1 = <interface>[:<hosts>] $2 = zone
#
validate_interfaces_file
#
# Validate Hosts File
#
validate_hosts_file
#
# Validate IPSec File
#
f=$(find_file ipsec)
if [ -f $f ]; then
progress_message "Processing $f..."
setup_ipsec $f
fi
[ -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=$2
zone=$1
validate_zone $zone || startup_error "Unknown zone: $zone"
[ "$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
#
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
#
# Normalize the first argument to this function
#
newhost="$interface:$host"
terminator=fatal_error
#
# Create a new Zone state file
# Check for duplicates and create a new zone state file
#
> ${STATEDIR}/zones_$$
#
# Add $1 to the Zone state file
#
while read z hosts; do
if [ "$z" = "$zone" ]; then
for h in $hosts; do
if [ "$h" = "$newhost" ]; then
rm -f ${STATEDIR}/zones_$$
startup_error "$1 already in zone $zone"
fi
for host in $hostlist; do
if [ "$h" = "$host" ]; then
rm -f ${STATEDIR}/zones_$$
startup_error "$host already in zone $zone"
fi
done
done
[ -z "$hosts" ] && hosts=$newhost || hosts="$hosts $newhost"
[ -z "$hosts" ] && hosts=$hostlist || hosts="$hosts $hostlist"
fi
eval ${z}_hosts=\"$hosts\"
@ -6750,60 +6742,73 @@ add_to_zone() # $1 = <interface>[:<hosts>] $2 = zone
done < ${STATEDIR}/zones
mv -f ${STATEDIR}/zones_$$ ${STATEDIR}/zones
terminator=fatal_error
#
# 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
# matches the new host(s)#
# Create a new Zone state file
#
chain=${zone}_dnat
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
# the nat table PREROUTING chain to jump to that chain when the source
# matches the new host(s)#
#
chain=${zone}_dnat
if nat_chain_exists $chain; then
do_iptables -t nat -A $(dynamic_in $interface) $(source_ip_range $host) $policyin -j $chain
fi
#
# Insert new rules into the filter table for the passed interface
#
while read z1 z2 chain; do
if [ "$z1" = "$zone" ]; then
if [ "$z2" = "$FW" ]; then
do_iptables -A $(dynamic_in $interface) $(match_source_hosts $host) $policyin -j $chain
else
source_chain=$(dynamic_fwd $interface)
eval dest_hosts=\"\$${z2}_hosts\"
for h in $dest_hosts; do
iface=${h%%:*}
hosts=${h#*:}
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
fi
done
fi
elif [ "$z2" = "$zone" ]; then
if [ "$z1" = "$FW" ]; then
#
# Add a rule to the dynamic out chain for the interface
#
do_iptables -A $(dynamic_out $interface) $(match_dest_hosts $host) $policyout -j $chain
else
eval source_hosts=\"\$${z1}_hosts\"
for h in $source_hosts; do
iface=${h%%:*}
hosts=${h#*:}
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
fi
done
fi
if nat_chain_exists $chain; then
do_iptables -t nat -A $(dynamic_in $interface) $(source_ip_range $host) $(match_ipsec_in $zone $newhost) -j $chain
fi
done < ${STATEDIR}/chains
#
# Insert new rules into the filter table for the passed interface
#
while read z1 z2 chain; do
if [ "$z1" = "$zone" ]; then
if [ "$z2" = "$FW" ]; then
do_iptables -A $(dynamic_in $interface) $(match_source_hosts $host) $(match_ipsec_in $z1 $newhost) -j $chain
else
source_chain=$(dynamic_fwd $interface)
eval dest_hosts=\"\$${z2}_hosts\"
for h in $dest_hosts; do
iface=${h%%:*}
hosts=${h#*:}
if [ "$iface" != "$interface" -o "$hosts" != "$host" ]; then
do_iptables -A $source_chain $(match_source_hosts $host) -o $iface $(match_dest_hosts $hosts) $(match_ipsec_out $z2 $h) -j $chain
fi
done
fi
elif [ "$z2" = "$zone" ]; then
if [ "$z1" = "$FW" ]; then
#
# Add a rule to the dynamic out chain for the interface
#
do_iptables -A $(dynamic_out $interface) $(match_dest_hosts $host) $(match_ipsec_out $z2 $newhost) -j $chain
else
eval source_hosts=\"\$${z1}_hosts\"
for h in $source_hosts; do
iface=${h%%:*}
hosts=${h#*:}
if [ "$iface" != "$interface" -o "$hosts" != "$host" ]; then
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
done
fi
fi
done < ${STATEDIR}/chains
progress_message "$newhost added to zone $zone"
done
rm -rf $TMP_DIR
progress_message "$1 added to zone $2"
}
#
@ -6811,146 +6816,166 @@ add_to_zone() # $1 = <interface>[:<hosts>] $2 = zone
#
delete_from_zone() # $1 = <interface>[:<hosts>] $2 = zone
{
#
# Delete the subject host(s) from the zone state file
#
delete_from_zones_file()
{
> ${STATEDIR}/zones_$$
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=
while read z hosts; do
if [ "$z" = "$zone" ]; then
temp=$hosts
hosts=
for h in $temp; do
if [ "$h" = "$delhost" ]; then
echo Yes
else
hosts="$hosts $h"
fi
done
fi
echo "$z $hosts" >> ${STATEDIR}/zones_$$
done < ${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
#
# Validate Interfaces File
#
validate_interfaces_file
#
# Validate Hosts File
#
validate_hosts_file
#
# Validate IPSec File
#
f=$(find_file ipsec)
if [ -f $f ]; then
progress_message "Processing $f..."
setup_ipsec $f
fi
zone=$2
[ -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 remove $1 from firewall zone"
[ "$zone" = $FW ] && startup_error "Can't delete from the 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
#
> ${STATEDIR}/zones_$$
while read z hosts; do
if [ "$z" = "$zone" ]; then
temp=$hosts
hosts=
for host in $hostlist; do
found=
for h in $temp; do
if [ "$h" = "$host" ]; then
found=Yes
break
fi
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
done
[ -n "$found" ] || hosts="$hosts $h"
done
fi
eval ${z}_hosts=\"$hosts\"
echo "$z $hosts" >> ${STATEDIR}/zones_$$
done < ${STATEDIR}/zones
mv -f ${STATEDIR}/zones_$$ ${STATEDIR}/zones
terminator=fatal_error
#
# 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
#
# Delete rules rules the input chains for the passed interface
#
while read z1 z2 chain; do
if [ "$z1" = "$zone" ]; then
if [ "$z2" = "$FW" ]; then
qt_iptables -D $(dynamic_in $interface) $(match_source_hosts $host) $policyin -j $chain
else
source_chain=$(dynamic_fwd $interface)
eval dest_hosts=\"\$${z2}_hosts\"
for h in $dest_hosts $delhost; do
iface=${h%%:*}
hosts=${h#*:}
for delhost in $hostlist; do
interface=${delhost%%:*}
host=${delhost#*:}
#
# Delete any nat table entries for the host(s)
#
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
#
while read z1 z2 chain; do
if [ "$z1" = "$zone" ]; then
if [ "$z2" = "$FW" ]; then
qt_iptables -D $(dynamic_in $interface) $(match_source_hosts $host) $(match_ipsec_in $z1 $newhost) -j $chain
else
source_chain=$(dynamic_fwd $interface)
eval dest_hosts=\"\$${z2}_hosts\"
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
fi
done
[ "$z2" = "$zone" ] && dest_hosts="$dest_hosts $hostlist"
for h in $dest_hosts; do
iface=${h%%:*}
hosts=${h#*:}
if [ "$iface" != "$interface" -o "$hosts" != "$host" ]; then
qt_iptables -D $source_chain $(match_source_hosts $host) -o $iface $(match_dest_hosts $hosts) $(match_ipsec_out $z2 $h) -j $chain
fi
done
fi
elif [ "$z2" = "$zone" ]; then
if [ "$z1" = "$FW" ]; then
qt_iptables -D $(dynamic_out $interface) $(match_dest_hosts $host) $(match_ipsec_out $z2 $delhost) -j $chain
else
eval source_hosts=\"\$${z1}_hosts\"
for h in $source_hosts; do
iface=${h%%:*}
hosts=${h#*:}
if [ "$iface" != "$interface" -o "$hosts" != "$host" ]; then
qt_iptables -D $(dynamic_fwd $iface) $(match_source_hosts $hosts) -o $interface $(match_dest_hosts $host) $(match_ipsec_out $z2 $delhost) -j $chain
fi
done
fi
fi
elif [ "$z2" = "$zone" ]; then
if [ "$z1" = "$FW" ]; then
qt_iptables -D $(dynamic_out $interface) $(match_dest_hosts $host) $policyout -j $chain
else
eval source_hosts=\"\$${z1}_hosts\"
done < ${STATEDIR}/chains
for h in $source_hosts; do
iface=${h%%:*}
hosts=${h#*:}
progress_message "$delhost removed from zone $zone"
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
fi
done
fi
fi
done < ${STATEDIR}/chains
done
rm -rf $TMP_DIR
progress_message "$1 removed from zone $2"
}
#
@ -7123,7 +7148,7 @@ do_initialize() {
ensure_config_path
#
# 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.
#
@ -7409,7 +7434,7 @@ case "$COMMAND" in
;;
add)
[ $# -ne 3 ] && usage
[ $# -lt 3 ] && usage
do_initialize
my_mutex_on
if ! qt $IPTABLES -L shorewall -n ; then
@ -7418,12 +7443,13 @@ case "$COMMAND" in
my_mutex_off
exit 2;
fi
add_to_zone $2 $3
shift
add_to_zone $@
my_mutex_off
;;
delete)
[ $# -ne 3 ] && usage
[ $# -lt 3 ] && usage
do_initialize
my_mutex_on
if ! qt $IPTABLES -L shorewall -n ; then
@ -7432,7 +7458,8 @@ case "$COMMAND" in
my_mutex_off
exit 2;
fi
delete_from_zone $2 $3
shift
delete_from_zone $@
my_mutex_off
;;

View File

@ -29,10 +29,10 @@
case $1 in
add)
echo "add: add <interface>[:<bridge-port>][:<host>] <zone>
Adds a host or subnet to a dynamic zone usually used with VPN's.
echo "add: add <interface>[:<bridge-port>][:<host-list>] ... <zone>
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.
Example:
@ -95,11 +95,11 @@ debug)
;;
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.
shorewall delete interface[:port][:host] zone - Deletes the specified
interface (and bridge port/host if included) from the specified zone.
shorewall delete interface[:port][:host-list] ... zone - Deletes the specified
interfaces (and bridge ports/hosts if included) from the specified zone.
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.
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:
@ -806,3 +809,12 @@ New Features:
If not specified or if specified as empty (e.g., DROPINVALID="")
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
;;
add|delete)
[ $# -ne 3 ] && usage 1
exec $SHOREWALL_SHELL $FIREWALL $debugging $nolock $1 $2 $3
[ $# -lt 3 ] && usage 1
exec $SHOREWALL_SHELL $FIREWALL $debugging $nolock $@
;;
show|list)
[ -n "$debugging" ] && set -x