#!/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 </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 </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