#!/bin/bash #A library of functions and subroutines for Mason #Copyright 2004, William Stearns #See the main Mason script for license and copyright information. checkconf () { #FIXME - double check all vars have default values. echo -n "Check vars..." >/dev/stderr MASONDIR=${MASONDIR:-"/var/lib/mason/"} ; if [ ! -d $MASONDIR ]; then mkdir --parents $MASONDIR ; chown root.root $MASONDIR ; chmod 700 $MASONDIR ; fi MASONCONF=${MASONCONF:-"/etc/masonrc"} ; if [ ! -f $MASONCONF ]; then touch $MASONCONF ; fi NAMECACHE=${NAMECACHE:-"${MASONDIR}morehosts"} ; if [ ! -f $NAMECACHE ]; then touch $NAMECACHE ; fi NETCACHE=${NETCACHE:-"${MASONDIR}netconvert"} ; if [ ! -f $NETCACHE ]; then touch $NETCACHE ; fi BASERULEFILE=${BASERULEFILE:-"${MASONDIR}baserules"} ; if [ ! -f $BASERULEFILE ]; then touch $BASERULEFILE ; fi NEWRULEFILE=${NEWRULEFILE:-"${MASONDIR}newrules"} ; if [ ! -f $NEWRULEFILE ]; then touch $NEWRULEFILE ; fi PACKETLOGFILE=${PACKETLOGFILE:-"/var/log/messages"} MASONEXE=${MASONEXE:-"/usr/bin/mason"} if [ -z "${SERVICES}" ]; then SERVICES="/etc/services" #I used to add in the following 2 files. I do not now because I got too many false matches from nmap-services. #if [ -f ${MASONDIR}moreservices ]; then SERVICES="${SERVICES} ${MASONDIR}moreservices" ; fi #if [ -f ${MASONDIR}nmap-services ]; then SERVICES="${SERVICES} ${MASONDIR}nmap-services" ; fi fi NOLOGSUFFIX=${NOLOGSUFFIX:-"N"} #If you change this, change it in ruleshell too. DEBUG=${DEBUG:-"NO"} DYNIF=${DYNIF:-""} INCOMINGINTERFACES=${INCOMINGINTERFACES:-`/sbin/route -n | grep '^0\.0\.0\.0[ \t]' | awk '{print $8}'`} case $NEWRULEPOLICY in #Set LCPOLICY (lower case) and UCPOLICY... accept|ACCEPT) LCPOLICY="accept" ; UCPOLICY="ACCEPT" ;; reject|REJECT) LCPOLICY="reject" ; UCPOLICY="REJECT" ;; deny|DENY) LCPOLICY="deny " ; UCPOLICY="DENY " ;; *) echo WARNING! NEWRULEPOLICY is neither accept, reject, nor deny >/dev/stderr echo in ${MASONCONF}. It is being reset to \"accept\". Please fix! >/dev/stderr LCPOLICY="accept" ; UCPOLICY="ACCEPT" ;; esac case $DEFAULTPOLICY in accept|ACCEPT) DEFAULTPOLICY="accept" ; ;; reject|REJECT) DEFAULTPOLICY="reject" ; ;; deny|DENY) DEFAULTPOLICY="deny " ; ;; *) echo WARNING! DEFAULTPOLICY is neither accept, reject, nor deny >/dev/stderr echo in ${MASONCONF}. It is being reset to \"accept\". Please fix! >/dev/stderr DEFAULTPOLICY="accept" ;; esac case $LOGGINGPOLICY in accept|ACCEPT) LOGGINGPOLICY="accept" ; ;; reject|REJECT) LOGGINGPOLICY="reject" ; ;; deny|DENY) LOGGINGPOLICY="deny " ; ;; *) LOGGINGPOLICY=$NEWRULEPOLICY ;; esac case $FLUSHEDPOLICY in accept|ACCEPT) FLUSHEDPOLICY="accept" ; ;; reject|REJECT) FLUSHEDPOLICY="reject" ; ;; deny|DENY) FLUSHEDPOLICY="deny " ; ;; *) FLUSHEDPOLICY=accept ;; esac case $ECHOCOMMAND in ipfwadm|IPFWADM) ECHOCOMMAND="ipfwadm" ;; ipchains|IPCHAINS) ECHOCOMMAND="ipchains" ;; cisco|CISCO) ECHOCOMMAND="cisco" ;; no|NO|none|NONE) ECHOCOMMAND="none" ;; *) if [ -f /proc/net/ip_fwchains ]; then ECHOCOMMAND="ipchains" elif [ -f /proc/net/ip_input ]; then ECHOCOMMAND="ipfwadm" else ECHOCOMMAND="ipchains" #Set default here fi ;; esac case $DOCOMMAND in ipfwadm|IPFWADM) DOCOMMAND="ipfwadm" if [ ! -f /proc/net/ip_input ]; then echo WARNING! User has requested ipfwadm, but it appears to be >/dev/stderr echo unavailable. Proceeding, but this is not likely to work. >/dev/stderr fi if [ ! -x /sbin/ipfwadm ]; then echo WARNING! User has requested ipfwadm, but /sbin/ipfwadm is not >/dev/stderr echo executable. Proceeding, but this is not likely to work. >/dev/stderr fi ;; ipchains|IPCHAINS) DOCOMMAND="ipchains" if [ ! -f /proc/net/ip_fwchains ]; then echo WARNING! User has requested ipchains, but it appears to be >/dev/stderr echo unavailable. Proceeding, but this is not likely to work. >/dev/stderr fi if [ ! -x /sbin/ipchains ]; then echo WARNING! User has requested ipchains, but /sbin/ipchains is not >/dev/stderr echo executable. Proceeding, but this is not likely to work. >/dev/stderr fi ;; no|NO|none|NONE) DOCOMMAND="none" ;; *) if [ -f /proc/net/ip_fwchains ]; then DOCOMMAND="ipchains" if [ ! -x /sbin/ipchains ]; then echo WARNING! This kernel uses ipchains, but /sbin/ipchains is not >/dev/stderr echo executable. Proceeding, but this is not likely to work. >/dev/stderr echo Please get a copy of the ipchains binary and place it in /sbin . >/dev/stderr fi elif [ -f /proc/net/ip_input ]; then DOCOMMAND="ipfwadm" if [ ! -x /sbin/ipfwadm ]; then echo WARNING! This kernel uses ipfwadm, but /sbin/ipfwadm is not >/dev/stderr echo executable. Proceeding, but this is not likely to work. >/dev/stderr echo Please get a copy of the ipfwadm binary and place it in /sbin . >/dev/stderr fi else DOCOMMAND="none" #Well, we can't _do_ either! echo WARNING! Neither ipchains nor ipfwadm appears to be >/dev/stderr echo unavailable. Proceeding anyways. >/dev/stderr fi ;; esac case $HEARTBEAT in YES|yes|TRUE|true) HEARTBEAT="YES" ;; NO|no|NONE|none|FALSE|false) HEARTBEAT="NO" ;; *) HEARTBEAT="YES" ;; esac case $IPCONV in HOSTNAME|hostname|HOST|host) IPCONV="HOST" ;; NETWORK|network|NET|net) IPCONV="NETWORK" ;; NO|no|NONE|none) IPCONV="NONE" ;; #CUSTOM|custom) IPCONV="CUSTOM" ;; *) IPCONV="NETWORK" ;; esac case $HOSTLOOKUP in NO|no|NONE|none) HOSTLOOKUP="NONE" ;; FILES|files|FILESONLY|filesonly) HOSTLOOKUP="FILESONLY" ;; FULL|full|YES|yes) HOSTLOOKUP="FULL" ;; *) HOSTLOOKUP="FULL" ;; esac DOBEEP=${DOBEEP:-"YES"} # "YES" = beep at user with new rule, "NO" = dont PORT_MASQ_BEGIN=${PORT_MASQ_BEGIN:-61000} PORT_MASQ_END=${PORT_MASQ_END:-65096} TRACEROUTE_BEGIN=${TRACEROUTE_BEGIN:-33434} TRACEROUTE_END=${TRACEROUTE_END:-33524} IRC_BEGIN=${IRC_BEGIN:-6666} IRC_END=${IRC_END:-6671} MAXDISPLAYS=${MAXDISPLAYS:-6} X_BEGIN=${X_BEGIN:-6000} X_END=${X_END:-$[ $X_BEGIN + $MAXDISPLAYS -1 ]} OPENWIN_BEGIN=${OPENWIN_BEGIN:-2000} OPENWIN_END=${OPENWIN_END:-$[ $OPENWIN_BEGIN + $MAXDISPLAYS -1 ]} VNCJAVA_BEGIN=${VNCJAVA_BEGIN:-5800} VNCJAVA_END=${VNCJAVA_END:-$[ $VNCJAVA_BEGIN + $MAXDISPLAYS -1 ]} VNC_BEGIN=${VNC_BEGIN:-5900} VNC_END=${VNC_END:-$[ $VNC_BEGIN + $MAXDISPLAYS -1 ]} SSP=${SSP:-""} SCP=${SCP:-""} LOWSSHPORT=${LOWSSHPORT:-"1010"} if [ -z "$EDITOR" ]; then for TRYEDITOR in `type -path mcedit` \ `type -path pico` \ `type -path vi` \ `type -path jove` \ `type -path nedit` \ `type -path emacs`; do if [ -z "$EDITOR" ]; then EDITOR=$TRYEDITOR echo Editor default of $EDITOR taken. >/dev/stderr fi done unset TRYEDITOR if [ -z "$EDITOR" ]; then echo No editor was specified by the EDITOR= variable and >/dev/stderr echo this script was unable to find mcedit, pico, vi, jove, nedit or emacs >/dev/stderr echo on your system. Please set EDITOR=the_name_of_an_editor >/dev/stderr echo in $MASONCONF or your environment and re-start. >/dev/stderr fi #no suitable editor found fi if [ "$ECHOCOMMAND" = "cisco" ]; then SINGLEMACHSPEC=" 0.0.0.0" CMNT='!' else SINGLEMACHSPEC="/32" CMNT="#" fi } #End of checkconf checksys () { if [ ! -d /proc/1 ]; then echo WARNING! Proc filesystem not supported or not mounted. Please fix and restart. exit fi if [ -f /proc/net/ip_fwchains ]; then : elif [ -f /proc/net/ip_input ]; then : else echo This kernel supports neither ipchains nor ipfwadm! >/dev/stderr #DOCOMMAND="none" #Should we force to none? fi } #End of checksys #------------------------------------------------------------------------- # clientportrange function, returns the individual port or range of # ports for the given client port, server port, and protocol parameters. #------------------------------------------------------------------------- clientportrange () { CLIENTPORT=$1 ; SERVERPORT=$2 ; PRPROTO=$3 CPRRETVAL="1024:65535" if [ $CLIENTPORT -ge $PORT_MASQ_BEGIN ] && [ $CLIENTPORT -le $PORT_MASQ_END ]; then CPRRETVAL="${PORT_MASQ_BEGIN}:${PORT_MASQ_END}" elif [ $CLIENTPORT -ge $TRACEROUTE_BEGIN ] && [ $CLIENTPORT -le $TRACEROUTE_END ] && [ "$PRPROTO" = "udp" ]; then CPRRETVAL="${TRACEROUTE_BEGIN}:${TRACEROUTE_END}" elif [ $SERVERPORT -ge $TRACEROUTE_BEGIN ] && [ $SERVERPORT -le $TRACEROUTE_END ] && [ "$PRPROTO" = "udp" ]; then if [ $CLIENTPORT -ge 32768 ]; then CPRRETVAL="32768:65535" ; fi #According to the traceroute 1.4a5 source, the source port for a udp traceroute is set to the pid #with the high bit set. This translates into 32768-65535; remember, the pid could be 32768. elif [ "$PRPROTO" = "udp" ] && [ $SERVERPORT -ge 6770 ] && [ $SERVERPORT -le 7170 ]; then #RealAudio if [ $CLIENTPORT -ge 6970 ] && [ $CLIENTPORT -le 7170 ]; then CPRRETVAL="6970:7170" elif [ $CLIENTPORT -ge 6770 ] && [ $CLIENTPORT -le 7170 ]; then CPRRETVAL="6770:7170" fi else case "${SERVERPORT}/${PRPROTO}" in "22/tcp"|"ssh/tcp") if [ $CLIENTPORT -le 1023 ]; then while [ "$CLIENTPORT" -lt "$LOWSSHPORT" ]; do #LOWSSHPORT=`expr $LOWSSHPORT - 10` LOWSSHPORT=$[ $LOWSSHPORT - 10 ] done CPRRETVAL="${LOWSSHPORT}:1023" fi ;; "111/tcp"|"sunrpc/tcp"|"rpcbind/tcp"|"111/udp"|"sunrpc/udp"|"rpcbind/tcp"|"635/tcp"|"mount/tcp"|"635/udp"|"mount/udp"|"2049/udp"|"nfs/udp") #sunrpc/tcp: 600-1014 viewed with rpcinfo client, sunrpc/udp: 600-1022 viewed with nfs mount and unmount #mount/tcp: 605-1022 viewed with nfs mount and unmount, mount/udp: 601-1022 viewed with nfs mount and unmount #nfs/udp: 610-1014 and nfs viewed if [ $CLIENTPORT -le 1023 ]; then if [ $CLIENTPORT -ge 600 ]; then CPRRETVAL="600:1023" else CPRRETVAL="$CLIENTPORT" fi fi ;; "2049/tcp"|"nfs/tcp") #Starts at 800 and works its way down, may reuse ports? #Probably do a min port like ssh. For the moment, use 760 to 800 if [ $CLIENTPORT -le 1023 ]; then if [ $CLIENTPORT -ge 760 ] && [ $CLIENTPORT -le 800 ]; then CPRRETVAL="760:800" else CPRRETVAL="$CLIENTPORT" fi fi ;; *) if [ $CLIENTPORT -le 1023 ]; then CPRRETVAL="$CLIENTPORT" ; fi ;; esac fi echo $CPRRETVAL } #End of clientportrange #------------------------------------------------------------------------- # convmasktobits function, returns the number of bits in the netmask parameter. #------------------------------------------------------------------------- convmasktobits () { case $1 in 255.255.255.255) echo 32 ;; 255.255.255.254) echo 31 ;; 255.255.255.252) echo 30 ;; 255.255.255.248) echo 29 ;; 255.255.255.240) echo 28 ;; 255.255.255.224) echo 27 ;; 255.255.255.192) echo 26 ;; 255.255.255.128) echo 25 ;; 255.255.255.0) echo 24 ;; 255.255.254.0) echo 23 ;; 255.255.252.0) echo 22 ;; 255.255.248.0) echo 21 ;; 255.255.240.0) echo 20 ;; 255.255.224.0) echo 19 ;; 255.255.192.0) echo 18 ;; 255.255.128.0) echo 17 ;; 255.255.0.0) echo 16 ;; 255.254.0.0) echo 15 ;; 255.252.0.0) echo 14 ;; 255.248.0.0) echo 13 ;; 255.240.0.0) echo 12 ;; 255.224.0.0) echo 11 ;; 255.192.0.0) echo 10 ;; 255.128.0.0) echo 9 ;; 255.0.0.0) echo 8 ;; 254.0.0.0) echo 7 ;; 252.0.0.0) echo 6 ;; 248.0.0.0) echo 5 ;; 240.0.0.0) echo 4 ;; 224.0.0.0) echo 3 ;; 192.0.0.0) echo 2 ;; 128.0.0.0) echo 1 ;; 0.0.0.0) echo 0 ;; *) echo 32 ;; esac } #End of convmasktobits #------------------------------------------------------------------------- # convmasktocisco function, returns the cisco "reverse netmask" of the netmask parameter. #------------------------------------------------------------------------- convmasktocisco () { #This could be done in fewer lines by subtracting each octet from 255. #I'm trying to avoid forking as it hurts performance. case $1 in 255.255.255.255) echo 0.0.0.0 ;; 255.255.255.254) echo 0.0.0.1 ;; 255.255.255.252) echo 0.0.0.3 ;; 255.255.255.248) echo 0.0.0.7 ;; 255.255.255.240) echo 0.0.0.15 ;; 255.255.255.224) echo 0.0.0.31 ;; 255.255.255.192) echo 0.0.0.63 ;; 255.255.255.128) echo 0.0.0.127 ;; 255.255.255.0) echo 0.0.0.255 ;; 255.255.254.0) echo 0.0.1.255 ;; 255.255.252.0) echo 0.0.3.255 ;; 255.255.248.0) echo 0.0.7.255 ;; 255.255.240.0) echo 0.0.15.255 ;; 255.255.224.0) echo 0.0.31.255 ;; 255.255.192.0) echo 0.0.63.255 ;; 255.255.128.0) echo 0.0.127.255 ;; 255.255.0.0) echo 0.0.255.255 ;; 255.254.0.0) echo 0.1.255.255 ;; 255.252.0.0) echo 0.3.255.255 ;; 255.248.0.0) echo 0.7.255.255 ;; 255.240.0.0) echo 0.15.255.255 ;; 255.224.0.0) echo 0.31.255.255 ;; 255.192.0.0) echo 0.63.255.255 ;; 255.128.0.0) echo 0.127.255.255 ;; 255.0.0.0) echo 0.255.255.255 ;; 254.0.0.0) echo 1.255.255.255 ;; 252.0.0.0) echo 3.255.255.255 ;; 248.0.0.0) echo 7.255.255.255 ;; 240.0.0.0) echo 15.255.255.255 ;; 224.0.0.0) echo 31.255.255.255 ;; 192.0.0.0) echo 63.255.255.255 ;; 128.0.0.0) echo 127.255.255.255 ;; 0.0.0.0) echo 255.255.255.255 ;; *) echo 0.0.0.0 ;; esac } #End of convmasktocisco flushfirewall () { #Flush the existing rules so we start with a clean slate. if [ -f /proc/net/ip_fwchains ]; then echo -n Flushing... >/dev/stderr FLUSHEDPOLICY=`echo $FLUSHEDPOLICY | tr a-z A-Z` /sbin/ipchains -P output $FLUSHEDPOLICY /sbin/ipchains -F output /sbin/ipchains -P forward $FLUSHEDPOLICY /sbin/ipchains -F forward /sbin/ipchains -P input $FLUSHEDPOLICY /sbin/ipchains -F input if [ -n "${NOLOGSUFFIX}" ]; then /sbin/ipchains -F output${NOLOGSUFFIX} >/dev/null 2>/dev/null /sbin/ipchains -F forward${NOLOGSUFFIX} >/dev/null 2>/dev/null /sbin/ipchains -F input${NOLOGSUFFIX} >/dev/null 2>/dev/null fi echo Done! elif [ -f /proc/net/ip_input ]; then echo -n Flushing... >/dev/stderr FLUSHEDPOLICY=`echo $FLUSHEDPOLICY | tr A-Z a-z` /sbin/ipfwadm -O -p $FLUSHEDPOLICY /sbin/ipfwadm -O -f /sbin/ipfwadm -F -p $FLUSHEDPOLICY /sbin/ipfwadm -F -f /sbin/ipfwadm -I -p $FLUSHEDPOLICY /sbin/ipfwadm -I -f echo Done! else echo This kernel supports neither ipchains nor ipfwadm! >/dev/stderr fi } #End of flushfirewall #------------------------------------------------------------------------- # generalizeip function. For the given ip address parameter, return one # of the following: # - $DYNIFADDR for interfaces with dynamic IP addresses. # - the corresponding hostname # - itself, if a local address, broadcast address, or special address. # - its IP network # - as a last resort, 0/0 # User can select operation with IPCONV= in masonconf. #------------------------------------------------------------------------- generalizeip () { GIRETVAL="${1}${SINGLEMACHSPEC}" ISASSIGNED="NO" for ONEIF in $DYNIF ; do DYNIP=$(eval echo \${$(eval echo ${ONEIF}ADDR)}) #No, really. if [ "$1" = "$DYNIP" ]; then GIRETVAL="\${${ONEIF}ADDR}" #Do not add /32 here - that shell variable _has_ /32 in it. ISASSIGNED="YES" #LINEHASDYNAMIC="YES" #Not exported from a function - not currently used fi done if [ "$ISASSIGNED" = "NO" ]; then case $IPCONV in HOST) GIRETVAL="`nameof ${1}`${SINGLEMACHSPEC}" ;; NETWORK) #Handle special addresses case $1 in 0.0.0.0) GIRETVAL="0.0.0.0${SINGLEMACHSPEC}" ISASSIGNED="YES" ;; 127.0.0.1) GIRETVAL="localhost${SINGLEMACHSPEC}" ISASSIGNED="YES" ;; 255.255.255.255) GIRETVAL="255.255.255.255${SINGLEMACHSPEC}" ISASSIGNED="YES" ;; esac #Leave local IP addresses and broadcasts as they are. if [ "$ISASSIGNED" = "NO" ]; then for ONELOCALIP in $ALLIPS $ALLBCS ; do if [ "$1" = "$ONELOCALIP" ]; then GIRETVAL="`nameof ${1}`${SINGLEMACHSPEC}" ISASSIGNED="YES" fi done fi #If IP is in a local netblock, generalize to that netblock. if [ "$ISASSIGNED" = "NO" ]; then for ONENET in `cat ${NETCACHE}` ; do if [ "$ISASSIGNED" = "NO" ]; then NETMASK=${ONENET##*/} ; ONENET=${ONENET%/*} BROADCAST=${ONENET##*-} ; ONENET=${ONENET%-*} if iple $ONENET $1 ; then if iple $1 $BROADCAST ; then if [ "$ECHOCOMMAND" = "cisco" ]; then GIRETVAL="${ONENET} `convmasktocisco ${NETMASK}`" else GIRETVAL="${ONENET}/`convmasktobits ${NETMASK}`" fi ISASSIGNED="YES" fi fi fi done fi if [ "$ISASSIGNED" = "NO" ]; then GIRETVAL="0/0" ; ISASSIGNED="YES" ; fi ;; NONE) ;; #CUSTOM) ;; esac fi echo $GIRETVAL } #End of generalizeip #------------------------------------------------------------------------- # ipeq function, returns true/false: ip addresses are equal? #------------------------------------------------------------------------- #Not currently used... ipeq () { SPLITIP=$1 unset I1O1 I1O2 I1O3 I1O4 I1O1=${SPLITIP%%.*} ; SPLITIP=${SPLITIP#*.} I1O2=${SPLITIP%%.*} ; SPLITIP=${SPLITIP#*.} I1O3=${SPLITIP%%.*} ; SPLITIP=${SPLITIP#*.} I1O4=$SPLITIP SPLITIP=$2 unset I2O1 I2O2 I2O3 I2O4 I2O1=${SPLITIP%%.*} ; SPLITIP=${SPLITIP#*.} I2O2=${SPLITIP%%.*} ; SPLITIP=${SPLITIP#*.} I2O3=${SPLITIP%%.*} ; SPLITIP=${SPLITIP#*.} I2O4=$SPLITIP if [ $I1O1 -eq $I2O1 ] && [ $I1O2 -eq $I2O2 ] && [ $I1O3 -eq $I2O3 ] && [ $I1O4 -eq $I2O4 ]; then return 0 #True else return 1 #False fi } #End of ipeq #------------------------------------------------------------------------- # iple function, returns true (0) if first IP <= second IP, else false(1) #------------------------------------------------------------------------- iple () { #if iple 128.2.3.4 127.0.0.1 ; then echo less than or eq >/dev/stderr ; else echo ge >/dev/stderr ; fi SPLITIP=$1 unset I1O1 I1O2 I1O3 I1O4 I1O1=${SPLITIP%%.*} ; SPLITIP=${SPLITIP#*.} I1O2=${SPLITIP%%.*} ; SPLITIP=${SPLITIP#*.} I1O3=${SPLITIP%%.*} ; SPLITIP=${SPLITIP#*.} I1O4=$SPLITIP SPLITIP=$2 unset I2O1 I2O2 I2O3 I2O4 I2O1=${SPLITIP%%.*} ; SPLITIP=${SPLITIP#*.} I2O2=${SPLITIP%%.*} ; SPLITIP=${SPLITIP#*.} I2O3=${SPLITIP%%.*} ; SPLITIP=${SPLITIP#*.} I2O4=$SPLITIP if [ $I1O1 -lt $I2O1 ]; then return 0 elif [ $I1O1 -gt $I2O1 ]; then return 1 elif [ $I1O2 -lt $I2O2 ]; then return 0 elif [ $I1O2 -gt $I2O2 ]; then return 1 elif [ $I1O3 -lt $I2O3 ]; then return 0 elif [ $I1O3 -gt $I2O3 ]; then return 1 elif [ $I1O4 -lt $I2O4 ]; then return 0 elif [ $I1O4 -gt $I2O4 ]; then return 1 else return 0 fi } #End of iple #------------------------------------------------------------------------- # loadconf function, called at start and on receipt of SIGUSR1 #------------------------------------------------------------------------- loadconf () { if [ "$NEEDLF" = "YES" ]; then echo >/dev/stderr ; NEEDLF="NO" ; fi #This is the configuration file mason uses. The parameters in it can be #changed while Mason is running as long as the SIGUSR1 signal is sent to #Mason afterwards. This can be done by typing "killall -USR1 mason" if [ -f $MASONCONF ]; then echo -n "Loading options from ${MASONCONF}..." >/dev/stderr . $MASONCONF else touch $MASONCONF chmod 700 $MASONCONF echo Unable to load options, $MASONCONF does not exist. >/dev/stderr fi checkconf echo -n "Load IPs and networks..." >/dev/stderr #set ALLIPS and ALLBCS (broadcasts) ALLIPS="`ifconfig | grep 'inet addr' | sed -e 's/.*addr://' -e 's/ .*//'` \ `route -n | grep '^[0-9\.]* *[0-9\.]* *255\.255\.255\.255' | awk '{print $1}'`" ALLBCS=`ifconfig | grep 'Bcast' | sed -e 's/.*Bcast://' -e 's/ .*//'` #FIXME: ALLBCS includes net addresses too? #load the NETCACHE file with all non-trivial networks in the routing table. rm -f $NETCACHE touch $NETCACHE chmod 700 $NETCACHE for ONENET in `route -n | grep -v '^127\.' | grep -v '^0\.0\.0\.0' | grep '^[0-9]' | awk '{print $1 "/" $3}'` ; do case $ONENET in */255.255.255.255) : ;; */255.255.255.254) : ;; */255.255.255.252) : ;; */0.0.0.0) : ;; *) eval `ipcalc --broadcast ${ONENET%%/*} ${ONENET##*/}` echo ${ONENET%%/*}-${BROADCAST}/${ONENET##*/} >>$NETCACHE #network-broadcast/netmask ;; esac done echo "Done." >/dev/stderr SIGGED="YES" #We received a signal #FIXME - put killall -SIGUSR1 mason in ip-up... } #End of loadconf #------------------------------------------------------------------------- # nameof function, returns the hostname from the IP address parameter. #------------------------------------------------------------------------- nameof () { #Use the namecache file, /etc/hosts, and finally "host" command to look #up names for source and destination addresses. NAMEOFRETVAL=$1 if [ "$HOSTLOOKUP" = "FILESONLY" ] || [ "$HOSTLOOKUP" = "FULL" ]; then ONEHOSTNAME=`cat $NAMECACHE /etc/hosts | egrep "^${1}[^0-9]" | tail --lines=1 | awk '{print $2}'` if [ -n "$ONEHOSTNAME" ]; then NAMEOFRETVAL="$ONEHOSTNAME" fi fi if [ "$HOSTLOOKUP" = "FULL" ] && [ -z "$ONEHOSTNAME" ] && [ "$SRCPORT" != "53" ] && [ "$DESTPORT" != "53" ]; then if host -t ptr $1 >/dev/null 2>/dev/null ; then ONEHOSTNAME=`host -t ptr $1 2>/dev/null | grep 'domain name pointer' | head --lines=1 | sed -e 's/.* //'` if [ -n "$ONEHOSTNAME" ]; then echo -e "${1}\t${ONEHOSTNAME}" >>$NAMECACHE NAMEOFRETVAL="$ONEHOSTNAME" fi fi fi echo $NAMEOFRETVAL } #End of nameof runlearnfirewall () { if [ -f /proc/net/ip_fwchains ]; then DEFAULTPOLICY=`echo $DEFAULTPOLICY | tr a-z A-Z` if [ "`cat /proc/sys/net/ipv4/ip_forward`" = "0" ]; then echo "Please note that forwarding is disabled in the kernel." >/dev/stderr #/sbin/ipchains -A forward -j DENY #Possible to add, but unncessary. fi if [ -n "${BLOCKEDHOSTS}" ]; then echo -n Blockedhost blocks... for BLOCKEDHOST in $BLOCKEDHOSTS ; do /sbin/ipchains -I input -s $BLOCKEDHOST -j DENY $LOG /sbin/ipchains -I output -s $BLOCKEDHOST -j DENY $LOG /sbin/ipchains -I input -d $BLOCKEDHOST -j DENY $LOG /sbin/ipchains -I output -d $BLOCKEDHOST -j DENY $LOG done else echo -n No Blockedhost blocks... fi if [ -n "${NOINCOMING}" ] && [ -n "${INCOMINGINTERFACES}" ]; then echo -n Incoming blocks... for OUTSIDEIF in $INCOMINGINTERFACES ; do for BLOCKPROTO in $NOINCOMING ; do /sbin/ipchains -I input -i $OUTSIDEIF -p ${BLOCKPROTO##*/} -d 0/0 ${BLOCKPROTO%%/*} -j DENY $LOG done done else echo -n No incoming blocks... fi cp -pf /etc/hosts /etc/hosts.bak ; cat $NAMECACHE >>/etc/hosts echo -n Fixed rules... . $BASERULEFILE echo -n New rules... . $NEWRULEFILE mv -f /etc/hosts.bak /etc/hosts #ALLCHAINS=`ipchains -L -n | grep '^Chain' | awk '{print $2}'` ALLCHAINS="input output forward" #Finally, create a "nolog' chain for each of the existing chains, have each existing #chain jump to it, then log everything else. echo -n Adding logging rules... for ACHAIN in $ALLCHAINS ; do /sbin/ipchains -F ${ACHAIN}${NOLOGSUFFIX} >/dev/null 2>/dev/null #Flush it as it might have existed before. if ! /sbin/ipchains -L ${ACHAIN}${NOLOGSUFFIX} >/dev/null 2>/dev/null ; then #If nolog chain does not exist /sbin/ipchains -N ${ACHAIN}${NOLOGSUFFIX} #Create it fi /sbin/ipchains -A $ACHAIN -j ${ACHAIN}${NOLOGSUFFIX} /sbin/ipchains -A $ACHAIN -l /sbin/ipchains -P $ACHAIN $DEFAULTPOLICY done echo Done! elif [ -f /proc/net/ip_input ]; then DEFAULTPOLICY=`echo $DEFAULTPOLICY | tr A-Z a-z` if [ "`cat /proc/sys/net/ipv4/ip_forward`" = "0" ]; then echo "Please note that forwarding is disabled in the kernel." >/dev/stderr #/sbin/ipfwadm -F -i deny #Possible to add, but unncessary. fi if [ -n "$BLOCKEDHOSTS" ]; then echo -n Blockedhost blocks... for BLOCKEDHOST in $BLOCKEDHOSTS ; do /sbin/ipfwadm -I -i deny -S $BLOCKEDHOST $LOG /sbin/ipfwadm -O -i deny -S $BLOCKEDHOST $LOG /sbin/ipfwadm -I -i deny -D $BLOCKEDHOST $LOG /sbin/ipfwadm -O -i deny -D $BLOCKEDHOST $LOG done else echo -n No Blockedhost blocks... fi if [ -n "$NOINCOMING" ] && [ -n "$INCOMINGINTERFACES" ]; then echo -n Incoming blocks... for OUTSIDEIF in $INCOMINGINTERFACES ; do for BLOCKPROTO in $NOINCOMING ; do /sbin/ipfwadm -I -i deny -W $OUTSIDEIF -P ${BLOCKPROTO##*/} -D 0/0 ${BLOCKPROTO%%/*} $LOG done done else echo -n No incoming blocks... fi cp -pf /etc/hosts /etc/hosts.bak ; cat $NAMECACHE >>/etc/hosts echo -n Fixed rules... . $BASERULEFILE echo -n New rules... . $NEWRULEFILE mv -f /etc/hosts.bak /etc/hosts ALLCHAINS="I O F" #Finally, log everything else. echo -n Adding logging rules... for ACHAIN in $ALLCHAINS ; do /sbin/ipfwadm -${ACHAIN} -a ${LOGGINGPOLICY} -o /sbin/ipfwadm -${ACHAIN} -p $DEFAULTPOLICY done echo Done! else echo This kernel supports neither ipchains nor ipfwadm! >/dev/stderr fi } #End of runlearnfirewall runstandardfirewall () { if [ -f /proc/net/ip_fwchains ]; then DEFAULTPOLICY=`echo $DEFAULTPOLICY | tr a-z A-Z` if [ "`cat /proc/sys/net/ipv4/ip_forward`" = "0" ]; then echo "Please note that forwarding is disabled in the kernel." >/dev/stderr #/sbin/ipchains -A forward -j DENY #Possible to add, but unncessary. fi if [ -n "$BLOCKEDHOSTS" ]; then echo -n Blockedhost blocks... for BLOCKEDHOST in $BLOCKEDHOSTS ; do /sbin/ipchains -I input -s $BLOCKEDHOST -j DENY $LOG /sbin/ipchains -I output -s $BLOCKEDHOST -j DENY $LOG /sbin/ipchains -I input -d $BLOCKEDHOST -j DENY $LOG /sbin/ipchains -I output -d $BLOCKEDHOST -j DENY $LOG done else echo -n No Blockedhost blocks... fi if [ -n "$NOINCOMING" ] && [ -n "$INCOMINGINTERFACES" ]; then echo -n Incoming blocks... for OUTSIDEIF in $INCOMINGINTERFACES ; do for BLOCKPROTO in $NOINCOMING ; do /sbin/ipchains -I input -i $OUTSIDEIF -p ${BLOCKPROTO##*/} -d 0/0 ${BLOCKPROTO%%/*} -j DENY $LOG done done else echo -n No incoming blocks... fi cp -pf /etc/hosts /etc/hosts.bak ; cat $NAMECACHE >>/etc/hosts echo -n Fixed rules... . $BASERULEFILE mv -f /etc/hosts.bak /etc/hosts #ALLCHAINS=`ipchains -L -n | grep '^Chain' | awk '{print $2}'` ALLCHAINS="input output forward" for ACHAIN in $ALLCHAINS ; do /sbin/ipchains -P $ACHAIN $DEFAULTPOLICY done echo Done! elif [ -f /proc/net/ip_input ]; then DEFAULTPOLICY=`echo $DEFAULTPOLICY | tr A-Z a-z` if [ "`cat /proc/sys/net/ipv4/ip_forward`" = "0" ]; then echo "Please note that forwarding is disabled in the kernel." >/dev/stderr #/sbin/ipfwadm -F -i deny #Possible to add, but unncessary. fi if [ -n "$BLOCKEDHOSTS" ]; then echo -n Blockedhost blocks... for BLOCKEDHOST in $BLOCKEDHOSTS ; do /sbin/ipfwadm -I -i deny -S $BLOCKEDHOST $LOG /sbin/ipfwadm -O -i deny -S $BLOCKEDHOST $LOG /sbin/ipfwadm -I -i deny -D $BLOCKEDHOST $LOG /sbin/ipfwadm -O -i deny -D $BLOCKEDHOST $LOG done else echo -n No Blockedhost blocks... fi if [ -n "$NOINCOMING" ] && [ -n "$INCOMINGINTERFACES" ]; then echo -n Incoming blocks... for OUTSIDEIF in $INCOMINGINTERFACES ; do for BLOCKPROTO in $NOINCOMING ; do /sbin/ipfwadm -I -i deny -W $OUTSIDEIF -P ${BLOCKPROTO##*/} -D 0/0 ${BLOCKPROTO%%/*} $LOG done done else echo -n No incoming blocks... fi cp -pf /etc/hosts /etc/hosts.bak ; cat $NAMECACHE >>/etc/hosts echo -n Fixed rules... . $BASERULEFILE mv -f /etc/hosts.bak /etc/hosts ALLCHAINS="I O F" for ACHAIN in $ALLCHAINS ; do /sbin/ipfwadm -${ACHAIN} -p $DEFAULTPOLICY done echo Done! else echo This kernel supports neither ipchains nor ipfwadm! >/dev/stderr fi } #End of runstandardfirewall #------------------------------------------------------------------------- # serverportrange subroutine, tries to determine whether the given numeric # port and protocol specify a server port. If so, returns the appropriate # readable representation for that server and sets the comment. # If no corresponding server port is known, both are left blank. #------------------------------------------------------------------------- serverportrange () { #Params: numeric port, proto PARTIALCOMMENT="" ; READABLEPORT="" SERVICELINE="`cat ${SERVICES} | grep "${1}/${2}" | head -n 1`" SERVICE="`echo $SERVICELINE | awk '{print $1}'`" if [ `cat /etc/services | grep "${1}/${2}" | wc -l` -eq 0 ]; then #Merge line from additional services files to /etc/services if necessary if [ -n "$SERVICELINE" ]; then echo -e "$SERVICELINE ##(added by Mason)" >>/etc/services fi fi #if #registered in sunrpc #process sunrpc port, change following to elif if [ "$2" = "udp" ] && [ $1 -ge $TRACEROUTE_BEGIN ] && [ $1 -le $TRACEROUTE_END ]; then READABLEPORT="${TRACEROUTE_BEGIN}:${TRACEROUTE_END}" ; PARTIALCOMMENT="TRACEROUTE/$PROTO" elif [ "$2" = "udp" ] && [ $1 -ge 6970 ] && [ $1 -le 7170 ]; then READABLEPORT="6970:7170" ; PARTIALCOMMENT="RADATA/$PROTO" elif [ "$2" = "udp" ] && [ $1 -ge 6770 ] && [ $1 -le 7170 ]; then READABLEPORT="6770:7170" ; PARTIALCOMMENT="RA30DATA/$PROTO" elif [ "$2" = "tcp" ] && [ $1 -ge $X_BEGIN ] && [ $1 -le $X_END ]; then READABLEPORT="${X_BEGIN}:${X_END}" ; PARTIALCOMMENT="X/$PROTO" elif [ "$2" = "tcp" ] && [ $1 -ge $OPENWIN_BEGIN ] && [ $1 -le $OPENWIN_END ]; then READABLEPORT="${OPENWIN_BEGIN}:${OPENWIN_END}" ; PARTIALCOMMENT="OPENWIN/$PROTO" elif [ "$2" = "tcp" ] && [ $1 -ge $VNCJAVA_BEGIN ] && [ $1 -le $VNCJAVA_END ]; then READABLEPORT="${VNCJAVA_BEGIN}:${VNCJAVA_END}" ; PARTIALCOMMENT="VNCJAVA/$PROTO" elif [ "$2" = "tcp" ] && [ $1 -ge $VNC_BEGIN ] && [ $1 -le $VNC_END ]; then READABLEPORT="${VNC_BEGIN}:${VNC_END}" ; PARTIALCOMMENT="VNC/$PROTO" elif [ "$2" = "tcp" ] && [ $1 -ge $IRC_BEGIN ] && [ $1 -le $IRC_END ]; then READABLEPORT="${IRC_BEGIN}:${IRC_END}" ; PARTIALCOMMENT="IRC/$PROTO" elif [ -n "$SERVICE" ]; then READABLEPORT=${SERVICE} ; PARTIALCOMMENT="${SERVICE}/$PROTO" fi #echo $READABLEPORT #Can't do this because we need to return PARTIALCOMMENT as well. } #end of serverportrange #------------------------------------------------------------------------- # sigexitscript function, called on receipt of SIGHUP #------------------------------------------------------------------------- sigexitscript () { if [ "$NEEDLF" = "YES" ]; then echo >/dev/stderr ; NEEDLF="NO" ; fi echo Received HUP signal, exiting at next pass >/dev/stderr EXITMASON="YES" } #End of sigexitscript #------------------------------------------------------------------------- # settos subroutine, sets the TOS variable for the given port, port range, and protocol. #------------------------------------------------------------------------- # Once Cisco's TOS format is known, that will get set here as well. #params: port, port range, protocol settos () { #http://www.cis.ohio-state.edu/htbin/rfc/rfc1349.html, esp. Appendix 2 #I generally follow what's in the IPCHAINS-Howto and RFC 1349 (with the exception of SMTP), and #chose to put pop3 and imap in the minimize cost category and web as maximize throughput. #I would truly welcome any dialog, public or private, on whether the following set of #TOS settings is appropriate for a general purpose firewall. TOS="" #I specifically do _not_ test for what policy is being used. Even if the policy is currently #reject or deny, the user might change it to accept later in the rule file, in which case the TOS flag should be set. case "${2}/${3}" in "${IRC_BEGIN}:${IRC_END}/tcp") TOS=" -t 0x01 0x10" ;; #IRC Minimize delay esac case "${1}/${3}" in "21/tcp") TOS=" -t 0x01 0x10" ;; #FTP Minimize delay "23/tcp"|"22/tcp"|"513/tcp") TOS=" -t 0x01 0x10" ;; #Telnet,SSH,rlogin Minimize delay "53/udp") TOS=" -t 0x01 0x10" ;; #dns Minimize delay "69/udp") TOS=" -t 0x01 0x10" ;; #tftp Minimize delay "20/tcp"|"25/tcp") TOS=" -t 0x01 0x08" ;; #FTP-data,SMTP Maximize throughput "53/tcp") TOS=" -t 0x01 0x08" ;; #DNS zone transfer Maximize throughput "80/tcp"|"443/tcp"|"563/tcp") TOS=" -t 0x01 0x08" ;; #Web & secure web Maximize throughput "8080/tcp"|"3128/tcp") TOS=" -t 0x01 0x08" ;; #Web Caches Maximize throughput "161/udp") TOS=" -t 0x01 0x04" ;; #SNMP Maximize reliability "119/tcp"|"110/tcp"|"143/tcp") TOS=" -t 0x01 0x02" ;; #NNTP,POP3,IMAP Minimize cost esac } #End of settos