#!/bin/bash # # Firewall persistent bozos that sendmail would block anyway via DNSBL or Greet_Pause # (the ones who just don't give up trying to spam us...) # Only block (and tarpit) if they've been rejected by sendmail three times so far. # Also block sites trying to spam mailman administrative addresses if greylisting is in use. # # Since this is based on sendmail logs, a persistent IP will cycle between # this blocklist and being rejected by sendmail. If they are removed from the # DNSBLs that sendmail uses they will eventually be accepted again (in a few days) # by the firewall. # # Intended to be run regularly from /etc/cron.daily or /etc/cron.hourly # # Copyright (C) 2006-2007 John Hardin # $Id: spammer-firewall,v 1.27 2008/05/20 16:53:34 root Exp root $ # Master copy at http://www.impsec.org/~jhardin/antispam/ # Released under the GPL v2 or later # Contact the author for commercial licensing # # If you also install LaBrea, this will tarpit the worst offenders. # LaBrea available at http://sourceforge.net/projects/labrea/ # ** LaBrea patches may be needed! see: # ** http://sourceforge.net/tracker/index.php?func=detail&aid=1612799&group_id=70896&atid=529395 # ** http://sourceforge.net/tracker/index.php?func=detail&aid=1612677&group_id=70896&atid=529393 # ** http://sourceforge.net/tracker/index.php?func=detail&aid=1612818&group_id=70896&atid=529395 # ######## # Assumes the following structure in your base firewall script: # # #----------------------------------------------------------- # # chain to log and discard repetitive spam traffic # /sbin/iptables -N spammer # /sbin/iptables -A spammer -j LOG --log-prefix "Spammer: " # /sbin/iptables -A spammer -j DROP # # #----------------------------------------------------------- # # chain to test inbound email # /sbin/iptables -N flt-smtp # # /sbin/iptables -A INPUT -p tcp --sport 1024:65535 --dport 25 -j flt-smtp # /sbin/iptables -A INPUT -p tcp --sport 1024:65535 --dport 25 -j ACCEPT # ######## /sbin/iptables -F flt-smtp > /var/tmp/spammer_bpf_tmp grep 'AUTH=server, relay=' /var/log/maillog | sed -e 's/^.*relay=[^[]*\[//' -e 's/].*//' | sort | uniq > /var/tmp/authuserips OR=' and src host (' # I have observed kernel crashes (!) under joe-job load # if these limits are too large. If your mailserver crashes # unexpectedly, try adjusting these. # Limit size of BPF filter rule for labrea, if desired: # Tarpit up to this many of the worst offenders. # Set to negative to firewall only, no tarpit. BPFCNT=40 # Limit size of firewall list. # add this many more firewall rules after BPF limit is reached. FWCNT=0 ( # My /etc/mail/access explicit rejection rules for spammers include the text "go away" grep 'ruleset=check_rcpt' /var/log/maillog |\ egrep ' (listed at|go away)' |\ sed -e 's/^.* \[//' -e 's/\].*//' # Enable FEATURE(`greet_pause',1000) in sendmail.mc for this grep 'pre-greeting' /var/log/maillog |\ grep -v '\.hotmail\.com ' |\ sed -e 's/^.* \[//' -e 's/\].*//' # Catch mailman admin spammers if you're greylisting. # Adjust the time to match whatever your initial greylist # retry time is set to. # The akst[a-z]{7,25}mnsdgs@ from name format seems to be # pretty consistent with one-shot spams that greylisting # successfully blocks. Let's tarpit them if they keep trying. # Infrequent traffic, look through more logs. zgrep 'delayed for 00:15:00' /var/log/maillog /var/log/maillog.[12]* |\ egrep '(-request|-owner|mailman|akst[a-z]{3,25}mnsdgs)@' |\ grep -v '<>' |\ awk '{print $8}' # Repeated protocol failures - under deliberate attack? #grep 'did not issue MAIL/EXPN/VRFY/ETRN during connection to MTA' /var/log/maillog |\ # sed -e 's/^.* \[//' -e 's/\].*//' # manual additions - they get ten hits per appearance awk '/^ *[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+/ {print $1}' /root/smtp_tarpit_ip_list |\ while read IPADDR do echo $IPADDR echo $IPADDR echo $IPADDR echo $IPADDR echo $IPADDR echo $IPADDR echo $IPADDR echo $IPADDR echo $IPADDR echo $IPADDR done ) |\ sort |\ uniq -c |\ grep -v ' [123] ' |\ sort -nr |\ while read RANK IPADDR do if grep -q "^${IPADDR}$" /var/tmp/authuserips then continue fi BPFCNT=$((BPFCNT - 1)) if [ "$BPFCNT" -ge 0 ] then /sbin/iptables -A flt-smtp -s "$IPADDR" -j spammer echo -n "$OR" "$IPADDR" >> /var/tmp/spammer_bpf_tmp else FWCNT=$((FWCNT - 1)) if [ "$FWCNT" -ge 0 ] then /sbin/iptables -A flt-smtp -s "$IPADDR" -j spammer fi fi OR=' or' done rm /var/tmp/authuserips if [ -s "/var/tmp/spammer_bpf_tmp" ] then echo -n 'dst host' `ifconfig eth0 | grep 'inet addr:' | sed -e 's/.*addr://' | awk '{print $1}'` > /etc/mail/spammer_bpf_new echo -n ' and tcp dst port 25' >> /etc/mail/spammer_bpf_new cat /var/tmp/spammer_bpf_tmp >> /etc/mail/spammer_bpf_new echo -n ')' >> /etc/mail/spammer_bpf_new if [ -x /usr/local/bin/labrea ] then if [ -s "/etc/mail/spammer_bpf" ] then if diff /etc/mail/spammer_bpf_new /etc/mail/spammer_bpf > /dev/null then # BPF hasn't changed if ps fax | grep labrea | grep -q /spammer_bpf then # don't restart labrea unnecessarily rm -f /var/tmp/spammer_bpf_tmp exit fi fi fi cp /etc/mail/spammer_bpf_new /etc/mail/spammer_bpf ps fax | grep labrea | grep /spammer_bpf | awk '{print $1}' | xargs --no-run-if-empty kill -15 sleep 1 ps fax | grep labrea | grep /spammer_bpf | awk '{print $1}' | xargs --no-run-if-empty kill -9 ( sleep 10 /bin/nice /usr/local/bin/labrea -z -x -v -P -p 32 -b -F /etc/mail/spammer_bpf ) & fi fi rm -f /var/tmp/spammer_bpf_tmp