#!/bin/bash set -e #For those who actually read code, welcome. Please note: there appears to be support for #accepting "ipchains -L -n -x -v" input. It sorta works, it generally doesn't. I won't #be working on it in the near future. Play with it if you'd like. #Last YYYY code used: 0024, use 0025 next #cat </dev/null # (The above line allows me to put the documentation right in the #script... Cool, eh? OK, I've had enough fun. Now stop wasting customer #CPU Cycles! *smile*) # #>>>>>>>>>>>>>>>If you read nothing else, please read this<<<<<<<<<<<<<<<< # # This program offers an aid to creating firewall rules. It offers #ABSOLUTELY NO intelligence in deciding what should be allowed or #disallowed. It has ABSOLUTELY NO ability to understand your security #policy and implement it. YOU are responsible for reviewing the rules and #massaging them to fit your needs. ## While the documentation in mason.txt attempts to provide some #general guidelines on how to use Mason, please remember: the author has #no knowledge of what you want your firewall to do and has not tailored the #documentation or program to specially fit your needs. If there is ever a #discrepancy between your needs and the program output or your needs and #the documentation, the program and/or documentation are _dead_ _wrong_. # # #Copyleft: # Mason interactively creates a Linux packet filtering firewall. # Copyright (C) 1998-2000 William Stearns # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. # # The author can also be reached at: # William Stearns #email: wstearns@pobox.com (preferred) #web: http://www.stearns.org/mason/ #snail: 6 Manchester Dr. # Lebanon NH, 03766, USA # # # This code is entirely owned by William Stearns #(wstearns@pobox.com) and has no relation to any employer or employer #sponsored project. # ##------------------------------ Mason ------------------------------ # The Mason script interactively builds a (fire)wall on a Linux #machine. For more details about how this is done, please see mason.txt, #which gives background, theory of operation, a quick start, and additional #documentation on firewalls and firewall gotchas. # mason.txt and related documentation should have been installed to #/usr/doc/mason-{version}/ . If they are missing or you would like to make #sure you have the latest version, please go to #http://www.pobox.com/~wstearns/mason/ . # All configuration of this program is done in the /etc/masonrc ##file. This script should probably not be directly edited. # #- Bill Stearns # ##The EOTEXT1 line is the end of the text and the start of the code. #EOTEXT1 CKPTMASON=" mason: Ground0" ; #ckpt $CKPTMASON #ZZZZ #DEBUG="non-null" MASONDIR=${MASONDIR:-"/var/lib/mason/"} MASONCONF=${MASONCONF:-"/etc/masonrc"} MASONLIB=${MASONLIB:-"/var/lib/mason/masonlib"} if [ -f $MASONLIB ]; then . $MASONLIB else #Can't use wrap here - no library. echo Missing $MASONLIB library file. Please get a complete copy of Mason from >/dev/stderr echo http://www.pobox.com/~wstearns/mason/ . Exiting. >/dev/stderr sleep 10 exit 1 fi catchall trap preexit 0 #This gets nullified if we get a SIGHUP or SIGINT; see sigexitscript. #------------------------------------------------------------------------- # Start setting up. #------------------------------------------------------------------------- CKPTMASON=" mason: Setup" ; #ckpt $CKPTMASON #LOGCHAINSEXIST="yes" In the process of being removed. Only used in checksys. #REMOVEME LAST1="" ; LAST2="" ; LAST3="" ; LAST4="" ; LAST5="" ; LAST6="" ; LAST7="" ; LAST8="" ; CURRENT="" EXITMASON=${EXITMASON:-"NO"} trap sigexitscript SIGHUP trap sigexitscript SIGINT #Ctrl-C generates this trap loadconf SIGUSR1 loadconf checksys #---------- Start of Main code ---------- CKPTMASON=" mason: Start main" ; #ckpt $CKPTMASON echo $ENH "${HEADER}---- ${BLUE}Mason${HEADER} firewall builder for Linux ----${NORM}" >/dev/stderr echo $ENH "${HEADER}---- see http://www.pobox.com/~wstearns/mason/ for more info. ----${NORM}" >/dev/stderr echo $ENH "${HEADER}---- William Stearns ----${NORM}" >/dev/stderr if [ -n "$MASONVER" ]; then echo $ENH "${HEADER}(This is release $MASONVER )${NORM}" >/dev/stderr fi SIGGED="NO" CKPTMASON=" mason: Save pid" ; #ckpt $CKPTMASON echo "$$" >>$MASONPIDFILE #NAMECACHE Support has been disabled ##Hmmm... I _hate_ overwriting /etc/passwd... #if [ -L $NAMECACHE ]; then # rm -f $NAMECACHE #fi # ##Create the name cache file if it doesn't exist #if [ ! -e $NAMECACHE ]; then # touch $NAMECACHE # #This is a security-related program. I don't want to let people know who we're even talking to. # chmod og-rwx $NAMECACHE #fi for ONEIF in $DYNIF ; do if [ ! -f ${MASONDIR}${ONEIF}-ips ]; then touch ${MASONDIR}${ONEIF}-ips ; fi ipof $ONEIF >>${MASONDIR}${ONEIF}-ips || logfail $LINENO ifconfig $ONEIF and save #if [ "$DYNIFMODE" != "ANYADDRESS" ]; then echo -n "$CMNT $CMNT" ; fi if [ "$DYNIFMODE" = "ANYADDRESS" ]; then #This is a hidden option. The use of 0/0 to match a dynamic address opens some disturbing possibilities for holes in the firewall that I don't really want to uncover. echo "export ${ONEIF}ADDR=\"0/0\" ${CMNT} ${CMNT}Use this if you want to match any address on $ONEIF." fi if [ "$DYNIFMODE" != "SPECIFICIP" ]; then echo -n "$CMNT $CMNT" ; fi echo "export ${ONEIF}ADDR=\"\`ifconfig $ONEIF 2>/dev/null | awk '/inet addr/{print substr($2,6)}'\`$SINGLEMACHSPEC\" ${CMNT} ${CMNT}Use this if you want to match a single address on $ONEIF." if [ "$DYNIFMODE" != "SMALLESTRANGE" ]; then echo -n "$CMNT $CMNT" ; fi #FIXME - what if the file is empty? echo "export ${ONEIF}ADDR=\"$(encompassingnetworkof $(cat ${MASONDIR}${ONEIF}-ips | sort | uniq) || logfail $LINENO return encompassing network for $ONEIF)\" ${CMNT} ${CMNT}Use this if you want to match all addresses seen so far on $ONEIF." eval ${ONEIF}ADDR=`ipof $ONEIF` || logfail $LINENO Set $ONEIF into environment done #DEBUG #set -x #FIXME - output this header even if we switch to ipchains-save, but only once per mason run. if [ "$ECHOCOMMAND" = "ipchains-save" ]; then for ONECHAIN in input forward output ; do echo ':'$ONECHAIN $DEFAULTPOLICY done if [ -n "$NOLOGSUFFIX" ]; then for ONECHAIN in `chainnameof input` `chainnameof forward` `chainnameof output` ; do echo ':'$ONECHAIN$NOLOGSUFFIX '-' done fi fi #Get the first log entry #CKPTMASON=" mason: Get log entry" ; #ckpt $CKPTMASON CKPTMASON="" ; #ckpt $CKPTMASON unset ACK COMMENT CURRCHAIN DEST DESTHOST DESTIP DESTPORT DIR DIRLETTER \ DOACK ECHOACK IF IGNOREPORT INIF ISLOGLINE \ J1 J2 J3 J4 J5 J6 J7 J8 J9 J10 J11 J12 J13 J14 J15 J16 J17 J18 J19 J20 J21 J22 J23 J24 J25 J26 J27 J28 J29 J30 \ O3 O4 O5 O6 O7 O8 O9 O10 O11 O12 O13 \ A3 A4 A5 A6 A7 A8 A9 A10 A11 A12 A13 \ LINEHASDYNAMIC LOGTHIS MESSPOL NUMBYTES NUMPACKETS PROTO SRC SRCHOST SRCIP SRCPORT SYNFLAG SYNFLAGSEEN TAIL TOS || : #unset DFFLAG FFLAG FOFLAG IFLAG LFLAG SFLAG TFLAG || : #These fields are not used at this time. if [ -n "$MINMARK" ]; then INCMINMARK="0" ; fi TOS="" if ! read J1 J2 J3 J4 J5 J6 J7 J8 J9 J10 J11 J12 J13 J14 J15 J16 J17 J18 J19 J20 J21 J22 J23 J24 J25 J26 J27 J28 J29 J30 ; then if [ "$SIGGED" != "YES" ]; then EXITMASON="YES" ; fi fi while [ "$SIGGED" = "YES" ]; do SIGGED="NO" if ! read J1 J2 J3 J4 J5 J6 J7 J8 J9 J10 J11 J12 J13 J14 J15 J16 J17 J18 J19 J20 J21 J22 J23 J24 J25 J26 J27 J28 J29 J30 ; then if [ "$SIGGED" != "YES" ]; then EXITMASON="YES" ; fi fi done CKPTMASON=" mason: post get log entry" ; #ckpt $CKPTMASON while [ "$EXITMASON" != "YES" ] && [ -n "$J1" ] && [ "$J1" != '!!EXIT!!' ]; do CKPTMASON=" mason: In main loop" ; #ckpt $CKPTMASON #Only do the work if the line is a firewalling log entry. if [ "$J6 $J7" = "Packet log:" ]; then #Load variables from ipchains log entry INFORMAT="ipchains-log" case $J8 in output) DIR='output ' ; DIRLETTER='O' ;; input) DIR='input ' ; DIRLETTER='I' ;; forward) DIR='forward' ; DIRLETTER='F' ;; *) wrap ${WARN}Unknown direction $J8${NORM} >/dev/stderr ;; esac IF="$J10" protonum2name "${J11##PROTO=}" SRC="$J12" ; DEST="$J13" #SRC and DEST are only temporary variables for ipfwadm and ipchains formats to split into SRCIP and SRCPORT in a mo. SRCPORT=${SRC##*:} DESTPORT=${DEST##*:} SRCIP=${SRC%%:*} DESTIP=${DEST%%:*} #Even if there were a way to extract a mark value from the log line, it wouldn't seem correct to use it. #MESSPOL="$J9" ; LFLAG="$J14" ; SFLAG="$J15" ; IFLAG="$J16" ; FFLAG="$J17" ; TFLAG="$J18" #Unused SYNFLAG="$J19" if [ "$SYNFLAG" = "SYN" ]; then SYNFLAGSEEN="YES" else SYNFLAG="" fi ISLOGLINE="YES" elif [ "$J5 $J6" = "kernel: IP" ]; then #Load variables from ipfwadm log entry INFORMAT="ipfwadm-log" case $J7 in #Formerly [ "`echo $J7 | cut -b 1-3`" = "fw-" ] fw-out|fw-in|fw-fwd) case $J7 in fw-out) DIR='output ' ; DIRLETTER='O' ;; fw-in) DIR='input ' ; DIRLETTER='I' ;; fw-fwd) DIR='forward' ; DIRLETTER='F' ;; *) wrap ${WARN}Unknown direction $J7${NORM} >/dev/stderr ;; esac IF="$J9" PROTO=`echo $J10 | tr A-Z a-z` SRC="$J11" ; DEST="$J12" #SRC and DEST are only temporary variables for ipfwadm and ipchains formats to split into SRCIP and SRCPORT in a mo. SRCIP=${SRC%%:*} DESTIP=${DEST%%:*} #MESSPOL="$J8" ; LFLAG="$J13" ; SFLAG="$J14" ; IFLAG="$J15" ; FOFLAG="$J16" ; TFLAG="$J17" ; DFFLAG="$J18" #Unused #Break up ipfwadmin's habit of gluing the icmp port onto the protocol. if [ "${PROTO%%/*}" = "icmp" ]; then SRCPORT=${PROTO##*/} PROTO="icmp" DESTPORT="" if [ "$DEBUG" = "YES" ]; then wrap proto= $PROTO srcport= $SRCPORT destport= $DESTPORT >/dev/stderr ; fi else SRCPORT=${SRC##*:} DESTPORT=${DEST##*:} fi ISLOGLINE="YES" #No need to set IGNOREPORT - ipfwadm only handles tcp, udp, and icmp. ;; esac elif [ "$J5" = "kernel:" ]; then #Load variables from possible iptables log entry case $J6 in #Formerly [ "`echo $J6 | cut -b 1-4`" = "SRC=" ] IN=*|SRC=*) #FIXME - it seems reasonably likely that J6 might be something other than SRC= in some circumstances. INFORMAT="iptables-log" #FIXME - more than 30 fields needed? for ONEFIELD in $J6 $J7 $J8 $J9 $J10 $J11 $J12 $J13 $J14 $J15 $J16 $J17 $J18 $J19 $J20 $J21 $J22 $J23 $J24 $J25 $J26 $J27 $J28 $J29 $J30 ; do case $ONEFIELD in DPT=*) DESTPORT=${ONEFIELD##*=} ;; DST=*) DESTIP=${ONEFIELD##*=} ;; PROTO=*) PROTO=`echo ${ONEFIELD##*=} | tr A-Z a-z` ;; SPT=*) SRCPORT=${ONEFIELD##*=} ;; SRC=*) SRCIP=${ONEFIELD##*=} ;; TYPE=*) SRCPORT=${ONEFIELD##*=} ;; #FIXME - not sure about subcode #ZZZZ #FIXME - gracefully handle passing the interface to ipfwadm/ipchains/etc. IN=*) INIF=${ONEFIELD##*=} ;; OUT=*) IF=${ONEFIELD##*=} ;; #ACK) #ACK set ;; #SYN) #SYN set ;; #*) #Ignore (digits), ACK=digits, CODE=digits, DF, ID=digits, LEN=digits, OPT, PSH, RES=hexdigits, SEQ=digits, TOS=hexdigits, TTL=digits, URGP=digits, WINDOW=digits # ;; esac done if [ -n "$INIF" ] && [ -z "$IF" ]; then #FIXME - DIR needs to be lowercase for all but iptables DIR='INPUT ' ; DIRLETTER='I' elif [ -n "$INIF" ] && [ -n "$IF" ]; then DIR='FORWARD' ; DIRLETTER='F' elif [ -z "$INIF" ] && [ -n "$IF" ]; then DIR='OUTPUT ' ; DIRLETTER='O' elif [ -z "$INIF" ] && [ -z "$IF" ]; then #This case shouldn't happen DIR='' ; DIRLETTER='' fi #FIXME - if either ECHOCOMMAND or DOCOMMAND isn't iptables, we need to handle INIF -> IF if IF unset. It probably needs to be done in the ECHO/DO sections. Bash ${ } macro? ISLOGLINE="YES" #FIXME - temporary test code #ISLOGLINE="NO" #DIR='forward' ; DIRLETTER='F' #IF="lo" #wrap J1=$J1 J2=$J2 J3=$J3 J4=$J4 J5=$J5 J6=$J6 J7=$J7 J8=$J8 J9=$J9 J10=$J10 J11=$J11 J12=$J12 J13=$J13 J14=$J14 J15=$J15 J16=$J16 J17=$J17 J18=$J18 J19=$J19 DIR=$DIR DIRLETTER=$DIRLETTER DESTPORT=$DESTPORT DESTIP=$DESTIP PROTO=$PROTO SRCPORT=$SRCPORT SRCIP=$SRCIP >/dev/stderr #FIXME - what about these? #case $J7 in #fw-out) DIR='output ' ; DIRLETTER='O' ;; #fw-in) DIR='input ' ; DIRLETTER='I' ;; #fw-fwd) DIR='forward' ; DIRLETTER='F' ;; #*) wrap ${WARN}Unknown direction $J7${NORM} >/dev/stderr ;; #esac #IF="$J9" ##MESSPOL="$J8" ; LFLAG="$J13" ; SFLAG="$J14" ; IFLAG="$J15" ; FOFLAG="$J16" ; TFLAG="$J17" ; DFFLAG="$J18" #Unused #if [ "${PROTO%%/*}" = "icmp" ]; then # SRCPORT=${PROTO##*/} # PROTO="icmp" # DESTPORT="" # if [ "$DEBUG" = "YES" ]; then wrap proto= $PROTO srcport= $SRCPORT destport= $DESTPORT >/dev/stderr ; fi #else # SRCPORT=${SRC##*:} # DESTPORT=${DEST##*:} #fi #No need to set IGNOREPORT - ipfwadm only handles tcp, udp, and icmp. ;; esac elif [ "$J1" = "Chain" ]; then #Load variables from ipchains -Lv listing; this is a header line. CURRCHAIN=$J2 INFORMAT="ipchains-lv" elif [ "$J1" = "Chain" ]; then #Load variables from ipchains -Lv listing; this is a header line. : elif [ "$J6" = "0xFF" ] || [ "$J6" = "0x01" ]; then #Load variables from ipchains -Lv listing; this is a data line. case $J7 in 0x*) ISLOGLINE="YES" INFORMAT="ipchains-lv" case $CURRCHAIN in output) DIR='output' ; DIRLETTER='O' ;; input) DIR='input' ; DIRLETTER='I' ;; forward) DIR='forward' ; DIRLETTER='F' ;; "") wrap ${WARN}No chain name has been registered. Mason cannot process this entry.${NORM} >/dev/stderr ; ISLOGLINE="" ;; *) DIR="$CURRCHAIN" ; DIRLETTER='Q' if [ -z "$OTHERCHAINWARNISSUED" ]; then case "$ECHOCOMMAND" in ipchains|ipchains-lv|iptables) : ;; *) echo "$CMNT Any following rules with a direction of \"Q\" need to be edited. They" echo "$CMNT came from an ipchains/iptables rule other than input, output, or forward." OTHERCHAINWARNISSUED="YES" ;; esac fi ;; esac case $J5 in #FIXME - formalize this parsing. double check these, check other flag fields. -y*) ACK="! -k" ;; !y*) ACK="-k" ;; *l-) LOGTHIS="-l" ;; --*) ACK="" ;; esac MESSPOL=$J3 if [ "$J8" = "*" ]; then IF="" ; else IF="$J8" ; fi if [ "$J4" = "all" ]; then PROTO="" ; else protonum2name $J4 ; fi if [ "$J6 $J7" != "0xFF 0x00" ]; then TOS=" -t $J6 $J7" ; else TOS="" ; fi #FIXME - handle case of existing or missing mark and outsize fields case $J9 in */*) SRCIP="$J9" ;; *) SRCIP="$J9/32" ;; esac case $J10 in */*) DESTIP="$J10" ;; *) DESTIP="$J10/32" ;; esac NUMPACKETS=$J1 ; NUMBYTES=$J2 #LFLAG="$J13" ; SFLAG="$J14" ; IFLAG="$J15" ; FOFLAG="$J16" ; TFLAG="$J17" ; DFFLAG="$J18" #Unused case $J11 in n/a) SRCPORT="" ;; '*') SRCPORT="" ;; *:*) if [ "${J11%%:*}" = "${J11##*:}" ]; then SRCPORT=${J11%%:*} ; else SRCPORT=$J11 ; fi ;; *) SRCPORT=$J11 ;; esac case $J13 in '*') DESTPORT="" ;; *:*) if [ "${J13%%:*}" = "${J13##*:}" ]; then DESTPORT=${J13%%:*} ; else DESTPORT=$J13 ; fi ;; *) DESTPORT=$J13 ;; esac ;; esac elif [ "$J6" = "->" ]; then #Load variables from an ipfilter log line #1 2 3 4 5 6 7 8 9 10 11 12 13 14 #15:57:33.803147 ppp0 @0:2 b 100.100.100.103,443 -> 20.20.20.10,4923 PR tcp len 20 1488 -A # rule p flags # # #12:46:12.470951 xl0 @0:1 S 20.20.20.254 -> 255.255.255.255 PR icmp len 20 9216 icmp 9/0 # router discovery : fi CKPTMASON=" mason: Process line, set line policy" ; #ckpt $CKPTMASON if [ "$ISLOGLINE" = "YES" ]; then if [ "$INFORMAT" = "ipchains-lv" ] && { [ "$DOCOMMAND" = "ipchains" ] || [ "$DOCOMMAND" = "iptables" ] ; } ; then #We actually use the policy in each line in ipchains-lv entries case "$MESSPOL" in accept|ACCEPT) LCPOLICY="accept" ; UCPOLICY="ACCEPT" ;; reject|REJECT) LCPOLICY="reject" ; UCPOLICY="REJECT" ;; deny|DENY) LCPOLICY="deny" ; UCPOLICY="DENY" ;; "-") LCPOLICY="" ; UCPOLICY="" ;; *) LCPOLICY=$MESSPOL ; UCPOLICY=$MESSPOL ;; esac elif [ "$INFORMAT" = "ipchains-lv" ]; then #We actually use the policy in each line in ipchains-lv entries case "$MESSPOL" in accept|ACCEPT) LCPOLICY="accept" ; UCPOLICY="ACCEPT" ;; reject|REJECT) LCPOLICY="reject" ; UCPOLICY="REJECT" ;; deny|DENY) LCPOLICY="deny" ; UCPOLICY="DENY" ;; "-") #FIXME - technically these should be accounting rules for I and O, a warning for F. case "$NEWRULEPOLICY" in a*|A*) LCPOLICY="accept" ; UCPOLICY="ACCEPT" ;; r*|R*) LCPOLICY="reject" ; UCPOLICY="REJECT" ;; d*|D*) LCPOLICY="deny" ; UCPOLICY="DENY" ;; esac ;; *) LCPOLICY=$MESSPOL ; UCPOLICY=$MESSPOL ;; esac else case "$NEWRULEPOLICY" in a*|A*) LCPOLICY="accept" ; UCPOLICY="ACCEPT" ;; r*|R*) LCPOLICY="reject" ; UCPOLICY="REJECT" ;; d*|D*) LCPOLICY="deny" ; UCPOLICY="DENY" ;; esac fi #Handle AUTOMASQ feature. Masquerade packets forwarded to requested interfaces if source #address is a reserved (rfc1918) address. CKPTMASON=" mason: Process line, check for masq" ; #ckpt $CKPTMASON if [ "$DIRLETTER" = "F" ] && [ -n "$AUTOMASQIF" ] && [ "$LCPOLICY" = "accept" ] && reservedip $SRCIP ; then for ANIF in $AUTOMASQIF ; do if [ "$ANIF" = "$IF" ]; then UCPOLICY="MASQ" #For ipchains LCPOLICY="accept -m" #For ipfwadm #FIXME - iptables... fi done fi #If forwarding and automasq requested. if [ "$IGNOREPORT" = "YES" ]; then SRCPORT="" ; DESTPORT="" ; fi #Quickly put in a completely specific rule for this packet to stop the flow - it will be deleted later #in masonlib: LCPOLICY, UCPOLICY #from above: IF, DIR, DIRLETTER, PROTO, SRCIP, SRCPORT, DESTIP, DESTPORT #not set? ACK, SRCHOST, DESTHOST, TOS, DOACK UNDOSPECIFICRULE="" if [ "$DOCOMMAND" = "ipfwadm" ]; then CKPTMASON=" mason: Process line, ipfwadm specific rule" ; #ckpt $CKPTMASON #REMOVEME #$IPFWADMBIN -i $LCPOLICY ${IF:+"-W"} $IF -$DIRLETTER ${PROTO:+"-P"} $PROTO -S $SRCIP $SRCPORT -D $DESTIP $DESTPORT || logfail $LINENO Mason: YYYY 0001 #REMOVEME echo 0018 DIRLETTER $DIRLETTER >>${MASONDIR}masoncrash dorule i "$DIRLETTER" "$IF" '' "$PROTO" "$SRCIP" "$SRCPORT" "$DESTIP" "$DESTPORT" '' '' "$LCPOLICY" '' '' '' || logfail $LINENO Mason: YYYY 0018 #UNDOSPECIFICRULE="$IPFWADMBIN -d $LCPOLICY ${IF:+"-W"} $IF -$DIRLETTER ${PROTO:+"-P"} $PROTO -S $SRCIP $SRCPORT -D $DESTIP $DESTPORT || logfail $LINENO Mason: YYYY 0002" #FIXME global - quoting on ''? UNDOSPECIFICRULE="dorule d \"$DIRLETTER\" \"$IF\" '' \"$PROTO\" \"$SRCIP\" \"$SRCPORT\" \"$DESTIP\" \"$DESTPORT\" '' '' \"$LCPOLICY\" '' '' '' || logfail $LINENO Mason: YYYY 0019" CKPTMASON=" mason: Process line, ipfwadm post specific rule" ; #ckpt $CKPTMASON elif [ "$DOCOMMAND" = "ipchains" ]; then case $DIRLETTER in I) DODIR="`chainnameof input`$NOLOGSUFFIX" ;; O) DODIR="`chainnameof output`$NOLOGSUFFIX" ;; F) DODIR="`chainnameof forward`$NOLOGSUFFIX" ;; esac CKPTMASON=" mason: pre specific rule" ; #ckpt $CKPTMASON #REMOVEME #$IPCHAINSBIN -I $DODIR 1 ${IF:+"-i"} $IF ${PROTO:+"-p"} $PROTO -s $SRCIP $SRCPORT -d $DESTIP $DESTPORT ${UCPOLICY:+"-j"} $UCPOLICY || logfail $LINENO Mason: YYYY 0003 $IPCHAINSBIN -I $DODIR 1 ${IF:+"-i"} $IF ${PROTO:+"-p"} $PROTO -s $SRCIP $SRCPORT -d $DESTIP $DESTPORT ${UCPOLICY:+"-j"} $UCPOLICY #REMOVEME echo 0020 DODIR $DODIR >>${MASONDIR}masoncrash dorule i "$DODIR" "$IF" '' "$PROTO" "$SRCIP" "$SRCPORT" "$DESTIP" "$DESTPORT" '' '' "$UCPOLICY" '' '' '' || logfail $LINENO Mason: YYYY 0020 CKPTMASON=" mason: post specific rule" ; #ckpt $CKPTMASON #UNDOSPECIFICRULE="$IPCHAINSBIN -D $DODIR ${IF:+"-i"} $IF ${PROTO:+"-p"} $PROTO -s $SRCIP $SRCPORT -d $DESTIP $DESTPORT ${UCPOLICY:+"-j"} $UCPOLICY || logfail $LINENO Mason: YYYY 0004" UNDOSPECIFICRULE="dorule d \"$DODIR\" \"$IF\" '' \"$PROTO\" \"$SRCIP\" \"$SRCPORT\" \"$DESTIP\" \"$DESTPORT\" '' '' \"$UCPOLICY\" '' '' '' || logfail $LINENO Mason: YYYY 0021" unset DODIR || : #FIXME - add in iptables section for quick stop. Should we do a quick stop for iptables? fi # no need to handle DOCOMMAND=none :-) #Put the dynamic IP addresses in the current environment. for ONEIF in $DYNIF ; do CKPTMASON=" mason: eval dynif of $ONEIF" ; #ckpt $CKPTMASON #this just places the value of a var right back in that same var! #eval ${ONEIF}ADDR=$(eval echo \${$(eval echo ${ONEIF}ADDR)}) #No, really. That's the IP address. #Umm, this is what I think I need... *smile* eval ${ONEIF}ADDR=`ipof $ONEIF || logfail $LINENO Mason: YYYY 0005` done CKPTMASON=" mason: gen ip" ; #ckpt $CKPTMASON if [ "$INFORMAT" = "ipchains-lv" ]; then SRCHOST=$SRCIP DESTHOST=$DESTIP elif [ "$IGNOREPORT" = "YES" ]; then #For non tcp/udp/icmp protocols (w/o port numbers), restrict to machine to machine HOLDIPCONV="$IPCONV" #Convert to hostname, but honor Dynamic IP macros. Temporarily set IPCONV to HOST to do this. IPCONV="HOST" SRCHOST=`generalizeip $SRCIP` DESTHOST=`generalizeip $DESTIP` IPCONV="$HOLDIPCONV" else #If this is a DNS request and the server is one of those listed in /etc/resolv.conf, don't generalize the ip address. #Also, don't generalize if this is one of the Sparse Server or Sparse Client protocols. HOLDIPCONV="$IPCONV" ; HOLDHOSTLOOKUP="$HOSTLOOKUP" if [ "$SRCPORT" = "53" ] && ( [ "$PROTO" = "udp" ] || [ "$PROTO" = "tcp" ] ) ; then for ONEDNSSERVER in $DNSSERVERS ; do if [ "$SRCIP" = "$ONEDNSSERVER" ]; then if [ "$IPCONV" = "NETWORK" ]; then IPCONV="HOST" ; fi if [ "$HOSTLOOKUP" = "FULL" ]; then HOSTLOOKUP="FILESONLY" ; fi fi done fi for ONESPARSE in $SSP ; do if [ "$SRCPORT/$PROTO" = "$ONESPARSE" ] && [ "$IPCONV" = "NETWORK" ]; then IPCONV="HOST" ; fi done for ONESPARSE in $SCP ; do if [ "$DESTPORT/$PROTO" = "$ONESPARSE" ] && [ "$IPCONV" = "NETWORK" ]; then IPCONV="HOST" ; fi done SRCHOST=`generalizeip $SRCIP` IPCONV="$HOLDIPCONV" ; HOSTLOOKUP="$HOLDHOSTLOOKUP" HOLDIPCONV="$IPCONV" ; HOLDHOSTLOOKUP="$HOSTLOOKUP" if [ "$DESTPORT" = "53" ] && ( [ "$PROTO" = "udp" ] || [ "$PROTO" = "tcp" ] ) ; then for ONEDNSSERVER in $DNSSERVERS ; do if [ "$DESTIP" = "$ONEDNSSERVER" ]; then if [ "$IPCONV" = "NETWORK" ]; then IPCONV="HOST" ; fi if [ "$HOSTLOOKUP" = "FULL" ]; then HOSTLOOKUP="FILESONLY" ; fi fi done fi for ONESPARSE in $SSP ; do if [ "$DESTPORT/$PROTO" = "$ONESPARSE" ] && [ "$IPCONV" = "NETWORK" ]; then IPCONV="HOST" ; fi done for ONESPARSE in $SCP ; do if [ "$SRCPORT/$PROTO" = "$ONESPARSE" ] && [ "$IPCONV" = "NETWORK" ]; then IPCONV="HOST" ; fi done DESTHOST=`generalizeip $DESTIP` IPCONV="$HOLDIPCONV" ; HOSTLOOKUP="$HOLDHOSTLOOKUP" fi #Clean up protocol type and number fields, visualize source and dest port fields, set ack flag. #If port not in /etc/services and >=1024, generalize to "high port" CKPTMASON=" mason: port range and comment" ; #ckpt $CKPTMASON COMMENT2="" ; COMMENT="$CMNT" ; SRCCISCOPORTSPEC="" ; DESTCISCOPORTSPEC="" if [ "$PROTO" = "tcp" ] || [ "$PROTO" = "udp" ]; then if [ -n "$SRCPORT" ]; then serverportrange "$SRCPORT" "$PROTO" if [ "$INFORMAT" = "ipchains-lv" ]; then SRCSERVICE="$SRCPORT" ; else SRCSERVICE="$READABLEPORT" ; fi SRCCOMMENT="$PARTIALCOMMENT" fi if [ -n "$DESTPORT" ]; then serverportrange "$DESTPORT" "$PROTO" if [ "$INFORMAT" = "ipchains-lv" ]; then DESTSERVICE="$DESTPORT" ; else DESTSERVICE="$READABLEPORT" ; fi DESTCOMMENT="$PARTIALCOMMENT" fi CKPTMASON=" mason: src $SRCSERVICE $SRCCOMMENT dest $DESTSERVICE $DESTCOMMENT" ; #ckpt $CKPTMASON if [ "$INFORMAT" != "ipchains-lv" ]; then if [ "$PROTO" = "tcp" ] && [ "$INFORMAT" != "ipchains-lv" ]; then #The ack flag should be set if port=tcp and source port is a server service. #The one tcpdump I've seen of an ftp connection seems to indicate that the #ftp-data connection is from the _server_ to the client - backwards. #Passive mode FTP is supposed to reverse this. Ugh. And again, I say, Ugh. #FIXME - use the SYN / PENANCE flag Rusty's putting into later 2.2's. Thanks, Rusty! #From 2.2.10/ip_fw.c: #if(tcp->syn && !(tcp->ack || tcp->rst)) #tcpsyn=1; #if [ "$SYNFLAGSEEN" = "YES" ] && [ "SYNFLAG" != "SYN" ]; then #ACK="-k" #Change next line to elif - hmmm, did I if block this right? if [ -n "$SRCSERVICE" ] && [ -z "$DESTSERVICE" ] && [ "$SRCPORT/$PROTO" != "20/tcp" ]; then ACK="-k" fi #ZZZZ - auth exception... if [ "$GENERALIZETCPACK" = "YES" ] && [ "$ACK" = "-k" ]; then #If we're in this section we already know PROTO=tcp if [ "$UCPOLICY" = "ACCEPT" ] || [ "$UCPOLICY" = "MASQ" ]; then if isdigits "$SRCPORT"; then SRCSERVICE=`generalportrange "$SRCPORT"` ; SRCCOMMENT="GENERALIZED TCP RESPONSE - place last" fi if isdigits "$DESTPORT"; then DESTSERVICE=`generalportrange "$DESTPORT"` ; DESTCOMMENT="GENERALIZED TCP RESPONSE - place last" fi fi #Is accept or masq fi #Generalizetcpack and ack flag set fi #proto=tcp and not ipchains-lv CKPTMASON=" mason: port and service sservice $SRCSERVICE dservice $DESTSERVICE" ; #ckpt $CKPTMASON if [ -n "$SRCSERVICE" ] && [ -n "$DESTSERVICE" ]; then # Both source and destination ports are servers. Rare, but possible. SRCPORT=$SRCSERVICE DESTPORT=$DESTSERVICE elif [ -n "$SRCSERVICE" ]; then # Source port is a server port. DESTPORT=`clientportrange "$DESTPORT" "$SRCPORT" "$PROTO" "$ACK"` settos "$SRCPORT" "$SRCSERVICE" "$PROTO" SRCPORT=$SRCSERVICE elif [ -n "$DESTSERVICE" ]; then # Dest port is a server port. SRCPORT=`clientportrange "$SRCPORT" "$DESTPORT" "$PROTO" "$ACK"` settos "$DESTPORT" "$DESTSERVICE" "$PROTO" DESTPORT=$DESTSERVICE else # Neither source nor dest is a server port. #COMMENT2="$CMNT$CMNT S=`nameof $SRCIP`:$SRCPORT D=`nameof $DESTIP`:$DESTPORT" #FIXME - put in case to test for null, */0, local IP, otherwise display COMMENT2="$CMNT$CMNT" if [ -n "$SRCIP" ]; then COMMENT2="$COMMENT2 S=`nameof $SRCIP`" ; fi if [ -n "$SRCPORT" ]; then COMMENT2="$COMMENT2:$SRCPORT" ; fi if [ -n "$DESTIP" ]; then COMMENT2="$COMMENT2 D=`nameof $DESTIP`" ; fi if [ -n "$DESTPORT" ]; then COMMENT2="$COMMENT2:$DESTPORT" ; fi ORIGSRCPORT=$SRCPORT SRCPORT=`clientportrange "$SRCPORT" "$DESTPORT" "$PROTO" "$ACK"` DESTPORT=`clientportrange "$DESTPORT" "$ORIGSRCPORT" "$PROTO" "$ACK"` unset ORIGSRCPORT #if [ "$INFORMAT" != "ipchains-lv" ]; then TOS=" -t 0x01 0x08" ; fi #Maximize throughput on the assumption that this is FTP data or irc dcc? #If we have a high port to high port connection (darn ftp and irc dcc), do _not_ generalize to anywhere if [ "$SRCPORT" = "1024:65535" ] && [ "$DESTPORT" = "1024:65535" ]; then if [ "$SRCHOST" = "0/0" ]; then HOLDIPCONV="$IPCONV" ; IPCONV="HOST" ; SRCHOST=`generalizeip $SRCIP` ; IPCONV="$HOLDIPCONV" fi if [ "$DESTHOST" = "0/0" ]; then HOLDIPCONV="$IPCONV" ; IPCONV="HOST" ; DESTHOST=`generalizeip $DESTIP` ; IPCONV="$HOLDIPCONV" fi fi fi if [ -n "$SRCCOMMENT" ]; then COMMENT="$COMMENT $SRCCOMMENT" ; fi if [ -n "$DESTCOMMENT" ]; then if [ "$SRCCOMMENT" != "$DESTCOMMENT" ]; then COMMENT="$COMMENT $DESTCOMMENT" ; fi fi COMMENT="$COMMENT ($DIRLETTER)" SRCCISCOPORTSPEC="`port2ciscoport $SRCPORT $PROTO`" DESTCISCOPORTSPEC="`port2ciscoport $DESTPORT $PROTO`" fi #not ipchains-lv elif [ "$PROTO" = "icmp" ]; then #Handle ICMP comments convicmpcode $SRCPORT $DESTPORT #FIXME - maybe someday we'll do the cisco conversions to names too. DESTCISCOPORTSPEC=" $SRCPORT${DESTPORT:+" "}$DESTPORT" else #Handle non tcp/udp/icmp protocols COMMENT="$CMNT $PROTO ($DIRLETTER)" #COMMENT2="$CMNT$CMNT S=`nameof $SRCIP` D=`nameof $DESTIP`" COMMENT2="$CMNT$CMNT" #FIXME - put in case to test for null, */0, otherwise display if [ -n "$SRCIP" ]; then COMMENT2="$COMMENT2 S=`nameof $SRCIP`" ; fi if [ -n "$DESTIP" ]; then COMMENT2="$COMMENT2 D=`nameof $DESTIP`" ; fi fi if [ -n "$NUMPACKETS" ]; then COMMENT2="$COMMENT2 #^ $NUMPACKETS" ; fi if [ -n "$NUMBYTES" ]; then COMMENT2="$COMMENT2 #@ $NUMBYTES" ; fi #if [ "$LINEHASDYNAMIC" = "YES" ]; then COMMENT="$COMMENT DynamicIP" ; fi #LINEHASDYNAMIC is not exported because generalizeip is a function. Not used. CKPTMASON=" mason: var debug" ; #ckpt $CKPTMASON if [ "$DEBUG" = "YES" ]; then wrap J1=$J1 J2=$J2 J3=$J3 J4=$J4 J5=$J5 J6=$J6 J7=$J7 J8=$J8 J9=$J9 J10=$J10 J11=$J11 J12=$J12 J13=$J13 J14=$J14 J15=$J15 J16=$J16 J17=$J17 J18=$J18 J19=$J19 DIR=$DIR DIRLETTER=$DIRLETTER MESSPOL=$MESSPOL IF=$IF PROTO=$PROTO SRC=$SRC DEST=$DEST LFLAG=$LFLAG SFLAG=$SFLAG IFLAG=$IFLAG FOFLAG=$FOFLAG FFLAG=$FFLAG TFLAG=$TFLAG DFFLAG=$DFFLAG TAIL=$TAIL >/dev/stderr wrap Unused: DFFLAG, FFLAG, FOFLAG, IFLAG, LFLAG, MESSPOL, SFLAG, TFLAG >/dev/stderr fi #Actually create and implement the firewall command to display. CKPTMASON=" mason: Display" ; #ckpt $CKPTMASON DODISPLAY="YES" case "$ECHOCOMMAND" in #CURRENT=`awk "BEGIN {printf \"%x %0.0s %-12s %s x \n\", 57005, \"$AA$BB\", \"aaa\", \"cheeky\"}"` ipchains) CKPTMASON=" mason: ipchains display" ; #ckpt $CKPTMASON case "$ACK" in ""|" ") ECHOACK="" ;; "-k") ECHOACK="! -y" ;; "! -k") ECHOACK="-y" ;; esac if [ -n "$LOGTHIS" ]; then LOGTHIS="-l" ; fi #Handle 0/0 host spec or missing port spec - thanks, Rusty! case $SRCHOST in */0|*/0.0.0.0) if [ -n "$SRCPORT" ]; then SRCSPEC="--sport $SRCPORT " ; else SRCSPEC="" ; fi ;; *) if [ -n "$SRCPORT" ]; then SRCSPEC="-s $SRCHOST $SRCPORT " ; else SRCSPEC="-s $SRCHOST " ; fi ;; esac case $DESTHOST in */0|*/0.0.0.0) if [ -n "$DESTPORT" ]; then DESTSPEC="--dport $DESTPORT" ; else DESTSPEC="" ; fi ;; *) if [ -n "$DESTPORT" ]; then DESTSPEC="-d $DESTHOST $DESTPORT" ; else DESTSPEC="-d $DESTHOST" ; fi ;; esac #CURRENT="$IPCHAINSBIN -A $DIR ${IF:+"-i "}$IF ${PROTO:+"-p "}$PROTO $ECHOACK $SRCSPEC$DESTSPEC$TOS ${UCPOLICY:+"-j"} $UCPOLICY $LOGTHIS" #TOS is either blank or has a leading space #REMOVEME #FIXME - dont pad variables any more. -------------15----12----9----12---5---83 = 136 CKPTMASON=" mason: ipchains display - awk" ; #ckpt $CKPTMASON CURRENT=`awk "BEGIN {printf \"$IPCHAINSBIN %-11s %-8s %-11s %4s %-83s\", \ \"${DIR:+"-A "}$DIR\", \ \"${IF:+"-i "}$IF\", \ \"${PROTO:+"-p "}$PROTO\", \ \"$ECHOACK\", \ \"$SRCSPEC$DESTSPEC$TOS${MINMARK:+" -m "}$MINMARK${UCPOLICY:+" -j "}$UCPOLICY${LOGTHIS:+" "}$LOGTHIS\" \ }" || logfail $LINENO Mason: YYYY 0006` if [ -n "$MINMARK" ]; then INCMINMARK="1" ; fi ;; #ZZZZ - start of ECHOCOMMAND conversion to iptables. This is NOT complete. iptables) CKPTMASON=" mason: iptables display" ; #ckpt $CKPTMASON #FIXME - fix ACK matching case "$ACK" in ""|" ") ECHOACK="" ;; "-k") ECHOACK="! --syn" ;; "! -k") ECHOACK="--syn" ;; esac #FIXME - fix logging #if [ -n "$LOGTHIS" ]; then LOGTHIS="-l" ; fi #Handle 0/0 host spec or missing port spec - thanks, Rusty! case $PROTO in [Ii][Cc][Mm][Pp]) case $SRCHOST in */0|*/0.0.0.0) SRCSPEC="" ;; *) SRCSPEC="-s $SRCHOST " ;; esac case $DESTHOST in */0|*/0.0.0.0) DESTSPEC="" ;; *) DESTSPEC="-d $DESTHOST" ;; esac if [ -n "$SRCPORT" ]; then if [ -n "$DESTSPEC" ]; then DESTSPEC="$DESTSPEC " ; fi DESTSPEC="$DESTSPEC--icmp-type $SRCPORT" if [ -n "$DESTPORT" ]; then DESTSPEC="$DESTSPEC/$DESTPORT" fi fi ;; *) case $SRCHOST in */0|*/0.0.0.0) if [ -n "$SRCPORT" ]; then SRCSPEC="--sport $SRCPORT " ; else SRCSPEC="" ; fi ;; *) if [ -n "$SRCPORT" ]; then SRCSPEC="-s $SRCHOST --sport $SRCPORT " ; else SRCSPEC="-s $SRCHOST " ; fi ;; esac case $DESTHOST in */0|*/0.0.0.0) if [ -n "$DESTPORT" ]; then DESTSPEC="--dport $DESTPORT" ; else DESTSPEC="" ; fi ;; *) if [ -n "$DESTPORT" ]; then DESTSPEC="-d $DESTHOST --dport $DESTPORT" ; else DESTSPEC="-d $DESTHOST" ; fi ;; esac ;; esac if [ -n "$INIF" ] && [ -n "$IF" ]; then IFSPEC="-i $INIF -o $IF" elif [ -n "$INIF" ]; then IFSPEC="-i $INIF" elif [ -n "$IF" ]; then IFSPEC="-o $IF" else IFSPEC="" fi #CURRENT="$IPTABLESBIN -A $DIR ${IF:+"-i "}$IF ${PROTO:+"-p "}$PROTO $ECHOACK $SRCSPEC$DESTSPEC$TOS ${UCPOLICY:+"-j"} $UCPOLICY $LOGTHIS" #TOS is either blank or has a leading space #REMOVEME #FIXME - dont pad variables any more. -------------15----12----9----12---5---83 = 136 CKPTMASON=" mason: iptables display - awk" ; #ckpt $CKPTMASON CURRENT=`awk "BEGIN {printf \"$IPTABLESBIN %-11s %-8s %-11s %4s %-83s\", \ \"${DIR:+"-A "}$DIR\", \ \"$IFSPEC\", \ \"${PROTO:+"-p "}$PROTO\", \ \"$ECHOACK\", \ \"$SRCSPEC$DESTSPEC$TOS${UCPOLICY:+" -j "}$UCPOLICY${LOGTHIS:+" "}$LOGTHIS\" \ }" || logfail $LINENO Mason: YYYY 0007` #${MINMARK:+" -m "}$MINMARK #FIXME - future mark support? #if [ -n "$MINMARK" ]; then INCMINMARK="1" ; fi ;; #ZZZZ - end of conversion ipchains-save) #Currently experimental CKPTMASON=" mason: ipchains-save display" ; #ckpt $CKPTMASON case "$ACK" in " ") ECHOACK="" ;; "-k") ECHOACK="! -y" ;; "! -k") ECHOACK="-y" ;; esac if [ -n "$LOGTHIS" ]; then LOGTHIS="-l" ; fi case $SRCHOST in */0|*/0.0.0.0) SRCSPEC=" -s 0.0.0.0/0.0.0.0" ;; *) SRCSPEC=" -s ${SRCHOST%%/*}/`bits2mask ${SRCHOST##*/}`" ;; esac case "$SRCPORT" in #serverportrange should have returned a numeric port for ipchains-save "") SRCSPEC="$SRCSPEC 0:65535" ;; *:*) SRCSPEC="$SRCSPEC $SRCPORT" ;; *) SRCSPEC="$SRCSPEC $SRCPORT:$SRCPORT" ;; esac case $DESTHOST in */0|*/0.0.0.0) DESTSPEC=" -d 0.0.0.0/0.0.0.0" ;; *) DESTSPEC=" -d ${DESTHOST%%/*}/`bits2mask ${DESTHOST##*/}`" ;; esac case "$DESTPORT" in "") DESTSPEC="$DESTSPEC 0:65535" ;; *:*) DESTSPEC="$DESTSPEC $DESTPORT" ;; *) DESTSPEC="$DESTSPEC $DESTPORT:$DESTPORT" ;; esac PROTONUMBER=`grep -i "^$PROTO[[:space:]]" /etc/protocols | awk '{print $2}' || logfail $LINENO Mason: YYYY 0008` #Head -1? if [ -z "$PROTONUMBER" ]; then #CURRENT="-A $DIR $SRCSPEC $DESTSPEC ${IF:+"-i "}$IF ${PROTO:+"-p "}$PROTO $TOS ${UCPOLICY:+"-j "}$UCPOLICY $LOGTHIS $ECHOACK ${MINMARK:+"-m"} $MINMARK" #TOS is either blank or has a leading space #REMOVEME CURRENT=`awk "BEGIN {printf \"%-111s\", \ \"${DIR:+"-A "}$DIR$SRCSPEC$DESTSPEC${IF:+" -i "}$IF${PROTO:+" -p "}$PROTO$TOS${UCPOLICY:+" -j "}$UCPOLICY${LOGTHIS:+" "}$LOGTHIS${ECHOACK:+" "}$ECHOACK${MINMARK:+" -m "}$MINMARK\" }" || logfail $LINENO Mason: YYYY 0009` else #CURRENT="-A $DIR $SRCSPEC $DESTSPEC ${IF:+"-i "}$IF ${PROTONUMBER:+"-p "}$PROTONUMBER $TOS ${UCPOLICY:+"-j "}$UCPOLICY $LOGTHIS $ECHOACK ${MINMARK:+"-m"} $MINMARK" #TOS is either blank or has a leading space #REMOVEME CURRENT=`awk "BEGIN {printf \"%-111s\", \ \"${DIR:+"-A "}$DIR$SRCSPEC$DESTSPEC${IF:+" -i "}$IF${PROTONUMBER:+" -p "}$PROTONUMBER$TOS${UCPOLICY:+" -j "}$UCPOLICY${LOGTHIS:+" "}$LOGTHIS${ECHOACK:+" "}$ECHOACK${MINMARK:+" -m "}$MINMARK\" }" || logfail $LINENO Mason: YYYY 0010` fi ;; ipfwadm) CKPTMASON=" mason: ipfwadm display" ; #ckpt $CKPTMASON if [ -n "$LOGTHIS" ]; then LOGTHIS="-o" ; fi #CURRENT="$IPFWADMBIN -a $LCPOLICY ${IF:+"-W "}$IF ${DIRLETTER:+"-"}$DIRLETTER ${PROTO:+"-P "}$PROTO $ACK -S $SRCHOST $SRCPORT -D $DESTHOST $DESTPORT$TOS $LOGTHIS" #REMOVEME CURRENT=`awk "BEGIN {printf \"$IPFWADMBIN %-9s %-8s %-2s %-11s %4s %-72s\", \ \"${LCPOLICY:+"-a "}$LCPOLICY\", \ \"${IF:+"-W "}$IF\", \ \"${DIRLETTER:+"-"}$DIRLETTER\", \ \"${PROTO:+"-P "}$PROTO\", \ \"$ACK\", \ \"-S $SRCHOST $SRCPORT -D $DESTHOST $DESTPORT$TOS $LOGTHIS\" \ }" || logfail $LINENO Mason: YYYY 0011` case $PROTO in [Tt][Cc][Pp]|[Uu][Dd][Pp]|[Ii][Cc][Mm][Pp]) #FIXME - should we be actually running a rule here? I really think this is wrong. eval "$IPFWADMBIN ${LCPOLICY:+"-i"} $LCPOLICY ${IF:+"-W"} $IF -$DIRLETTER ${PROTO:+"-P"} $PROTO $ACK -S $SRCHOST $SRCPORT -D $DESTHOST $DESTPORT $TOS $LOGTHIS || logfail $LINENO Mason: YYYY 0012" ;; *) CURRENT="#(invalid protocol for ipfwadm) $CURRENT" #only show the warning once. if [ -z "$NONIPFWADMPROTOWARNED" ]; then wrap ${WARN}ipfwadm cannot handle protocols other than tcp, udp and icmp. This rule wanted to use protocol: $PROTO . This is the only warning you will get this run.${NORM} >/dev/stderr NONIPFWADMPROTOWARNED="YES" fi ;; esac ;; cisco) #FIXME handle comments to user for $IF, $DIRLETTER, fix "eq", TOS format? no forwarding rules (maybe in baserules?) #FIXME - is this screwing up the DOCOMMAND=ipchains parameters? CKPTMASON=" mason: cisco display" ; #ckpt $CKPTMASON if [ "$DIRLETTER" = "F" ]; then DODISPLAY="NO" ; wrap Forwarding rule skipped in cisco mode. >/dev/stderr elif [ "$IF" = "lo" ]; then DODISPLAY="NO" ; wrap Loopback interface skipped in cisco mode. >/dev/stderr else case "$LCPOLICY" in "reject"|"deny "|"deny") CISCOPOLICY="deny" ;; "accept"|"accept -m") CISCOPOLICY="permit" ;; #Cisco Masq? sorry, do not know how. *) CISCOPOLICY="unknown" ;; esac case "$ACK" in " ") ECHOACK="" ;; "-k") ECHOACK="established" ;; "! -k") ECHOACK="" ;; esac if [ -n "$LOGTHIS" ]; then LOGTHIS="log" ; fi if [ -n "$TOS" ]; then CISCOTOS=" tos$TOS" ; else CISCOTOS="" ; fi case $IF in eth0) CISCOIF="E0" ;; eth1) CISCOIF="E1" ;; eth2) CISCOIF="E2" ;; eth3) CISCOIF="E3" ;; ppp0) CISCOIF="S0" ;; ppp1) CISCOIF="S1" ;; ppp2) CISCOIF="S2" ;; ppp3) CISCOIF="S3" ;; tr0) CISCOIF="To0" ;; tr1) CISCOIF="To1" ;; tr2) CISCOIF="To2" ;; tr3) CISCOIF="To3" ;; *) CISCOIF="`echo "$IF" | sed -e 's/^eth/E/' -e 's/^ppp/S/' -e 's/^tr/To/'`" ;; esac #CURRENT="access-list $DIRLETTER$CISCOIF $CISCOPOLICY $PROTO $SRCHOST$SRCCISCOPORTSPEC $DESTHOST$DESTCISCOPORTSPEC$CISCOTOS $ECHOACK $LOGTHIS" #REMOVEME CURRENT=`awk "BEGIN {printf \"access-list %-4s %-6s %-8s %-90s\", \ \"$DIRLETTER$CISCOIF\", \ \"$CISCOPOLICY\", \ \"$PROTO\", \ \"$SRCHOST$SRCCISCOPORTSPEC $DESTHOST$DESTCISCOPORTSPEC$CISCOTOS $ECHOACK $LOGTHIS\" \ }" || logfail $LINENO Mason: YYYY 0013` fi ;; esac # No need to handle ECHOCOMMAND=none :-) CKPTMASON=" mason: finished display" ; #ckpt $CKPTMASON if [ "$DEBUG" = "YES" ]; then echo current= "$CURRENT" >/dev/stderr ; fi if [ -n "$UNDOSPECIFICRULE" ]; then eval "$UNDOSPECIFICRULE" ; fi #Don't do anything if this is the same as one of the last 8 rules. This #reduces the occurence of repeated rules showing up. CKPTMASON=" mason: Implement new rule" ; #ckpt $CKPTMASON #Yank mark values before comparing case `echo $CURRENT | sed -e 's/ -m [0-9][0-9]* //'` in $LAST1|$LAST2|$LAST3|$LAST4|$LAST5|$LAST6|$LAST7|$LAST8) if [ "$HEARTBEAT" = "YES" ]; then echo -n "-" >/dev/stderr ; NEEDLF="YES" ; fi ;; *) if [ "$NEEDLF" = "YES" ]; then echo >/dev/stderr ; NEEDLF="NO" ; fi if [ "$DOBEEP" = "YES" ]; then echo -n -e "\a" >/dev/stderr ; fi if [ "$DODISPLAY" = "YES" ]; then case $ECHOCOMMAND in ipchains|ipfwadm|cisco|iptables) echo "$CURRENT $COMMENT $COMMENT2" ;; ipchains-save) echo $CURRENT ;; esac fi #Put a real rule in the rule chain so that we don't log it again. We need to use eval since ${xxxHOST} may be a $DYNIP #and may need to be evaluated to its real value. CKPTMASON=" mason: Actually put new rule in" ; #ckpt $CKPTMASON if [ "$DOCOMMAND" = "ipfwadm" ]; then if [ -n "$LOGTHIS" ]; then LOGTHIS="-o" ; fi case $PROTO in [Tt][Cc][Pp]|[Uu][Dd][Pp]|[Ii][Cc][Mm][Pp]) #FIXME - here and below - watch out for data fields that have their own parameters "-t 0x..." #REMOVEME #eval "$IPFWADMBIN ${LCPOLICY:+"-i"} $LCPOLICY ${IF:+"-W"} $IF -$DIRLETTER ${PROTO:+"-P"} $PROTO $ACK -S $SRCHOST $SRCPORT -D $DESTHOST $DESTPORT $TOS $LOGTHIS || logfail $LINENO Mason: YYYY 0014" #REMOVEME echo 0022 DIRLETTER $DIRLETTER >>${MASONDIR}masoncrash dorule "i" "$DIRLETTER" "$IF" '' "$PROTO" "$SRCHOST" "$SRCPORT" "$DESTHOST" "$DESTPORT" '' "$ACK" "$LCPOLICY" "$TOS" "$LOGTHIS" "" || logfail $LINENO Mason: YYYY 0022 ;; *) #only show the warning once. if [ -z "$NONIPFWADMPROTOWARNED" ]; then wrap ${WARN}ipfwadm cannot handle protocols other than tcp, udp and icmp. This rule wanted to use protocol: $PROTO. This is the only warning you will get this run${NORM}. >/dev/stderr NONIPFWADMPROTOWARNED="YES" fi ;; esac elif [ "$DOCOMMAND" = "ipchains" ]; then case "$ACK" in ""|" ") DOACK="" ;; "-k") DOACK="! -y" ;; "! -k") DOACK="-y" ;; esac if [ -n "$LOGTHIS" ]; then LOGTHIS="-l" ; fi #FIXME - yank these once we're using dorule. case $DIRLETTER in I) DIR="`chainnameof input`$NOLOGSUFFIX" ;; O) DIR="`chainnameof output`$NOLOGSUFFIX" ;; F) DIR="`chainnameof forward`$NOLOGSUFFIX" ;; esac #REMOVEME #eval "$IPCHAINSBIN ${DIR:+"-I"} $DIR 1 ${IF:+"-i"} $IF ${PROTO:+"-p"} $PROTO $DOACK -s $SRCHOST $SRCPORT -d $DESTHOST $DESTPORT $TOS ${MINMARK:+"-m"} $MINMARK ${UCPOLICY:+"-j"} $UCPOLICY $LOGTHIS || logfail $LINENO Mason: YYYY 0015" #REMOVEME echo 0023 DIR $DIR >>${MASONDIR}masoncrash dorule i "$DIR" "$IF" '' "$PROTO" "$SRCHOST" "$SRCPORT" "$DESTHOST" "$DESTPORT" "$MINMARK" "$DOACK" "$UCPOLICY" "$TOS" "$LOGTHIS" "" || logfail $LINENO Mason: YYYY 0023 if [ -n "$MINMARK" ]; then INCMINMARK="1" ; fi #ZZZZ - start conversion to iptables. NOT complete. elif [ "$DOCOMMAND" = "iptables" ]; then case "$ACK" in ""|" ") DOACK="" ;; "-k") DOACK="! -y" ;; "! -k") DOACK="-y" ;; esac if [ -n "$LOGTHIS" ]; then LOGTHIS="-l" ; fi #FIXME - simplify, no case needed. global fix. case $DIRLETTER in I) DIR="`chainnameof INPUT`$NOLOGSUFFIX" ;; O) DIR="`chainnameof OUTPUT`$NOLOGSUFFIX" ;; F) DIR="`chainnameof FORWARD`$NOLOGSUFFIX" ;; esac #REMOVEME #eval "$IPTABLESBIN ${DIR:+"-I"} $DIR 1 ${IF:+"-i"} $IF ${PROTO:+"-p"} $PROTO $DOACK -s $SRCHOST $SRCPORT -d $DESTHOST $DESTPORT $TOS ${MINMARK:+"-m"} $MINMARK ${UCPOLICY:+"-j"} $UCPOLICY $LOGTHIS || logfail $LINENO Mason: YYYY 0016" #REMOVEME echo 0024 DIR $DIR >>${MASONDIR}masoncrash #Returns INPUTN, FORWARDN, OUTPUTN dorule i "$DIR" "$INIF" "$IF" "$PROTO" "$SRCHOST" "$SRCPORT" "$DESTHOST" "$DESTPORT" "$MINMARK" "$DOACK" "$UCPOLICY" "$TOS" "$LOGTHIS" "" || logfail $LINENO Mason: YYYY 0024 if [ -n "$MINMARK" ]; then INCMINMARK="1" ; fi #ZZZZ - end iptables conversion fi # no need to handle DOCOMMAND=none :-) CKPTMASON=" mason: push current rule on last stack" ; #ckpt $CKPTMASON LAST8=$LAST7 ; LAST7=$LAST6 ; LAST6=$LAST5 ; LAST5=$LAST4 LAST4=$LAST3 ; LAST3=$LAST2 ; LAST2=$LAST1 ; LAST1=`echo $CURRENT | sed -e 's/ -m [0-9][0-9]* //' || logfail $LINENO Mason: YYYY 0017` ;; esac #Check that current isn't equal to one of the previous 8 rules. if [ "$DEBUG" = "YES" ]; then wrap src= $SRCIP $SRCPORT dest= $DESTIP $DESTPORT if= $IF proto= $PROTO >/dev/stderr ; fi if [ "$LCPOLICY" = "accept -m" ]; then #Reset policy to non-masq for the next rule. UCPOLICY="ACCEPT" ; LCPOLICY="accept" fi fi #if ISLOGLINE if [ -n "$MINMARK" ]; then MINMARK=$[ $MINMARK + $INCMINMARK ] ; fi #Get the next log entry and start over. unset ACK COMMENT DEST DESTHOST DESTIP DESTPORT DIR DIRLETTER DOACK ECHOACK IF IGNOREPORT INIF ISLOGLINE \ LINEHASDYNAMIC LOGTHIS MESSPOL NUMBYTES NUMPACKETS PROTO SRC SRCHOST SRCIP SRCPORT SYNFLAG SYNFLAGSEEN TAIL TOS || : #unset DFFLAG FFLAG FOFLAG IFLAG LFLAG SFLAG TFLAG || : #These are unused. if [ -n "$MINMARK" ]; then INCMINMARK="0" ; fi TOS="" A3=$O3 ; A4=$O4 ; A5=$O5 ; A6=$O6 ; A7=$O7 ; A8=$O8 ; A9=$O9 ; A10=$O10 ; A11=$O11 ; A12=$O12 ; A13=$O13 O3=$J3 ; O4=$J4 ; O5=$J5 ; O6=$J6 ; O7=$J7 ; O8=$J8 ; O9=$J9 ; O10=$J10 ; O11=$J11 ; O12=$J12 ; O13=$J13 #CKPTMASON=" mason: reading next line" ; #ckpt $CKPTMASON CKPTMASON="" ; #ckpt $CKPTMASON if ! read J1 J2 J3 J4 J5 J6 J7 J8 J9 J10 J11 J12 J13 J14 J15 J16 J17 J18 J19 J20 J21 J22 J23 J24 J25 J26 J27 J28 J29 J30 ; then if [ "$SIGGED" != "YES" ]; then EXITMASON="YES" ; fi fi #Keep reading until a line with different firewall values is found. #FIXME - test for J19 once SYN checking is in place. J20+? #FIXME {O3=J3||INFORMAT=ipfwadm } or something like that for fields that don't need to be checked? A function? while { [ "$O3" = "$J3" ] && [ "$O4" = "$J4" ] && [ "$O5" = "$J5" ] && [ "$O6" = "$J6" ] && \ [ "$O7" = "$J7" ] && [ "$O8" = "$J8" ] && [ "$O9" = "$J9" ] && [ "$O10" = "$J10" ] && \ [ "$O11" = "$J11" ] && [ "$O12" = "$J12" ] && [ "$O13" = "$J13" ] ; } || { [ "$A3" = "$J3" ] && [ "$A4" = "$J4" ] && [ "$A5" = "$J5" ] && [ "$A6" = "$J6" ] && \ [ "$A7" = "$J7" ] && [ "$A8" = "$J8" ] && [ "$A9" = "$J9" ] && [ "$A10" = "$J10" ] && \ [ "$A11" = "$J11" ] && [ "$A12" = "$J12" ] && [ "$A13" = "$J13" ] ; } || { [ "$SIGGED" = "YES" ] ; } ; do #CKPTMASON=" mason: duped line or sigged" ; #ckpt $CKPTMASON CKPTMASON="" ; #ckpt $CKPTMASON if [ "$EXITMASON" = "YES" ]; then continue ; fi if [ "$SIGGED" = "YES" ]; then SIGGED="NO" else if [ "$HEARTBEAT" = "YES" ]; then echo -n "." >/dev/stderr ; NEEDLF="YES" ; fi A3=$O3 ; A4=$O4 ; A5=$O5 ; A6=$O6 ; A7=$O7 ; A8=$O8 ; A9=$O9 ; A10=$O10 ; A11=$O11 ; A12=$O12 ; A13=$O13 O3=$J3 ; O4=$J4 ; O5=$J5 ; O6=$J6 ; O7=$J7 ; O8=$J8 ; O9=$J9 ; O10=$J10 ; O11=$J11 ; O12=$J12 ; O13=$J13 fi if ! read J1 J2 J3 J4 J5 J6 J7 J8 J9 J10 J11 J12 J13 J14 J15 J16 J17 J18 J19 J20 J21 J22 J23 J24 J25 J26 J27 J28 J29 J30 ; then if [ "$SIGGED" != "YES" ]; then EXITMASON="YES" ; fi fi done done #CKPTMASON=" mason: outside of main loop" ; #ckpt $CKPTMASON CKPTMASON="" ; #ckpt $CKPTMASON if [ "$NEEDLF" = "YES" ]; then echo >/dev/stderr ; NEEDLF="NO" ; fi if [ "$J1" = '!!EXIT!!' ]; then wrap Mason is exiting because of an exit request on stdin. >/dev/stderr elif [ "$EXITMASON" = "YES" ]; then wrap Mason is exiting because of a SIGHUP or EXITMASON=YES. >/dev/stderr else wrap Mason is exiting because of an end of input data. >/dev/stderr fi CKPTMASON="" exit 0