shorewall_code/Shorewall/lib.maclist
2007-01-14 19:26:17 +00:00

260 lines
7.3 KiB
Bash

#!/bin/sh
#
# Shorewall 3.4 -- /usr/share/shorewall/lib.tcrules
#
# This program is under GPL [http://www.gnu.org/copyleft/gpl.htm]
#
# (c) 1999,2000,2001,2002,2003,2004,2005,2006,2007 - Tom Eastep (teastep@shorewall.net)
#
# Complete documentation is available at http://shorewall.net
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of Version 2 of the GNU General Public License
# as published by the Free Software Foundation.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA
#
# This library is loaded by /usr/share/shorewall/compiler when the maclist option
# is specified in an entry in the interfaces file.
#
#
# Set up MAC Verification
#
setup_mac_lists() # $1 = Phase Number
{
local interface
local mac
local addresses
local address
local chain
local chain1
local macpart
local blob
local hosts
local ipsec
local policy=
create_mac_chain()
{
case $MACLIST_TABLE in
filter)
createchain $1 no
;;
*)
createmanglechain $1
;;
esac
}
have_mac_chain()
{
local result
case $MACLIST_TABLE in
filter)
havechain $1 && result=0 || result=1
;;
*)
havemanglechain $1 && result=0 || result=1
;;
esac
return $result
}
#
# Generate the list of interfaces having MAC verification
#
maclist_interfaces=
for hosts in $maclist_hosts; do
hosts=${hosts#*^}
interface=${hosts%%:*}
if ! list_search $interface $maclist_interfaces; then\
if [ -z "$maclist_interfaces" ]; then
maclist_interfaces=$interface
else
maclist_interfaces="$maclist_interfaces $interface"
fi
fi
done
progress_message "$DOING MAC Verification on $maclist_interfaces -- Phase $1..."
#
# Create chains.
#
if [ $1 -eq 1 ]; then
for interface in $maclist_interfaces; do
chain=$(mac_chain $interface)
create_mac_chain $chain
#
# If we're using the mangle table and the interface is DHCP-enabled then we need to accept DHCP broadcasts from 0.0.0.0
#
if [ $MACLIST_TABLE = mangle ] && interface_has_option $interface dhcp; then
run_iptables -t mangle -A $chain -s 0.0.0.0 -d 255.255.255.255 -p udp --dport 67:68 -j RETURN
fi
if [ -n "$MACLIST_TTL" ]; then
chain1=$(macrecent_target $interface)
create_mac_chain $chain1
run_iptables -A $chain -t $MACLIST_TABLE -m recent --rcheck --seconds $MACLIST_TTL --name $chain -j RETURN
run_iptables -A $chain -t $MACLIST_TABLE -j $chain1
run_iptables -A $chain -t $MACLIST_TABLE -m recent --update --name $chain -j RETURN
run_iptables -A $chain -t $MACLIST_TABLE -m recent --set --name $chain
fi
done
#
# Process the maclist file producing the verification rules
#
while read disposition interface mac addresses; do
level=
case $disposition in
ACCEPT:*)
level=${disposition#*:}
disposition=ACCEPT
target=RETURN
;;
ACCEPT)
target=RETURN
;;
REJECT:*)
[ $MACLIST_TABLE = mangle ] && fatal_error "DISPOSITION = REJECT is incompatible with MACLIST_TABLE=mangle"
target=reject
disposition=REJECT
;;
REJECT)
[ $MACLIST_TABLE = mangle ] && fatal_error "DISPOSITION = REJECT is incompatible with MACLIST_TABLE=mangle"
target=reject
;;
DROP:*)
level=${disposition#*:}
disposition=DROP
target=DROP
;;
DROP)
target=DROP
;;
*)
addresses="$mac"
mac="$interface"
interface="$disposition"
disposition=ACCEPT
target=RETURN
;;
esac
physdev_part=
if [ -n "$BRIDGING" ]; then
case $interface in
*:*)
physdev_part="-m physdev --physdev-in ${interface#*:}"
interface=${interface%:*}
;;
esac
fi
[ -n "$MACLIST_TTL" ] && chain=$(macrecent_target $interface) || chain=$(mac_chain $interface)
if ! have_mac_chain $chain ; then
fatal_error "No hosts on $interface have the maclist option specified"
fi
if [ x${mac:=-} = x- ]; then
if [ -z "$addresses" ]; then
fatal_error "You must specify a MAC address or an IP address"
else
macpart=
fi
else
macpart=$(mac_match $mac)
fi
if [ -z "$addresses" ]; then
[ -n "$level" ] && \
log_rule_limit $level $chain $(mac_chain $interface) $disposition "$LOGLIMIT" "" -A -t $MACLIST_TABLE $macpart $physdev_part
run_iptables -A $chain -t $MACLIST_TABLE $macpart $physdev_part -j $target
else
for address in $(separate_list $addresses) ; do
[ -n "$level" ] && \
log_rule_limit $level $chain $(mac_chain $interface) $disposition "$LOGLIMIT" "" -A -t $MACLIST_TABLE $macpart -s $address $physdev_part
run_iptables2 -A $chain -t $MACLIST_TABLE $macpart -s $address $physdev_part -j $target
done
fi
done < $TMP_DIR/maclist
#
# Generate jumps from the input and forward chains
#
for hosts in $maclist_hosts; do
ipsec=${hosts%^*}
[ -n "$POLICY_MATCH" ] && policy="-m policy --pol $ipsec --dir in" || policy=
hosts=${hosts#*^}
interface=${hosts%%:*}
hosts=${hosts#*:}
case $MACLIST_TABLE in
filter)
for chain in $(first_chains $interface) ; do
run_iptables -A $chain $(match_source_hosts $hosts) -m state --state NEW \
$policy -j $(mac_chain $interface)
done
;;
*)
run_iptables -t mangle -A PREROUTING -i $interface $(match_source_hosts $hosts) -m state --state NEW \
$policy -j $(mac_chain $interface)
;;
esac
done
else
#
# Must take care of our own broadcasts and multicasts then terminate the verification
# chains
#
for interface in $maclist_interfaces; do
[ -n "$MACLIST_TTL" ] && chain=$(macrecent_target $interface) || chain=$(mac_chain $interface)
if [ -n "$MACLIST_LOG_LEVEL" -o $MACLIST_DISPOSITION != ACCEPT ]; then
indent >&3 << __EOF__
if interface_is_usable $interface; then
ip -f inet addr show $interface 2> /dev/null | grep 'inet.*brd' | sed 's/inet //; s/brd //; s/scope.*//;' | while read address broadcast; do
address=\${address%/*}
if [ -n "\$broadcast" ]; then
run_iptables -t $MACLIST_TABLE -A $chain -s \$address -d \$broadcast -j RETURN
fi
run_iptables -t $MACLIST_TABLE -A $chain -s \$address -d 255.255.255.255 -j RETURN
run_iptables -t $MACLIST_TABLE -A $chain -s \$address -d 224.0.0.0/4 -j RETURN
done
else
fatal_error "Interface $interface must be up before Shorewall can start"
fi
__EOF__
fi
CHAIN=$chain
append_file maclog
if [ -n "$MACLIST_LOG_LEVEL" ]; then
log_rule_limit $MACLIST_LOG_LEVEL $chain $(mac_chain $interface) $MACLIST_DISPOSITION "$LOGLIMIT" "" -A -t $MACLIST_TABLE
fi
if [ $MACLIST_DISPOSITION != ACCEPT ]; then
run_iptables -A $chain -t $MACLIST_TABLE -j $MACLIST_TARGET
fi
done
fi
}