pf suggestions for paced attack

A. Wright andrew at qemg.org
Tue May 4 12:55:13 UTC 2010


I wrote:
>> If anyone is interested, I can send (or I suppose post) the scripts.

Balázs Mátéffy wrote:

> Would you be so kind to share those scripts?

No problem; the scripts are below.

I run them both in /usr/local/bin

Note the usual caveats about running scripts as root;
some squashing of problems is done by setting PATH to
the empty string in the scripts and using the fully
qualified path to all executables.

I run /usr/local/bin/authlog_watcher in the background from
/etc/rc.d; I then have a rule:
  	block return log quick on $EXT_IF from { <attackers> } to any
in my /etc/pf.conf to make the actual filtering happen.

As you can see, the entire thing is quite simple -- the first
script simply is a loop fed from the auth.log file (note -F
to resync after log rotation).  The second script is triggered
by the first when there is any activity of interest, and its
purpose is to examine the log (within a recent date range)
and count whether there are too many attempts.

I hope this helps out.

Andrew.

---- 8< --- authlog_watcher --- 8< ------------------------------
#!/bin/sh --

#
# Trigger our attack filtering script when relevant authlog
# activity occurs
#
# $Id: authlog_watcher 118 2010-05-03 16:46:55Z andrew $
#

PATH=""

/usr/bin/tail -F /var/log/auth.log | {
  	while read line
  	do
  		sshd_test=`/bin/expr "${line}" : ".*sshd.*"`
  		if [ ${sshd_test} -gt 0 ]
  		then
  			inv_test=`/bin/expr "${line}" : ".*invalid.*"`
  			fail_test=`/bin/expr "${line}" : ".*Failed.*"`
  			err_test=`/bin/expr "${line}" : ".*error.*"`
  			if [ ${err_test} -gt 0 \
  				-o ${err_test} -gt 0 \
  				-o ${fail_test} -gt 0 ]
  			then
  				/bin/sh /usr/local/bin/filter-current-attackers
  			fi
  		fi
  	done
}

---- 8< --- filter-current-attackers --- 8< ----------------------
#!/bin/sh --

#
# Invoked by the authlog_watcher script when activity involving
# failed login occurs.  This script parses the auth.log file
# and for any lines that indicate kiddies, add them to the
# "attackers" table used/managed by pf to filter connections.
#
# $Id: filter-current-attackers 118 2010-05-03 16:46:55Z andrew $
#

PATH=""

TAG="current-attackers"
RAWLIST="/tmp/${TAG}.$$.raw"
IPLIST_RAW="/tmp/${TAG}.$$.IPlist.raw"
IPLIST_UNIQ="/tmp/${TAG}.$$.IPlist.uniq"
TMP="/tmp/${TAG}.$$.tmp"

LOG="/var/log"
ATTACKERS="/etc/attackers"

umask 077

trap "echo 'Cleanup' ; rm -f ${IPLIST_UNIQ} ${IPLIST_RAW} ${RAWLIST} ${TMP} ; exit 1" 2 3 15

/usr/bin/touch /tmp/filter-current-attackers.timestamp

{
  	/usr/bin/find ${LOG} -name 'auth.log.*' -mtime -2 | \
  		/usr/bin/sort -t. -r -n -k 2,2 | \
  		while read f
  		do
  			case $f in
  			*.gz)   /usr/bin/zcat -f $f | /usr/bin/tail +2;;
  			*.bz2)  /usr/bin/bzcat -f $f | /usr/bin/tail +2;;
  			esac
  		done
  		[ -f ${LOG}/auth.log ] && /bin/cat $LOG/auth.log | /usr/bin/tail +2
} | /usr/bin/grep sshd > ${RAWLIST}

> ${IPLIST_RAW}

/bin/cat ${RAWLIST} | /usr/bin/grep "Invalid" \
  		| /usr/bin/sed -e 's/.* //' | /usr/bin/awk '{print $1;}' > ${IPLIST_RAW}

/bin/cat ${RAWLIST} | /usr/bin/grep "POSSIBLE BREAK-IN" \
  	| /usr/bin/sed -e 's:\(.*\)\([ \[]\)\([0-9]*[.][0-9]*[.][0-9]*[.][0-9]*\)\(.*\):\3:' \
  	>> ${IPLIST_RAW}

/usr/bin/sort -u ${IPLIST_RAW} > ${IPLIST_UNIQ}

{
  	while read IP
  	do
  		if [ `/bin/expr "${IP}" : "[0-9]*[.][0-9]*[.][0-9]*[.][0-9]*"` -eq 0 ]
  		then
  			echo "  Invalid IP format : [${IP}]"
  			continue
  		fi

  		# Explicitly avoid adding any machine on campus to the list
#		if [ `/bin/expr "${IP}" : "138[.]73[.]*"` -gt 0 ] # MtA
#		then
#			continue
#		fi


  		# check that there are at least 10 instances,
  		# to avoid locking ourselves out on a Thumbsday
  		/usr/bin/grep ${IP} ${IPLIST_RAW} > ${TMP}
  		LINECOUNT=`/usr/bin/wc ${TMP} | /usr/bin/awk '{print $1;}'`

  		if [ ${LINECOUNT} -gt 10 ]
  		then
  			if
  				#pfctl -q -t attackers -T test ${IP}
  				/usr/bin/grep ${IP} ${ATTACKERS} > /dev/null
  			then
  				:
  				# already in table
  			else
  				/usr/bin/logger -p auth.notice \
  					"Adding ${IP} to pfctl filter"
  				/sbin/pfctl -q -t attackers -T add ${IP}
  				/bin/echo "Added ${IP} "`host ${IP}` \
  					| mail -s "Added attacker ${IP}" root
  			fi
  		else
  			:
  		fi
  	done
} < ${IPLIST_UNIQ}

## store the current state
/sbin/pfctl -q -t attackers -T show > ${TMP}

## get rid of anything more than four weeks old
/sbin/pfctl -q -t attackers -T expire 2419200

## save what we have to the table we load on boot
/sbin/pfctl -q -t attackers -T show > ${ATTACKERS}

# check whether the table has expired anything
if
      /usr/bin/cmp -s ${TMP} ${ATTACKERS}
then
      :
else
      /bin/echo "These addresses have expired:"
      /usr/bin/diff ${TMP} ${ATTACKERS} | sed -e 's/^/    /'
fi

/bin/rm -f ${IPLIST_UNIQ} ${RAWLIST} ${IPLIST_RAW} ${TMP}


More information about the freebsd-questions mailing list