Stop spam flood attack with postfix and iptables
For about 2 or 3 months, I constantly get attacked by an army of robots trying to spam my mailbox for the domain exeko.com that by the way is participating in the busby seo challenge and a few of my clients domains. Yesterday night the spam flood attack was so violent that my poor little server hosted by OVH started to swap like a crazy cow !
I finally decided to write a little shell script to read the mail log file and extract the last minute of log to count the number of rejected attempts to send mail to my server by the same host and ban this host using iptables if a defined limit is reached.
Here is a version of my script:
#!/bin/bash
IPT=/sbin/iptables
LIMIT=10
cd /root/Filters
# first get one minute of log
grep "`date +"%b %d %H:%M:" --date="1 minutes ago"`" /var/log/mail.info > minutelog
# now extract the rejected attempts, sort and count uniq ip
cat minutelog | grep "reject:" | cut -d" " -f10 | cut -d"[" -f2 | cut -d"]" -f 1 | sort | uniq -c | sort -n | sed 's/^[ \t]*//' > tmp1
# for each line in result
while read line
do
MYCOUNT=`echo $line | cut -d" " -f1`
MYIP=`echo $line | cut -d" " -f2`
if [ $MYCOUNT -lt $LIMIT ] ;
then
echo $MYIP is ok: $MYCOUNT attempts
else
echo blocking the spammer at $MYIP with $MYCOUNT attempts
$IPT -I INPUT -i eth0 --proto tcp -s $MYIP --destination-port 25 -j DROP
echo $MYIP >> blocked.smtp
fi
done < tmp1
rm -f minutelog
rm -f tmp1
You can also download this script here: filter_smtp.zip
This shell script is running for about 12 hours on my mail server and it already stopped 701 spamming machines. Any feedback on the script is welcome !
Posted in linux, shell scripts
July 17th, 2008 at 3:52
Jonathan,
Found your blog post as the 5th result of a Google search for “stopping a spam flood”. I’ve started running your script on our system to help mitigate a flood attack that has been intense enough to at times cause postfix to use up all the ports on our MySQL server looking up bogus generated names. Thanks very much.
Andrew
February 1st, 2009 at 15:06
I found ubuntu 8.04 will generate “Feb 01″ instead of “Feb 1″, which is used in /var/mail.info.
Following code is better used at Feb 1.
LASTMIN=`date +”%b %_d %H:%M:” –date=”1 minutes ago”`
#echo LASTMIN is $LASTMIN
grep -i “$LASTMIN” /var/log/mail.info > minutelog
February 20th, 2009 at 3:40
Great script, i was using ddos deflate so far, to block apache botnets. But it wasn’t very effective against spam botnets that were attacking on port 25. This really helped a lot… I was about to code my own one, but i said i’d give it a try with googling a bit
glad i did… thanks again.
June 18th, 2009 at 23:38
Great idea.
I just had one problem about the month in the date command, that in debian (italian) writes the month in italian, but in log files is in english.
So that how it looks now:
#!/bin/bashIPT=/sbin/iptables
LIMIT=10
# first get one minute of log
grep "`date +" %d %H:%M:" --date="1 minutes ago"`" /var/log/mail.info > /tmp/minutelog
# now extract the rejected attempts, sort and count uniq ip
cat /tmp/minutelog | grep "reject:" | cut -d" " -f10 | cut -d"[" -f2 | cut -d"]" -f 1 | sort | uniq -c | sort -n | sed "s/^[ \t]*//" > /tmp/rejectedlog
# for each line in result
while read line
do
MYCOUNT=`echo $line | cut -d" " -f1`
MYIP=`echo $line | cut -d" " -f2`
if [ $MYCOUNT -gt $LIMIT ]; then
$IPT -A INPUT --proto tcp -s $MYIP --destination-port 25 -j LOG --log-prefix 'filter_smtp ' --log-level 4
$IPT -A INPUT --proto tcp -s $MYIP --destination-port 25 -j DROP
echo $MYIP >> /tmp/blocked_ip_smtp
fi
done < /tmp/rejectedlog
rm -f /tmp/minutelog
rm -f /tmp/rejectedlog
Thanks a lot
February 7th, 2010 at 21:53
I have a atack of spam but it`s go i 1512 / min
your script is okey but only if you have spam flood 12 / min
April 19th, 2010 at 19:44
Great script, I had some configuration issues with my mailserver and ended up on about any spam-bot-net out there…
Your script helped me stop the still coming to me