Blocking SMTP AUTH brute-force password guessing with fail2ban

Version $Id: fail2ban.html,v 1.2 2014/01/07 15:16:33 madhatta Exp madhatta $

  1. Installation
  2. Configuration
  3. Testing

I'm suffering a lot from people trying to guess valid username/password duples for authenticating to my SMTP server. This is bad for several reasons: if they were to succeed, they could relay vast quantities of rubbish email off my server, taking advantage of my IP addresses' reasonably good reputation in the sender stakes. Some (though not all) valid SMTP login duples are also valid ssh login duples, and that would lead to an even worse compromise of the server. But even unsuccessful attempts take up resources on the server (mostly, memory) leading to a shortfall, and possible activation of the OOM-killer and consequent service disruption to legitimate users.

At the moment I have my NAGIOS server watching the logs for evidence of failures, and memory shortfalls, and SMSing me when they're found. This leads to notifications such as:

Service: smtp/imap authentication failures
Host: teaparty

Date/Time: Tue Jan 7 11:30:23 GMT 2014

Additional Info:

CRITICAL: Found 51 lines (limit=4/10): Jan  7 11:30:11 lory saslauthd[8198]: pam_unix(smtp:auth): authentication failure: logname= uid=0 euid=0 tty= ruser= rhost=
Service: memory
Host: teaparty

Date/Time: Tue Jan 7 11:31:12 GMT 2014

Additional Info:

CRITICALs: committed is 7301853184.00 (outside range [:3000000000]).

But in addition to costing me money (SMS sending isn't free), when I get one of these I have to drop everything and sort the problem out. It would be much better if there were some daemon that ran on teaparty, watched the logs for evidence of brute-forcing, and ban that offending IP address from connecting to the service for a period.

Well, there is, and it's called fail2ban.


On teaparty, the RPM was available from the RPMForge repository, which I have configured in to yum, so installed failban with a simple yum install fail2ban

I'm pleased to report that it ships with no "jails" (which appears to be fail2ban-speak for "log files that I'm watching for certain regexps with a view to taking certain actions") configured, so initially, it won't throw anyone out of anything. I know this because

[madhatta@lory fail2ban]$ sudo fail2ban-client status
ERROR  Unable to contact server. Is it running?
[madhatta@lory fail2ban]$ sudo service fail2ban start
Starting fail2ban:                                         [  OK  ]
[madhatta@lory fail2ban]$ sudo fail2ban-client status
|- Number of jail:	0
`- Jail list:		

I have established that the signature I'm looking for in my logs is this

Jan  7 11:25:45 lory sendmail[1558]: s07BPgwK001558: AUTH failure (LOGIN): authentication failure (-13) SASL(-13): authentication failure: checkpass failed, relay=[]
in /var/log/facility/mail (my syslogging is a custom setup; you'll need to adapt this to wherever your sendmail logs its complaints).


I added the following to my jail.conf:
enabled  = true
filter   = smtp-auth
action   = iptables[name=SMTP, port=smtp, protocol=tcp]
logpath  = /var/log/facility/mail
maxretry = 3
and put the following in /etc/fail2ban/filter.d/smtp-auth.conf:
failregex = sendmail.*authentication failure: checkpass failed, relay=\[<HOST>\]$
ignoreregex = 
I tested the filter file against the logfile with

sudo fail2ban-regex /var/log/facility/mail /etc/fail2ban/filter.d/smtp-auth.conf |less

and received much output like

Running tests

Use regex file : /etc/fail2ban/filter.d/smtp-auth.conf
Use log file   : /var/log/facility/mail


Failregex: 1249 total
|- #) [# of hits] regular expression
|  1) [1249] sendmail.*authentication failure: checkpass failed,

Ignoreregex: 0 total


Addresses found:
[1] (Tue Jan 07 11:25:41 2014) (Tue Jan 07 11:25:42 2014)
Date template hits:
52380 hit(s): MONTH Day Hour:Minute:Second

Success, the total number of match is 1249
and moreover saw the following rule in iptables:
[madhatta@lory fail2ban]$ sudo iptables -L -n -v|head -3
Chain INPUT (policy DROP 8 packets, 392 bytes)
 pkts bytes target         prot opt in     out     source        destination
  259  116K fail2ban-SMTP  tcp  --  *      *           tcp dpt:25 
plus the client reports a single jail configured:
[madhatta@lory fail2ban]$ sudo fail2ban-client status
|- Number of jail:	1
`- Jail list:		smtp-auth


I tested it by using an ALPINE session from a remote server to which I have shell access, with the following line in my .pinerc:
But when I tried repeatedly to send an email with the wrong password, nothing happened. /var/log/facility/mail showed this:
Jan  7 14:53:46 lory sendmail[28424]: s07EriLI028424: AUTH failure (PLAIN): authentication failure (-13) SASL(-13): authentication failure: Password verification failed, []
which is subtly different from the log entry above. I modified the regexp in /etc/fail2ban/filter.d/smtp-auth.conf to read
failregex = sendmail.*authentication failure \(-13\) SASL\(-13\):
authentication failure:.*relay=.*\[<HOST>\]
and confirmed it worked with fail2ban-regex. After kicking fail2ban, the following was logged in /var/log/fail2ban.log:
2014-01-07 14:59:04,912 fail2ban.actions: WARNING [smtp-auth] Ban
and the following iptables rule appeared:
[madhatta@lory fail2ban]$ sudo iptables -L fail2ban-SMTP -n -v
Chain fail2ban-SMTP (1 references)
 pkts bytes target     prot opt in     out     source        destination
    5   300 DROP       all  --  *      * 
  113 32955 RETURN     all  --  *      * 
The alpine client was unable to connect to port 25 on the mail server. A few minutes later, the following log entry appeared in fail2ban.log
2014-01-07 15:09:05,643 fail2ban.actions: WARNING [smtp-auth] Unban
and the iptables rule went away.

This HOWTO was most helpful when it came to understanding some of the basic concepts, but the project documentation was best of all for giving me a good grounding in the fail2ban way.

Back to Technotes index
Back to main page