Remove/replace all characters before and after a specific character & Deal with “postfix/smtpd too many errors after UNKNOWN from unknown”

Plenty of logs on an e-mail server like the one below:

Sep  3 05:31:01 web postfix/smtpd[7858]: too many errors after UNKNOWN from unknown[]
(These logs seem to be caused by botnets trying to send spam, or broken spam bots trying to send spam emails to server, but fail to complete the transaction. )

Needed to extract the IP address from logs. Solution:

Replace all characters before [ with blank space and all after ] with blank space :

sed ‘s/.*\[//’ | sed -e ‘s/\].*//’  The full command:

tail -f /var/log/maillog | grep “too many errors” |  sed ‘s/.*\[//’ | sed -e ‘s/\].*//’ >/var/log/ips.log

Next, needed to count how many times each line (IP) is repeating:

awk ‘NF{a[$NF]++}END{for(i in a)print i,a[i]}’ /var/log/ips.log | sort >/var/log/ips2.log This will produce results as below: 8 6 29

If we want to block incoming tcp connection on port 25 from IPs repeating more than 20 times in the above list, I created a small script:


s1=(`cat /var/log/ips2.log | awk ‘{print $2}’`);  # store in a string the counted repeats
s2=(`cat /var/log/ips2.log | awk ‘{print $1}’`); # store the IPs in a string

for (( i = 0 ; i < ${#s1[@]} ; i++ ))
        if [ ${s1[i]} -gt 20 ]
                   iptables -t raw -A PREROUTING -i eth0 -p tcp –dport 25 -s ${s2[i]} -j DROP;

A different/better approach would be to read the mail logs every 5 min and execute the script below:

s1=(`cat /usr/local/psa/var/log/maillog  | grep “too many errors” |  sed ‘s/.*\[//’ | sed -e ‘s/\].*//’`);
s2=(`iptables -nL -t raw | grep DROP | awk ‘{ print $4 }’`);  # IPs already blocked in table row

for (( i = 0 ; i < ${#s1[@]} ; i++ ));
            for (( j = 0 ; j < ${#s2[@]} ; j++ ));
                    if [ ${s1[i]} = ${s2[j]} ]
                           echo “${s1[i]} is already blocked!”;
            if [ $k -eq 0 ]
                   iptables -t raw -A PREROUTING -i eth0 -p tcp –dport 25 -s ${s1[i]} -j DROP;
                   echo “${s1[i]} has been blocked!”;


If you have thousands of IPs you may want to consider using ipset.







This entry was posted in Linux and tagged , , . Bookmark the permalink.

Leave a Reply

Your email address will not be published. Required fields are marked *