
Originally Posted by
TomG
• Is there a specific location where webmail logons (and failed attempts) are logged to?
/opt/zimbra/log/audit.log and /opt/zimbra/log/mailbox.log
• Of course, we would like to know if there is some advice to prevent such successful hacking attempts in the future.
You can use fail2ban to ban IP addresses or hosts. I use it in conjunction with iptables. For mail, here's my jail.conf entries:
Code:
[zimbra-account]
enabled = true
filter = zimbra
action = iptables-allports[name=Zimbra-account]
sendmail[name=Zimbra-account, dest=it@somewhere.com]
logpath = /opt/zimbra/log/mailbox.log
bantime = -1
maxretry = 5
[zimbra-audit]
enabled = true
filter = zimbra
action = iptables-allports[name=Zimbra-audit]
sendmail[name=Zimbra-audit, dest=it@somewhere.com]
logpath = /opt/zimbra/log/audit.log
bantime = -1
maxretry = 5
[zimbra-recipient]
enabled = true
filter = zimbra
action = iptables-allports[name=Zimbra-recipient]
sendmail[name=Zimbra-recipient, dest=it@somewhere.com]
logpath = /var/log/maillog
findtime = 604800
bantime = 172800
maxretry = 5
[postfix]
enabled = true
filter = postfix
action = iptables-multiport[name=Postfix, port=smtp, protocol=tcp]
sendmail-buffered[name=Postfix, dest=it@somewhere.com]
logpath = /var/log/maillog
bantime = 172800
maxretry = 5
[postfix-connections]
enabled = true
filter = postfix-connections
action = iptables[name=Postfix-Connections, port=smtp, protocol=tcp]
sendmail[name=Postfix-Connections, dest=it@somewhere.com]
logpath = /var/log/maillog
bantime = %(permanent)s
ignoreip = 127.0.0.1
[sasl-iptables]
enabled = true
filter = sasl
action = iptables-allports[name=sasl]
sendmail[name=sasl, dest=it@somewhere.com]
logpath = /var/log/maillog
bantime = -1
maxretry = 5
# Stop phpMyAdmin probes
[apache-phpMyAdmin]
enabled = true
filter = apache-phpMyAdmin
action = iptables-allports[name=phpMyAdmin]
sendmail-buffered[name=phpMyAdmin, lines=5, dest=it@somewhere.com]
logpath = /opt/zimbra/log/httpd_access.log
bantime = -1
maxretry = 1 Make sure to exempt your own networks from getting banned. In jail.conf:
Code:
ignoreip = 127.0.0.1 172.16.99.0/24 172.16.98.0/24 10.1.1.0/24
I added some time aliases to jail.conf, just before the jail definitions:
Code:
# Time aliases
## bantime of 3600 = 60*60 = one hour
## bantime of 86400 = 60*60*24 = one day
## bantime of 604800 = 60*60*24*7 = one week
## bantime of 2592000 = 60*60*24*30 = (approx) one month
## bantime of 31536000 = 60*60*24*365 = (approx) one year
one_hour = 3600
one_day = 86400
one_hour = 3600
one_day = 86400
one_week = 604800
one_month = 2592000
one_year = 31536000
permanent = -1
## Use the aliases like this:
## findtime = %(one_week)s
## bantime = %(one_week)s
## the "s" is for string, and must be included
and the filter in /etc/fail2ban/filter.d/zimbra.conf:
Code:
# Fail2Ban configuration file
#
# Author:
#
# $Revision: 1 $
#
[Definition]
# Option: failregex
# Notes.: regex to match the password failures messages in the logfile. The
# host must be matched by a group named "host". The tag "<HOST>" can
# be used for standard IP/hostname matching and is only an alias for
# (?:::f{4,6}:)?(?P<host>[\w\-.^_]+)
# Values: TEXT
#
failregex = \[ip=<HOST>;\] account - authentication failed for .* \(no such account\)$
\[ip=<HOST>;\] security - cmd=Auth; .* error=authentication failed for .*, invalid password;$
;oip=<HOST>;.* security - cmd=Auth; .* protocol=soap; error=authentication failed for .* invalid password;$
\[oip=<HOST>;.* SoapEngine - handler exception: authentication failed for .*, account not found$
\[ip=<HOST>;.* SoapEngine - handler exception: authentication failed for .*, account not found$
WARN .*;ip=<HOST>;ua=ZimbraWebClient .* security - cmd=AdminAuth; .* error=authentication failed for .*;$
NOQUEUE: reject: RCPT from .*\[<HOST>\]: 550 5.1.1 .*: Recipient address rejected:
# .*\[ip=<HOST>;\] .* - authentication failed for .* \(invalid password\)
#
# Option: ignoreregex
# Notes.: regex to ignore. If this regex matches, the line is ignored.
# Values: TEXT
#
ignoreregex = You can use a bantime of -1 to not timeout the ban, or some high number in seconds to ban for a specific time span. The banned IPs get dropped when you restart the server or fail2ban, unless you add code to reinstate the ban list across restarts. If you do that, your ban list might eventually grow huge.
I added some stuff to the /etc/init.d/fail2ban init script, to maintain IP bans across restarts:
Code:
[root@mail init.d]# diff -u fail2ban.orig fail2ban
--- fail2ban.orig 2010-02-14 09:01:56.000000000 -0700
+++ fail2ban 2011-12-22 16:17:35.000000000 -0700
@@ -37,10 +37,20 @@
echo_failure
fi
echo
+ if [ -x /tmp/banned_ips ] ; then /tmp/banned_ips >/dev/null ; fi
return $RETVAL
}
stop() {
+ echo "Saving current banned IPs..."
+ if [ -e /tmp/banned_ips ] ; then rm -f /tmp/banned_ips ; fi
+ jails=$(fail2ban-client status | grep Jail\ list: | sed 's/.*Jail list:\t\+//;s/,//g')
+ for jail in ${jails}; do
+ for ip in $(fail2ban-client status ${jail}|grep IP\ list|sed 's/.*IP list:\t//'); do
+ echo "fail2ban-client set ${jail} banip ${ip}" >>/tmp/banned_ips
+ done
+ done
+ if [ -e /tmp/banned_ips ] ; then chmod 770 /tmp/banned_ips ; fi
echo -n $"Stopping fail2ban: "
getpid
RETVAL=$? My full /etc/init.d/fail2ban init script:
Code:
#!/bin/bash
#
# chkconfig: - 92 08
# description: Fail2ban daemon
# http://fail2ban.sourceforge.net/wiki/index.php/Main_Page
# process name: fail2ban-server
#
#
# Author: Tyler Owen
#
# Source function library.
. /etc/init.d/functions
# Check that the config file exists
[ -f /etc/fail2ban/fail2ban.conf ] || exit 0
FAIL2BAN="/usr/bin/fail2ban-client"
RETVAL=0
getpid() {
pid=`ps -eo pid,comm | grep fail2ban- | awk '{ print $1 }'`
}
start() {
echo -n $"Starting fail2ban: "
getpid
if [ -z "$pid" ]; then
$FAIL2BAN -x start > /dev/null
RETVAL=$?
fi
if [ $RETVAL -eq 0 ]; then
touch /var/lock/subsys/fail2ban
echo_success
else
echo_failure
fi
echo
if [ -x /tmp/banned_ips ] ; then /tmp/banned_ips >/dev/null ; fi
return $RETVAL
}
stop() {
echo "Saving current banned IPs..."
if [ -e /tmp/banned_ips ] ; then rm -f /tmp/banned_ips ; fi
jails=$(fail2ban-client status | grep Jail\ list: | sed 's/.*Jail list:\t\+//;s/,//g')
for jail in ${jails}; do
for ip in $(fail2ban-client status ${jail}|grep IP\ list|sed 's/.*IP list:\t//'); do
echo "fail2ban-client set ${jail} banip ${ip}" >>/tmp/banned_ips
done
done
if [ -e /tmp/banned_ips ] ; then chmod 770 /tmp/banned_ips ; fi
echo -n $"Stopping fail2ban: "
getpid
RETVAL=$?
if [ -n "$pid" ]; then
$FAIL2BAN stop > /dev/null
sleep 1
getpid
if [ -z "$pid" ]; then
rm -f /var/lock/subsys/fail2ban
echo_success
else
echo_failure
fi
else
echo_failure
fi
echo
return $RETVAL
}
# See how we were called.
case "$1" in
start)
start
;;
stop)
stop
;;
status)
getpid
if [ -n "$pid" ]; then
echo "Fail2ban (pid $pid) is running..."
$FAIL2BAN status
else
RETVAL=1
echo "Fail2ban is stopped"
fi
;;
restart)
stop
start
;;
*)
echo $"Usage: $0 {start|stop|status|restart}"
exit 1
;;
esac
exit $RETVAL If you want to maintain banned IPs across restarts, you will probably need to patch /usr/share/fail2ban/server/filter.py in order for the banip directive to work:
Code:
[root@mail server]# diff -u fail2ban-0.8.4/fail2ban/server/filter.py filter.py
--- fail2ban-0.8.4/fail2ban/server/filter.py 2011-12-21 17:11:38.000000000 -0700
+++ filter.py 2011-12-22 16:30:13.000000000 -0700
@@ -31,7 +31,7 @@
from mytime import MyTime
from failregex import FailRegex, Regex, RegexException
-import logging, re, os
+import logging, re, os, time
# Gets the instance of the logger.
logSys = logging.getLogger("fail2ban.filter")
@@ -191,7 +191,7 @@
def addBannedIP(self, ip):
unixTime = time.time()
- self.failManager.addFailure(FailTicket(ip, unixTime))
+ self.jail.putFailTicket(FailTicket(ip, unixTime))
return ip
## This patch is for v0.8.4. I'm using fail2ban 0.8.6, downloaded from github, so YMMV.
Note also regarding maintaining bans, that you may get a flood of emails from fail2ban after restarts, as it reinstates bans. I set up a filter in my email client to trash those:
Fail2Ban IP renewals:
- Match All
- Subject contains "[Fail2Ban]"
- Body contains "(0 failures)"
- Perform these actions:
I changed the sasl.conf filter, as the default wasn't working for me:
Code:
failregex = \[<HOST>\]: SASL (?:LOGIN|PLAIN|(?:CRAM|DIGEST)-MD5) authentication failed
I added a postfix-connections.conf fail2ban filter, for IP addresses that flood postfix over the default 50 connection limit:
Code:
failregex = warning: Connection concurrency limit exceeded: 51 from (.*)\[<HOST>\]
Note also that if a legitimate user repeatedly fails to login correctly, they will get banned too. You would need to remove them from the ban list using iptables:
Code:
[root@mail fail2ban]# iptables -L --line-numbers
Chain INPUT (policy ACCEPT)
target prot opt source destination
fail2ban-Zimbra-audit tcp -- anywhere anywhere
Chain fail2ban-Zimbra-audit (1 references)
num target prot opt source destination
1 DROP all -- bad.spammer.com anywhere
2 DROP all -- legitimate.user.com anywhere
or, you can display just IP addresses, to avoid the slow reverse DNS lookup:
Code:
[root@mail fail2ban]# iptables -nL --line-numbers
Chain INPUT (policy ACCEPT)
target prot opt source destination
fail2ban-Zimbra-audit tcp -- 0.0.0.0/0 0.0.0.0/0
Chain fail2ban-Zimbra-audit (1 references)
num target prot opt source destination
1 DROP all -- 66.77.88.99 0.0.0.0/0
2 DROP all -- 11.33.55.77 0.0.0.0/0
You would remove the ban on the legitimate user like so:
Code:
iptables -D fail2ban-Zimbra-audit 2