#dnsdoschk.sh #Used to alert on DNS connections above a threshold on a specific firewall interface #for a full discussion on its use, see the paper http://www.altsec.info/fwlogproj/Stingley-GIAC-GOLD-2009.pdf # Copyright (C) 2008 Mark Stingley # mark AT altsec.info # http://www.altsec.info # 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. # # See http://www.gnu.org/licenses/licenses.html#GPL or write to the # Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, # MA 02111-1307 USA # # Changelog: #Version 20090903.01 #!/bin/sh #create the temporary files TMPFILE=`tempfile` TMPQRY=`tempfile` MAILTMP=`tempfile` #store the times for NOW and 5 minutes ago in MySQL date time format TNOW=`date "+%Y-%m-%d %H:%M"` TTHEN=`date -d "5 minutes ago" "+%Y-%m-%d %H:%M"` #convert HH:MM to HHMM for comparison to a known surge period MINUTE=`date -d "$TNOW" "+%H%M"` #the daily surge occurs between 04:00 and 04:15 TLOW="0400" THIGH="0415" #create a list of reported DNS DOS hosts, if it doesn’t exist if [ ! -f /var/run/dnschk.list ]; then touch /var/run/dnschk.list fi #create a query file with the following criteria #1. examine the last five minutes (THEN and NOW) #2. grab only DNS (port 53) traffic #3. traffic for DNS servers at 192.168.19.12 and 192.168.19.13 #4. where the source is subnets 192.168.51,52,53, and 54 # these were subnets traversing the firewall for internal DNS echo "select distinct count(*) as count,fw1src,fw1dst from fw1logs.fw1logs where fw1time between \"$TTHEN\" and \"$TNOW\" and fw1service = \"53\" and (fw1dst = \"192.168.19.12\" or fw1dst = \"192.168.19.13\") and (fw1src like \"192.168.51.%\" or fw1src like \"192.168.52.%\" or fw1src like \"192.168.53.%\" or fw1src like \"192.168.54.%\") group by fw1src,fw1dst order by count desc limit 10;" > $TMPQRY # ISQL needs a blank line after the query echo "" >> $TMPQRY #use awk to grab counts above the limit ($2>2000) isql32 -b FW1-Logs32 logger some-password < $TMPQRY | grep '\.' | awk -F"|" '{if ($2>2000) print $2$3}' >> $TMPFILE #example output for a definite problem #+-------+----------------+---------------+ #| count | fw1src | fw1dst | #+-------+----------------+---------------+ #| 42595 | 192.168.52.152 | 192.168.19.13 | #| 20293 | 192.168.52.152 | 192.168.19.12 | #| 55 | 192.168.53.223 | 192.168.19.12 | #| 50 | 192.168.52.153 | 192.168.19.12 | #| 49 | 192.168.53.226 | 192.168.19.12 | #| 49 | 192.168.53.71 | 192.168.19.12 | #| 48 | 192.168.53.225 | 192.168.19.12 | #+-------+----------------+---------------+ # read one line at a time from the file, exiting if empty while read LINE; do if [ "$LINE" ]; then #store the count and the ip address for notification CNT=`echo "$LINE" | awk '{print $1}'` IP=`echo "$LINE" | awk '{print $2}'` #ignore the known surge from 192.168.53.14 if it’s the right time if ([ "$IP" == "192.168.53.14" ] && [ $MINUTE -ge $TLOW ] && [ $MINUTE -le $THIGH ] ); then #log the known surge alert to a separate file echo "$TNOW: $IP - $CNT hits, skipped" >> /var/log/loggrabber/dnsskip.txt continue fi #check if the offender has already been reported grep "$IP" /var/run/dnschk.list #if not, store the ip address then send email alerts if [ $? -ne 0 ]; then echo "$IP" >> /var/run/dnschk.list echo "DNS DOS detected" > $MAILTMP echo `date "+%Y-%m-%d %H:%M"` >> $MAILTMP echo -e "\n\n" >> $MAILTMP echo "$IP, $CNT connections" >> $MAILTMP mail -s "$IP: DNS DOS" some.user@example.com < $MAILTMP mail -s "$IP: DNS DOS" phone.number@mms.example.com < $MAILTMP sleep 15 fi fi done < $TMPFILE #delete the temporary files rm -f $TMPFILE rm -f $TMPQRY rm -f $MAILTMP