From owner-freebsd-questions@FreeBSD.ORG Tue May 4 12:55:13 2010 Return-Path: Delivered-To: freebsd-questions@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [69.147.83.52]) by hub.freebsd.org (Postfix) with ESMTP id 705BC106566B for ; Tue, 4 May 2010 12:55:13 +0000 (UTC) (envelope-from ahamiltonwright@mta.ca) Received: from smtpx.mta.ca (smtpx.mta.ca [138.73.1.138]) by mx1.freebsd.org (Postfix) with ESMTP id 1E57B8FC1A for ; Tue, 4 May 2010 12:55:12 +0000 (UTC) Received: from [138.73.29.51] (port=49187 helo=qemg.org) by smtpx.mta.ca with esmtpsa (TLSv1:AES256-SHA:256) (Exim 4.71) (envelope-from ) id 1O9HeY-0003A8-SE; Tue, 04 May 2010 09:55:10 -0300 Date: Tue, 4 May 2010 09:55:10 -0300 (ADT) From: "A. Wright" To: =?ISO-8859-15?Q?Bal=E1zs_M=E1t=E9ffy?= In-Reply-To: Message-ID: References: <20100503144110.GA14402@elwood.starfire.mn.org> <4BDEF9E4.9020806@infracaninophile.co.uk> <20100503163933.GA15599@elwood.starfire.mn.org> User-Agent: Alpine 2.00 (BSF 1167 2008-08-23) MIME-Version: 1.0 Content-Type: MULTIPART/MIXED; BOUNDARY="142510029-1802741886-1272977710=:1908" Sender: ahamiltonwright@mta.ca Cc: "freebsd-questions@freebsd.org" Subject: Re: pf suggestions for paced attack X-BeenThere: freebsd-questions@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: User questions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 04 May 2010 12:55:13 -0000 This message is in MIME format. The first part should be readable text, while the remaining parts are likely unreadable without MIME-aware tools. --142510029-1802741886-1272977710=:1908 Content-Type: TEXT/PLAIN; charset=iso-8859-1; format=flowed Content-Transfer-Encoding: QUOTED-PRINTABLE I wrote: >> If anyone is interested, I can send (or I suppose post) the scripts. Bal=E1zs M=E1t=E9ffy 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: =09block return log quick on $EXT_IF from { } 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=3D"" /usr/bin/tail -F /var/log/auth.log | { =09while read line =09do =09=09sshd_test=3D`/bin/expr "${line}" : ".*sshd.*"` =09=09if [ ${sshd_test} -gt 0 ] =09=09then =09=09=09inv_test=3D`/bin/expr "${line}" : ".*invalid.*"` =09=09=09fail_test=3D`/bin/expr "${line}" : ".*Failed.*"` =09=09=09err_test=3D`/bin/expr "${line}" : ".*error.*"` =09=09=09if [ ${err_test} -gt 0 \ =09=09=09=09-o ${err_test} -gt 0 \ =09=09=09=09-o ${fail_test} -gt 0 ] =09=09=09then =09=09=09=09/bin/sh /usr/local/bin/filter-current-attackers =09=09=09fi =09=09fi =09done } ---- 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=3D"" TAG=3D"current-attackers" RAWLIST=3D"/tmp/${TAG}.$$.raw" IPLIST_RAW=3D"/tmp/${TAG}.$$.IPlist.raw" IPLIST_UNIQ=3D"/tmp/${TAG}.$$.IPlist.uniq" TMP=3D"/tmp/${TAG}.$$.tmp" LOG=3D"/var/log" ATTACKERS=3D"/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 { =09/usr/bin/find ${LOG} -name 'auth.log.*' -mtime -2 | \ =09=09/usr/bin/sort -t. -r -n -k 2,2 | \ =09=09while read f =09=09do =09=09=09case $f in =09=09=09*.gz) /usr/bin/zcat -f $f | /usr/bin/tail +2;; =09=09=09*.bz2) /usr/bin/bzcat -f $f | /usr/bin/tail +2;; =09=09=09esac =09=09done =09=09[ -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" \ =09=09| /usr/bin/sed -e 's/.* //' | /usr/bin/awk '{print $1;}' > ${IPLIST= _RAW} /bin/cat ${RAWLIST} | /usr/bin/grep "POSSIBLE BREAK-IN" \ =09| /usr/bin/sed -e 's:\(.*\)\([ \[]\)\([0-9]*[.][0-9]*[.][0-9]*[.][0-9]= *\)\(.*\):\3:' \ =09>> ${IPLIST_RAW} /usr/bin/sort -u ${IPLIST_RAW} > ${IPLIST_UNIQ} { =09while read IP =09do =09=09if [ `/bin/expr "${IP}" : "[0-9]*[.][0-9]*[.][0-9]*[.][0-9]*"` -eq = 0 ] =09=09then =09=09=09echo " Invalid IP format : [${IP}]" =09=09=09continue =09=09fi =09=09# Explicitly avoid adding any machine on campus to the list #=09=09if [ `/bin/expr "${IP}" : "138[.]73[.]*"` -gt 0 ] # MtA #=09=09then #=09=09=09continue #=09=09fi =09=09# check that there are at least 10 instances, =09=09# to avoid locking ourselves out on a Thumbsday =09=09/usr/bin/grep ${IP} ${IPLIST_RAW} > ${TMP} =09=09LINECOUNT=3D`/usr/bin/wc ${TMP} | /usr/bin/awk '{print $1;}'` =09=09if [ ${LINECOUNT} -gt 10 ] =09=09then =09=09=09if =09=09=09=09#pfctl -q -t attackers -T test ${IP} =09=09=09=09/usr/bin/grep ${IP} ${ATTACKERS} > /dev/null =09=09=09then =09=09=09=09: =09=09=09=09# already in table =09=09=09else =09=09=09=09/usr/bin/logger -p auth.notice \ =09=09=09=09=09"Adding ${IP} to pfctl filter" =09=09=09=09/sbin/pfctl -q -t attackers -T add ${IP} =09=09=09=09/bin/echo "Added ${IP} "`host ${IP}` \ =09=09=09=09=09| mail -s "Added attacker ${IP}" root =09=09=09fi =09=09else =09=09=09: =09=09fi =09done } < ${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} --142510029-1802741886-1272977710=:1908--