Howto avoid being "cut off" by spamhaus.org

As you probably know spamhaus limits your smtp and DNS traffic (http://www.spamhaus.org/organization/dnsblusage/ for more info) and in case of big servers this can be a serious problem.

Luckily, Costel Balta sent me a solution to the problem that I'm going to paste below. In short, he suggests to dinamically create firewall rules via iptables (or better shorewall) to avoid connections from suspicious IPs in order to decrease the number of requests to the RBL lists of about 80%.

ipsets and swatch are also needed to manage iptables rules and scan your logs respectively.

A big thanks to Costel Balta for the following tutorial; this is not the first time that he posts an original idea.


First of all the ingredients:

Install using your distro's specifics (yum, apt-get, yast..).

Create the ipset:

ipset create blacklistip hash:ip timeout 86400

this command creates an ipset named  "blacklistip" with the format "hash:ip" whith a timeout of 24 hours (witch means that every ip you add to this ipset is removed after 24 hours).

Some interesting example about ipset/iptables here:
http://blog.laimbock.com/2013/09/22/how-to-block-countries-with-ipdeny-ip-country-blocks-ipset-and-iptables-on-el6/
and here:
http://www.linuxjournal.com/content/advanced-firewall-configurations-ipset

Create a configuration file for swatch :

> vi /etc/swatch.conf
#
# Swatch configuration file for constant monitoring
#

#match spamhaus
watchfor   /451 http\:\/\/www.spamhaus.org/
        exec ipset -exist add blacklistip $3

#match spamcop
watchfor   /451 Blocked/
        exec ipset -exist add blacklistip $3

First line of each match does just that, match any line containing that expression.
Second line execute ipset command passing   the third column of the log line (the ip address) as a parameter.

I have tried to go further by adding to blacklist also the ip that generates log lines like:

CHKUSER rejected sender: from <ewpueak@yhqq.net::> remote <yhqq.net:unknown:180.118.218.189> rcpt <> : invalid sender MX domain

or

CHKUSER rejected intrusion: from <mosquitok92@bmacapital.com::> remote <[147.30.5.86]:unknown:147.30.5.86> rcpt <inexistent@mydomain.com> : rcpt ignored, session over intrusion threshold

for this I added another two "WATCHFOR" to my swatch.conf :

#Look for CHKUSER bad MX, if found, block them!
watchfor /CHKUSER rejected sender/
        exec "/usr/local/bin/ipblock $_"

#Look for session over intrusion threshold, if found, block them!
watchfor /CHKUSER rejected intrusion/
        exec "/usr/local/bin/ipblock $_"

those two are passing the entire log line to the script bellow, witch extracts the IP and adds it to our ipset.

> less /usr/local/bin/ipblock
----------------------------------------------------------------
#!/bin/sh
ip=`grep -Eo '([0-9]{1,3}\.){3}[0-9]{1,3}' $1`
ipset -exist add blacklistip $ip

start swatch :

/usr/bin/swatch -c /etc/swatch.conf --script-dir=/var/run --daemon \
--pid-file /var/run/swatch.pid -t /var/log/qmail/smtpd/current

Some (of my) servers need "--awk-field-syntax " to the "swatch" start command, so the previous command should be adjusted as follows in some case

/usr/bin/swatch -c /etc/swatch.conf --awk-field-syntax --script-dir=/var/run --daemon \
--pid-file /var/run/swatch.pid -t /var/log/qmail/smtpd/current

I don't know if is a perl version or swatch itself issue. 

I have also added this to /etc/rc.local.

If using shorewall, add "blacklist" to your interface in /etc/shorewall/interfaces ex:

"net     all             dhcp,physical=+,routeback,optional,blacklist"

edit/create /etc/shorewall/blacklist like this:

#ADDRESS/SUBNET PROTOCOL PORT
+blacklistip    TCP     25
#LAST LINE -- ADD YOUR ENTRIES BEFORE THIS ONE -- DO NOT REMOVE

you may leave out the protocol (TCP) and/or port (25) if you want to completely block the offending ip.

Adjust your shorewall.conf logging setting according to your preferences and don forget to restart shorewall.

If you are using plain iptables refer to examples on the links at the  top.