#!/bin/sh # # Shorewall 3.3 -- /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 # # 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 }