#!/bin/bash #A library of functions and subroutines for Mason #Copyright 1999-2001, William Stearns #See the main Mason script for license and copyright information. #Notes to myself: #Safe to remove curly braces if char following variable is not letter, digit, or underscore. #${ONENET%%/*} = stuff before / #${ONENET##*/} = stuff after / #ipchains -L -n -v -x: bytes 1-8 are the count, 10-19 are bytes, 66-75 is the mark. #export BBB="bbb" ; export ADDCOUNTSCRIPT="-e s/aa/bbbb/ -e s/$BBB/z/" ; echo "aa" | sed $ADDCOUNTSCRIPT # | sed -e 's/\^ [0-9]*//' # ? Expands to the status of the most recently executed foreground pipeline. # - Expands to the current option flags as specified upon invocation, by the set builtin command, or # those set by the shell itself (such as the -i flag). # $ Expands to the process ID of the shell. In a () subshell, it expands to the process ID of the cur- # rent shell, not the subshell. # ! Expands to the process ID of the most recently executed background (asynchronous) command. # For a single background task, this is the PID. # For a backgrounded pipe, this is the PID of the last object in the pipe. # For a ( X | Y | Z... ) & , this is the pid of the encapsulating shell. Killing $! kills that shell, but not inhabitants who get orphaned but keep running. #FIXME - figure out how to add counts to NOINCOMING and BLOCKEDHOSTS rules? #A="`echo | tr '\012' '\001' `" #Produces a Ctrl-A unlikely to exist in normal text #Class A 0-127, Class B 128-191, Class C 192-223, Class D 224-254. #A long time ago that would have been a good way to calculate the netmask automatically. Unfortunately, CIDR makes that useless now. # || logfail $LINENO masonlib: YYYY #### the_command_that_was_supposed_to_run #Last YYYY code used: 0149, use 0150 next if [ -f /usr/lib/samlib/samlib ]; then . /usr/lib/samlib/samlib else echo "/usr/lib/samlib/samlib is missing - please get it from" >/dev/stderr echo "http://www.stearns.org/samlib/" >/dev/stderr echo "Exiting." >/dev/stderr exit 1 fi for ONEFUNC in askYN encompassingnetworkof ipeq iple iplt ipof isdigits \ isnumericip mask2bits mask2cisco networksoverlap seqfunc wrap ; do if ! type $ONEFUNC >/dev/null 2>/dev/null ; then echo "Missing $ONEFUNC , please update samlib from" >/dev/stderr echo "http://www.stearns.org/samlib/" >/dev/stderr echo "Exiting." >/dev/stderr exit 1 fi done MASONVER="1.0.0, 5/12/2002" #------------------------------------------------------------------------- # addcounts procedure, adds the packet counts to the rules in a file. #------------------------------------------------------------------------- addcounts () { #SUDO checked #Params: $* is/are the filespec(s) for the files that need counts added. CKPTADDCOUNTS=" addcounts: Start $*" ; #ckpt $CKPTADDCOUNTS #FIXME - test for iptables || [ -n "`lsmod | grep '^ip_tables '`" ] #Hmmm... will iptables have mark values? if [ -f /proc/net/ip_fwchains ] && [ "$SORTMODE" = "PACKETCOUNTS" ]; then #We can only match up counts to rules if we have mark values, i.e. ipchains. updatecounts HEXMARKS="" ; DECMARKS="" #FIXME - $* instead of $1? for ONEMARK in `grep ' -m ' $1 | sed -e 's/.* -m \([^ ]*\) .*/\1/' || logfail $LINENO masonlib: 0001 grep ' -m ' $1 pipe sed -e 's/.* -m \([^ ]*\) .*/\1/'` ; do case $ONEMARK in 0x*) HEXMARKS="YES" ;; [0-9]*) DECMARKS="YES" ;; esac done CKPTADDCOUNTS=" addcounts: hexmarks $HEXMARKS decmarks $DECMARKS" ; #ckpt $CKPTADDCOUNTS if [ -n "$HEXMARKS$DECMARKS" ]; then #Only do the work if some of the rules have mark values. ADDCOUNTSCRIPT="-e s/[[:space:]]*#\^[[:space:]][0-9]*//" #Erase any old counts ( #^ 12345 ) ADDCOUNTSCRIPT="$ADDCOUNTSCRIPT -e s/[[:space:]]*$//" #Erase any trailing spaces for ONECOUNT in `sed -e 's@ 0x@/0x@' $PACKETCOUNTFILE | grep '/0x'` ; do #packetcount/markvalue pairs if [ "$HEXMARKS" = "YES" ]; then #In short: Add " #^ packetcount" at the end of a line that has " -m 0xmarkvalue " in it. The /../ at the beginning tells sed to only apply this substitution to lines matching this pattern. ADDCOUNTSCRIPT="$ADDCOUNTSCRIPT -e /-m[[:space:]]${ONECOUNT##*/}/s@^\(.*[[:space:]]-m[[:space:]]${ONECOUNT##*/}[[:space:]].*\)@\1SpAcE#^SpAcE${ONECOUNT%%/*}SpAcE@" fi if [ "$DECMARKS" = "YES" ]; then #As above, but match the decimal version "$[0xmarkvalue]". ADDCOUNTSCRIPT="$ADDCOUNTSCRIPT -e /-m[[:space:]]$[${ONECOUNT##*/}]/s@^\(.*[[:space:]]-m[[:space:]]$[${ONECOUNT##*/}][[:space:]].*\)@\1SpAcE#^SpAcE${ONECOUNT%%/*}SpAcE@" fi done CKPTADDCOUNTS=" addcounts: script created, processing files" ; #ckpt $CKPTADDCOUNTS for ONEFILE in $* ; do DUPMARKS=`grep '[[:space:]]-m[[:space:]]' $ONEFILE | sed -e 's/^.*[[:space:]]-m[[:space:]]*\([x0-9]*\).*$/\1/' | uniq -d || logfail $LINENO masonlib: YYYY 0002` if [ -n "$DUPMARKS" ]; then wrap ${WARN}Warning - the following marks are used more than once in $ONEFILE:${NORM} >/dev/stderr for ONEMARK in $DUPMARKS ; do case $ONEMARK in 0x*) echo -n "$ONEMARK = $[ $ONEMARK ] " >/dev/stderr ;; *) echo -n "$ONEMARK " >/dev/stderr ;; esac done echo >/dev/stderr wrap ${WARN}This will give incorrect packet counts.${NORM} >/dev/stderr fi sed $ADDCOUNTSCRIPT -e 's/SpAcE/ /g' $ONEFILE >$ONEFILE.temp || logfail $LINENO masonlib: YYYY 0003 #I couldn't figure out the quoting to allow actual spaces in the ADDCOUNTSCRIPT variable. cat $ONEFILE.temp >$ONEFILE || logfail $LINENO masonlib: YYYY 0004 rm -f $ONEFILE.temp || logfail $LINENO masonlib: YYYY 0005 done fi fi CKPTADDCOUNTS="" } #End of addcounts #------------------------------------------------------------------------- # bits2mask function, returns the netmask for the number of bits parameter. #------------------------------------------------------------------------- bits2mask () { #SUDO checked case $1 in 32|*/32) echo 255.255.255.255 ;; 31|*/31) echo 255.255.255.254 ;; 30|*/30) echo 255.255.255.252 ;; 29|*/29) echo 255.255.255.248 ;; 28|*/28) echo 255.255.255.240 ;; 27|*/27) echo 255.255.255.224 ;; 26|*/26) echo 255.255.255.192 ;; 25|*/25) echo 255.255.255.128 ;; 24|*/24) echo 255.255.255.0 ;; 23|*/23) echo 255.255.254.0 ;; 22|*/22) echo 255.255.252.0 ;; 21|*/21) echo 255.255.248.0 ;; 20|*/20) echo 255.255.240.0 ;; 19|*/19) echo 255.255.224.0 ;; 18|*/18) echo 255.255.192.0 ;; 17|*/17) echo 255.255.128.0 ;; 16|*/16) echo 255.255.0.0 ;; 15|*/15) echo 255.254.0.0 ;; 14|*/14) echo 255.252.0.0 ;; 13|*/13) echo 255.248.0.0 ;; 12|*/12) echo 255.240.0.0 ;; 11|*/11) echo 255.224.0.0 ;; 10|*/10) echo 255.192.0.0 ;; 9|*/9) echo 255.128.0.0 ;; 8|*/8) echo 255.0.0.0 ;; 7|*/7) echo 254.0.0.0 ;; 6|*/6) echo 252.0.0.0 ;; 5|*/5) echo 248.0.0.0 ;; 4|*/4) echo 240.0.0.0 ;; 3|*/3) echo 224.0.0.0 ;; 2|*/2) echo 192.0.0.0 ;; 1|*/1) echo 128.0.0.0 ;; 0|*/0) echo 0.0.0.0 ;; *) echo 255.255.255.255 ;; esac } #End of bits2mask #------------------------------------------------------------------------- # broadcastof function, returns the broadcast of the given ip and netmask. #------------------------------------------------------------------------- broadcastof () { #SUDO checked #The broadcast is (ip bitwise-or (255.255.255.255-netmask)) CKPTBROADCASTOF=" broadcastof: Start $1 mask $2" ; #ckpt $CKPTBROADCASTOF case $2 in 32|255.255.255.255) echo $1 ;; 0|0.0.0.0) echo 255.255.255.255 ;; *) SPLITIP=$1 I1O1=${SPLITIP%%.*} ; SPLITIP=${SPLITIP#*.} I1O2=${SPLITIP%%.*} ; SPLITIP=${SPLITIP#*.} I1O3=${SPLITIP%%.*} ; SPLITIP=${SPLITIP#*.} I1O4=$SPLITIP case $2 in [0-9]|[1-2][0-9]|3[0-2]) SPLITIP=`bits2mask $2` ;; *) SPLITIP=$2 ;; esac I2O1=${SPLITIP%%.*} ; SPLITIP=${SPLITIP#*.} I2O2=${SPLITIP%%.*} ; SPLITIP=${SPLITIP#*.} I2O3=${SPLITIP%%.*} ; SPLITIP=${SPLITIP#*.} I2O4=$SPLITIP echo $[ $I1O1 | (255-$I2O1) ].$[ $I1O2 | (255-$I2O2) ].$[ $I1O3 | (255-$I2O3) ].$[ $I1O4 | (255-$I2O4) ] ;; esac CKPTBROADCASTOF="" } #End of broadcastof #------------------------------------------------------------------------- # catchall procedure. Catch every darn signal. Because I'm _really_ # tired of getting random children nuked. #------------------------------------------------------------------------- catchall () { #SUDO checked #All signals except SIGKILL are caught. trap 'logger SIGHUP' SIGHUP trap 'logger SIGINT' SIGINT trap 'logger SIGQUIT' SIGQUIT trap 'logger SIGILL' SIGILL trap 'logger SIGTRAP' SIGTRAP #Warning. BIG Sandbox talk. #Who the &(%@ decided that SIGIOT needed to be renamed? #Renamed? You've _got_ to be kidding me. #We now have to poll for the name of signal 6. #I absolutely refuse to apologize for the following kludge; trap should accept #both the old and the new name. #GRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR! # trap 'logger SIGIOT' SIGIOT #OK, this is overkill, just use the "trap on 6 that follows # trap 'logger SIGIOT' `kill -l | grep '\W6)' | sed -e 's/.*\W6)//' | awk '{print $1}'` trap 'logger SIGIOT' 6 trap 'logger SIGBUS' SIGBUS trap 'logger SIGFPE' SIGFPE trap 'logger SIGUSR1' SIGUSR1 trap 'logger SIGSEGV' SIGSEGV trap 'logger SIGUSR2' SIGUSR2 trap 'logger SIGPIPE' SIGPIPE trap 'logger SIGALRM' SIGALRM trap 'logger SIGTERM' SIGTERM trap 'logger SIGCHLD' SIGCHLD trap 'logger SIGCONT' SIGCONT trap 'logger SIGSTOP' SIGSTOP trap 'logger SIGTSTP' SIGTSTP trap 'logger SIGTTIN' SIGTTIN trap 'logger SIGTTOU' SIGTTOU trap 'logger SIGURG' SIGURG trap 'logger SIGXCPU' SIGXCPU trap 'logger SIGXFSZ' SIGXFSZ trap 'logger SIGVTALRM' SIGVTALRM trap 'logger SIGPROF' SIGPROF trap 'logger SIGWINCH' SIGWINCH trap 'logger SIGIO' SIGIO trap 'logger SIGPWR' SIGPWR } #End of catchall #------------------------------------------------------------------------- # chainnameof function, returns the form of the chain appropriate for the given DOCOMMAND #------------------------------------------------------------------------- chainnameof () { #SUDO checked if [ "$1" = "" ]; then wrap ${WARN}Missing chain name in chainnameof.${NORM} >/dev/stderr else case $DOCOMMAND in [Ii][Pp][Ff][Ww][Aa][Dd][Mm]) case $1 in [Ii]*) echo "-I" ;; [Ff]*) echo "-F" ;; [Oo]*) echo "-O" ;; esac ;; [Ii][Pp][Cc][Hh][Aa][Ii][Nn][Ss]) case $1 in [Ii][Nn][Pp][Uu][Tt]) echo "input" ;; [Ff][Oo][Rr][Ww][Aa][Rr][Dd]) echo "forward" ;; [Oo][Uu][Tt][Pp][Uu][Tt]) echo "output" ;; *) echo "$1" ;; esac ;; [Ii][Pp][Tt][Aa][Bb][Ll][Ee][Ss]) case $1 in [Ii][Nn][Pp][Uu][Tt]) echo "INPUT" ;; [Ff][Oo][Rr][Ww][Aa][Rr][Dd]) echo "FORWARD" ;; [Oo][Uu][Tt][Pp][Uu][Tt]) echo "OUTPUT" ;; *) echo "$1" ;; esac ;; [Nn][Oo][Nn][Ee]) : ;; esac #Case docommand fi } #End of chainnameof #------------------------------------------------------------------------- #After loading /etc/masonrc, this procedure puts sane values in for everything. #------------------------------------------------------------------------- checkconf () { CKPTCHECKCONF=" checkconf: Start" ; #ckpt $CKPTCHECKCONF echo -n "Check vars..." >/dev/stderr MASONDIR=${MASONDIR:-"/var/lib/mason/"} if [ ! -d $MASONDIR ]; then mkdir --parents $MASONDIR || logfail $LINENO masonlib: 0006 mkdir --parents $MASONDIR chown root.root $MASONDIR || logfail $LINENO masonlib: 0007 chown root.root $MASONDIR chmod 700 $MASONDIR || logfail $LINENO masonlib: 0008 chmod 700 $MASONDIR fi MASONCONF=${MASONCONF:-"/etc/masonrc"} ; if [ ! -f $MASONCONF ]; then touch $MASONCONF || logfail $LINENO masonlib: 0009 touch $MASONCONF ; fi #NAMECACHE support has been disabled #NAMECACHE=${NAMECACHE:-"${MASONDIR}morehosts"} ; if [ ! -f $NAMECACHE ]; then touch $NAMECACHE || logfail $LINENO masonlib: 0010 touch $NAMECACHE ; fi #The NETCACHE file is no longer used; place any customized values in the NETWORKS variable. #NETCACHE=${NETCACHE:-"${MASONDIR}netconvert"} ; if [ ! -f $NETCACHE ]; then touch $NETCACHE || logfail $LINENO masonlib: 0011 touch $NETCACHE ; fi BASERULEFILE=${BASERULEFILE:-"${MASONDIR}baserules"} ; if [ ! -f $BASERULEFILE ]; then touch $BASERULEFILE || logfail $LINENO masonlib: 0012 touch $BASERULEFILE ; fi NEWRULEFILE=${NEWRULEFILE:-"${MASONDIR}newrules"} ; if [ ! -f $NEWRULEFILE ]; then touch $NEWRULEFILE || logfail $LINENO masonlib: 0013 touch $NEWRULEFILE ; fi PACKETCOUNTFILE=${PACKETCOUNTFILE:-"${MASONDIR}packetcounts"} ; if [ ! -f $PACKETCOUNTFILE ]; then touch $PACKETCOUNTFILE || logfail $LINENO masonlib: 0014 touch $PACKETCOUNTFILE ; fi #SYSTEMRULEFILE=${SYSTEMRULEFILE:-"${MASONDIR}systemrules"} ; if [ ! -f $SYSTEMRULEFILE ]; then touch $SYSTEMRULEFILE || logfail $LINENO masonlib: 0015 touch $SYSTEMRULEFILE ; fi PACKETLOGFILE=${PACKETLOGFILE:-"/var/log/messages"} MASONEXE=${MASONEXE:-"/usr/bin/mason"} MASONDECIDE=${MASONDECIDE:-"/usr/bin/mason-decide"} CKPTCHECKCONF=" checkconf: Set up ANSI escape codes" ; #ckpt $CKPTCHECKCONF if [ "$USEANSI" != "NO" ]; then ENH="-e" BLACK="\033[1;30m" RED="\033[1;31m" GREEN="\033[1;32m" YELLOW="\033[1;33m" BLUE="\033[1;34m" PINK="\033[1;35m" TURQUOISE="\033[1;36m" NORM="\033[1;37m" BRIGHT="\033[1;39m" else ENH="" BLACK="" RED="" GREEN="" YELLOW="" BLUE="" PINK="" TURQUOISE="" NORM="" BRIGHT="" fi KEY="$GREEN" WARN="$RED" HEADER="$TURQUOISE" #Ipnatctl isn't used any more. # if [ -z "$IPNATCTLBIN" ]; then # if type -path ipnatctl >/dev/null ; then IPNATCTLBIN=`type -path ipnatctl | head -1` # elif [ -x /sbin/ipnatctl ]; then IPNATCTLBIN='/sbin/ipnatctl' # elif [ -x /usr/local/bin/ipnatctl ]; then IPNATCTLBIN='/usr/local/bin/ipnatctl' # else # IPNATCTLBIN='ipnatctl' # wrap ${WARN}ipnatctl was not found in your path or in /usr/local/bin. You may need to copy it or add an explicit path to it in the following commands.${NORM} >/dev/stderr # fi # fi if [ -z "$IPTABLESBIN" ]; then if type -path iptables >/dev/null ; then IPTABLESBIN=`type -path iptables | head -1` elif [ -x /sbin/iptables ]; then IPTABLESBIN='/sbin/iptables' elif [ -x /usr/local/bin/iptables ]; then IPTABLESBIN='/usr/local/bin/iptables' else IPTABLESBIN='iptables' wrap ${WARN}iptables was not found in your path, in /usr/local/bin or in /sbin. You may need to copy it or add an explicit path to it in the following commands.${NORM} >/dev/stderr fi fi if [ -z "$IPCHAINSBIN" ]; then if type -path ipchains >/dev/null ; then IPCHAINSBIN=`type -path ipchains | head -1` elif [ -x /sbin/ipchains ]; then IPCHAINSBIN='/sbin/ipchains' #elif [ -x /usr/local/bin/ipchains ]; then IPCHAINSBIN='/usr/local/bin/ipchains' else IPCHAINSBIN='ipchains' wrap ${WARN}ipchains was not found in your path or in /sbin. You may need to copy it or add an explicit path to it in the following commands.${NORM} >/dev/stderr fi fi if [ -z "$IPFWADMBIN" ]; then if type -path ipfwadm >/dev/null ; then IPFWADMBIN=`type -path ipfwadm | head -1` elif [ -x /sbin/ipfwadm ]; then IPFWADMBIN='/sbin/ipfwadm' #elif [ -x /usr/local/bin/ipfwadm ]; then IPFWADMBIN='/usr/local/bin/ipfwadm' else IPFWADMBIN='ipfwadm' wrap ${WARN}ipfwadm was not found in your path or in /sbin. You may need to copy it or add an explicit path to it in the following commands.${NORM} >/dev/stderr fi fi if [ ! -d /var/run ]; then mkdir --parents /var/run || logfail $LINENO masonlib: 0016 mkdir --parents /var/run ; fi MASONPIDFILE=${MASONPIDFILE:-"/var/run/mason.pid"} 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"} DEBUG=${DEBUG:-"NO"} BLOCKEDHOSTS=${BLOCKEDHOSTS:-""} DYNIF=${DYNIF:-""} AUTOMASQIF=${AUTOMASQIF:-""} SSP=${SSP:-""} SCP=${SCP:-""} NOINCOMING=${NOINCOMING:-""} NOOUTGOING=${NOOUTGOING:-""} VERBOSE=${VERBOSE:-"YES"} DEFROUTEIFS=`/sbin/route -n | grep '^0\.0\.0\.0[ \t]' | awk '{print $8}' | sort | uniq || logfail $LINENO masonlib: YYYY 0017` INCOMINGINTERFACES=${INCOMINGINTERFACES:-$DEFROUTEIFS} OUTGOINGINTERFACES=${OUTGOINGINTERFACES:-$DEFROUTEIFS} CKPTCHECKCONF=" checkconf: Check policies" ; #ckpt $CKPTCHECKCONF case $NEWRULEPOLICY in #Set LCPOLICY (lower case) and UCPOLICY... [Aa][Cc][Cc][Ee][Pp][Tt]) LCPOLICY="accept" ; UCPOLICY="ACCEPT" ;; [Rr][Ee][Jj][Ee][Cc][Tt]) LCPOLICY="reject" ; UCPOLICY="REJECT" ;; [Dd][Ee][Nn][Yy]) LCPOLICY="deny" ; UCPOLICY="DENY" ;; *) wrap ${WARN}WARNING! NEWRULEPOLICY is neither accept, reject, nor deny in $MASONCONF.${NORM} >/dev/stderr while [ "$LCPOLICY" != "accept" ] && [ "$LCPOLICY" != "reject" ] && [ "$LCPOLICY" != "deny" ] ; do wrap Please choose ${KEY}accept${NORM}, ${KEY}reject${NORM}, or ${KEY}deny${NORM}: >/dev/stderr read NEWRULEPOLICY JUNK || : case "$NEWRULEPOLICY" in [Aa][Cc][Cc][Ee][Pp][Tt]) LCPOLICY="accept" ; UCPOLICY="ACCEPT" ;; [Rr][Ee][Jj][Ee][Cc][Tt]) LCPOLICY="reject" ; UCPOLICY="REJECT" ;; [Dd][Ee][Nn][Yy]) LCPOLICY="deny" ; UCPOLICY="DENY" ;; esac done if echo -n $ENH "Shall I write this value to $MASONCONF(${KEY}Y${NORM}/${KEY}N${NORM})" >/dev/stderr ; askYN >/dev/stderr ; then echo "NEWRULEPOLICY=$NEWRULEPOLICY" >>$MASONCONF fi wrap NEWRULEPOLICY is being reset to \"$NEWRULEPOLICY\". >/dev/stderr ;; esac case $DEFAULTPOLICY in [Aa][Cc][Cc][Ee][Pp][Tt]) DEFAULTPOLICY="accept" ;; [Rr][Ee][Jj][Ee][Cc][Tt]) DEFAULTPOLICY="reject" ;; [Dd][Ee][Nn][Yy]) DEFAULTPOLICY="deny" ;; *) wrap ${WARN}WARNING! DEFAULTPOLICY is neither accept, reject, nor deny in $MASONCONF.${NORM} >/dev/stderr while [ "$DEFAULTPOLICY" != "accept" ] && [ "$DEFAULTPOLICY" != "reject" ] && [ "$DEFAULTPOLICY" != "deny" ] ; do wrap Please choose ${KEY}accept${NORM}, ${KEY}reject${NORM}, or ${KEY}deny${NORM}: >/dev/stderr read DEFAULTPOLICY JUNK || : case "$DEFAULTPOLICY" in [Aa][Cc][Cc][Ee][Pp][Tt]) DEFAULTPOLICY="accept" ;; [Rr][Ee][Jj][Ee][Cc][Tt]) DEFAULTPOLICY="reject" ;; [Dd][Ee][Nn][Yy]) DEFAULTPOLICY="deny" ;; esac done if echo -n $ENH "Shall I write this value to $MASONCONF(${KEY}Y${NORM}/${KEY}N${NORM})" ; askYN ; then echo "DEFAULTPOLICY=$DEFAULTPOLICY" >>$MASONCONF fi wrap DEFAULTPOLICY is being reset to \"$DEFAULTPOLICY\". >/dev/stderr ;; esac CKPTCHECKCONF=" checkconf: Post default policy" ; #ckpt $CKPTCHECKCONF case $LOGGINGPOLICY in [Aa][Cc][Cc][Ee][Pp][Tt]) LOGGINGPOLICY="accept" ;; [Rr][Ee][Jj][Ee][Cc][Tt]) LOGGINGPOLICY="reject" ;; [Dd][Ee][Nn][Yy]) LOGGINGPOLICY="deny" ;; *) LOGGINGPOLICY=$NEWRULEPOLICY ;; esac case $FLUSHEDPOLICY in [Aa][Cc][Cc][Ee][Pp][Tt]) FLUSHEDPOLICY="accept" ;; [Rr][Ee][Jj][Ee][Cc][Tt]) FLUSHEDPOLICY="reject" ;; [Dd][Ee][Nn][Yy]) FLUSHEDPOLICY="deny" ;; *) FLUSHEDPOLICY="accept" ;; esac case $ECHOCOMMAND in [Ii][Pp][Ff][Ww][Aa][Dd][Mm]) ECHOCOMMAND="ipfwadm" ;; [Ii][Pp][Cc][Hh][Aa][Ii][Nn][Ss]) ECHOCOMMAND="ipchains" ;; [Ii][Pp][Cc][Hh][Aa][Ii][Nn][Ss]-[Ss][Aa][Vv][Ee]) ECHOCOMMAND="ipchains-save" ;; [Ii][Pp][Tt][Aa][Bb][Ll][Ee][Ss]) ECHOCOMMAND="iptables" ;; [Cc][Ii][Ss][Cc][Oo]) ECHOCOMMAND="cisco" ;; [Nn][Oo]|[Nn][Oo][Nn][Ee]) ECHOCOMMAND="none" ;; *) if [ -f /proc/net/ip_fwchains ]; then ECHOCOMMAND="ipchains" elif [ -f /proc/net/ip_input ]; then ECHOCOMMAND="ipfwadm" elif [ -n "`lsmod | grep '^ip_tables '`" ]; then ECHOCOMMAND="iptables" else ECHOCOMMAND="ipchains" #Set default here fi ;; esac CKPTCHECKCONF=" checkconf: pre docommand" ; #ckpt $CKPTCHECKCONF case $DOCOMMAND in [Ii][Pp][Ff][Ww][Aa][Dd][Mm]) DOCOMMAND="ipfwadm" if [ ! -f /proc/net/ip_input ]; then wrap ${WARN}WARNING! User has requested ipfwadm, but it appears to be unavailable. Proceeding, but this is not likely to work.${NORM} >/dev/stderr sleep 10 fi if [ ! -x "$IPFWADMBIN" ]; then wrap ${WARN}WARNING! User has requested ipfwadm, but $IPFWADMBIN is not executable. Proceeding, but this is not likely to work.${NORM} >/dev/stderr sleep 10 fi ;; [Ii][Pp][Cc][Hh][Aa][Ii][Nn][Ss]) DOCOMMAND="ipchains" if [ ! -f /proc/net/ip_fwchains ]; then wrap ${WARN}WARNING! User has requested ipchains, but it appears to be unavailable. Proceeding, but this is not likely to work.${NORM} >/dev/stderr sleep 10 fi if [ ! -x "$IPCHAINSBIN" ]; then wrap ${WARN}WARNING! User has requested ipchains, but $IPCHAINSBIN is not executable. Proceeding, but this is not likely to work.${NORM} >/dev/stderr sleep 10 fi ;; [Ii][Pp][Tt][Aa][Bb][Ll][Ee][Ss]) DOCOMMAND="iptables" #FIXME - how to reliably test for kernel iptables support #if [ -z "`lsmod | grep '^ip_tables '`" ]; then # wrap ${WARN}WARNING! User has requested iptables, but it appears to be unavailable. Proceeding, but this is not likely to work.${NORM} >/dev/stderr # sleep 10 #fi if [ ! -x "$IPTABLESBIN" ]; then wrap ${WARN}WARNING! User has requested iptables, but $IPTABLESBIN is not executable. Proceeding, but this is not likely to work.${NORM} >/dev/stderr sleep 10 fi ;; [Nn][Oo]|[Nn][Oo][Nn][Ee]) DOCOMMAND="none" ;; *) if [ -f /proc/net/ip_fwchains ]; then DOCOMMAND="ipchains" if [ ! -x "$IPCHAINSBIN" ]; then wrap ${WARN}WARNING! This kernel uses ipchains, but $IPCHAINSBIN is not executable. Proceeding, but this is not likely to work. Please get a copy of the ipchains binary and place it in /sbin .${NORM} >/dev/stderr sleep 10 fi elif [ -f /proc/net/ip_input ]; then DOCOMMAND="ipfwadm" if [ ! -x "$IPFWADMBIN" ]; then wrap ${WARN}WARNING! This kernel uses ipfwadm, but $IPFWADMBIN is not executable. Proceeding, but this is not likely to work. Please get a copy of the ipfwadm binary and place it in /sbin .${NORM} >/dev/stderr sleep 10 fi #FIXME - find reliable test for kernel iptables support. #elif [ -n "`lsmod | grep '^ip_tables '`" ]; then else DOCOMMAND="iptables" if [ ! -x "$IPTABLESBIN" ]; then wrap ${WARN}WARNING! This kernel uses iptables, but $IPTABLESBIN is not executable. Proceeding, but this is not likely to work. Please get a copy of the iptables binary and place it in /sbin .${NORM} >/dev/stderr sleep 10 fi #else # DOCOMMAND="none" #Well, we cant _do_ any! # wrap ${WARN}WARNING! ipchains, ipfwadm and iptables appear to be unavailable. Proceeding anyways.${NORM} >/dev/stderr # sleep 10 fi ;; esac CKPTCHECKCONF=" checkconf: check heartbeat" ; #ckpt $CKPTCHECKCONF case $HEARTBEAT in [Yy][Ee][Ss]|[Tt][Rr][Uu][Ee]) HEARTBEAT="YES" ;; [Nn][Oo]|[Nn][Oo][Nn][Ee]|[Ff][Aa][Ll][Ss][Ee]) HEARTBEAT="NO" ;; *) HEARTBEAT="YES" ;; esac case $DOBEEP in [Yy][Ee][Ss]|[Tt][Rr][Uu][Ee]) DOBEEP="YES" ;; [Nn][Oo]|[Nn][Oo][Nn][Ee]|[Ff][Aa][Ll][Ss][Ee]) DOBEEP="NO" ;; *) DOBEEP="YES" ;; esac case $SPOOFBLOCKS in [Yy][Ee][Ss]|[Tt][Rr][Uu][Ee]) if [ "$DOCOMMAND" = "ipchains" ] || [ "$DOCOMMAND" = "iptables" ]; then SPOOFBLOCKS="YES" #I believe that the spoof blocking is now safe even in the case of overlapping routes. #The only dangerous case is where packets arrive from a network not in the routing table #for that interface - including asymmetric routing setups like one way satellite/cable. #Even in that case, you can add a specific or default route to that network by hand... #if routesoverlap ; then # wrap ${WARN}Warning! - Spoof blocking has been requested, but the following entries in your routing table overlap and point to different interfaces:${NORM} >/dev/stderr # echo $OVERLAPPINGROUTES >/dev/stderr # wrap ${WARN}Continuing, but communication from machines in the overlapping portion will be disrupted.${NORM} >/dev/stderr # sleep 20 #fi else wrap Spoof blocking is only available under ipchains and iptables. >/dev/stderr SPOOFBLOCKS="YES" fi ;; [Nn][Oo]|[Nn][Oo][Nn][Ee]|[Ff][Aa][Ll][Ss][Ee]) SPOOFBLOCKS="NO" ;; *) SPOOFBLOCKS="YES" #See above note. #if routesoverlap ; then # SPOOFBLOCKS="NO" #else # SPOOFBLOCKS="YES" #fi ;; esac case $LOGBLOCKS in [Yy][Ee][Ss]|[Tt][Rr][Uu][Ee]|-[Ll]|-[Oo]) LOGBLOCKS="-l" ;; [Nn][Oo]|[Nn][Oo][Nn][Ee]|[Ff][Aa][Ll][Ss][Ee]) LOGBLOCKS="" ;; *) LOGBLOCKS="" ;; esac case $SORTMODE in [Pp][Rr][Oo][Tt][Oo][Cc][Oo][Ll]) SORTMODE="PROTOCOL" ;; [Pp][Aa][Cc][Kk][Ee][Tt][Cc][Oo][Uu][Nn][Tt][Ss]) SORTMODE="PACKETCOUNTS" ;; *) SORTMODE="PROTOCOL" ;; esac case $IPCONV in [Hh][Oo][Ss][Tt][Nn][Aa][Mm][Ee]|[Hh][Oo][Ss][Tt]) IPCONV="HOST" ;; [Nn][Ee][Tt][Ww][Oo][Rr][Kk]|[Nn][Ee][Tt]) IPCONV="NETWORK" ;; [Nn][Oo]|[Nn][Oo][Nn][Ee]|[Ff][Aa][Ll][Ss][Ee]) IPCONV="NONE" ;; #[Cc][Uu][Ss][Tt][Oo][Mm]) IPCONV="CUSTOM" ;; *) IPCONV="NETWORK" ;; esac case $HOSTLOOKUP in [Nn][Oo]|[Nn][Oo][Nn][Ee]|[Ff][Aa][Ll][Ss][Ee]) HOSTLOOKUP="NONE" ;; [Ff][Ii][Ll][Ee][Ss]|[Ff][Ii][Ll][Ee][Ss][Oo][Nn][Ll][Yy]) HOSTLOOKUP="FILESONLY" ;; [Ff][Uu][Ll][Ll]|[Yy][Ee][Ss]) HOSTLOOKUP="FULL" ;; *) HOSTLOOKUP="FULL" ;; esac if ! type -path host >/dev/null 2>/dev/null ; then if [ "$HOSTLOOKUP" = "FULL" ]; then wrap ${WARN}The \"host\" utility is not available for resolving IP addresses into hostnames. Until this is available, Mason will only use /etc/hosts for resolution. This warning can be disabled by setting HOSTLOOKUP=\"FILESONLY\" in /etc/masonrc .${NORM} >/dev/stderr HOSTLOOKUP="FILESONLY" fi fi case $GENERALIZETCPACK in [Yy][Ee][Ss]|[Tt][Rr][Uu][Ee]) GENERALIZETCPACK="YES" ;; [Nn][Oo]|[Nn][Oo][Nn][Ee]|[Ff][Aa][Ll][Ss][Ee]) GENERALIZETCPACK="NO" ;; *) GENERALIZETCPACK="NO" ;; esac case $DYNIFMODE in [Aa][Nn][Yy][Aa][Dd][Dd][Rr][Ee][Ss][Ss]) DYNIFMODE="ANYADDRESS" ;; [Ss][Mm][Aa][Ll][Ll][Ee][Ss][Tt][Rr][Aa][Nn][Gg][Ee]) DYNIFMODE="SMALLESTRANGE" ;; [Ss][Pp][Ee][Cc][Ii][Ff][Ii][Cc][Ii][Pp]) DYNIFMODE="SPECIFICIP" ;; *) DYNIFMODE="SMALLESTRANGE" ;; esac CKPTCHECKCONF=" checkconf: Check networks" ; #ckpt $CKPTCHECKCONF TEMPNETWORKS="$NETWORKS" NETWORKS="" #FIXME - sort with the most specific up top? Ugh. for ONENET in $TEMPNETWORKS ; do case $ONENET in #convert /m netmasks over to /n.n.n.n */[0-9]|*/[1-2][0-9]|*/3[0-2]) ONENET="${ONENET%%/*}/`bits2mask ${ONENET##*/}`" ;; esac case $ONENET in RUNTIME.NETWORKS) for RUNTIMENET in `route -n | grep -v '^127\.' | grep -v '^0\.0\.0\.0' | grep '^[0-9]' | awk '{print $1 "/" $3}' || logfail $LINENO masonlib: YYYY 0019` ; do case $RUNTIMENET in */255.255.255.255|*/255.255.255.254|*/255.255.255.252|*/0.0.0.0) : ;; *) NETWORKS="$NETWORKS ${RUNTIMENET%%/*}-`broadcastof ${RUNTIMENET%%/*} ${RUNTIMENET##*/}`/${RUNTIMENET##*/}" ;; esac done ;; */0.0.0.0|*/0) wrap ${WARN}$ONENET is not a valid network for generalization.${NORM} >/dev/stderr ;; *-*/*) NETWORKS="$NETWORKS $ONENET" ;; */*) NETWORKS="$NETWORKS ${ONENET%%/*}-`broadcastof ${ONENET%%/*} ${ONENET##*/}`/${ONENET##*/}" ;; 0|0.*) NETWORKS="$NETWORKS 0.0.0.0-0.255.255.255/255.0.0.0" ;; 127|127.*) NETWORKS="$NETWORKS 127.0.0.0-127.255.255.255/255.0.0.0" ;; *) ROUTEMASK=`route -n | grep "^$ONENET[[:space:]]" | awk '{print $3}' | uniq || logfail $LINENO masonlib: YYYY 0020` if [ `echo "$ROUTEMASK" | wc -l` -eq 1 ]; then NETWORKS="$NETWORKS $ONENET-`broadcastof $ONENET $ROUTEMASK`/$ROUTEMASK" else wrap ${WARN}Unable to determine the netmask for $ONENET. Please put an entry in the form network-broadcast/netmask in the NETWORKS variable in $MASONCONF .${NORM} >/dev/stderr fi ;; esac done unset TEMPNETWORKS if [ -z "$NETWORKS" ]; then #load the NETWORKS variable with all non-trivial networks in the routing table. for RUNTIMENET in `route -n | grep -v '^127\.' | grep -v '^0\.0\.0\.0' | grep '^[0-9]' | awk '{print $1 "/" $3}' || logfail $LINENO masonlib: YYYY 0021` ; do case $RUNTIMENET in */255.255.255.255|*/255.255.255.254|*/255.255.255.252|*/0.0.0.0) : ;; *) NETWORKS="$NETWORKS ${RUNTIMENET%%/*}-`broadcastof ${RUNTIMENET%%/*} ${RUNTIMENET##*/}`/${RUNTIMENET##*/}" ;; #network-broadcast/netmask esac done fi CKPTCHECKCONF=" checkconf: Check ports" ; #ckpt $CKPTCHECKCONF 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 ]} CKPTCHECKCONF=" checkconf: Check minmark" ; #ckpt $CKPTCHECKCONF #FIXME - do this for iptables once iptables supports mark values. if [ -n "$MINMARK" ] && [ -f /proc/net/ip_fwchains ]; then MINMARK=$[ $MINMARK ] #Or should we use `echo $MINMARK | tr -d -c '[0-9]\n'` ? for ONEMARK in `ipchains -L -n -x -v | cut -b 66-75 - | grep '0x' || :` ; do #Formerly YYYY 0022 if [ $MINMARK -le $[ $ONEMARK ] ]; then MINMARK=$[ $ONEMARK + 1 ] ; fi done fi #Remove duplicates CKPTCHECKCONF=" checkconf: Remove dups" ; #ckpt $CKPTCHECKCONF if [ -n "$SSP" ]; then SSP=`echo "$SSP" | tr ' ' '\012' | sort | uniq || logfail $LINENO masonlib: YYYY 0023` ; fi if [ -n "$SCP" ]; then SCP=`echo "$SCP" | tr ' ' '\012' | sort | uniq || logfail $LINENO masonlib: YYYY 0024` ; fi if [ -n "$BLOCKEDHOSTS" ]; then BLOCKEDHOSTS=`echo "$BLOCKEDHOSTS" | tr ' ' '\012' | sort | uniq || logfail $LINENO masonlib: YYYY 0025` ; fi if [ -n "$DYNIF" ]; then DYNIF=`echo "$DYNIF" | tr ' ' '\012' | sort | uniq || logfail $LINENO masonlib: YYYY 0026` ; fi if [ -n "$NOINCOMING" ]; then NOINCOMING=`echo "$NOINCOMING" | tr ' ' '\012' | sort | uniq || logfail $LINENO masonlib: YYYY 0027` ; fi if [ -n "$NOOUTGOING" ]; then NOOUTGOING=`echo "$NOOUTGOING" | tr ' ' '\012' | sort | uniq || logfail $LINENO masonlib: YYYY 0028` ; fi if [ -n "$POISONPROTOCOLS" ]; then POISONPROTOCOLS=`echo "$POISONPROTOCOLS" | tr ' ' '\012' | sort | uniq || logfail $LINENO masonlib: YYYY 0029` ; fi #We can't dedupe this because we need the most specific nets first; a "sort" may destroy this order. #if [ -n "$NETWORKS" ]; then NETWORKS=`echo "$NETWORKS" | tr ' ' '\012' | sort | uniq || logfail $LINENO masonlib: YYYY 0030` ; fi LOWSSHPORT=${LOWSSHPORT:-"1010"} CKPTCHECKCONF=" checkconf: Check editor" ; #ckpt $CKPTCHECKCONF 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 wrap Editor default of $EDITOR taken. >/dev/stderr fi done unset TRYEDITOR || : if [ -z "$EDITOR" ]; then wrap ${WARN}No editor was specified by the EDITOR= variable and this script was unable to find mcedit, pico, vi, jove, nedit or emacs on your system. Please set EDITOR=the_name_of_an_editor in $MASONCONF or your environment and re-start.${NORM} >/dev/stderr sleep 15 fi #no suitable editor found fi if [ "$ECHOCOMMAND" = "cisco" ]; then SINGLEMACHSPEC=" 0.0.0.0" ; CMNT='!' else SINGLEMACHSPEC="/32" ; CMNT="#" fi CKPTCHECKCONF="" } #End of checkconf #------------------------------------------------------------------------- # checksys procedure. Perform some basic checks on the system. #------------------------------------------------------------------------- checksys () { CKPTCHECKSYS=" checksys: Start" ; #ckpt $CKPTCHECKSYS if [ ! -d /proc/1 ]; then wrap ${WARN}WARNING! Proc filesystem not supported or not mounted. Please fix and restart.${NORM} >/dev/stderr sleep 10 exit 0 fi if [ ! -f /proc/net/ip_fwchains ] && [ ! -f /proc/net/ip_input ] && [ -z "`lsmod | grep '^ip_tables '`" ]; then wrap ${WARN}This kernel does not support ipchains, ipfwadm or iptables!${NORM} >/dev/stderr #DOCOMMAND="none" #Should we force to none? fi #A misconstructed path will probably make the checks for basic utils and path fail; make sure the big 4 are in for these tests. PREMASONPATH="$PATH" PATH="/sbin:/usr/sbin:/bin:/usr/bin:$PATH" MISSINGUTILS="" #I don't test for rm (it's an alias on rh), shell builtins, or ipfwadm, ipchains, iptables or host (we test for them later). #LSB compliant distributions provide all of the following except: bash(but sh is required), ifconfig, and route (ps?). is lsmod in LSB? #FIXME - fall back on "ip route", etc.? for ONEUTIL in awk bash cat chmod cut grep head ifconfig lsmod mkdir ps route sed sleep sort tail touch tr uniq wc ; do if ! type -path $ONEUTIL >/dev/null 2>/dev/null ; then MISSINGUTILS="$MISSINGUTILS $ONEUTIL" fi done if [ -n "$MISSINGUTILS" ]; then wrap ${WARN}The following tool/tools do not appear to be available on this system:${NORM} >/dev/stderr wrap $MISSINGUTILS >/dev/stderr wrap ${NORM}You should try to get these before continuing. Press Ctrl-C to fix this, or wait 10 seconds if you want to try continuing anyways - cross your fingers.${NORM} >/dev/stderr sleep 10 fi #Now add in the main 4 bin/sbin path elements if missing. for ONEPATH in `set | grep '^PATH=' | sed -e 's/^PATH=/ /' -e 's/:/ /g' || logfail $LINENO masonlib: YYYY 0031` ; do if [ "$ONEPATH" = "/bin" ]; then BINOK="YES" ; fi if [ "$ONEPATH" = "/sbin" ]; then SBINOK="YES" ; fi if [ "$ONEPATH" = "/usr/bin" ]; then USRBINOK="YES" ; fi if [ "$ONEPATH" = "/usr/sbin" ]; then USRSBINOK="YES" ; fi done PATH=$PREMASONPATH ; unset PREMASONPATH MISSINGPATH="" if [ "$USRBINOK" != "YES" ]; then MISSINGPATH="/usr/bin:$MISSINGPATH" ; fi if [ "$BINOK" != "YES" ]; then MISSINGPATH="/bin:$MISSINGPATH" ; fi if [ "$USRSBINOK" != "YES" ]; then MISSINGPATH="/usr/sbin:$MISSINGPATH" ; fi if [ "$SBINOK" != "YES" ]; then MISSINGPATH="/sbin:$MISSINGPATH" ; fi if [ -n "$MISSINGPATH" ]; then export PATH="$MISSINGPATH$PATH" wrap ${WARN}Note: The following directory/directories was/were not included in your PATH variable: \"$MISSINGPATH\"${NORM} >/dev/stderr fi unset MISSINGPATH #Keep track of all IP's in use every time this is run. for ONEIF in `ifconfig | grep 'Link encap' | awk '{print $1}' || logfail $LINENO masonlib: YYYY 0032` ; do NEWIP=`ipof $ONEIF || logfail $LINENO masonlib: YYYY 0033` if [ ! -f $MASONDIR$ONEIF-ips ]; then touch $MASONDIR$ONEIF-ips ; fi if [ -z "`cat $MASONDIR$ONEIF-ips | grep ^$NEWIP\$`" ]; then if [ -z "$MASONDIR" ]; then wrap ${WARN}Warning - MASONDIR unset in masonlib in checksys.${NORM} >/dev/stderr fi echo $NEWIP >>$MASONDIR$ONEIF-ips fi done #FIXME - add iptables CKPTCHECKSYS=" checksys: Create logchains" ; #ckpt $CKPTCHECKSYS if [ "$DOCOMMAND" = "ipchains" ]; then if [ ! -f /proc/net/ip_fwchains ]; then wrap ${WARN}WARNING! User has requested ipchains, but it appears to be unavailable. Proceeding, but this is not likely to work.${NORM} >/dev/stderr sleep 10 fi if [ ! -x "$IPCHAINSBIN" ]; then wrap ${WARN}WARNING! User has requested ipchains, but $IPCHAINSBIN is not executable. Proceeding, but this is not likely to work.${NORM} >/dev/stderr sleep 10 fi if [ -n "$NOLOGSUFFIX" ]; then for ONECHAIN in `chainnameof input` `chainnameof output` `chainnameof forward` ; do #Was `$IPCHAINSBIN -L -n | grep '^Chain ' | awk '{print $2}'` #case $ONECHAIN in #*$NOLOGSUFFIX) : ;; #*) # For each chain (except for the nolog chains themselves) check that a corresponding nolog chain exists. #Do not use -n - it does not work for this. if ! $IPCHAINSBIN -L $ONECHAIN$NOLOGSUFFIX >/dev/null 2>/dev/null ; then #If nolog chain does not exist #LOGCHAINSEXIST="no" #In the process of being removed; just placing NOLOGSUFFIX="" below is all that's needed. #REMOVEME NOLOGSUFFIX="" wrap ${WARN}The $ONECHAIN chain exists without a corresponding $ONECHAIN$NOLOGSUFFIX chain. For the moment, the \"nolog\" feature will revert to sticking the rules at the top of the original chain.${NORM} >/dev/stderr fi # ;; #esac done #if [ "$LOGCHAINSEXIST" = "no" ]; then NOLOGSUFFIX="" ; fi #In the process of being removed. #REMOVEME fi fi CKPTCHECKSYS=" checksys: Check promisc" ; #ckpt $CKPTCHECKSYS if [ -n "`ifconfig | grep MTU | grep PROMISC`" ]; then wrap ${WARN}Warning: at least one of your interfaces is in promiscuous mode. You are likely to create a lot of rules you did not want. Unless you know this is what you want, you should turn off promiscuous mode on all interfaces. Press Ctrl-c now or this will continue in 15 seconds.${NORM} >/dev/stderr sleep 15 fi CKPTCHECKSYS="" } #End of checksys #------------------------------------------------------------------------- # ckpt (checkpoint) procedure. Logs where we are in Mason in case bash # kills us so we can know where to look for a command with a non-zero # return value. I had hoped to use #trap "echo $LINENO" 0 # but this seems to return the line on which the trap command is placed, # not the line being executed when we exit. # This is only intended for use by developers. #------------------------------------------------------------------------- ckpt () { if [ -f ${MASONDIR}ckpt ]; then echo $* >>${MASONDIR}ckpt ; fi #echo $* >/dev/stderr } #End of ckpt #------------------------------------------------------------------------- # clientportrange function, returns the individual port or range of # ports for the given client port, server port, and protocol parameters. #------------------------------------------------------------------------- clientportrange () { #SUDO checked #I don't make an exception for auth=113/tcp here as we'd never hit this function with a "client" port in /etc/services. CLIENTPORT="$1" ; SERVERPORT="$2" ; PRPROTO="$3" ; ACKFLAG="$4" CPRRETVAL="1024:65535" CKPTCLIENTPORTRANGE=" clientportrange: client $1 server $2 proto $3 ack $4" ; #ckpt $CKPTCLIENTPORTRANGE if [ "$ACKFLAG" = "-k" ]; then ACKFLAG="! -y" ; fi if [ -n "$1" ] && isdigits "$1" ; then #Please use caution if you're trying to group these together! if [ "$GENERALIZETCPACK" = "YES" ] && [ "$PRPROTO" = "tcp" ] && [ "$ACKFLAG" = "! -y" ] && [ "$UCPOLICY" = "ACCEPT" ] && [ $CLIENTPORT -le 1023 ]; then CPRRETVAL="0:1023" elif [ "$GENERALIZETCPACK" = "YES" ] && [ "$PRPROTO" = "tcp" ] && [ "$ACKFLAG" = "! -y" ] && [ "$UCPOLICY" = "MASQ" ] && [ $CLIENTPORT -le 1023 ]; then CPRRETVAL="0:1023" elif [ "$GENERALIZETCPACK" = "YES" ] && [ "$PRPROTO" = "tcp" ] && [ "$ACKFLAG" = "! -y" ] && [ "$UCPOLICY" = "ACCEPT" ] && [ $CLIENTPORT -ge "$PORT_MASQ_BEGIN" ] && [ $CLIENTPORT -le "$PORT_MASQ_END" ]; then CPRRETVAL="$PORT_MASQ_BEGIN:$PORT_MASQ_END" elif [ "$GENERALIZETCPACK" = "YES" ] && [ "$PRPROTO" = "tcp" ] && [ "$ACKFLAG" = "! -y" ] && [ "$UCPOLICY" = "MASQ" ] && [ $CLIENTPORT -ge "$PORT_MASQ_BEGIN" ] && [ $CLIENTPORT -le "$PORT_MASQ_END" ]; then CPRRETVAL="$PORT_MASQ_BEGIN:$PORT_MASQ_END" elif [ "$GENERALIZETCPACK" = "YES" ] && [ "$PRPROTO" = "tcp" ] && [ "$ACKFLAG" = "! -y" ] && [ "$UCPOLICY" = "ACCEPT" ] && [ $CLIENTPORT -ge "1024" ]; then CPRRETVAL="1024:65535" elif [ "$GENERALIZETCPACK" = "YES" ] && [ "$PRPROTO" = "tcp" ] && [ "$ACKFLAG" = "! -y" ] && [ "$UCPOLICY" = "MASQ" ] && [ $CLIENTPORT -ge "1024" ]; then CPRRETVAL="1024:65535" elif [ $CLIENTPORT -ge $PORT_MASQ_BEGIN ] && [ $CLIENTPORT -le $PORT_MASQ_END ]; then CPRRETVAL="$PORT_MASQ_BEGIN:$PORT_MASQ_END" elif [ "$PRPROTO" = "udp" ] && [ $CLIENTPORT -ge $TRACEROUTE_BEGIN ] && [ $CLIENTPORT -le $TRACEROUTE_END ] ; then CPRRETVAL="$TRACEROUTE_BEGIN:$TRACEROUTE_END" elif [ -n "$SERVERPORT" ] && isdigits "$SERVERPORT" && [ $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 [ -n "$SERVERPORT" ] && isdigits "$SERVERPORT" && [ "$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/[Tt][Cc][Pp]|[Ss][Ss][Hh]/[Tt][Cc][Pp]) if [ $CLIENTPORT -le 1023 ]; then while [ "$CLIENTPORT" -lt "$LOWSSHPORT" ]; do LOWSSHPORT=$[ $LOWSSHPORT - 10 ] done CPRRETVAL="$LOWSSHPORT:1023" fi ;; #Some nat boxes replace the client port with a port below 1023 on a dns lookup. Ugh. #FIXME - do we need to do this for tcp too? 53/[Uu][Dd][Pp]|[Dd][Oo][Mm][Aa][Ii][Nn]/[Uu][Dd][Pp]|[Nn][Aa][Mm][Ee][Ss][Ee][Rr][Vv][Ee][Rr]/[Uu][Dd][Pp]) if [ $CLIENTPORT -eq 53 ]; then CPRRETVAL="53" elif [ $CLIENTPORT -ge 20 ] && [ $CLIENTPORT -le 1023 ]; then CPRRETVAL="20:1023" elif [ $CLIENTPORT -le 1023 ]; then #We're down into the chargen/echo range. Ugh. CPRRETVAL="$CLIENTPORT" fi ;; 111/[Tt][Cc][Pp]|sunrpc/[Tt][Cc][Pp]|rpcbind/[Tt][Cc][Pp]|111/[Uu][Dd][Pp]|sunrpc/[Uu][Dd][Pp]|rpcbind/[Tt][Cc][Pp]|635/[Tt][Cc][Pp]|mount/[Tt][Cc][Pp]|635/[Uu][Dd][Pp]|mount/[Uu][Dd][Pp]|2049/[Uu][Dd][Pp]|nfs/[Uu][Dd][Pp]) #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/[Tt][Cc][Pp]|nfs/[Tt][Cc][Pp]) #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 fi echo $CPRRETVAL CKPTCLIENTPORTRANGE="" } #End of clientportrange #------------------------------------------------------------------------- # convicmpcode procedure. Take the icmp (code $1 and subcode $2) parameters # and set COMMENT. In the future, return a readable icmp code name? #------------------------------------------------------------------------- convicmpcode () { #SUDO checked case "$1/$2" in 0/*|echo-reply/*|pong/*) COMMENT="$CMNT Echo reply/icmp ($DIRLETTER)" ;; 3/0|network-unreachable/*) COMMENT="$CMNT Net Unreach/icmp ($DIRLETTER)" ;; 3/1|host-unreachable/*) COMMENT="$CMNT Host Unreach/icmp ($DIRLETTER)" ;; 3/2|protocol-unreachable/*) COMMENT="$CMNT Protocol Unreach/icmp ($DIRLETTER)" ;; 3/3|port-unreachable/*) COMMENT="$CMNT Port Unreach/icmp ($DIRLETTER)" ;; 3/4|fragmentation-needed/*) COMMENT="$CMNT Frag Needed and DF Set/icmp ($DIRLETTER)" ;; 3/5|source-route-failed/*) COMMENT="$CMNT Source Route Failed/icmp ($DIRLETTER)" ;; 3/6|network-unknown/*) COMMENT="$CMNT Dest Net Unknown/icmp ($DIRLETTER)" ;; 3/7|host-unknown/*) COMMENT="$CMNT Dest Host Unknown/icmp ($DIRLETTER)" ;; 3/8) COMMENT="$CMNT Source Host Isolated/icmp ($DIRLETTER)" ;; 3/9|network-prohibited/*) COMMENT="$CMNT Comm with Dest Net Admin Prohib/icmp ($DIRLETTER)" ;; 3/10|host-prohibited/*) COMMENT="$CMNT Comm with Dest Host Admin Prohib/icmp ($DIRLETTER)" ;; 3/11|TOS-network-unreachable/*) COMMENT="$CMNT Dest Net Unreach for TOS/icmp ($DIRLETTER)" ;; 3/12|TOS-host-unreachable/*) COMMENT="$CMNT Dest Host Unreach for TOS/icmp ($DIRLETTER)" ;; 3/13|communication-prohibited/*) COMMENT="$CMNT Comm Admin Prohib/icmp ($DIRLETTER)" ;; 3/14|host-precedence-violation/*) COMMENT="$CMNT Host Precedence Violation/icmp ($DIRLETTER)" ;; 3/15|precedence-cutoff/*) COMMENT="$CMNT Precedence cutoff in effect/icmp ($DIRLETTER)" ;; 3/*|destination-unreachable) COMMENT="$CMNT Dest Unreach/icmp ($DIRLETTER)" ;; 4/*|source-quench/*) COMMENT="$CMNT Source Quench/icmp ($DIRLETTER)" ;; 5/0|network-redirect/*) COMMENT="$CMNT Redir Datagram for (sub)Net/icmp ($DIRLETTER)" ;; 5/1|host-redirect/*) COMMENT="$CMNT Redir Datagram for Host/icmp ($DIRLETTER)" ;; 5/2|TOS-network-redirect/*) COMMENT="$CMNT Redir Datagram for TOS and Net/icmp ($DIRLETTER)" ;; 5/3|TOS-host-redirect/*) COMMENT="$CMNT Redir Datagram for TOS and Host/icmp ($DIRLETTER)" ;; 5/*|redirect/*) COMMENT="$CMNT Redirect/icmp ($DIRLETTER)" ;; 6/*) COMMENT="$CMNT Alt host address/icmp ($DIRLETTER)" ;; 8/*|echo-request/*|ping/*) COMMENT="$CMNT Echo req/icmp ($DIRLETTER)" ;; 9/*|router-advertisement/*) COMMENT="$CMNT Router Advertisement/icmp ($DIRLETTER)" ;; 10/*|router-solicitation/*) COMMENT="$CMNT Router Selection/icmp ($DIRLETTER)" ;; 11/0|ttl-zero-during-transit/*) COMMENT="$CMNT TTL exceeded in Transit/icmp ($DIRLETTER)" ;; 11/1|ttl-zero-during-reassembly/*) COMMENT="$CMNT Frag Reassembly Time Exceeded/icmp ($DIRLETTER)" ;; 11/*|time-exceeded/*|ttl-exceeded/*) COMMENT="$CMNT Time exceeded/icmp ($DIRLETTER)" ;; #FIXME is ip-header-bad a 12/0 (prob) or 12/2? 12/0) COMMENT="$CMNT Pointer indicates error/icmp ($DIRLETTER)" ;; 12/1|required-option-missing/*) COMMENT="$CMNT Missing Required Option/icmp ($DIRLETTER)" ;; 12/2) COMMENT="$CMNT Bad Length/icmp ($DIRLETTER)" ;; 12/*|parameter-problem/*) COMMENT="$CMNT Parameter prob/icmp ($DIRLETTER)" ;; 13/*|timestamp-request/*) COMMENT="$CMNT Timestamp req/icmp ($DIRLETTER)" ;; 14/*|timestamp-reply/*) COMMENT="$CMNT Timestamp reply/icmp ($DIRLETTER)" ;; 15/*) COMMENT="$CMNT Info req/icmp ($DIRLETTER)" ;; 16/*) COMMENT="$CMNT Info reply/icmp ($DIRLETTER)" ;; 17/*|address-mask-request/*) COMMENT="$CMNT Addr Mask req/icmp ($DIRLETTER)" ;; 18/*|address-mask-reply/*) COMMENT="$CMNT Addr Mask reply/icmp ($DIRLETTER)" ;; 30/*) COMMENT="$CMNT Traceroute/icmp ($DIRLETTER)" ;; 31/*) COMMENT="$CMNT Datagram Conv Err/icmp ($DIRLETTER)" ;; 32/*) COMMENT="$CMNT Mobile Host Redir/icmp ($DIRLETTER)" ;; 33/*) COMMENT="$CMNT IPv6 Where-Are-You/icmp ($DIRLETTER)" ;; 34/*) COMMENT="$CMNT IPv6 I-Am-Here/icmp ($DIRLETTER)" ;; 35/*) COMMENT="$CMNT Mobile Registration Req/icmp ($DIRLETTER)" ;; 36/*) COMMENT="$CMNT Mobile Registration Reply/icmp ($DIRLETTER)" ;; 37/*) COMMENT="$CMNT Domain Name Request/icmp ($DIRLETTER)" ;; 38/*) COMMENT="$CMNT Domain Name Reply/icmp ($DIRLETTER)" ;; 39/*) COMMENT="$CMNT SKIP/icmp ($DIRLETTER)" ;; 40/1) COMMENT="$CMNT Photuris unknown SPI/icmp ($DIRLETTER)" ;; 40/2) COMMENT="$CMNT Photuris auth fail/icmp ($DIRLETTER)" ;; 40/3) COMMENT="$CMNT Photuris decrypt fail/icmp ($DIRLETTER)" ;; 40/*) COMMENT="$CMNT Photuris/icmp ($DIRLETTER)" ;; #FIXME - include source and dest IPs for the following? *) COMMENT="$CMNT unknown-$SRCPORT/icmp ($DIRLETTER)" ;; esac } #End of convicmpcode #------------------------------------------------------------------------- # delcounts procedure, deletes the packet counts from the rules in a file. #------------------------------------------------------------------------- delcounts () { #Params: $1 is the filespec for the files that need counts removed. CKPTDELCOUNTS=" delcounts: Start $1" ; #ckpt $CKPTDELCOUNTS for ONEFILE in $1 ; do sed -e 's/[[:space:]]*#\^[[:space:]][0-9]*//' -e 's/[[:space:]]*$//' $ONEFILE >$ONEFILE.temp || logfail $LINENO masonlib: YYYY 0034 cat $ONEFILE.temp >$ONEFILE || logfail $LINENO masonlib: YYYY 0035 rm -f $ONEFILE.temp || logfail $LINENO masonlib: YYYY 0036 done CKPTDELCOUNTS="" } #End of delcounts #------------------------------------------------------------------------- # dorule procedure, adds, inserts, or deletes a rule to/from the running firewall. #------------------------------------------------------------------------- dorule () { #Remember positional parameters >=10 need to be in braces. #Parameters - order is important! : #1. action: AaIiDdFfNnPp (required) (F and N only use $2=chain, P uses $2=chain and ${12}=target) #2. chain or direction (required) #3. interface, or incoming interface for iptables. (optional) #4. null, or outgoing interface for iptables. (optional) #5. protocol lowercase name or number (optional) #6. source address (optional) #7. source port (optional) #8. dest ip (optional) #9. dest port (optional) #10. mark value (optional) #11. ack/syn (optional) #12. target/action (required - or is it? "Accounting" rules?) #13. TOS string (optional, enclose in quotes) #14. log rule (non-null means log, null means don't) #15. special iptables match string (optional) (future: or just additional stuff) #FIXME - specifically check for return code and at least log problems. #FIXME - log anomilies in input parameters. #dorule "AID" "chaindir" "inif" "outif" "proto" "sip" "sport" "dip" "dport" "mark" "synack" "action" "tos" "log" "matchorstuff" #dorule "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" #REMOVEME - DEBUG #echo 1 $1 2 $2 3 $3 4 $4 5 $5 6 $6 7 $7 8 $8 9 $9 10 ${10} 11 ${11} 12 ${12} 13 ${13} 14 ${14} 15 ${15} >>${MASONDIR}masoncrash if [ -d ${MASONDIR}debug ]; then #Internal debugging echo $1 >>${MASONDIR}debug/1 echo $2 >>${MASONDIR}debug/2 echo $3 >>${MASONDIR}debug/3 echo $4 >>${MASONDIR}debug/4 echo $5 >>${MASONDIR}debug/5 echo $6 >>${MASONDIR}debug/6 echo $7 >>${MASONDIR}debug/7 echo $8 >>${MASONDIR}debug/8 echo $9 >>${MASONDIR}debug/9 echo ${10} >>${MASONDIR}debug/10 echo ${11} >>${MASONDIR}debug/11 echo ${12} >>${MASONDIR}debug/12 echo ${13} >>${MASONDIR}debug/13 echo ${14} >>${MASONDIR}debug/14 echo ${15} >>${MASONDIR}debug/15 fi unset CHAINTARGET || : case $DOCOMMAND in #FIXME drop, reject, masq, redirect, return, specific_chain, queue, LOG and other module specific targets? #FIXME - _each_ of the input targets has to be handled in each of the firewall types. [Ii][Pp][Ff][Ww][Aa][Dd][Mm]) #Valid targets: accept, deny, reject, "accept -m", "-r port" case ${12} in [Aa][Cc][Cc][Ee][Pp][Tt]) CHAINTARGET="accept" ;; [Rr][Ee][Jj][Ee][Cc][Tt]) CHAINTARGET="reject" ;; [Dd][Ee][Nn][Yy]|[Dd][Rr][Oo][Pp]) CHAINTARGET="deny" ;; #FIXME - Handle case of $12=INPUTN or other. esac ;; [Ii][Pp][Cc][Hh][Aa][Ii][Nn][Ss]) #Valid targets: ACCEPT, DENY, REJECT, MASQ, REDIRECT, "REDIRECT 0", "REDIRECT port", RETURN, user chains, none at all. case ${12} in [Aa][Cc][Cc][Ee][Pp][Tt]) CHAINTARGET="ACCEPT" ;; [Rr][Ee][Jj][Ee][Cc][Tt]) CHAINTARGET="REJECT" ;; [Dd][Ee][Nn][Yy]|[Dd][Rr][Oo][Pp]) CHAINTARGET="DENY" ;; [Rr][Ee][Tt][Uu][Rr][Nn]) CHAINTARGET="RETURN" ;; esac ;; [Ii][Pp][Tt][Aa][Bb][Ll][Ee][Ss]) #Valid targets: ACCEPT, DROP, QUEUE, RETURN, LOG, none at all. case ${12} in [Aa][Cc][Cc][Ee][Pp][Tt]) CHAINTARGET="ACCEPT" ;; [Rr][Ee][Jj][Ee][Cc][Tt]) CHAINTARGET="REJECT" ;; [Dd][Ee][Nn][Yy]|[Dd][Rr][Oo][Pp]) CHAINTARGET="DROP" ;; [Rr][Ee][Tt][Uu][Rr][Nn]) CHAINTARGET="RETURN" ;; [Ll][Oo][Gg]) CHAINTARGET="LOG" ;; #FIXME - Temporary crutches NoSpoof) CHAINTARGET="NoSpoof" ;; INPUTN) CHAINTARGET="INPUTN" ;; OUTPUTN) CHAINTARGET="OUTPUTN" ;; FORWARDN) CHAINTARGET="FORWARDN" ;; esac ;; [Nn][Oo][Nn][Ee]) : ;; esac #Case docommand case $1 in [Ff]*) case $DOCOMMAND in [Ii][Pp][Ff][Ww][Aa][Dd][Mm]) $IPFWADMBIN `chainnameof $2` -f || logfail $LINENO masonlib: YYYY 0138 ;; [Ii][Pp][Cc][Hh][Aa][Ii][Nn][Ss]) $IPCHAINSBIN -F `chainnameof $2` || logfail $LINENO masonlib: YYYY 0139 ;; [Ii][Pp][Tt][Aa][Bb][Ll][Ee][Ss]) $IPTABLESBIN -F `chainnameof $2` || logfail $LINENO masonlib: YYYY 0140 ;; [Nn][Oo][Nn][Ee]) : ;; esac ;; #Case docommand [Nn]*) case $DOCOMMAND in [Ii][Pp][Ff][Ww][Aa][Dd][Mm]) : ;; #Not possible [Ii][Pp][Cc][Hh][Aa][Ii][Nn][Ss]) $IPCHAINSBIN -N `chainnameof $2` || logfail $LINENO masonlib: YYYY 0141 ;; [Ii][Pp][Tt][Aa][Bb][Ll][Ee][Ss]) $IPTABLESBIN -N `chainnameof $2` || logfail $LINENO masonlib: YYYY 0142 ;; [Nn][Oo][Nn][Ee]) : ;; esac ;; #Case docommand [Pp]*) case $DOCOMMAND in [Ii][Pp][Ff][Ww][Aa][Dd][Mm]) $IPFWADMBIN `chainnameof $2` -p $CHAINTARGET || logfail $LINENO masonlib: YYYY 0143 ;; [Ii][Pp][Cc][Hh][Aa][Ii][Nn][Ss]) $IPCHAINSBIN -P `chainnameof $2` $CHAINTARGET || logfail $LINENO masonlib: YYYY 0144 ;; [Ii][Pp][Tt][Aa][Bb][Ll][Ee][Ss]) $IPTABLESBIN -P `chainnameof $2` $CHAINTARGET || logfail $LINENO masonlib: YYYY 0145 ;; [Nn][Oo][Nn][Ee]) : ;; esac ;; #Case docommand *) case $DOCOMMAND in [Ii][Pp][Ff][Ww][Aa][Dd][Mm]) #FIXME - handle insert if ipfwadm case case $1 in [Aa]*) BUILDRULE="$IPFWADMBIN -a" ;; [Ii]*) BUILDRULE="$IPFWADMBIN -i" ;; [Dd]*) BUILDRULE="$IPFWADMBIN -d" ;; esac BUILDRULE="$BUILDRULE $CHAINTARGET" if [ -n "$3$4" ]; then BUILDRULE="$BUILDRULE -W $3$4" ; fi BUILDRULE="$BUILDRULE `chainnameof $2`" if [ -n "$5" ]; then BUILDRULE="$BUILDRULE -P $5" ; fi if [ -n "$6" ]; then BUILDRULE="$BUILDRULE -S $6 $7" ; else BUILDRULE="$BUILDRULE -S 0/0 $7" ; fi case $5 in #drop icmp subcode in dest port for ipfwadm. [Ii][Cc][Mm][Pp]) if [ -n "$8" ]; then BUILDRULE="$BUILDRULE -D $8" ; fi ;; *) if [ -n "$8" ]; then BUILDRULE="$BUILDRULE -D $8 $9" ; else BUILDRULE="$BUILDRULE -D 0/0 $9" ; fi ;; esac case "${11}" in "-y"|"! -k"|"--syn") BUILDRULE="$BUILDRULE -y" ;; "! -y"|"-k"|"! --syn") BUILDRULE="$BUILDRULE -k" ;; esac if [ -n "${13}" ]; then BUILDRULE="$BUILDRULE -t ${13}" ; fi if [ -n "${14}" ]; then BUILDRULE="$BUILDRULE -o" ; fi eval "$BUILDRULE" || logfail $LINENO masonlib: YYYY 0146 ;; [Ii][Pp][Cc][Hh][Aa][Ii][Nn][Ss]) case $1 in [Aa]*) BUILDRULE="$IPCHAINSBIN -A `chainnameof $2`" ;; [Ii]*) BUILDRULE="$IPCHAINSBIN -I `chainnameof $2` 1" ;; [Dd]*) BUILDRULE="$IPCHAINSBIN -D `chainnameof $2`" ;; esac if [ -n "$3$4" ]; then BUILDRULE="$BUILDRULE -i $3$4" ; fi if [ -n "$5" ]; then BUILDRULE="$BUILDRULE -p $5" ; fi if [ -n "$6$7" ]; then #If either has content if [ -n "$6" ]; then BUILDRULE="$BUILDRULE -s $6 $7" ; else BUILDRULE="$BUILDRULE --sport $7" ; fi fi if [ -n "$8$9" ]; then if [ -n "$8" ]; then BUILDRULE="$BUILDRULE -d $8 $9" ; else BUILDRULE="$BUILDRULE --dport $9" ; fi fi if [ -n "${10}" ]; then BUILDRULE="$BUILDRULE -m ${10}" ; fi case "${11}" in "-y"|"! -k"|"--syn") BUILDRULE="$BUILDRULE -y" ;; "! -y"|"-k"|"! --syn") BUILDRULE="$BUILDRULE ! -y" ;; esac if [ -n "$CHAINTARGET" ]; then BUILDRULE="$BUILDRULE -j $CHAINTARGET" ; fi if [ -n "${13}" ]; then BUILDRULE="$BUILDRULE -t ${13}" ; fi if [ -n "${14}" ]; then BUILDRULE="$BUILDRULE -l" ; fi eval "$BUILDRULE" || logfail $LINENO masonlib: YYYY 0147 ;; [Ii][Pp][Tt][Aa][Bb][Ll][Ee][Ss]) #FIXME - Check for missing $2? case $1 in [Aa]*) BUILDRULE="$IPTABLESBIN -A `chainnameof $2`" ;; [Ii]*) BUILDRULE="$IPTABLESBIN -I `chainnameof $2` 1" ;; [Dd]*) BUILDRULE="$IPTABLESBIN -D `chainnameof $2`" ;; esac if [ -n "$3" ]; then BUILDRULE="$BUILDRULE -i $3" ; fi if [ -n "$4" ]; then BUILDRULE="$BUILDRULE -o $4" ; fi if [ -n "$5" ]; then BUILDRULE="$BUILDRULE -p $5" ; fi if [ -n "$6" ]; then BUILDRULE="$BUILDRULE -s $6" ; fi if [ -n "$8" ]; then BUILDRULE="$BUILDRULE -d $8" ; fi case $5 in [Ii][Cc][Mm][Pp]) if [ -n "$7" ]; then BUILDRULE="$BUILDRULE --icmp-type $7" if [ -n "$9" ]; then BUILDRULE="$BUILDRULE/$9" ; fi fi ;; *) if [ -n "$7" ]; then BUILDRULE="$BUILDRULE --sport $7" ; fi if [ -n "$9" ]; then BUILDRULE="$BUILDRULE --dport $9" ; fi ;; esac #if [ -n "${10}" ]; then BUILDRULE="$BUILDRULE -m ${10}" ; fi #FIXME - mark values later? case "${11}" in "-y"|"! -k"|"--syn") BUILDRULE="$BUILDRULE --syn" ;; "! -y"|"-k"|"! --syn") BUILDRULE="$BUILDRULE ! --syn" ;; esac #if [ -n "${13}" ]; then BUILDRULE="$BUILDRULE -t ${13}" ; fi #FIXME - tos values later? if [ -n "${14}" ]; then eval "$BUILDRULE -j LOG" || logfail $LINENO masonlib: YYYY 0148 $BUILDRULE -j LOG fi if [ -n "$CHAINTARGET" ]; then BUILDRULE="$BUILDRULE -j $CHAINTARGET" ; fi #if [ -n "$DEBUG" ]; then echo $BUILDRULE ; fi eval $SUDO $BUILDRULE || logfail $LINENO masonlib: YYYY 0149 $BUILDRULE ;; [Nn][Oo][Nn][Ee]) : ;; esac #Case docommand ;; esac #Case $1=action } #End of dorule #------------------------------------------------------------------------- #Flush the existing rules so we start with a clean slate. #------------------------------------------------------------------------- flushfirewall () { #SUDO checked CKPTFLUSHFIREWALL=" flushfirewall: Start" ; #ckpt $CKPTFLUSHFIREWALL updatecounts echo -n Flushing... >/dev/stderr #REMOVEME #FLUSHEDPOLICY=`echo $FLUSHEDPOLICY | tr a-z A-Z || logfail $LINENO masonlib: 0037 echo $FLUSHEDPOLICY pipe tr a-z A-Z` #$IPCHAINSBIN -P output $FLUSHEDPOLICY || logfail $LINENO masonlib: 0038 $IPCHAINSBIN -P output $FLUSHEDPOLICY #$IPCHAINSBIN -F output || logfail $LINENO masonlib: 0039 $IPCHAINSBIN -F output #$IPCHAINSBIN -P forward $FLUSHEDPOLICY || logfail $LINENO masonlib: 0040 $IPCHAINSBIN -P forward $FLUSHEDPOLICY #$IPCHAINSBIN -F forward || logfail $LINENO masonlib: 0041 $IPCHAINSBIN -F forward #$IPCHAINSBIN -P input $FLUSHEDPOLICY || logfail $LINENO masonlib: 0042 $IPCHAINSBIN -P input $FLUSHEDPOLICY #$IPCHAINSBIN -F input || logfail $LINENO masonlib: 0043 $IPCHAINSBIN -F input #FLUSHEDPOLICY=`echo $FLUSHEDPOLICY | tr A-Z a-z || logfail $LINENO masonlib: 0046 echo $FLUSHEDPOLICY pipe tr A-Z a-z` #$IPFWADMBIN -O -p $FLUSHEDPOLICY || logfail $LINENO masonlib: 0047 $IPFWADMBIN -O -p $FLUSHEDPOLICY #$IPFWADMBIN -O -f || logfail $LINENO masonlib: 0048 $IPFWADMBIN -O -f #$IPFWADMBIN -F -p $FLUSHEDPOLICY || logfail $LINENO masonlib: 0049 $IPFWADMBIN -F -p $FLUSHEDPOLICY #$IPFWADMBIN -F -f || logfail $LINENO masonlib: 0050 $IPFWADMBIN -F -f #$IPFWADMBIN -I -p $FLUSHEDPOLICY || logfail $LINENO masonlib: 0051 $IPFWADMBIN -I -p $FLUSHEDPOLICY #$IPFWADMBIN -I -f || logfail $LINENO masonlib: 0052 $IPFWADMBIN -I -f for ONECHAIN in output forward input ; do dorule p "$ONECHAIN" '' '' '' '' '' '' '' '' '' "$FLUSHEDPOLICY" '' '' '' || logfail $LINENO masonlib: 0038/0040/0042/0047/0049/0051 dorule f "$ONECHAIN" '' '' '' '' '' '' '' '' '' '' '' '' '' || logfail $LINENO masonlib: 0039/0041/0043/0048/0050/0052 done if [ -f /proc/net/ip_fwchains ] || [ -n "`lsmod | grep '^ip_tables '`" ]; then #Flush the nolog chains if they exist, create them if not. CKPTFLUSHFIREWALL=" flushfirewall: Create or flush nolog chains." ; #ckpt $CKPTFLUSHFIREWALL if [ -n "$NOLOGSUFFIX" ]; then for ONECHAIN in `chainnameof output` `chainnameof forward` `chainnameof input` ; do flushornewchain "$ONECHAIN$NOLOGSUFFIX" done fi CKPTFLUSHFIREWALL=" flushfirewall: Create or flush NoSpoof chain." ; #ckpt $CKPTFLUSHFIREWALL flushornewchain NoSpoof fi echo Done! >/dev/stderr CKPTFLUSHFIREWALL="" } #End of flushfirewall #------------------------------------------------------------------------- #If the chain exists, flush it, otherwise create it. #------------------------------------------------------------------------- flushornewchain () { #SUDO checked if [ -n "$1" ]; then CHAINNAME="`chainnameof $1`" if [ -f /proc/net/ip_fwchains ]; then #REMOVEME #if [ `$SUDO $IPCHAINSBIN -L -n | grep "^Chain $CHAINNAME" | wc -l` -gt 0 ]; then if $SUDO $IPCHAINSBIN -L $CHAINNAME >/dev/null 2>/dev/null ; then #If chain exists $SUDO $IPCHAINSBIN -F $CHAINNAME >/dev/null 2>/dev/null || logfail $LINENO masonlib: 0044/0070/0089/0134 $IPCHAINSBIN -F $CHAINNAME else $SUDO $IPCHAINSBIN -N $CHAINNAME >/dev/null 2>/dev/null || logfail $LINENO masonlib: 0045/0071/0090 $IPCHAINSBIN -N $CHAINNAME fi elif [ -n "`lsmod | grep '^ip_tables '`" ]; then #FIXME, check everywhere. #if iptables -L -n >/dev/null 2>/dev/null ; then echo iptables successful ; fi if $SUDO $IPTABLESBIN -L $CHAINNAME >/dev/null 2>/dev/null ; then #If chain exists $SUDO $IPTABLESBIN -F $CHAINNAME >/dev/null 2>/dev/null || logfail $LINENO masonlib: 0135 $IPTABLESBIN -F $CHAINNAME else $SUDO $IPTABLESBIN -N $CHAINNAME >/dev/null 2>/dev/null || logfail $LINENO masonlib: 0136 $IPTABLESBIN -N $CHAINNAME fi fi fi } #End of flushornewchain #------------------------------------------------------------------------- # generalportrange function, returns the masq/high/low port range of the given port. #------------------------------------------------------------------------- generalportrange () { #SUDO checked #We have already tested for isdigits if [ $1 -eq 0 ]; then echo "0" elif [ $1 -eq 113 ]; then echo "113" elif [ $1 -eq 65535 ]; then echo "65535" elif [ $1 -ge 0 ] && [ $1 -le 1023 ]; then echo "0:1023" elif [ $1 -ge "$PORT_MASQ_BEGIN" ] && [ $1 -le "$PORT_MASQ_END" ]; then echo "$PORT_MASQ_BEGIN:$PORT_MASQ_END" elif [ $1 -ge "1024" ] && [ $1 -le "65535" ]; then echo "1024:65535" fi } #End of generalportrange #------------------------------------------------------------------------- # 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 () { #SUDO checked CKPTGENERALIZEIP=" generalizeip: address $1" ; #ckpt $CKPTGENERALIZEIP case $1 in anywhere|*/0|*/0.0.0.0) GIRETVAL="0/0" ;; */*) GIRETVAL="$1" ;; 22[4-9].*|23[0-9].*) GIRETVAL="`nameof $1`$SINGLEMACHSPEC" ;; #Multicast IP's should be left unique *) GIRETVAL="$1$SINGLEMACHSPEC" ISASSIGNED="NO" for ONEIF in $DYNIF ; do if [ "$1" = "$(eval echo \${$(eval echo ${ONEIF}ADDR)})" ]; then #The nested eval thing is the IP address of that interface. 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|0.0.0.0/32) GIRETVAL="0.0.0.0$SINGLEMACHSPEC" ; ISASSIGNED="YES" ;; 127.0.0.1|127.0.0.1/32) GIRETVAL="localhost$SINGLEMACHSPEC" ; ISASSIGNED="YES" ;; 255.255.255.255|255.255.255.255/32) GIRETVAL="255.255.255.255$SINGLEMACHSPEC" ; ISASSIGNED="YES" ;; *[-A-Za-z]*) GIRETVAL="$1" ; ISASSIGNED="YES" ;; #We should only be converting numeric addresses *) CKPTGENERALIZEIP=" generalizeip: all numeric" ; #ckpt $CKPTGENERALIZEIP #Leave local IP addresses and broadcasts as they are. #FIXME - pull broadcasts from /etc/hosts too? 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" ] && isnumericip $1 ; then #for ONENET in `cat $NETCACHE` ; do #Use NETWORKS now... for ONENET in $NETWORKS ; do if [ "$ISASSIGNED" = "NO" ]; then NETMASK=${ONENET##*/} ; ONENET=${ONENET%/*} BROADCAST=${ONENET##*-} ; ONENET=${ONENET%-*} if iple $ONENET $1 ; then if iple $1 $BROADCAST ; then GIHOLDHOSTLOOKUP="$HOSTLOOKUP" HOSTLOOKUP="FILESONLY" if [ "$ECHOCOMMAND" = "cisco" ]; then GIRETVAL="`nameof $ONENET` `mask2cisco $NETMASK`" else GIRETVAL="`nameof $ONENET`/`mask2bits $NETMASK`" fi HOSTLOOKUP="$GIHOLDHOSTLOOKUP" ISASSIGNED="YES" fi fi fi done fi ;; esac if [ "$ISASSIGNED" = "NO" ]; then GIRETVAL="0/0" ; ISASSIGNED="YES" ; fi ;; NONE) ;; #CUSTOM) ;; esac fi ;; esac echo $GIRETVAL CKPTGENERALIZEIP="" } #End of generalizeip #------------------------------------------------------------------------- # loadconf function, called at start and on receipt of SIGUSR1 #------------------------------------------------------------------------- loadconf () { CKPTLOADCONF=" loadconf: start" ; #ckpt $CKPTLOADCONF 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 || logfail $LINENO masonlib: 0053 . $MASONCONF else touch $MASONCONF || logfail $LINENO masonlib: 0054 touch $MASONCONF chmod 700 $MASONCONF || logfail $LINENO masonlib: 0055 chmod 700 $MASONCONF wrap ${WARN}WARNING - Unable to load options, $MASONCONF does not exist.${NORM} >/dev/stderr #Not a problem if colors unset. fi CKPTLOADCONF=" loadconf: post load $MASONCONF" ; #ckpt $CKPTLOADCONF checkconf echo -n "Load IPs, networks and nameservers..." >/dev/stderr #set ALLIPS and ALLBCS (broadcasts) ALLIPS="`ifconfig | grep 'inet addr' | sed -e 's/.*addr://' -e 's/ .*//' || logfail $LINENO masonlib: YYYY 0056` \ `route -n | grep '^[0-9\.]* *[0-9\.]* *255\.255\.255\.255' | awk '{print $1}' || logfail $LINENO masonlib: YYYY 0057`" ALLBCS=`ifconfig | grep 'Bcast' | sed -e 's/.*Bcast://' -e 's/ .*//' || logfail $LINENO masonlib: YYYY 0058` #FIXME: ALLBCS includes net addresses too? #FIXME - if netcache and the current netlist (below) are identical, briefly warn then delete netcache. if [ -n "$NETCACHE" ] && [ -n "`grep -v '^$' $NETCACHE || logfail $LINENO masonlib: YYYY 0059`" ]; then wrap ${WARN}WARNING! The $NETCACHE file is no longer used by Mason. Please transfer all values from this file to the NETWORKS variable in $MASONCONF.${NORM} >/dev/stderr fi #rm -f $NETCACHE ; touch $NETCACHE ; chmod 700 $NETCACHE CKPTLOADCONF=" loadconf: about to load dnsservers" ; #ckpt $CKPTLOADCONF DNSSERVERS=`grep '^nameserver' /etc/resolv.conf | awk '{print $2}' || logfail $LINENO masonlib: YYYY 0060` echo "Done." >/dev/stderr SIGGED="YES" #We received a signal #FIXME - put killall -SIGUSR1 mason in ip-up... CKPTLOADCONF="" } #End of loadconf #------------------------------------------------------------------------- # logfail subroutine, record the fact that a command returned non-true. #------------------------------------------------------------------------- logfail () { #To use, add: # || logfail $LINENO filename some words that will identify what bombed #at the end of any command that could conceivably return false. #DO NOT send ANYTHING to stdout - this function is used inside backticks. Use stderr if necessary. #Don't assume everything has been initialized yet. LOGRETVAL="$?" #This should be placed first to preserve the return code of the failed command. TEMPMASONDIR=${MASONDIR:-"/var/lib/mason/"} #FIXME - test if masoncrash is writable, fall back to stderr if not? wrap "`date` - $MASONVER" >>${TEMPMASONDIR}masoncrash case "$1" in 0|1) shift ;; [0-9]*) echo -n "Line $1, " >>${TEMPMASONDIR}masoncrash ; shift ;; esac wrap Caught failure \($LOGRETVAL\) on: $* >>${TEMPMASONDIR}masoncrash return 0 #True; this makes bash happy } #End of logfail #------------------------------------------------------------------------- # nameof function, returns the hostname from the IP address parameter. #------------------------------------------------------------------------- nameof () { #SUDO checked #Use /etc/hosts and the "host" command to look up names for source and destination addresses. CKPTNAMEOF=" nameof: Start" ; #ckpt $CKPTNAMEOF NAMEOFRETVAL="" #FIXME - Should we just drop everything after the /? NAMEOFINPUT=${1%%/32} CKPTNAMEOF=" nameof: check for dynifs" ; #ckpt $CKPTNAMEOF for ONEIF in $DYNIF ; do if [ "$NAMEOFINPUT" = "$(eval echo \${$(eval echo ${ONEIF}ADDR)})" ]; then #The nested eval thing is the IP address of that interface. NAMEOFRETVAL="\${${ONEIF}ADDR}" #Nameof is supposed to return something _without_ a /32, but the ppp0ADDR macros _have_ the /32. It's OK because GI already does its own DYNIF checking, and the only other place that uses it is in mason/comment2. #LINEHASDYNAMIC="YES" #Not exported from a function - not currently used fi done if [ -z "$NAMEOFRETVAL" ]; then if [ "$HOSTLOOKUP" = "FILESONLY" ] || [ "$HOSTLOOKUP" = "FULL" ]; then #The () subshell below is the equivalent of: "tail --lines=1 | awk '{print $2}'" ONEHOSTNAME=`egrep "^$NAMEOFINPUT[^0-9]" /etc/hosts | ( while read F1 F2 FREST ; do LLF2=$F2 ; done ; if [ -n "$LLF2" ]; then echo $LLF2 ; fi ) || logfail $LINENO masonlib: YYYY 0061` if [ -n "$ONEHOSTNAME" ]; then NAMEOFRETVAL="$ONEHOSTNAME" fi fi fi if [ -z "$NAMEOFRETVAL" ]; then case $NAMEOFINPUT in */0|*/0.0.0.0) NAMEOFRETVAL="0/0" ;; esac fi CKPTNAMEOF=" nameof: reverse host lookup" ; #ckpt $CKPTNAMEOF if [ "$HOSTLOOKUP" = "FULL" ] && [ -z "$NAMEOFRETVAL" ]; then #if ! reservedip $NAMEOFINPUT ; then #One approach might be to avoid looking up rfc1918 addresses entirely #FIXME - don't run host twice if host -t ptr $NAMEOFINPUT >/dev/null 2>/dev/null ; then ONEHOSTNAME=`host -t ptr $NAMEOFINPUT 2>/dev/null | grep 'domain name pointer' | head --lines=1 | sed -e 's/.* //' || logfail $LINENO masonlib: YYYY 0062` #do double reverse, see if same as input ip, only _then_ assign. #I specifically removed the head --lines=1 because I don't want to provide a round-robin name. ONEIPADDR=`host -t a $ONEHOSTNAME 2>/dev/null | grep 'has address' | sed -e 's/.* //' || logfail $LINENO masonlib: YYYY 0133` if [ -n "$ONEHOSTNAME" ] && [ "$NAMEOFINPUT" = "$ONEIPADDR" ] && [ "$ONEHOSTNAME" != "read-rfc1918-for-details.iana.net" ]; then #Grrr... NAMEOFRETVAL="$ONEHOSTNAME" fi fi #fi fi if [ -z "$NAMEOFRETVAL" ]; then NAMEOFRETVAL=$NAMEOFINPUT ; fi echo $NAMEOFRETVAL CKPTNAMEOF="" } #End of nameof #------------------------------------------------------------------------- # networkof function, returns the network of the given ip and netmask. #------------------------------------------------------------------------- networkof () { #SUDO checked #Basically, the network is (ip bitwise-and netmask) CKPTNETWORKOF=" networkof: Start $1 mask $2" ; #ckpt $CKPTNETWORKOF case $2 in 32|255.255.255.255) echo $1 ;; 0|0.0.0.0) echo 0.0.0.0 ;; *) SPLITIP=$1 I1O1=${SPLITIP%%.*} ; SPLITIP=${SPLITIP#*.} I1O2=${SPLITIP%%.*} ; SPLITIP=${SPLITIP#*.} I1O3=${SPLITIP%%.*} ; SPLITIP=${SPLITIP#*.} I1O4=$SPLITIP case $2 in [0-9]|[1-2][0-9]|3[0-2]) SPLITIP=`bits2mask $2` ;; *) SPLITIP=$2 ;; esac I2O1=${SPLITIP%%.*} ; SPLITIP=${SPLITIP#*.} I2O2=${SPLITIP%%.*} ; SPLITIP=${SPLITIP#*.} I2O3=${SPLITIP%%.*} ; SPLITIP=${SPLITIP#*.} I2O4=$SPLITIP echo $[ $I1O1 & $I2O1 ].$[ $I1O2 & $I2O2 ].$[ $I1O3 & $I2O3 ].$[ $I1O4 & $I2O4 ] ;; esac CKPTNETWORKOF="" } #End of networkof #------------------------------------------------------------------------- # oneblockproto procedure, blocks a single protocol from coming in on the given interface. #------------------------------------------------------------------------- oneblockproto () { #SUDO checked #Parameters: Protocol, (optional)Interface case $BLOCKPROTO in #${MINMARK:+"-m"} $MINMARK ; if [ -n "$MINMARK" ]; then MINMARK=$[$MINMARK+1] ; fi *.*/[Ii][Cc][Mm][Pp]) ICMPBOTH=${BLOCKPROTO%%/*} ; ICMPCODE=${ICMPBOTH%%.*} ; ICMPSUBCODE=${ICMPBOTH##*.} #REMOVEME #$IPCHAINSBIN -I input -i $2 -p icmp -s 0/0 $ICMPCODE -d 0/0 $ICMPSUBCODE -j DENY $LOGBLOCKS || logfail $LINENO masonlib: YYYY 0079 #Cannot do subcode on ipfwadm icmp. #$IPFWADMBIN -I -i deny -W $2 -P icmp -S 0/0 $ICMPCODE $LOGBLOCKS || logfail $LINENO masonlib: YYYY 0101 dorule i input "$2" '' icmp '' "$ICMPCODE" '' "$ICMPSUBCODE" '' '' deny '' "$LOGBLOCKS" '' || logfail $LINENO masonlib: YYYY 0079/0101 ;; */[Ii][Cc][Mm][Pp]) #REMOVEME #$IPCHAINSBIN -I input -i $2 -p icmp -s 0/0 ${BLOCKPROTO%%/*} -j DENY $LOGBLOCKS || logfail $LINENO masonlib: YYYY 0080 #$IPFWADMBIN -I -i deny -W $2 -P icmp -S 0/0 ${BLOCKPROTO%%/*} $LOGBLOCKS || logfail $LINENO masonlib: YYYY 0102 dorule i input "$2" '' icmp '' "${BLOCKPROTO%%/*}" '' '' '' '' deny '' "$LOGBLOCKS" "" || logfail $LINENO masonlib: YYYY 0080/0102 ;; 113/[Tt][Cc][Pp]|[Aa][Uu][Tt][Hh]/[Tt][Cc][Pp]) #REMOVEME #$IPCHAINSBIN -I input -i $2 -p tcp -d 0/0 ${BLOCKPROTO%%/*} -y -j REJECT $LOGBLOCKS || logfail $LINENO masonlib: YYYY 0081 #$IPFWADMBIN -I -i reject -W $2 -P tcp -D 0/0 ${BLOCKPROTO%%/*} -y $LOGBLOCKS || logfail $LINENO masonlib: YYYY 0103 dorule i input "$2" '' tcp '' '' '' "${BLOCKPROTO%%/*}" '' -y reject '' "$LOGBLOCKS" '' || logfail $LINENO masonlib: YYYY 0081/0103 ;; */[Tt][Cc][Pp]) #REMOVEME #$IPCHAINSBIN -I input -i $2 -p tcp -d 0/0 ${BLOCKPROTO%%/*} -y -j DENY $LOGBLOCKS || logfail $LINENO masonlib: YYYY 0082 #$IPFWADMBIN -I -i deny -W $2 -P tcp -D 0/0 ${BLOCKPROTO%%/*} -y $LOGBLOCKS || logfail $LINENO masonlib: YYYY 0104 dorule i input "$2" '' tcp '' '' '' "${BLOCKPROTO%%/*}" '' -y deny '' "$LOGBLOCKS" '' || logfail $LINENO masonlib: YYYY 0082/0104 ;; */*) #REMOVEME #$IPCHAINSBIN -I input -i $2 -p ${BLOCKPROTO##*/} -d 0/0 ${BLOCKPROTO%%/*} -j DENY $LOGBLOCKS || logfail $LINENO masonlib: YYYY 0083 #$IPFWADMBIN -I -i deny -W $2 -P ${BLOCKPROTO##*/} -D 0/0 ${BLOCKPROTO%%/*} $LOGBLOCKS || logfail $LINENO masonlib: YYYY 0105 dorule i input "$2" '' "${BLOCKPROTO##*/}" '' '' '' "${BLOCKPROTO%%/*}" '' '' deny '' "$LOGBLOCKS" '' || logfail $LINENO masonlib: YYYY 0083/0105 ;; *) #REMOVEME #$IPCHAINSBIN -I input -i $2 -p ${BLOCKPROTO##*/} -j DENY $LOGBLOCKS || logfail $LINENO masonlib: YYYY 0084 #$IPFWADMBIN -I -i deny -W $2 -P ${BLOCKPROTO##*/} $LOGBLOCKS || logfail $LINENO masonlib: YYYY 0106 dorule i input "$2" '' "${BLOCKPROTO##*/}" '' '' '' '' '' '' deny '' "$LOGBLOCKS" '' || logfail $LINENO masonlib: YYYY 0084/0106 ;; esac } #End of oneblockproto #------------------------------------------------------------------------- # port2ciscoport function, returns the individual port or range of # ports for the given port/port range and protocol parameters in cisco format. #------------------------------------------------------------------------- port2ciscoport () { #SUDO checked #Parameters: $1 is the port number, $2 is the protocol #FIXME - convert /udp, /tcp, /icmp over to case insensitive checks CKPTPORT2CISCOPORT=" port2ciscoport: Start" ; #ckpt $CKPTPORT2CISCOPORT PCPRETVAL="" case "$1/$2" in 0:1023/*) PCPRETVAL=" lt 1024" ;; 1024:65535/*) PCPRETVAL=" gt 1023" ;; #FIXME - this does not drop the protocol, I think. *:*/*) PCPRETVAL=" range ${1%%:*} ${1##*:}" ;; 179/tcp|bgp/tcp) PCPRETVAL=" eq bgp" ;; 19/tcp|chargen/tcp|ttyst/tcp|source/tcp) PCPRETVAL=" eq chargen" ;; 13/tcp|daytime/tcp) PCPRETVAL=" eq daytime" ;; 9/tcp|discard/tcp|sink/tcp|null/tcp) PCPRETVAL=" eq discard" ;; 53/tcp|domain/tcp|dns/tcp) PCPRETVAL=" eq domain" ;; 7/tcp|echo/tcp) PCPRETVAL=" eq echo" ;; 79/tcp|finger/tcp) PCPRETVAL=" eq finger" ;; 21/tcp|ftp/tcp) PCPRETVAL=" eq ftp" ;; 20/tcp|ftp-data/tcp) PCPRETVAL=" eq ftp-data" ;; 70/tcp|gopher/tcp) PCPRETVAL=" eq gopher" ;; 101/tcp|hostname/tcp|hostnames/tcp) PCPRETVAL=" eq hostname" ;; 194/tcp|irc/tcp) PCPRETVAL=" eq irc" ;; 543/tcp|klogin/tcp) PCPRETVAL=" eq klogin" ;; 544/tcp|kshell/tcp|krcmd/tcp) PCPRETVAL=" eq kshell" ;; 515/tcp|lpd/tcp|printer/tcp|spooler/tcp) PCPRETVAL=" eq lpd" ;; 109/tcp|pop-2/tcp|pop2/tcp|postoffice/tcp) PCPRETVAL=" eq pop2" ;; 110/tcp|pop-3/tcp|pop3/tcp) PCPRETVAL=" eq pop3" ;; 25/tcp|smtp/tcp) PCPRETVAL=" eq smtp" ;; 111/tcp|sunrpc/tcp|portmapper/tcp) PCPRETVAL=" eq sunrpc" ;; #I think the following was a mistake. Cisco's docs show a TCP syslog - I dont think there is one. syslog/tcp) PCPRETVAL=" eq syslog" ;; 65/tcp|tacacs-ds/tcp) PCPRETVAL=" eq tacacs-ds" ;; 517/tcp|talk/tcp) PCPRETVAL=" eq talk" ;; 23/tcp|telnet/tcp) PCPRETVAL=" eq telnet" ;; 37/tcp|time/tcp|timserver/tcp) PCPRETVAL=" eq time" ;; 540/tcp|uucp/tcp|uucpd/tcp) PCPRETVAL=" eq uucp" ;; 43/tcp|whois/tcp|nicname/tcp) PCPRETVAL=" eq whois" ;; 80/tcp|www/tcp|http/tcp) PCPRETVAL=" eq www" ;; 512/udp|biff/udp|comsat/udp) PCPRETVAL=" eq biff" ;; 68/udp|bootpc/udp) PCPRETVAL=" eq bootpc" ;; 67/udp|bootps/udp) PCPRETVAL=" eq bootps" ;; 9/udp|discard/udp|sink/udp|null/udp) PCPRETVAL=" eq discard" ;; 53/udp|dns/udp|domain/udp) PCPRETVAL=" eq dns" ;; 90/udp|dnsix/udp) PCPRETVAL=" eq dnsix" ;; 7/udp|echo/udp) PCPRETVAL=" eq echo" ;; 434/udp|mobile-ip/udp|mobileip-agent/udp) PCPRETVAL=" eq mobile-ip" ;; 42/udp|nameserver/udp|name/udp) PCPRETVAL=" eq nameserver" ;; 138/udp|netbios-dgm/udp) PCPRETVAL=" eq netbios-dgm" ;; 137/udp|netbios-ns/udp) PCPRETVAL=" eq netbios-ns" ;; 123/udp|ntp/udp) PCPRETVAL=" eq ntp" ;; 520/udp|rip/udp|route/udp|router/udp|routed/udp) PCPRETVAL=" eq rip" ;; 161/udp|snmp/udp) PCPRETVAL=" eq snmp" ;; 162/udp|snmptrap/udp|snmp-trap/udp) PCPRETVAL=" eq snmptrap" ;; 111/udp|sunrpc/udp|portmapper/udp) PCPRETVAL=" eq sunrpc" ;; 514/udp|syslog/udp) PCPRETVAL=" eq syslog" ;; 65/udp|tacacs-ds/udp) PCPRETVAL=" eq tacacs-ds" ;; 517/udp|talk/udp) PCPRETVAL=" eq talk" ;; 69/udp|tftp/udp) PCPRETVAL=" eq tftp" ;; 37/udp|time/udp) PCPRETVAL=" eq time" ;; 513/udp|who/udp|whod/udp) PCPRETVAL=" eq who" ;; 177/udp|xdmcp/udp) PCPRETVAL=" eq xdmcp" ;; *) if isdigits $1 ; then PCPRETVAL=" eq $1" else #FIXME - convert alpha port name ("telnet") back to the port number ("23") for Cisco. PCPRETVAL=" eq $1" fi ;; esac echo "$PCPRETVAL" CKPTPORT2CISCOPORT="" } #End of port2ciscoport #------------------------------------------------------------------------- # preexit procedure. Called on receipt of signal 0 (exiting) from bash #------------------------------------------------------------------------- #We check to see if any of the checkpoint variables are still set; if so, #the script probably crashed before finishing that module. Bitch to the user. #Be careful of system variables; they may not be loaded yet. preexit () { #ZZZZ #FIXME - test for masoncrash writable? if [ -n "$CKPTMGT$CKPTMASON$CKPTCHECKSYS$CKPTCLIENTPORTRANGE$CKPTGENERALIZEIP$CKPTIPLE$CKPTIPLT$CKPTISNUMERICIP$CKPTLOADCONF$CKPTSERVERPORTRANGE$CKPTADDCOUNTS$CKPTNAMEOF$CKPTBROADCASTOF$CKPTCHECKCONF$CKPTDELCOUNTS$CKPTFLUSHFIREWALL$CKPTPORT2CISCOPORT$CKPTPROTONUM2NAME$CKPTRULETAG$CKPTRUNFIREWALL$CKPTSETTOS$CKPTSORTRULEFILE$CKPTUNIQRULEFILE$CKPTUPDATECOUNTS$CKPTNETWORKOF" ]; then if [ -z "$MASONDIR" ]; then MASONDIR="/var/lib/mason/" ; fi echo >/dev/stderr wrap ${WARN}Abnormal exit from $0 $MASONVER.${NORM} >/dev/stderr wrap The author, William Stearns, would be very grateful if you would email the following information to wstearns@pobox.com, as well as anything else that you think might be relevant. It would help make future versions of mason more stable. The easiest way to do this is to attach ${MASONDIR}masoncrash to a message to wstearns@pobox.com . >/dev/stderr echo >/dev/stderr date >/dev/stderr wrap Most recent checkpoints: >/dev/stderr wrap $CKPTMGT $CKPTMASON $CKPTCHECKSYS $CKPTCLIENTPORTRANGE \ $CKPTGENERALIZEIP $CKPTIPLE $CKPTIPLT $CKPTISNUMERICIP $CKPTLOADCONF \ $CKPTSERVERPORTRANGE $CKPTADDCOUNTS $CKPTNAMEOF $CKPTBROADCASTOF \ $CKPTCHECKCONF $CKPTDELCOUNTS $CKPTFLUSHFIREWALL $CKPTPORT2CISCOPORT \ $CKPTPROTONUM2NAME $CKPTRULETAG $CKPTRUNFIREWALL \ $CKPTSETTOS $CKPTSORTRULEFILE \ $CKPTUNIQRULEFILE $CKPTUPDATECOUNTS $CKPTNETWORKOF >/dev/stderr wrap End of checkpoints. >/dev/stderr echo >/dev/stderr wrap This file was created as a result of a crash of $0 $MASONVER. It was created automatically. Please mail it to wstearns@pobox.com >>${MASONDIR}masoncrash date >>${MASONDIR}masoncrash wrap Most recent checkpoints: >>${MASONDIR}masoncrash wrap $CKPTMGT $CKPTMASON $CKPTCHECKSYS $CKPTCLIENTPORTRANGE \ $CKPTGENERALIZEIP $CKPTIPLE $CKPTIPLT $CKPTISNUMERICIP $CKPTLOADCONF \ $CKPTSERVERPORTRANGE $CKPTADDCOUNTS $CKPTNAMEOF $CKPTBROADCASTOF \ $CKPTCHECKCONF $CKPTDELCOUNTS $CKPTFLUSHFIREWALL $CKPTPORT2CISCOPORT \ $CKPTPROTONUM2NAME $CKPTRULETAG $CKPTRUNFIREWALL \ $CKPTSETTOS $CKPTSORTRULEFILE \ $CKPTUNIQRULEFILE $CKPTUPDATECOUNTS $CKPTNETWORKOF >>${MASONDIR}masoncrash wrap End of checkpoints. >>${MASONDIR}masoncrash echo >>${MASONDIR}masoncrash if [ -n "$MASONCONF" ]; then if [ -e "$MASONCONF" ]; then wrap Masonconf: >>${MASONDIR}masoncrash if type -path sed >/dev/null 2>/dev/null && type -path grep >/dev/null 2>/dev/null ; then cat $MASONCONF | sed -e 's/#.*//' | grep -v '^$' >>${MASONDIR}masoncrash || : else cat $MASONCONF >>${MASONDIR}masoncrash fi wrap End of Masonconf. >>${MASONDIR}masoncrash else wrap No Masonconf found. >>${MASONDIR}masoncrash fi else wrap Masonconf environment variable not set. >>${MASONDIR}masoncrash fi echo >>${MASONDIR}masoncrash wrap System details: >>${MASONDIR}masoncrash wrap It is not necessarily a problem if some of these are missing. >>${MASONDIR}masoncrash for ONESYSFILE in /sbin/ipchains /sbin/ipfwadm /proc/net/ip_input /proc/net/ip_fwchains /sbin/iptables /usr/local/bin/iptables ; do ls -ald $ONESYSFILE >>${MASONDIR}masoncrash 2>&1 || : done lsmod >>${MASONDIR}masoncrash 2>&1 || : mount -t proc >>${MASONDIR}masoncrash 2>&1 || : echo >>${MASONDIR}masoncrash fi } #End of preexit #------------------------------------------------------------------------- # protonum2name procedure, sets PROTO to the readable protocol name from protocol number and sets IGNOREPORT. #------------------------------------------------------------------------- protonum2name () { #SUDO checked CKPTPROTONUM2NAME=" protonum2name: Start" ; #ckpt $CKPTPROTONUM2NAME unset IGNOREPORT || : case $1 in 0|[Ii][Pp]) PROTO="ip" IGNOREPORT="YES" ;; 1|[Ii][Cc][Mm][Pp]) PROTO="icmp" ;; 2|[Ii][Gg][Mm][Pp]) PROTO="igmp" IGNOREPORT="YES" ;; 3|[Gg][Gg][Pp]) PROTO="ggp" IGNOREPORT="YES" ;; 4|[Ii][Pp][Ii][Pp]) PROTO="ipip" IGNOREPORT="YES" ;; 6|[Tt][Cc][Pp]) PROTO="tcp" ;; 8|[Ee][Gg][Pp]) PROTO="egp" IGNOREPORT="YES" ;; 12|[Pp][Uu][Pp]) PROTO="pup" IGNOREPORT="YES" ;; 17|[Uu][Dd][Pp]) PROTO="udp" ;; 22|[Ii][Dd][Pp]) PROTO="idp" IGNOREPORT="YES" ;; 41|[Ii][Pp][Vv]6) PROTO="ipv6" IGNOREPORT="YES" ;; 46|[Rr][Ss][Vv][Pp]) PROTO="rsvp" IGNOREPORT="YES" ;; 47|[Gg][Rr][Ee]) PROTO="gre" IGNOREPORT="YES" ;; 50|[Ee][Ss][Pp]) PROTO="esp" IGNOREPORT="YES" ;; 103|[Pp][Ii][Mm]) PROTO="pim" IGNOREPORT="YES" ;; 255|[Rr][Aa][Ww]) PROTO="raw" IGNOREPORT="YES" ;; *) PROTONAME=`grep "^[a-zA-Z]*\W*$1 *" /etc/protocols | awk '{print $1}' || logfail $LINENO masonlib: YYYY 0063` if [ -n "$PROTONAME" ]; then PROTO=$PROTONAME ; else PROTO=$1 ; fi unset PROTONAME IGNOREPORT="YES" ;; esac CKPTPROTONUM2NAME="" } #End of protonum2name #------------------------------------------------------------------------- # reservedip function, returns true/false: ip address is reserved (rfc1918)? #------------------------------------------------------------------------- #OK, technically a hostname _could_ correspond to a reserved address, but come on! #If we're being handed a hostname, we probably don't need to autoset masq anyways. reservedip () { #SUDO checked case $1 in *[-A-Za-z]*) return 1 ;; *) SPLITIP=$1 I1O1=${SPLITIP%%.*} ; SPLITIP=${SPLITIP#*.} I1O2=${SPLITIP%%.*} if [ $I1O1 -eq 10 ]; then return 0 #True elif [ $I1O1 -eq 172 ] && [ $I1O2 -ge 16 ] && [ $I1O2 -le 31 ]; then return 0 #True elif [ $I1O1 -eq 192 ] && [ $I1O2 -eq 168 ]; then return 0 #True else return 1 #False fi ;; esac } #End of reservedip #------------------------------------------------------------------------- # routesoverlap function. In short, if any two non-default routes in # the routing table overlap _and_ point at different interfaces, return true. #------------------------------------------------------------------------- routesoverlap () { #SUDO checked #My first pass at spoof blocking failed on the overlapping portion of two networks that arrive on #different nics. The new spoof blocking code handles that case, so this check is no longer needed. ALLROUTES="`route -n | cut -b 1-16,33-48,73-80 | grep '^[0-9]*\.[0-9]*\.[0-9]*\.[0-9]*[[:space:]]' | \ grep -v '^0\.0\.0\.0[[:space:]]' | awk '{print $1 "/" $2 "-" $3}' || logfail $LINENO masonlib: YYYY 0064`" #network/netmask-interface OVERLAPS=1 #False OVERLAPPINGROUTES="" for NET1 in $ALLROUTES ; do for NET2 in $ALLROUTES ; do if [ "${NET1##*-}" != "${NET2##*-}" ]; then #No need to check if they point to the same if if networksoverlap ${NET1%%-*} ${NET2%%-*} ; then OVERLAPS=0 if [ -n "$OVERLAPPINGROUTES" ]; then OVERLAPPINGROUTES="$OVERLAPPINGROUTES, " ; fi OVERLAPPINGROUTES="$OVERLAPPINGROUTES${NET1%%-*} and ${NET2%%-*}" fi fi done done if [ -n "$OVERLAPPINGROUTES" ]; then OVERLAPPINGROUTES="$OVERLAPPINGROUTES." ; fi return $OVERLAPS } #End of routesoverlap #------------------------------------------------------------------------- # ruletag function, returns a kind of hash of the rule to identify equivalence. #------------------------------------------------------------------------- ruletag () { #SUDO checked #Params: $* is an ipchains command. #This function returns a tag. This tag is used to determine if two rules can #be safely swapped; they can if their tags are identical. #Tag: first object/target(w/redirect port)/-l/#^ #This tag could also include the mark value. Hmmm, should it? CKPTRULETAG=" ruletag: Start" ; #ckpt $CKPTRULETAG RTRETVAL=$1 TARGET="" ; LOG="" ; COUNTTAG="" while [ -n "$1" ]; do case $1 in -j|--jump) NEXT="TARGET" ; TARGET="-j" ; shift ;; -l|--log) NEXT="" ; LOG="-l" ; shift ;; -A|--append|-D|--delete|-R|--replace|-I|--insert|-L|--list|-F|--flush|-Z|--zero|-N|--new-chain|-X|--delete-chain|-P|--policy|-M|--masquerading|-S|--set|-C|--check|-h|-p|--protocol|-s|--source|--source-port|-d|--destination|--destination-port|--icmp-type|-i|--interface|!|-f|--fragment|-b|--bidirectional|-v|--verbose|-n|--numeric|-o|--output|-m|--mark|-t|--TOS|-x|--exact|-y|--syn) NEXT="" ; shift ;; \#^) NEW="" ; COUNTTAG="#^" ; shift ;; \#*) NEXT="" ; shift $# ;; #Drop everything following a "#" *) case $NEXT in TARGET) TARGET="${TARGET}$1" ; shift ;; *) shift ;; esac ;; esac done echo "$RTRETVAL/$TARGET/$LOG/$COUNTTAG" CKPTRULETAG="" } #End of ruletag #------------------------------------------------------------------------- #Start up a firewall from scratch. #------------------------------------------------------------------------- runfirewall () { #SUDO checked #FIXME - add iptables support CKPTRUNFIREWALL=" runfirewall: Start" ; #ckpt $CKPTRUNFIREWALL #FIXME - use this or not? #if [ -f /proc/net/ip_fwchains ]; then # DEFAULTPOLICY=`echo $DEFAULTPOLICY | tr a-z A-Z || logfail $LINENO masonlib: YYYY 0065` # if [ "$LOGBLOCKS" = "-o" ]; then LOGBLOCKS="-l" ; fi #elif [ -f /proc/net/ip_input ]; then # DEFAULTPOLICY=`echo $DEFAULTPOLICY | tr A-Z a-z || logfail $LINENO masonlib: YYYY 0095` # if [ "$LOGBLOCKS" = "-l" ]; then LOGBLOCKS="-o" ; fi #else # CKPTRUNFIREWALL=" runfirewall: neither ipchains nor ipfwadm supported." ; #ckpt $CKPTRUNFIREWALL # wrap ${WARN}This kernel supports neither ipchains nor ipfwadm!${NORM} >/dev/stderr #fi if [ -f /proc/sys/net/ipv4/ip_forward ]; then #If forwarding is disabled _and_ there are two or more interfaces in the system if [ "`cat /proc/sys/net/ipv4/ip_forward`" = "0" ] && \ [ `ifconfig | cut -b 1-10 | grep -v ':' | grep -v '^lo' | grep -v '^ *$' | wc -l` -ge 2 ]; then wrap ${WARN}Please note that forwarding is disabled in the kernel. If this machine is expected to be a router, this should be fixed.${NORM} >/dev/stderr fi fi CKPTRUNFIREWALL=" runfirewall: ipchains/ipfwadm blockedhosts" ; #ckpt $CKPTRUNFIREWALL if [ -n "$BLOCKEDHOSTS" ]; then echo -n Blockedhost blocks... for BLOCKEDHOST in $BLOCKEDHOSTS ; do #Add this in if we reinstate marks on system rules, check below too. ${MINMARK:+"-m"} $MINMARK ; if [ -n "$MINMARK" ]; then MINMARK=$[$MINMARK+1] ; fi #REMOVEME #$IPCHAINSBIN -I input -s $BLOCKEDHOST -j DENY $LOGBLOCKS || logfail $LINENO masonlib: YYYY 0066 #$IPCHAINSBIN -I output -s $BLOCKEDHOST -j DENY $LOGBLOCKS || logfail $LINENO masonlib: YYYY 0067 #$IPCHAINSBIN -I input -d $BLOCKEDHOST -j DENY $LOGBLOCKS || logfail $LINENO masonlib: YYYY 0068 #$IPCHAINSBIN -I output -d $BLOCKEDHOST -j DENY $LOGBLOCKS || logfail $LINENO masonlib: YYYY 0069 #$IPFWADMBIN -I -i deny -S $BLOCKEDHOST $LOGBLOCKS || logfail $LINENO masonlib: YYYY 0096 #$IPFWADMBIN -O -i deny -S $BLOCKEDHOST $LOGBLOCKS || logfail $LINENO masonlib: YYYY 0097 #$IPFWADMBIN -I -i deny -D $BLOCKEDHOST $LOGBLOCKS || logfail $LINENO masonlib: YYYY 0098 #$IPFWADMBIN -O -i deny -D $BLOCKEDHOST $LOGBLOCKS || logfail $LINENO masonlib: YYYY 0099 dorule i input '' '' '' "$BLOCKEDHOST" '' '' '' '' '' deny '' "$LOGBLOCKS" '' || logfail $LINENO masonlib: YYYY 0066/0096 dorule i output '' '' '' "$BLOCKEDHOST" '' '' '' '' '' deny '' "$LOGBLOCKS" '' || logfail $LINENO masonlib: YYYY 0067/0097 dorule i input '' '' '' '' '' "$BLOCKEDHOST" '' '' '' deny '' "$LOGBLOCKS" '' || logfail $LINENO masonlib: YYYY 0068/0098 dorule i output '' '' '' '' '' "$BLOCKEDHOST" '' '' '' deny '' "$LOGBLOCKS" '' || logfail $LINENO masonlib: YYYY 0069/0099 done else echo -n No Blockedhost blocks... ; fi if [ -f /proc/net/ip_fwchains ] || [ -n "`lsmod | grep '^ip_tables '`" ]; then CKPTRUNFIREWALL=" runfirewall: ipchains/iptables spoofblocks" ; #ckpt $CKPTRUNFIREWALL if [ "$SPOOFBLOCKS" = "YES" ]; then echo -n Spoof blocks... #Add this in if we reinstate marks on system rules, check below too. ${MINMARK:+"-m"} $MINMARK ; if [ -n "$MINMARK" ]; then MINMARK=$[$MINMARK+1] ; fi flushornewchain NoSpoof #REMOVEME #$IPCHAINSBIN -I input -j NoSpoof || logfail $LINENO masonlib: YYYY 0072 dorule i input '' '' '' '' '' '' '' '' '' "NoSpoof" '' '' '' || logfail $LINENO masonlib: YYYY 0072 #In iptables, we have to check for spoofing on the forward chain as well. if [ -n "`lsmod | grep '^ip_tables '`" ]; then dorule i forward '' '' '' '' '' '' '' '' '' "NoSpoof" '' '' '' || logfail $LINENO masonlib: YYYY 0137 fi #We have a special #case to allow first. Say 192.168.0.1 is eth0's ip. If I telnet to that IP on this machine, #the source and destination addresses will be 192.168.0.1 - the spoof block would see this as #spoofing because the packets are showing up on an interface other than eth0. We need to exempt #lo from the check. '-j RETURN' on a chain inserted into input will do that. #REMOVEME #$IPCHAINSBIN -A NoSpoof -i lo -j RETURN || logfail $LINENO masonlib: YYYY 0073 dorule a NoSpoof lo '' '' '' '' '' '' '' '' return '' '' '' || logfail $LINENO masonlib: YYYY 0073 #REMOVEME ##Loop through loips as ok input on lo #for ONELOCALIP in `ifconfig | grep 'inet addr' | sed -e 's/.*addr://' -e 's/ .*//' || logfail $LINENO masonlib: YYYY 0074` ; do # $IPCHAINSBIN -I input -s ${ONELOCALIP} -i lo -j ACCEPT $LOGBLOCKS || logfail $LINENO masonlib: YYYY 0075 #done #If the packet's network and IP are in the (non-default) routing table, go back to the main firewall. for ONEROUTE in `route -n | cut -b 1-16,33-48,73-80 | grep '^[0-9]*\.[0-9]*\.[0-9]*\.[0-9]*[[:space:]]' | \ grep -v '^0\.0\.0\.0[[:space:]]' | awk '{print $1 "/" $2 "-" $3}' || logfail $LINENO masonlib: YYYY 0076` ; do #REMOVEME #$IPCHAINSBIN -A NoSpoof -s ${ONEROUTE%%-*} -i ${ONEROUTE##*-} -j RETURN || logfail $LINENO masonlib: YYYY 0077 dorule a NoSpoof "${ONEROUTE##*-}" '' '' "${ONEROUTE%%-*}" '' '' '' '' '' return '' '' '' || logfail $LINENO masonlib: YYYY 0077 done #Block packets coming from a given local net if they don't come from the nic leading to that net. for ONEROUTE in `route -n | cut -b 1-16,33-48,73-80 | grep '^[0-9]*\.[0-9]*\.[0-9]*\.[0-9]*[[:space:]]' | \ grep -v '^0\.0\.0\.0[[:space:]]' | awk '{print $1 "/" $2 "-" $3}' || logfail $LINENO masonlib: YYYY 0135` ; do #REMOVEME #$IPCHAINSBIN -A NoSpoof -s ${ONEROUTE%%-*} -i ! ${ONEROUTE##*-} -j DENY $LOGBLOCKS || logfail $LINENO masonlib: YYYY 0136 dorule a NoSpoof "! ${ONEROUTE##*-}" '' '' "${ONEROUTE%%-*}" '' '' '' '' '' deny '' "$LOGBLOCKS" '' || logfail $LINENO masonlib: YYYY 0136 done #If the packet is coming from a default route interface, accept it. for ONEROUTE in `route -n | cut -b 1-16,33-48,73-80 | grep '^[0-9]*\.[0-9]*\.[0-9]*\.[0-9]*[[:space:]]' | \ grep '^0\.0\.0\.0[[:space:]]' | awk '{print $1 "/" $2 "-" $3}' || logfail $LINENO masonlib: YYYY 0137` ; do #REMOVEME #$IPCHAINSBIN -A NoSpoof -i ${ONEROUTE##*-} -j RETURN || logfail $LINENO masonlib: YYYY 0138 dorule a NoSpoof "${ONEROUTE##*-}" '' '' '' '' '' '' '' '' return '' '' '' || logfail $LINENO masonlib: YYYY 0138 done #Finally, if it wasn't caught above, deny it. #REMOVEME #$IPCHAINSBIN -A NoSpoof -j DENY $LOGBLOCKS || logfail $LINENO masonlib: YYYY 0139 dorule a NoSpoof '' '' '' '' '' '' '' '' '' deny '' "$LOGBLOCKS" '' || logfail $LINENO masonlib: YYYY 0139 else echo -n Not blocking spoofed packets... ; fi elif [ -f /proc/net/ip_input ]; then echo -n Not blocking spoofed packets under ipfwadm... fi CKPTRUNFIREWALL=" runfirewall: ipchains/ipfwadm noleakrfc1918" ; #ckpt $CKPTRUNFIREWALL #This is a construction issue only; if rfc1918 packets leak through as the firewall is being constructed, #we deny them to tell the sending end to try again. Once the forward/MASQ rules are in place, #this won't be used again. if [ -n "$AUTOMASQIF" ]; then echo -n NoLeakRFC1918 blocks... for MASQIF in $AUTOMASQIF ; do #Add this in if we reinstate marks on system rules, check below too. ${MINMARK:+"-m"} $MINMARK ; if [ -n "$MINMARK" ]; then MINMARK=$[$MINMARK+1] ; fi for RESNET in 10.0.0.0/8 172.16.0.0/12 192.168.0.0/16 ; do #REMOVEME #$IPCHAINSBIN -I output -i $MASQIF -s $RESNET -j DENY || logfail $LINENO masonlib: YYYY 0078 #$IPFWADMBIN -O -i deny -W $MASQIF -S $RESNET || logfail $LINENO masonlib: YYYY 0100 dorule i output '' "$MASQIF" '' "$RESNET" '' '' '' '' '' deny '' '' '' done done else echo -n No NoLeakRFC1918 blocks... ; fi CKPTRUNFIREWALL=" runfirewall: ipchains noincoming" ; #ckpt $CKPTRUNFIREWALL if [ -n "$NOINCOMING" ] && [ -n "$INCOMINGINTERFACES" ]; then echo -n Incoming blocks... for OUTSIDEIF in $INCOMINGINTERFACES ; do for BLOCKPROTO in $NOINCOMING ; do oneblockproto $BLOCKPROTO $OUTSIDEIF done done else echo -n No incoming blocks... ; fi CKPTRUNFIREWALL=" runfirewall: ipchains/ipchains nooutgoing" ; #ckpt $CKPTRUNFIREWALL if [ -n "$NOOUTGOING" ] && [ -n "$OUTGOINGINTERFACES" ]; then echo -n Outgoing blocks... for OUTSIDEIF in $OUTGOINGINTERFACES ; do for BLOCKPROTO in $NOOUTGOING ; do case $BLOCKPROTO in #${MINMARK:+"-m"} $MINMARK ; if [ -n "$MINMARK" ]; then MINMARK=$[$MINMARK+1] ; fi *.*/[Ii][Cc][Mm][Pp]) ICMPBOTH=${BLOCKPROTO%%/*} ; ICMPCODE=${ICMPBOTH%%.*} ; ICMPSUBCODE=${ICMPBOTH##*.} #REMOVEME #$IPCHAINSBIN -I output -i $OUTSIDEIF -p icmp -s 0/0 $ICMPCODE -d 0/0 $ICMPSUBCODE -j DENY $LOGBLOCKS || logfail $LINENO masonlib: YYYY 0085 #Cannot do subcode on ipfwadm icmp. #$IPFWADMBIN -O -i deny -W $OUTSIDEIF -P icmp -S 0/0 $ICMPCODE $LOGBLOCKS || logfail $LINENO masonlib: YYYY 0107 dorule i output '' "$OUTSIDEIF" icmp '' "$ICMPCODE" '' "$ICMPSUBCODE" '' '' deny '' "$LOGBLOCKS" '' || logfail $LINENO masonlib: YYYY 0085/0107 ;; */[Ii][Cc][Mm][Pp]) #REMOVEME #$IPCHAINSBIN -I output -i $OUTSIDEIF -p icmp -s 0/0 ${BLOCKPROTO%%/*} -j DENY $LOGBLOCKS || logfail $LINENO masonlib: YYYY 0086 #$IPFWADMBIN -O -i deny -W $OUTSIDEIF -P icmp -S 0/0 ${BLOCKPROTO%%/*} $LOGBLOCKS || logfail $LINENO masonlib: YYYY 0108 dorule i output '' "$OUTSIDEIF" icmp '' "${BLOCKPROTO%%/*}" '' '' '' '' deny '' "$LOGBLOCKS" '' || logfail $LINENO masonlib: YYYY 0086/0108 ;; #*/*) #FIXME - convert over to dorules. # $IPCHAINSBIN -I output -i $OUTSIDEIF -p ${BLOCKPROTO##*/} -d 0/0 ${BLOCKPROTO%%/*} -j DENY $LOGBLOCKS || logfail $LINENO masonlib: YYYY 0087 # $IPFWADMBIN -O -i deny -W $OUTSIDEIF -P ${BLOCKPROTO##*/} -D 0/0 ${BLOCKPROTO%%/*} $LOGBLOCKS || logfail $LINENO masonlib: YYYY 0109 # ;; #*) # $IPCHAINSBIN -I output -i $OUTSIDEIF -p ${BLOCKPROTO##*/} -j DENY $LOGBLOCKS || logfail $LINENO masonlib: YYYY 0088 # $IPFWADMBIN -O -i deny -W $OUTSIDEIF -P ${BLOCKPROTO##*/} $LOGBLOCKS || logfail $LINENO masonlib: YYYY 0110 # ;; esac done done else echo -n No outgoing blocks... ; fi set +e #Turn off failure checking; Mason has no control over the final contents of these files. #echo -n System rules... #. $SYSTEMRULEFILE # CKPTRUNFIREWALL=" runfirewall: ipchains/ipfwadm baserules" ; #ckpt $CKPTRUNFIREWALL echo -n Fixed rules... . $BASERULEFILE if [ "$1" = "LEARN" ] || [ "$1" = "learn" ]; then CKPTRUNFIREWALL=" runfirewall: ipchains/ipfwadm newrules" ; #ckpt $CKPTRUNFIREWALL echo -n New rules... . $NEWRULEFILE fi set -e if [ "$1" = "LEARN" ] || [ "$1" = "learn" ]; then CKPTRUNFIREWALL=" runfirewall: ipchains/ipfwadm logging rules" ; #ckpt $CKPTRUNFIREWALL echo -n Adding logging rules... #Finally, create a "nolog' chain for each of the existing chains, have each existing #chain jump to it. for ACHAIN in `chainnameof input` `chainnameof output` `chainnameof forward` ; do if [ -n "$NOLOGSUFFIX" ]; then flushornewchain $ACHAIN$NOLOGSUFFIX fi #${MINMARK:+"-m"} $MINMARK ; if [ -n "$MINMARK" ]; then MINMARK=$[$MINMARK+1] ; fi #REMOVEME #$IPCHAINSBIN -A $ACHAIN -j $ACHAIN$NOLOGSUFFIX || logfail $LINENO masonlib: YYYY 0091 #ZZZZ dorule a "$ACHAIN" '' '' '' '' '' '' '' '' '' "$ACHAIN$NOLOGSUFFIX" '' '' '' || logfail $LINENO masonlib: YYYY 0091 done #Finally, log everything else. for ACHAIN in input output forward ; do #REMOVEME #$IPCHAINSBIN -A $ACHAIN -l || logfail $LINENO masonlib: YYYY 0092 #$IPFWADMBIN -$ACHAIN -a $LOGGINGPOLICY -o || logfail $LINENO masonlib: YYYY 0111 dorule a "$ACHAIN" '' '' '' '' '' '' '' '' '' "$LOGGINGPOLICY" '' "-l" '' || logfail $LINENO masonlib: YYYY 0092/0111 done fi CKPTRUNFIREWALL=" runfirewall: ipchains/ipfwadm policy" ; #ckpt $CKPTRUNFIREWALL for ACHAIN in input output forward ; do #REMOVEME #$IPCHAINSBIN -P $ACHAIN $DEFAULTPOLICY || logfail $LINENO masonlib: YYYY 0093/0094 #$IPFWADMBIN -$ACHAIN -p $DEFAULTPOLICY || logfail $LINENO masonlib: YYYY 0112/0113 dorule p "$ACHAIN" '' '' '' '' '' '' '' '' '' "$DEFAULTPOLICY" '' '' '' || logfail $LINENO masonlib: YYYY 0093/0094/0112/0113 done echo Done! CKPTRUNFIREWALL="" } #End of runfirewall #Compatibility wrappers: #------------------------------------------------------------------------- #Start up a firewall from scratch. Use both baserules and newrules. #------------------------------------------------------------------------- runlearnfirewall () { #SUDO checked wrap ${WARN}"Please use \"runfirewall LEARN\" instead of runlearnfirewall"${NORM} >/dev/stderr runfirewall LEARN } #End of runlearnfirewall #------------------------------------------------------------------------- #Start up a firewall from scratch. Only use baserules. #------------------------------------------------------------------------- runstandardfirewall () { #SUDO checked wrap ${WARN}"Please use \"runfirewall STANDARD\" instead of runstandardfirewall"${NORM} >/dev/stderr runfirewall STANDARD } #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 () { #SUDO checked #Params: numeric port, proto CKPTSERVERPORTRANGE=" serverportrange: port $1 proto $2" ; #ckpt $CKPTSERVERPORTRANGE PARTIALCOMMENT="" ; READABLEPORT="" if isdigits "$1" ; then #The () subshell below is the equivalent of: "head -n 1 | awk '{print $1}'`" SERVICE="`grep "[[:space:]]$1/$2" $SERVICES | ( if read F1 FREST ; then echo $F1 ; fi ) || logfail $LINENO masonlib: YYYY 0114`" #Mason will not be manipulating /etc/services. #SERVICELINE="`grep "[[:space:]]$1/$2" $SERVICES | head -n 1 || logfail $LINENO masonlib: YYYY 0115`" #if [ `grep "[[:space:]]$1/$2" /etc/services | 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 if [ "$ECHOCOMMAND" != "ipchains-save" ]; then READABLEPORT=$SERVICE ; PARTIALCOMMENT="$SERVICE/$PROTO" else READABLEPORT=$1 ; PARTIALCOMMENT="$SERVICE/$PROTO" fi fi CKPTSERVERPORTRANGE=" serverportrange: isdigits $READABLEPORT $PARTIALCOMMENT" ; #ckpt $CKPTSERVERPORTRANGE elif [ -n "`grep -E $1 /etc/services || logfail $LINENO masonlib: YYYY 0116`" ]; then # $1 is already converted to text and a server port #FIXME - is the above check all that is needed? #egrep "^$1[[:space:]]+[0-9]+/$2" READABLEPORT=$1 PARTIALCOMMENT="$1/$PROTO" CKPTSERVERPORTRANGE=" serverportrange: isname $READABLEPORT $PARTIALCOMMENT" ; #ckpt $CKPTSERVERPORTRANGE #handle special server port ranges like the above elif [ "$2" = "udp" ] && [ "$1" = "$TRACEROUTE_BEGIN:$TRACEROUTE_END" ]; then READABLEPORT="$TRACEROUTE_BEGIN:$TRACEROUTE_END" ; PARTIALCOMMENT="TRACEROUTE/$PROTO" elif [ "$2" = "udp" ] && [ "$1" = "6970:7170" ]; then READABLEPORT="6970:7170" ; PARTIALCOMMENT="RADATA/$PROTO" elif [ "$2" = "udp" ] && [ "$1" = "6770:7170" ]; then READABLEPORT="6770:7170" ; PARTIALCOMMENT="RA30DATA/$PROTO" elif [ "$2" = "tcp" ] && [ "$1" = "$X_BEGIN:$X_END" ]; then READABLEPORT="$X_BEGIN:$X_END" ; PARTIALCOMMENT="X/$PROTO" CKPTSERVERPORTRANGE=" serverportrange: setting to X" ; #ckpt $CKPTSERVERPORTRANGE elif [ "$2" = "tcp" ] && [ "$1" = "$OPENWIN_BEGIN:$OPENWIN_END" ]; then READABLEPORT="$OPENWIN_BEGIN:$OPENWIN_END" ; PARTIALCOMMENT="OPENWIN/$PROTO" elif [ "$2" = "tcp" ] && [ "$1" = "$VNCJAVA_BEGIN:$VNCJAVA_END" ]; then READABLEPORT="$VNCJAVA_BEGIN:$VNCJAVA_END" ; PARTIALCOMMENT="VNCJAVA/$PROTO" elif [ "$2" = "tcp" ] && [ "$1" = "$VNC_BEGIN:$VNC_END" ]; then READABLEPORT="$VNC_BEGIN:$VNC_END" ; PARTIALCOMMENT="VNC/$PROTO" elif [ "$2" = "tcp" ] && [ "$1" = "$IRC_BEGIN:$IRC_END" ]; then READABLEPORT="$IRC_BEGIN:$IRC_END" ; PARTIALCOMMENT="IRC/$PROTO" elif [ "$2" = "tcp" ] && [ "$1" = "512:514" ]; then READABLEPORT="512:514" ; PARTIALCOMMENT="R-COMMANDS/$PROTO" else CKPTSERVERPORTRANGE=" serverportrange: neither $1 $2" ; #ckpt $CKPTSERVERPORTRANGE fi #echo $READABLEPORT #Can't do this because we need to return PARTIALCOMMENT as well. CKPTSERVERPORTRANGE="" } #end of serverportrange #------------------------------------------------------------------------- # showstate procedure, used to display the state of the running program #------------------------------------------------------------------------- showstate () { #SUDO checked #Param: p1 is the string to be displayed. if [ "$USEANSI" != "NO" ]; then if [ "${TERM}" = "xterm" -o "${TERM}" = "xterm-color" ]; then echo -ne "\033]0;${1}\007" fi fi } #end of showstate #------------------------------------------------------------------------- # sigexitscript function, called on receipt of SIGHUP #------------------------------------------------------------------------- sigexitscript () { #SUDO checked #FIXME - should this be 'trap 0'? trap - 0 #If we were asked to exit, no need to process a "crash" unset CKPTMGT CKPTMASON CKPTCHECKSYS CKPTCLIENTPORTRANGE \ CKPTGENERALIZEIP CKPTIPLE CKPTIPLT CKPTISNUMERICIP CKPTLOADCONF \ CKPTSERVERPORTRANGE CKPTADDCOUNTS CKPTNAMEOF CKPTBROADCASTOF \ CKPTCHECKCONF CKPTDELCOUNTS CKPTFLUSHFIREWALL CKPTPORT2CISCOPORT \ CKPTPROTONUM2NAME CKPTRULETAG CKPTRUNFIREWALL \ CKPTSETTOS CKPTSORTRULEFILE \ CKPTUNIQRULEFILE CKPTUPDATECOUNTS CKPTNETWORKOF || : if [ "$NEEDLF" = "YES" ]; then echo >/dev/stderr ; NEEDLF="NO" ; fi wrap Received HUP signal, exiting at next pass >/dev/stderr #FIXME - this needs to be written to the ONEKILLFILE; do we have access to that? export it? if type -path logger >/dev/null 2>/dev/null ; then logger '!!EXIT!!' fi EXITMASON="YES" #FIXME - should we just exit 0? exit 0 } #End of sigexitscript #------------------------------------------------------------------------- # settos subroutine, sets the TOS variable for the given port, port range, and protocol. #------------------------------------------------------------------------- #params: port, port range, protocol settos () { #SUDO checked #FIXME - can we set TOS on iptables? CKPTSETTOS=" settos: Start" ; #ckpt $CKPTSETTOS if [ "$INFORMAT" != "ipchains-lv" ]; then #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. #I also specifically don't check to see whether this is an output rule. It's overkill to #set if on in, out, _and_ forward, but the user might only be generating input rules with Mason. case "$2/$3" in "$IRC_BEGIN:$IRC_END/[Tt][Cc][Pp]") TOS=" -t 0x01 0x10" ;; #IRC Minimize delay "$TRACEROUTE_BEGIN:$TRACEROUTE_END/[Uu][Dd][Pp]") TOS=" -t 0x01 0x10" ;; #Traceroute Minimize delay esac case "$1/$3" in "21/[Tt][Cc][Pp]") TOS=" -t 0x01 0x10" ;; #FTP Minimize delay "23/[Tt][Cc][Pp]"|"22/[Tt][Cc][Pp]"|"513/[Tt][Cc][Pp]") TOS=" -t 0x01 0x10" ;; #Telnet,SSH,rlogin Minimize delay "53/[Uu][Dd][Pp]") TOS=" -t 0x01 0x10" ;; #dns Minimize delay "69/[Uu][Dd][Pp]") TOS=" -t 0x01 0x10" ;; #tftp Minimize delay "20/[Tt][Cc][Pp]"|"25/[Tt][Cc][Pp]") TOS=" -t 0x01 0x08" ;; #FTP-data,SMTP Maximize throughput "53/[Tt][Cc][Pp]") TOS=" -t 0x01 0x08" ;; #DNS zone transfer Maximize throughput "80/[Tt][Cc][Pp]"|"443/[Tt][Cc][Pp]"|"563/[Tt][Cc][Pp]") TOS=" -t 0x01 0x08" ;; #Web & secure web Maximize throughput "8080/[Tt][Cc][Pp]"|"3128/[Tt][Cc][Pp]") TOS=" -t 0x01 0x08" ;; #Web Caches Maximize throughput "161/[Uu][Dd][Pp]") TOS=" -t 0x01 0x04" ;; #SNMP Maximize reliability "119/[Tt][Cc][Pp]"|"110/[Tt][Cc][Pp]"|"143/[Tt][Cc][Pp]") TOS=" -t 0x01 0x02" ;; #NNTP,POP3,IMAP Minimize cost esac fi #FIXME - iptables if [ "$ECHOCOMMAND" = "cisco" ]; then case "$TOS" in " -t 0x01 0x02") TOS=" min-monetary-cost" ;; " -t 0x01 0x04") TOS=" max-reliability" ;; " -t 0x01 0x08") TOS=" max-throughput" ;; " -t 0x01 0x10") TOS=" min-delay" ;; esac elif [ "$ECHOCOMMAND" = "ipchains-save" ]; then case "$TOS" in " -t 0x01 0x02") TOS=" -t 01 02" ;; " -t 0x01 0x04") TOS=" -t 01 04" ;; " -t 0x01 0x08") TOS=" -t 01 08" ;; " -t 0x01 0x10") TOS=" -t 01 10" ;; esac fi CKPTSETTOS="" } #End of settos #------------------------------------------------------------------------- # sortrulefile procedure, sorts a rulefile so that the rules that process the most packets are at the top. #------------------------------------------------------------------------- sortrulefile () { #Params: $1 is the filespec for the files that need to be sorted by counts. CKPTSORTRULEFILE=" sortrulefile: Start" ; #ckpt $CKPTSORTRULEFILE for ONEFILE in $1 ; do echo -n Adding counts and sorting $ONEFILE... LASTRULETAG="" FILECOUNT="0" ; if [ -f $ONEFILE.0 ]; then rm -f $ONEFILE.0 || logfail $LINENO masonlib: YYYY 0117 ; fi CKPTSORTRULEFILE=" sortrulefile: addcounts" ; #ckpt $CKPTSORTRULEFILE addcounts $ONEFILE #Break up input file into sections that can safely be sorted #Redirect stdin to work around an f^@&ing annoying limitation in the read command. CKPTSORTRULEFILE=" sortrulefile: split into equivalent sections." ; #ckpt $CKPTSORTRULEFILE exec 5<&0 < "$ONEFILE" while read ONELINE ; do NEWRULETAG="`ruletag $ONELINE`" if [ "$NEWRULETAG" != "$LASTRULETAG" ]; then FILECOUNT=$[ $FILECOUNT + 1 ] if [ -f $ONEFILE.$FILECOUNT ]; then rm -f $ONEFILE.$FILECOUNT || logfail $LINENO masonlib: YYYY 0118 ; fi fi echo "$ONELINE" >>$ONEFILE.$FILECOUNT LASTRULETAG="$NEWRULETAG" done exec 0<&5 5<&- #Sort the sections that need it and re-assemble $ONEFILE CKPTSORTRULEFILE=" sortrulefile: reassemble" ; #ckpt $CKPTSORTRULEFILE rm -f $ONEFILE.new || logfail $LINENO masonlib: YYYY 0119 for SECTION in `seqfunc 0 $FILECOUNT` ; do if [ -f "$ONEFILE.$SECTION" ]; then if [ `grep '#\^' $ONEFILE.$SECTION | wc -l` -gt 0 ]; then sort -t '^' +1 -n -r $ONEFILE.$SECTION >>$ONEFILE.new || logfail $LINENO masonlib: YYYY 0120 else cat $ONEFILE.$SECTION >>$ONEFILE.new || logfail $LINENO masonlib: YYYY 0121 fi rm -f $ONEFILE.$SECTION || logfail $LINENO masonlib: YYYY 0122 fi done cat $ONEFILE.new >$ONEFILE || logfail $LINENO masonlib: YYYY 0123 rm -f $ONEFILE.new || logfail $LINENO masonlib: YYYY 0124 done echo Done! CKPTSORTRULEFILE="" } #End of sortrulefile #------------------------------------------------------------------------- # uniqrulefile subroutine, sorts the given file and removes duplicates. #------------------------------------------------------------------------- uniqrulefile () { #params: $1: filename of file to sort # This one takes a little explanation. I want to sort by the text after the first #, grouping similar rules #next to each other so that uniq can remove duplicates. Normally, sort -t '#' +1 $1 | uniq >$1.sorted #would do the trick. # Because we may have mark values on the lines, I have to convince uniq to ignore the mark values when #deciding whether adjacent lines are uniq. The only way I see to do that is to: #- add a fake field at the beginning of each line. Make it !!! at first. If the line has a mark value, #replace the !!! with the mark value and leave a placeholder ("ZzMaRkZz") in the mark value's place. #- sort and uniq as above, but use "-1" to skip over the first field. #- for each line with the placeholder, move the first field (the mark value) back to replace the placeholder. #- for any remaining lines with the bogus "!!!", remove it. # Elegant? no. Functional? Yes. CKPTUNIQRULEFILE=" uniqrulefile: delcounts" ; #ckpt $CKPTUNIQRULEFILE delcounts $1 cp -pf $1 $1.bak || logfail $LINENO masonlib: YYYY 0125 #sort -t '#' +1 $1 | uniq >$1.sorted #This worked until we had mark values. CKPTUNIQRULEFILE=" uniqrulefile: main pipeline" ; #ckpt $CKPTUNIQRULEFILE cat $1 | \ sed -e 's/^/!!! /' \ -e 's/^!!! \(.* -m \)\([0-9][0-9]*\)\( .*\)/\2 \1ZzMaRkZz\3/' | \ sort +1 | \ uniq -1 | \ sort -t '#' +1 | \ uniq -1 | \ sed -e 's/^\([0-9][0-9]*\) \(.* -m \)ZzMaRkZz\( .*\)/\2\1\3/' \ -e 's/^!!! //' >$1.sorted || logfail $LINENO masonlib: YYYY 0126 cat $1.sorted >$1 || logfail $LINENO masonlib: YYYY 0127 #This preserves the permissions of fwrules rm -f $1.sorted || logfail $LINENO masonlib: YYYY 0128 if [ "$SORTMODE" = "PACKETCOUNTS" ]; then CKPTUNIQRULEFILE=" uniqrulefile: sortrulefile" ; #ckpt $CKPTUNIQRULEFILE sortrulefile $1 fi CKPTUNIQRULEFILE="" } #End of uniqrulefile #------------------------------------------------------------------------- # updatecounts procedure, keeps a copy of the current packet counts if # there are more packets in the running firewall than in the archived copy. #------------------------------------------------------------------------- updatecounts () { #Params: none CKPTUPDATECOUNTS=" updatecounts: Start" ; #ckpt $CKPTUPDATECOUNTS #FIXME - update for iptables if [ -f /proc/net/ip_fwchains ] && [ "$SORTMODE" = "PACKETCOUNTS" ]; then #We can only match up counts to rules if we have mark values, i.e. ipchains. if [ -z "$LASTMINMARK" ] || [ "$LASTMINMARK" = "0" ]; then LASTMINARK=$MINMARK elif [ "$MINMARK" -ge "$LASTMINMARK" ]; then #Erase old counts if we've made new rules. cat /dev/null >$PACKETCOUNTFILE || : CURRENTCOUNT=0 LASTMINMARK=$MINMARK fi if [ -z "$CURRENTCOUNT" ] || [ "$CURRENTCOUNT" = "0" ]; then #Add up number of packets in current cache. CURRENTCOUNT=0 CKPTUPDATECOUNTS=" updatecounts: sum packetcountfile" ; #ckpt $CKPTUPDATECOUNTS for ONECOUNT in `awk '{print $1}' $PACKETCOUNTFILE || logfail $LINENO masonlib: YYYY 0129` ; do CURRENTCOUNT=$[ $CURRENTCOUNT + $ONECOUNT ] done fi NEWCOUNT=0 CKPTUPDATECOUNTS=" updatecounts: sum running firewall" ; #ckpt $CKPTUPDATECOUNTS for ONECOUNT in `ipchains -L -n -x -v | cut -b 1-9,66-75 - | grep '0x' | awk '{print $1}' || logfail $LINENO masonlib: YYYY 0130` ; do NEWCOUNT=$[ $NEWCOUNT + $ONECOUNT ] done if [ $NEWCOUNT -gt $CURRENTCOUNT ]; then #Are there more packets in the running firewall? CKPTUPDATECOUNTS=" updatecounts: replace packetcountfile" ; #ckpt $CKPTUPDATECOUNTS ipchains -L -n -x -v | cut -b 1-9,66-75 - | grep '0x' >$PACKETCOUNTFILE || logfail $LINENO masonlib: YYYY 0131 CURRENTCOUNT=$NEWCOUNT fi DUPMARKS=`ipchains -L -n -x -v | cut -b 1-9,66-75 - | grep '0x' | awk '{print $2}' | sort | uniq -d || logfail $LINENO masonlib: YYYY 0132` if [ -n "$DUPMARKS" ]; then wrap ${WARN}Warning - the following marks are used more than once in the currently running firewall:${NORM} >/dev/stderr for ONEMARK in $DUPMARKS ; do case $ONEMARK in 0x*) echo -n "$ONEMARK = $[ $ONEMARK ] " >/dev/stderr ;; *) echo -n "$ONEMARK " >/dev/stderr ;; esac done echo >/dev/stderr wrap This will give incorrect packet counts in your rulefiles. >/dev/stderr fi fi CKPTUPDATECOUNTS="" } #End of updatecounts