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,252 @@ 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
# Check for duplicates and create a new zone state file
#
if ! chain_exists $(input_chain $interface) ; then
startup_error "Unknown interface $interface"
fi
> ${STATEDIR}/zones_$$
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"
while read z hosts; do
if [ "$z" = "$zone" ]; then
for h in $hosts; do
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=$hostlist || hosts="$hosts $hostlist"
fi
eval ${z}_hosts=\"$hosts\"
echo "$z $hosts" >> ${STATEDIR}/zones_$$
done < ${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
# 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) $(match_ipsec_in $zone $newhost) -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) $(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
}
#
# Delete a host or networks from a 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=
#
# 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
#
> ${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
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
[ -z "$hosts" ] && hosts=$newhost || hosts="$hosts $newhost"
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\"
@ -6750,207 +6921,61 @@ add_to_zone() # $1 = <interface>[:<hosts>] $2 = zone
done < ${STATEDIR}/zones
mv -f ${STATEDIR}/zones_$$ ${STATEDIR}/zones
#
# 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
fi
done < ${STATEDIR}/chains
rm -rf $TMP_DIR
progress_message "$1 added to zone $2"
}
#
# Delete a host or networks from a 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_$$
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
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
#
# 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\"
for h in $source_hosts; do
iface=${h%%:*}
hosts=${h#*:}
done < ${STATEDIR}/chains
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
progress_message "$delhost removed from zone $zone"
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