#!/bin/bash
#builds a wall ... what else?
#Copyright 1998 William Stearns
#This code is entirely owned by William Stearns (wstearns@pobox.com) and 
#has no relation to any employer.
#Ideas
# #!/bin/bash at top of newrules
# run newrules, then append to it
# group local machines into subnet rule (configurable)
# group foreign machines into additional rule?
# pad if and proto fields to line up
#
#Quick start:
#- compile a kernel with firewall and firewall logging enabled, boot into it.
#- set any custom firewall rules you wish.
cat <<EOTEXT1 >/dev/null
	ipfwadm -I -f
	ipfwadm -O -f
	ipfwadm -F -f

	ipfwadm -O -i accept -D 0/0 53 -P udp
	ipfwadm -I -i accept -S 0/0 53 -P udp
	ipfwadm -I -i accept -D 0/0 53 -P udp
	ipfwadm -O -i accept -S 0/0 53 -P udp

	ipfwadm -O -i accept -W ppp0 -P udp -D 0/0 53
	ipfwadm -I -i accept -W ppp0 -P udp -S 0/0 53

#	ipfwadm -O -i accept -D 0/0 53 -P tcp
#	ipfwadm -I -i accept -S 0/0 53 -P tcp
#	ipfwadm -I -i accept -D 0/0 53 -P tcp
#	ipfwadm -O -i accept -S 0/0 53 -P tcp
EOTEXT1
#- in one window, do	(grep 'IP fw-'?)
#	tail --lines=0 -f /var/log/messages | mason >newrules
#- in another, do
cat <<EOTEXT2 >/dev/null
	ipfwadm -I -a deny -o
	ipfwadm -F -a deny -o
	ipfwadm -O -a deny -o
EOTEXT2
# - To watch the fireworks, do:
#	tail -f --lines=0 /var/log/messages newrules
# or
#	cat newrules | sort -t '#' +1 | sed -e 's/.*\-W //' | less -S
# -Bill Stearns


#DEBUG="YES"
DEBUG="NO"
#ECHOCOMMAND="NO"
#DOCOMMAND="NO"
ECHOCOMMAND="YES"
DOCOMMAND="YES"
LAST1=""
LAST2=""
LAST3=""
LAST4=""
LAST5=""
CURRENT=""

read MESSAGE
while [ "${MESSAGE}" != "" ]; do
    unset COMMENT DESTHOST DESTIP DESTPORT DIR IF PROTO SRCHOST SRCIP SRCPORT
    MESSAGE=`echo ${MESSAGE} | grep ' kernel\: ' \
     | sed -e 's/.* kernel\: //' \
     | grep '^IP fw\-'`

    if [ "${DEBUG}" = "YES" ]; then echo message= ${MESSAGE} ; fi
    if [ "${MESSAGE}" != "" ]; then

        case `echo ${MESSAGE} | awk '{print $2}'` in
        fw-out)	DIR='O'							;;
        fw-in)	DIR='I'							;;
        fw-fwd)	DIR='F'							;;
        *)	echo Huh?  X`echo ${MESSAGE} | awk '{print $5}'`X	;;
        esac

              IF=`echo ${MESSAGE} | awk '{print $4}'`
           PROTO=`echo ${MESSAGE} | awk '{print $5}' | tr A-Z a-z`
           SRCIP=`echo ${MESSAGE} | awk '{print $6}' | sed -e 's/\:.*//'`
         SRCPORT=`echo ${MESSAGE} | awk '{print $6}' | sed -e 's/.*\://'`
          DESTIP=`echo ${MESSAGE} | awk '{print $7}' | sed -e 's/\:.*//'`
        DESTPORT=`echo ${MESSAGE} | awk '{print $7}' | sed -e 's/.*\://'`

	if [ `echo ${IF} | wc --bytes` -lt 5 ]; then
	    IF=`echo "${IF}     " | cut -b 1-4`
	fi

#Configurable name lookup?
	
	SRCHOST=`cat /etc/hosts | egrep "^${SRCIP}[^0-9]" | awk '{print $2}'`
	if [ "${SRCHOST}" != "" ]; then
	    SRCIP=${SRCHOST}
	elif [ "${SRCPORT}" != "53" -a "${DESTPORT}" != "53" ]; then
	    SRCHOST=`host ${SRCIP} | grep '^Name' | sed -e 's/.* //'`
	    if [ "${SRCHOST}" != "" ]; then
	        SRCIP=${SRCHOST}
	    fi
	fi

	DESTHOST=`cat /etc/hosts | egrep "^${DESTIP}[^0-9]" | awk '{print $2}'`
	if [ "${DESTHOST}" != "" ]; then
	    DESTIP=${DESTHOST}
	elif [ "${SRCPORT}" != "53" -a "${DESTPORT}" != "53" ]; then
	    DESTHOST=`host ${DESTIP} | grep '^Name' | sed -e 's/.* //'`
	    if [ "${DESTHOST}" != "" ]; then
	        DESTIP=${DESTHOST}
	    fi
	fi

	if [ "`echo ${PROTO} | sed -e 's/\/.*//'`" = "icmp" ]; then
	    SRCPORT=`echo ${PROTO} | sed -e 's/.*\///'`
	    PROTO="icmp"
	    DESTPORT=""
	    if [ "${DEBUG}" = "YES" ]; then echo proto= ${PROTO} srcport= ${SRCPORT} destport= ${DESTPORT} ; fi

	    case ${SRCPORT} in
	    0)		COMMENT="# Echo reply/icmp(${DIR})"		;;
	    3)		COMMENT="# Dest Unreach/icmp(${DIR})"		;;
	    4)		COMMENT="# Source Quench/icmp(${DIR})"		;;
	    5)		COMMENT="# Redirect/icmp(${DIR})"		;;
	    8)		COMMENT="# Echo req/icmp(${DIR})"		;;
	    11)		COMMENT="# Time exceeded/icmp(${DIR})"		;;
	    12)		COMMENT="# Parameter prob/icmp(${DIR})"		;;
	    13)		COMMENT="# Timestamp req/icmp(${DIR})"		;;
	    14)		COMMENT="# Timestamp reply/icmp(${DIR})"	;;
	    15)		COMMENT="# Info req/icmp(${DIR})"		;;
	    16)		COMMENT="# Info reply/icmp(${DIR})"		;;
	    17)		COMMENT="# Addr Mask req/icmp(${DIR})"		;;
	    18)		COMMENT="# Addr Mask reply/icmp(${DIR})"	;;
	    esac
	else
	    COMMENT="#"
	    MATCHSERVICE=`cat /etc/services | grep "${SRCPORT}/${PROTO}"`
	    if [ "${MATCHSERVICE}" != "" ]; then
	        SRCPORT=`echo ${MATCHSERVICE} | awk '{print $1}'`
	    else
	        case ${SRCPORT} in
	        [0-9]|[1-9][0-9]|[1-9][0-9][0-9]|10[0-1][0-9]|102[0-3])	: ;;
	        *)			SRCPORT="1024:65535"		;;
	        esac
	    fi
	    if [ "${SRCPORT}" != "1024:65535" ]; then
		COMMENT="${COMMENT} ${SRCPORT}/${PROTO} "
	    fi

	    MATCHSERVICE=`cat /etc/services | grep "${DESTPORT}/${PROTO}"`
	    if [ "${MATCHSERVICE}" != "" ]; then
	        DESTPORT=`echo ${MATCHSERVICE} | awk '{print $1}'`
	    else
	        case ${DESTPORT} in
	        [0-9]|[1-9][0-9]|[1-9][0-9][0-9]|10[0-1][0-9]|102[0-3]) : ;;
	        *)			DESTPORT="1024:65535"		;;
	        esac
	    fi
	    if [ "${DESTPORT}" != "1024:65535" ]; then
	        if [ "${SRCPORT}" != "${DESTPORT}" ]; then
		    COMMENT="${COMMENT} ${DESTPORT}/${PROTO}"
		fi
	    fi
	    COMMENT="${COMMENT} (${DIR})"
	fi


	case ${PROTO} in
	tcp)		PROTO="tcp "					;;
	udp)		PROTO="udp "					;;
	esac

        CURRENT="ipfwadm -a accept -W ${IF} -${DIR} -P ${PROTO} -S ${SRCIP}/32 ${SRCPORT} -D ${DESTIP}/32 ${DESTPORT}"
	if [ `echo ${CURRENT} | wc --bytes` -lt 101 ]; then
	    CURRENT=`echo "${CURRENT}                                         " | cut -b 1-100`
	fi
	CURRENT="${CURRENT} ${COMMENT}"

	if [ "${DEBUG}" = "YES" ]; then echo current= ${CURRENT} ; fi
	case ${CURRENT} in
	${LAST1})	:	;;
	${LAST2})	:	;;
	${LAST3})	:	;;
	${LAST4})	:	;;
	${LAST5})	:	;;
	*)
            if [ "${ECHOCOMMAND}" = "YES" ]; then 
                echo "${CURRENT}"
            fi

            if [ "${DOCOMMAND}" = "YES" ]; then 
                ipfwadm -i accept -W ${IF} -${DIR} -P ${PROTO} -S ${SRCIP}/32 ${SRCPORT} -D ${DESTIP}/32 ${DESTPORT}
            fi
	    LAST5=${LAST4}
	    LAST4=${LAST3}
	    LAST3=${LAST2}
	    LAST2=${LAST1}
	    LAST1=${CURRENT}	;;
	esac

	if [ "${DEBUG}" = "YES" ]; then 
	    echo ${MESSAGE}
	    echo src= ${SRCIP} ${SRCPORT} dest= ${DESTIP} ${DESTPORT}
	    echo if= ${IF} proto= ${PROTO}
	    echo
	fi
    fi
    read MESSAGE
done

