From 2ec808728bf7ecfba1a054d02a6071d1607083d9 Mon Sep 17 00:00:00 2001 From: teastep Date: Sun, 27 Aug 2006 21:01:22 +0000 Subject: [PATCH] Modularize maclist git-svn-id: https://shorewall.svn.sourceforge.net/svnroot/shorewall/trunk@4465 fbd18981-670d-0410-9b5c-8dc0c1a9a2bb --- Shorewall/compiler | 227 -------------------------------------- Shorewall/functions | 10 +- Shorewall/lib.maclist | 250 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 258 insertions(+), 229 deletions(-) create mode 100644 Shorewall/lib.maclist diff --git a/Shorewall/compiler b/Shorewall/compiler index bda21b1c9..bb1138c4c 100755 --- a/Shorewall/compiler +++ b/Shorewall/compiler @@ -641,233 +641,6 @@ disable_critical_hosts() done } -# -# Set up MAC Verification -# -setup_mac_lists() { - 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..." - # - # Create chains. - # - 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 - expandv disposition interface mac addresses - - 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 - # - # 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__ - -blob=\$(ip link show $interface 2> /dev/null) - -[ -z "\$blob" ] && \ - fatal_error "Interface $interface must be up before Shorewall can start" - -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 - -__EOF__ - fi - - 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 - # - # Generate jumps from the input and forward chains - # - for hosts in $maclist_hosts; do - ipsec=${hosts%^*} - hosts=${hosts#*^} - [ -n "$POLICY_MATCH" ] && policy="-m policy --pol $ipsec --dir in" || policy= - 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 -} - # # Set up SYN flood protection # diff --git a/Shorewall/functions b/Shorewall/functions index 2408eada7..126765a14 100644 --- a/Shorewall/functions +++ b/Shorewall/functions @@ -568,7 +568,10 @@ validate_interfaces_file() { case $option in -) ;; - dhcp|tcpflags|arp_filter|routefilter|maclist|logmartians|sourceroute|blacklist|proxyarp|nosmurfs|upnp|-) + dhcp|tcpflags|arp_filter|routefilter|logmartians|sourceroute|blacklist|proxyarp|nosmurfs|upnp|-) + ;; + maclist) + lib_load maclist "The 'maclist' option" ;; norfc1918) if [ "$PROGRAM" = compiler ]; then @@ -808,8 +811,11 @@ validate_hosts_file() { for option in $(separate_list $options) ; do case $option in - norfc1918|blacklist|maclist|tcpflags|nosmurfs|-) + norfc1918|blacklist|tcpflags|nosmurfs|-) ;; + maclist) + lib_load maclist "The 'maclist' option" + ;; ipsec) [ -n "$POLICY_MATCH" ] || \ startup_error "Your kernel and/or iptables does not support policy match: ipsec" diff --git a/Shorewall/lib.maclist b/Shorewall/lib.maclist new file mode 100644 index 000000000..8c4ddb62b --- /dev/null +++ b/Shorewall/lib.maclist @@ -0,0 +1,250 @@ +#!/bin/sh +# +# Shorewall 3.2 -- /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 - 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 + +# +# Set up MAC Verification +# +setup_mac_lists() { + 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..." + # + # Create chains. + # + 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 + expandv disposition interface mac addresses + + 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 + # + # 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__ + +blob=\$(ip link show $interface 2> /dev/null) + +[ -z "\$blob" ] && \ + fatal_error "Interface $interface must be up before Shorewall can start" + +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 + +__EOF__ + fi + + 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 + # + # Generate jumps from the input and forward chains + # + for hosts in $maclist_hosts; do + ipsec=${hosts%^*} + hosts=${hosts#*^} + [ -n "$POLICY_MATCH" ] && policy="-m policy --pol $ipsec --dir in" || policy= + 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 +} +