Spamhaus SBL + XBL check script

The following script determines the number of messages received by a Sendmail mail server from hosts listed in the Spamhaus SBL (Spamhaus Block List) + XBL (Exploits Block List) DNS blacklists.

Our internal mail relays use a 10.x IP addressing format, so messages from these servers are not included in "Total messages." Servers that should not be included may be configured in the EXCLUDE script variable.

Ideally, I would like to implement the Spamhaus SBL + XBL DNS blacklists on our perimeter mail relays. Providing these statistics to management may help get approval for implementing these blacklists.

#!/bin/sh

# Path to mail log; mail log may either be uncompressed
# or compressed with gzip
#MAILLOG=/var/log/maillog
MAILLOG=/var/log/maillog/maillog.0.gz

# Paths to other programs
GZIP=/usr/bin/gzip
DIG=/usr/local/bin/dig
PERL=/usr/bin/perl

# DNSBL to query
DNSBL=sbl-xbl.spamhaus.org

# If the relay is in the DNSBL, the DNS lookup will return
# values from 127.0.0.[2-6]
IN_DNSBL=127.0.0.[2-6]

# Regex of relays to exclude. We will exclude
# any 10.x.x.x relays
EXCLUDE='^10\.'

# Use "gzip" or "cat" to read $MAILLOG depending on whether it is compressed
if [ -n "`echo $MAILLOG | awk '/\.gz$/ { print }'`" ] ; then
   COMMAND="$GZIP -cd"
else
   COMMAND="cat"
fi

$COMMAND $MAILLOG | \
$PERL -ne 'if (m/from=.*relay=.*\[(\d+\.\d+\.\d+\.\d+)\]/) { print "$1\n" }' \
| sort | egrep -v $EXCLUDE | uniq -c | sort -n > $$.tmp

while read LINE
do
   set $LINE
   COUNT=$1
   IP_ADDRESS=$2
   IP_BACKWARD=`echo $IP_ADDRESS | awk -F\. '{ print $4"."$3"."$2"."$1 }'`
   if [ -n "`$DIG ${IP_BACKWARD}.sbl-xbl.spamhaus.org | grep $IN_DNSBL`" ] ; then
      echo "$IP_ADDRESS\t$COUNT\t$DNSBL" >> $$_1.tmp
   else
      echo "$IP_ADDRESS\t$COUNT" >> $$_1.tmp
   fi
done < $$.tmp

# How many messages are in the DNSBL?
MSGS_IN_DNSBL=`awk 'NF==3 { msgs_in_dnsbl += $2 } END { print msgs_in_dnsbl }' \
   $$_1.tmp`
# If none, set MSGS_IN_DNSBL variable to 0
[ -z "$MSGS_IN_DNSBL" ] && MSGS_IN_DNSBL=0

# How many total messages were there?
TOTAL_MSGS=`awk '{ total_msgs += $2 } END { print total_msgs }' $$_1.tmp`

# If there were more than 0 messages in DNSBL, compute the percentage
# of total messages that were in DNSBL
[ "$MSGS_IN_DNSBL" -gt 0 ] && PERCENT_IN_DNSBL=`echo \
"scale = 4; $MSGS_IN_DNSBL / $TOTAL_MSGS * 100" | bc | cut -c1-5`

echo "  Messages in DNSBL: $MSGS_IN_DNSBL"
echo "     Total messages: $TOTAL_MSGS"
# Only print percentage of total messages in DNSBL if number of messages
# in DNSBL is greater than 0
[ "$PERCENT_IN_DNSBL" -gt 0 ] && \
   echo "% Messages in DNSBL: ${PERCENT_IN_DNSBL}%"

# Remove temporary files
rm $$.tmp $$_1.tmp

Example output:

Back to brandonhutchinson.com.
Last modified: 01/06/2005