#!/bin/sh # 2000.08.25 kjw - this script is called by both ppp and pcmcia to setup # ipchains security # # USAGE: $0 (up|down) (internal|external) $DEVICE $IPLOCAL # USAGE: $0 init # # Theory of operations: # First, the ipchains policies, as set by /etc/rc.d/rc.local # input set to accept # forward set to deny # output set to accept # # all input rules will be to DENY packets that I don't want. order is # thus unimportant # # all forward rules will be MASQ for external and ACCEPT from internals. # order is important; MASQ need to be inserted and ACCEPT appended ######################################################################### ## begin subroutines ## IPC='/sbin/ipchains' delete_external_ipchains() { # expects DEVICE, $IPLOCAL # Convenience defines: IF=$DEVICE for RULE in input forward output ; do RUL=`echo $RULE | cut -c1-3` # delete references to our chains echo "$IPC --delete $RULE --interface $IF --jump $IF-$RUL" $IPC --delete $RULE --interface $IF --jump $IF-$RUL # delete the chains themselves echo "$IPC -F $IF-$RUL" $IPC -F $IF-$RUL echo "$IPC -X $IF-$RUL" $IPC -X $IF-$RUL done } create_external_ipchains() { # uses $IPC # expects DEVICE, IPLOCAL # IPLOCAL=ip address of the local interface # DEVICE=interface name, i.e. ppp0, eth1 delete_external_ipchains # Convenience defines: _DEST='--destination' _TCP="--protocol tcp" _UDP="--protocol udp" IF=$DEVICE for RULE in inp for out ; do # create or null==delete echo "$IPC --new-chain $IF-$RULE" $IPC --new-chain $IF-$RULE done ## NOTE: we don't need to include --interface $DEVICE because that ## check is done BEFORE jumping to the $IF-{inp,for,out} rules # Only allow packets targeted at that interface echo "$IPC --append $IF-inp --destination ! $IPLOCAL/32 --jump DENY" $IPC --append $IF-inp --destination ! $IPLOCAL/32 --jump DENY # Deny specific (local) services, since we still need # to allow privledged ports (<=1024) # 515 = lpr, 80 = http, 25 = smtp, 4321 = pmcd, 4330 = pmlogger ctrl # 21 = ftpd, 53 = named # use 'REJECT' instead of 'DENY' so that you get a Connection Refused, # just as if the service did not exist. for SERVICE in 515 80 25 4321 4330 21 53 ; do echo "$IPC --append $IF-inp $_DEST $IPLOCAL $SERVICE $_TCP --jump REJECT" $IPC --append $IF-inp $_DEST $IPLOCAL $SERVICE $_TCP --jump REJECT done # reject udp services # 67 = bootp (dhcpd), 53 = named for SERVICE in 67 53 ; do echo "$IPC --append $IF-inp $_DEST $IPLOCAL $SERVICE $_UDP --jump REJECT" $IPC --append $IF-inp $_DEST $IPLOCAL $SERVICE $_UDP --jump REJECT done unset SERVICE # everything going out an external if should be masq'ed to that addr anyways echo "$IPC --append $IF-for --jump MASQ" $IPC --append $IF-for --jump MASQ # Now that our personal chains are created, attach them to the real chains # deny obviously bad packets first. only packets for that if are allowed, # since it's a masquerading interface. echo "$IPC --insert input 1 --interface $IF --jump $IF-inp" $IPC --insert input 1 --interface $IF --jump $IF-inp # since we're masquerading, we should masq first before hitting internal # "internal, so just fwd it as is". echo "$IPC --insert forward 1 --interface $IF --jump $IF-for" $IPC --insert forward 1 --interface $IF --jump $IF-for # ... no output rules? ... #echo "$IPC --append output --interface $IF --jump $IF-out" # $IPC --append output --interface $IF --jump $IF-out } do_internal_ipchains() { # uses $IPC # expects _APPEND, _INSERT, _INSERT_POSITION to be defined # and IPLOCAL, DEVICE NET=`ipcalc --network $IPLOCAL 0xffffff00 | cut -f2 -d=` # Convenience defines: _DENY='--jump DENY' _MASQ='--jump MASQ' _ACCE='--jump ACCEPT' _TCP="--protocol tcp" _IF="--interface $DEVICE" # allow internal packets to be routed around echo "$IPC $_APPEND forward $_IF --source 10.0.0.0/8 --destination 10.0.0.0/8 $_ACCE" $IPC $_APPEND forward $_IF --source 10.0.0.0/8 --destination 10.0.0.0/8 $_ACCE # allow only packets from the internal interface (leaf, not transit network) echo "$IPC $_APPEND input $_IF --source ! $NET/24 $_DENY" $IPC $_APPEND input $_IF --source ! $NET/24 $_DENY } ## end subroutines ## ######################################################################### exec >/tmp/ipchains_config.$3.log exec 2>&1 ## parse and verify command-line MODE=$1 echo "Mode $MODE" if [ "$MODE" != 'init' -a "$MODE" != 'up' -a "$MODE" != 'down' ] ; then echo "ERROR: Mode [$MODE] is none of 'init', 'up' or 'down'" exit 5 fi if [ "$MODE" = 'init' ] ; then $IPC -P input ACCEPT $IPC -P forward DENY $IPC -P output ACCEPT # set tcp connections to timeout in 6000 seconds (100 minutes) instead # of the default 15 minutes. leave tcp-fin and udp unchanged. /sbin/ipchains -M -S 6000 0 0 exit 0 fi TYPE=$2 DEVICE=$3 IPLOCAL=$4 echo "Type $TYPE" echo "Interface $DEVICE" echo "IP address $IPLOCAL" logger -t ipchains_config "$MODE IF=$DEVICE IP=$IPLOCAL" if [ "$TYPE" != 'external' -a "$TYPE" != 'internal' ] then echo "ERROR: Type [$TYPE] is none of 'internal' or 'external'" exit 5 fi ## do the down stuff if [ "$MODE" = 'down' ] ; then _APPEND='--delete' _INSERT='--delete' _INSERT_POSITION= if [ "$TYPE" = 'external' ] ; then delete_external_ipchains else do_internal_ipchains ; fi exit 0 fi ## else do the up stuff if [ "$MODE" = 'up' ] ; then _APPEND='--append' _INSERT='--insert' _INSERT_POSITION=1 if [ "$TYPE" = 'external' ] ; then create_external_ipchains else do_internal_ipchains ; fi exit 0 fi