mirror of https://github.com/fail2ban/fail2ban
Recognize restored (from database) tickets after restart (tell action restored state of the ticket);
Prevent executing of several actions (e.g. mail, send-mail etc) on restart (bans were already notified). Test cases extended (smtp and by restart in ServerReloadTest). Closes gh-1141 Closes gh-921pull/1669/head
parent
4a65e069e1
commit
ee3c787cc6
|
@ -58,7 +58,8 @@ actioncheck =
|
|||
# Tags: See jail.conf(5) man page
|
||||
# Values: CMD
|
||||
#
|
||||
actionban = oifs=${IFS};
|
||||
actionban = %(_bypass_if_restored)s
|
||||
oifs=${IFS};
|
||||
IFS=.; SEP_IP=( <ip> ); set -- ${SEP_IP}; ADDRESSES=$(dig +short -t txt -q $4.$3.$2.$1.abuse-contacts.abusix.org);
|
||||
IFS=,; ADDRESSES=$(echo $ADDRESSES)
|
||||
IFS=${oifs}
|
||||
|
|
|
@ -26,6 +26,10 @@
|
|||
# configure how often the buffer is flushed).
|
||||
#
|
||||
|
||||
[INCLUDES]
|
||||
|
||||
before = helpers-common.conf
|
||||
|
||||
[Definition]
|
||||
|
||||
# Option: actionstart
|
||||
|
@ -64,7 +68,8 @@ actioncheck =
|
|||
# few seconds out, are incorrect. See
|
||||
# http://sourceforge.net/tracker/index.php?func=detail&aid=2017795&group_id=121032&atid=689047
|
||||
#
|
||||
actionban = TZONE=`date +%%z | sed 's/\([+-]..\)\(..\)/\1:\2/'`
|
||||
actionban = %(_bypass_if_restored)s
|
||||
TZONE=`date +%%z | sed 's/\([+-]..\)\(..\)/\1:\2/'`
|
||||
DATETIME="`perl -e '@t=localtime(<time>);printf "%%4d-%%02d-%%02d %%02d:%%02d:%%02d",1900+$t[5],$t[4]+1,$t[3],$t[2],$t[1],$t[0]'` $TZONE"
|
||||
PROTOCOL=`awk '{IGNORECASE=1;if($1=="<protocol>"){print $2;exit}}' /etc/protocols`
|
||||
if [ -z "$PROTOCOL" ]; then PROTOCOL=<protocol>; fi
|
||||
|
@ -91,7 +96,8 @@ actionban = TZONE=`date +%%z | sed 's/\([+-]..\)\(..\)/\1:\2/'`
|
|||
# Tags: See jail.conf(5) man page
|
||||
# Values: CMD
|
||||
#
|
||||
actionunban = if [ -f <tmpfile>.first ]; then
|
||||
actionunban = %(_bypass_if_restored)s
|
||||
if [ -f <tmpfile>.first ]; then
|
||||
NOW=`date +%%s`
|
||||
LOGAGE=$(($NOW - `cat <tmpfile>.first`))
|
||||
if [ $LOGAGE -gt <maxbufferage> ]; then
|
||||
|
|
|
@ -7,6 +7,9 @@
|
|||
_grep_logs = logpath="<logpath>"; grep <grepopts> -E %(_grep_logs_args)s $logpath | <greplimit>
|
||||
_grep_logs_args = '(^|[^0-9])<ip>([^0-9]|$)'
|
||||
|
||||
# Used for actions, that should not by executed if ticket was restored:
|
||||
_bypass_if_restored = if [ '<restored>' = '1' ]; then exit 0; fi;
|
||||
|
||||
[Init]
|
||||
greplimit = tail -n <grepmax>
|
||||
grepmax = 1000
|
||||
|
|
|
@ -4,6 +4,11 @@
|
|||
#
|
||||
#
|
||||
|
||||
[INCLUDES]
|
||||
|
||||
before = helpers-common.conf
|
||||
|
||||
|
||||
[Definition]
|
||||
|
||||
# Option: actionstart
|
||||
|
@ -45,7 +50,8 @@ actioncheck =
|
|||
# Tags: See jail.conf(5) man page
|
||||
# Values: CMD
|
||||
#
|
||||
actionban = printf %%b "`date`: <ip> (<failures> failures)\n" >> <tmpfile>
|
||||
actionban = %(_bypass_if_restored)s
|
||||
printf %%b "`date`: <ip> (<failures> failures)\n" >> <tmpfile>
|
||||
LINE=$( wc -l <tmpfile> | awk '{ print $1 }' )
|
||||
if [ $LINE -ge <lines> ]; then
|
||||
printf %%b "Hi,\n
|
||||
|
|
|
@ -52,7 +52,9 @@ _ban_mail_content = ( printf %%b "Hi,\n
|
|||
printf %%b "\n
|
||||
Regards,\n
|
||||
Fail2Ban" )
|
||||
actionban = %(_ban_mail_content)s | <mailcmd> "[Fail2Ban] <name>: banned <ip> from `uname -n`" <dest>
|
||||
|
||||
actionban = %(_bypass_if_restored)s
|
||||
%(_ban_mail_content)s | <mailcmd> "[Fail2Ban] <name>: banned <ip> from `uname -n`" <dest>
|
||||
|
||||
# Option: actionunban
|
||||
# Notes.: command executed when unbanning an IP. Take care that the
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
[INCLUDES]
|
||||
|
||||
before = mail-whois-common.conf
|
||||
helpers-common.conf
|
||||
|
||||
[Definition]
|
||||
|
||||
|
@ -40,7 +41,8 @@ actioncheck =
|
|||
# Tags: See jail.conf(5) man page
|
||||
# Values: CMD
|
||||
#
|
||||
actionban = printf %%b "Hi,\n
|
||||
actionban = %(_bypass_if_restored)s
|
||||
printf %%b "Hi,\n
|
||||
The IP <ip> has just been banned by Fail2Ban after
|
||||
<failures> attempts against <name>.\n\n
|
||||
Here is more information about <ip> :\n
|
||||
|
|
|
@ -4,6 +4,10 @@
|
|||
#
|
||||
#
|
||||
|
||||
[INCLUDES]
|
||||
|
||||
before = helpers-common.conf
|
||||
|
||||
[Definition]
|
||||
|
||||
# Option: actionstart
|
||||
|
@ -36,7 +40,8 @@ actioncheck =
|
|||
# Tags: See jail.conf(5) man page
|
||||
# Values: CMD
|
||||
#
|
||||
actionban = printf %%b "Hi,\n
|
||||
actionban = %(_bypass_if_restored)s
|
||||
printf %%b "Hi,\n
|
||||
The IP <ip> has just been banned by Fail2Ban after
|
||||
<failures> attempts against <name>.\n
|
||||
Regards,\n
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
[INCLUDES]
|
||||
|
||||
before = sendmail-common.conf
|
||||
helpers-common.conf
|
||||
|
||||
[Definition]
|
||||
|
||||
|
@ -58,7 +59,8 @@ actioncheck =
|
|||
# Tags: See jail.conf(5) man page
|
||||
# Values: CMD
|
||||
#
|
||||
actionban = printf %%b "`date`: <ip> (<failures> failures)\n" >> <tmpfile>
|
||||
actionban = %(_bypass_if_restored)s
|
||||
printf %%b "`date`: <ip> (<failures> failures)\n" >> <tmpfile>
|
||||
LINE=$( wc -l <tmpfile> | awk '{ print $1 }' )
|
||||
if [ $LINE -ge <lines> ]; then
|
||||
printf %%b "Subject: [Fail2Ban] <name>: summary from `uname -n`
|
||||
|
|
|
@ -20,7 +20,8 @@ before = sendmail-common.conf
|
|||
# Tags: See jail.conf(5) man page
|
||||
# Values: CMD
|
||||
#
|
||||
actionban = ( printf %%b "Subject: [Fail2Ban] <name>: banned <ip> from `uname -n`
|
||||
actionban = %(_bypass_if_restored)s
|
||||
( printf %%b "Subject: [Fail2Ban] <name>: banned <ip> from `uname -n`
|
||||
Date: `LC_ALL=C date +"%%a, %%d %%h %%Y %%T %%z"`
|
||||
From: <sendername> <<sender>>
|
||||
To: <dest>\n
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
[INCLUDES]
|
||||
|
||||
before = sendmail-common.conf
|
||||
helpers-common.conf
|
||||
|
||||
[Definition]
|
||||
|
||||
|
@ -16,7 +17,8 @@ before = sendmail-common.conf
|
|||
# Tags: See jail.conf(5) man page
|
||||
# Values: CMD
|
||||
#
|
||||
actionban = printf %%b "Subject: [Fail2Ban] <name>: banned <ip> from `uname -n`
|
||||
actionban = %(_bypass_if_restored)s
|
||||
printf %%b "Subject: [Fail2Ban] <name>: banned <ip> from `uname -n`
|
||||
Date: `LC_ALL=C date +"%%a, %%d %%h %%Y %%T %%z"`
|
||||
From: <sendername> <<sender>>
|
||||
To: <dest>\n
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
[INCLUDES]
|
||||
|
||||
before = sendmail-common.conf
|
||||
helpers-common.conf
|
||||
|
||||
[Definition]
|
||||
|
||||
|
@ -16,7 +17,8 @@ before = sendmail-common.conf
|
|||
# Tags: See jail.conf(5) man page
|
||||
# Values: CMD
|
||||
#
|
||||
actionban = printf %%b "Subject: [Fail2Ban] <name>: banned <ip> from `uname -n`
|
||||
actionban = %(_bypass_if_restored)s
|
||||
printf %%b "Subject: [Fail2Ban] <name>: banned <ip> from `uname -n`
|
||||
Date: `LC_ALL=C date +"%%a, %%d %%h %%Y %%T %%z"`
|
||||
From: <sendername> <<sender>>
|
||||
To: <dest>\n
|
||||
|
|
|
@ -17,7 +17,8 @@ before = sendmail-common.conf
|
|||
# Tags: See jail.conf(5) man page
|
||||
# Values: CMD
|
||||
#
|
||||
actionban = ( printf %%b "Subject: [Fail2Ban] <name>: banned <ip> from `uname -n`
|
||||
actionban = %(_bypass_if_restored)s
|
||||
( printf %%b "Subject: [Fail2Ban] <name>: banned <ip> from `uname -n`
|
||||
Date: `LC_ALL=C date +"%%a, %%d %%h %%Y %%T %%z"`
|
||||
From: <sendername> <<sender>>
|
||||
To: <dest>\n
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
[INCLUDES]
|
||||
|
||||
before = sendmail-common.conf
|
||||
helpers-common.conf
|
||||
|
||||
[Definition]
|
||||
|
||||
|
@ -16,7 +17,8 @@ before = sendmail-common.conf
|
|||
# Tags: See jail.conf(5) man page
|
||||
# Values: CMD
|
||||
#
|
||||
actionban = printf %%b "Subject: [Fail2Ban] <name>: banned <ip> from `uname -n`
|
||||
actionban = %(_bypass_if_restored)s
|
||||
printf %%b "Subject: [Fail2Ban] <name>: banned <ip> from `uname -n`
|
||||
Date: `LC_ALL=C date +"%%a, %%d %%h %%Y %%T %%z"`
|
||||
From: <sendername> <<sender>>
|
||||
To: <dest>\n
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
[INCLUDES]
|
||||
|
||||
before = sendmail-common.conf
|
||||
helpers-common.conf
|
||||
|
||||
[Definition]
|
||||
|
||||
|
@ -16,7 +17,8 @@ before = sendmail-common.conf
|
|||
# Tags: See jail.conf(5) man page
|
||||
# Values: CMD
|
||||
#
|
||||
actionban = printf %%b "Subject: [Fail2Ban] <name>: banned <ip> from `uname -n`
|
||||
actionban = %(_bypass_if_restored)s
|
||||
printf %%b "Subject: [Fail2Ban] <name>: banned <ip> from `uname -n`
|
||||
Date: `LC_ALL=C date +"%%a, %%d %%h %%Y %%T %%z"`
|
||||
From: <sendername> <<sender>>
|
||||
To: <dest>\n
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
[INCLUDES]
|
||||
|
||||
before = sendmail-common.conf
|
||||
helpers-common.conf
|
||||
|
||||
[Definition]
|
||||
|
||||
|
@ -16,7 +17,8 @@ before = sendmail-common.conf
|
|||
# Tags: See jail.conf(5) man page
|
||||
# Values: CMD
|
||||
#
|
||||
actionban = printf %%b "Subject: [Fail2Ban] <name>: banned <ip> from `uname -n`
|
||||
actionban = %(_bypass_if_restored)s
|
||||
printf %%b "Subject: [Fail2Ban] <name>: banned <ip> from `uname -n`
|
||||
Date: `LC_ALL=C date +"%%a, %%d %%h %%Y %%T %%z"`
|
||||
From: <sendername> <<sender>>
|
||||
To: <dest>\n
|
||||
|
|
|
@ -211,6 +211,8 @@ class SMTPAction(ActionBase):
|
|||
Dictionary which includes information in relation to
|
||||
the ban.
|
||||
"""
|
||||
if aInfo.get('restored'):
|
||||
return
|
||||
aInfo.update(self.message_values)
|
||||
message = "".join([
|
||||
messages['ban']['head'],
|
||||
|
|
|
@ -30,6 +30,10 @@
|
|||
#
|
||||
#
|
||||
|
||||
[INCLUDES]
|
||||
|
||||
before = helpers-common.conf
|
||||
|
||||
[Definition]
|
||||
|
||||
actionstart =
|
||||
|
@ -38,7 +42,8 @@ actionstop =
|
|||
|
||||
actioncheck =
|
||||
|
||||
actionban = oifs=${IFS}; IFS=.;SEP_IP=( <ip> ); set -- ${SEP_IP}; ADDRESSES=$(dig +short -t txt -q $4.$3.$2.$1.abuse-contacts.abusix.org); IFS=${oifs}
|
||||
actionban = %(_bypass_if_restored)s
|
||||
oifs=${IFS}; IFS=.;SEP_IP=( <ip> ); set -- ${SEP_IP}; ADDRESSES=$(dig +short -t txt -q $4.$3.$2.$1.abuse-contacts.abusix.org); IFS=${oifs}
|
||||
IP=<ip>
|
||||
FROM=<sender>
|
||||
SERVICE=<service>
|
||||
|
|
|
@ -219,9 +219,9 @@ class CommandAction(ActionBase):
|
|||
self.timeout = 60
|
||||
## Command executed in order to initialize the system.
|
||||
self.actionstart = ''
|
||||
## Command executed when an IP address gets banned.
|
||||
## Command executed when ticket gets banned.
|
||||
self.actionban = ''
|
||||
## Command executed when an IP address gets removed.
|
||||
## Command executed when ticket gets removed.
|
||||
self.actionunban = ''
|
||||
## Command executed in order to check requirements.
|
||||
self.actioncheck = ''
|
||||
|
|
|
@ -348,6 +348,8 @@ class Actions(JailThread, Mapping):
|
|||
aInfo["failures"] = bTicket.getAttempt()
|
||||
aInfo["time"] = bTicket.getTime()
|
||||
aInfo["matches"] = "\n".join(bTicket.getMatches())
|
||||
# to bypass actions, that should not be executed for restored tickets
|
||||
aInfo["restored"] = 1 if ticket.restored else 0
|
||||
if self._jail.database is not None:
|
||||
mi4ip = lambda overalljails=False, self=self, \
|
||||
mi={'ip':ip, 'ticket':bTicket}: self.__getBansMerged(mi, overalljails)
|
||||
|
@ -449,6 +451,8 @@ class Actions(JailThread, Mapping):
|
|||
aInfo["failures"] = ticket.getAttempt()
|
||||
aInfo["time"] = ticket.getTime()
|
||||
aInfo["matches"] = "".join(ticket.getMatches())
|
||||
# to bypass actions, that should not be executed for restored tickets
|
||||
aInfo["restored"] = 1 if ticket.restored else 0
|
||||
if actions is None:
|
||||
logSys.notice("[%s] Unban %s", self._jail.name, aInfo["ip"])
|
||||
for name, action in unbactions.iteritems():
|
||||
|
|
|
@ -94,7 +94,7 @@ class SMTPActionTest(unittest.TestCase):
|
|||
"Subject: [Fail2Ban] %s: stopped" %
|
||||
self.jail.name in self.smtpd.data)
|
||||
|
||||
def testBan(self):
|
||||
def _testBan(self, restored=False):
|
||||
aInfo = {
|
||||
'ip': "127.0.0.2",
|
||||
'failures': 3,
|
||||
|
@ -102,8 +102,13 @@ class SMTPActionTest(unittest.TestCase):
|
|||
'ipjailmatches': "Test fail 1\nTest Fail2\n",
|
||||
'ipmatches': "Test fail 1\nTest Fail2\nTest Fail3\n",
|
||||
}
|
||||
if restored:
|
||||
aInfo['restored'] = 1
|
||||
|
||||
self.action.ban(aInfo)
|
||||
if restored: # no mail, should raises attribute error:
|
||||
self.assertRaises(AttributeError, lambda: self.smtpd.mailfrom)
|
||||
return
|
||||
self.assertEqual(self.smtpd.mailfrom, "fail2ban")
|
||||
self.assertEqual(self.smtpd.rcpttos, ["root"])
|
||||
subject = "Subject: [Fail2Ban] %s: banned %s" % (
|
||||
|
@ -124,6 +129,12 @@ class SMTPActionTest(unittest.TestCase):
|
|||
self.action.ban(aInfo)
|
||||
self.assertIn(aInfo['ipmatches'], self.smtpd.data)
|
||||
|
||||
def testBan(self):
|
||||
self._testBan()
|
||||
|
||||
def testNOPByRestored(self):
|
||||
self._testBan(restored=True)
|
||||
|
||||
def testOptions(self):
|
||||
self.action.start()
|
||||
self.assertEqual(self.smtpd.mailfrom, "fail2ban")
|
||||
|
|
|
@ -756,9 +756,10 @@ class Fail2banServerTest(Fail2banClientServerBase):
|
|||
return
|
||||
_write_file(fn, "w",
|
||||
"[Definition]",
|
||||
"restore = ",
|
||||
"actionstart = echo '[<name>] %s: ** start'" % actname, start,
|
||||
"actionreload = echo '[<name>] %s: .. reload'" % actname, reload,
|
||||
"actionban = echo '[<name>] %s: ++ ban <ip>'" % actname, ban,
|
||||
"actionban = echo '[<name>] %s: ++ ban <ip> %%(restore)s'" % actname, ban,
|
||||
"actionunban = echo '[<name>] %s: -- unban <ip>'" % actname, unban,
|
||||
"actionstop = echo '[<name>] %s: __ stop'" % actname, stop,
|
||||
)
|
||||
|
@ -777,17 +778,22 @@ class Fail2banServerTest(Fail2banClientServerBase):
|
|||
"",
|
||||
"[test-jail1]", "backend = " + backend, "filter =",
|
||||
"action = ",
|
||||
" test-action1[name='%(__name__)s']" if 1 in actions else "",
|
||||
" test-action2[name='%(__name__)s']" if 2 in actions else "",
|
||||
" test-action1[name='%(__name__)s']" \
|
||||
if 1 in actions else "",
|
||||
" test-action2[name='%(__name__)s', restore='restored: <restored>']" \
|
||||
if 2 in actions else "",
|
||||
"logpath = " + test1log,
|
||||
" " + test2log if 2 in enabled else "",
|
||||
" " + test3log if 2 in enabled else "",
|
||||
"failregex = ^\s*failure (401|403) from <HOST>",
|
||||
" ^\s*error (401|403) from <HOST>" if 2 in enabled else "",
|
||||
" ^\s*error (401|403) from <HOST>" \
|
||||
if 2 in enabled else "",
|
||||
"enabled = true" if 1 in enabled else "",
|
||||
"",
|
||||
"[test-jail2]", "backend = " + backend, "filter =",
|
||||
"action = ",
|
||||
" test-action2[name='%(__name__)s', restore='restored: <restored>']" \
|
||||
if 2 in actions else "",
|
||||
"logpath = " + test2log,
|
||||
"enabled = true" if 2 in enabled else "",
|
||||
)
|
||||
|
@ -821,6 +827,10 @@ class Fail2banServerTest(Fail2banClientServerBase):
|
|||
self.assertLogged(
|
||||
"stdout: '[test-jail1] test-action1: ** start'",
|
||||
"stdout: '[test-jail1] test-action2: ** start'", all=True)
|
||||
# test restored is 0:
|
||||
self.assertLogged(
|
||||
"stdout: '[test-jail1] test-action2: ++ ban 192.0.2.1 restored: 0'",
|
||||
all=True, wait=MID_WAITTIME)
|
||||
|
||||
# broken jail was logged (in client and server log):
|
||||
self.assertLogged(
|
||||
|
@ -882,10 +892,10 @@ class Fail2banServerTest(Fail2banClientServerBase):
|
|||
self.assertNotLogged(
|
||||
"stdout: '[test-jail1] test-action1: -- unban 192.0.2.1'")
|
||||
|
||||
# don't need both actions anymore:
|
||||
# don't need action1 anymore:
|
||||
_write_action_cfg(actname="test-action1", allow=False)
|
||||
_write_action_cfg(actname="test-action2", allow=False)
|
||||
_write_jail_cfg(actions=[])
|
||||
# leave action2 just to test restored interpolation:
|
||||
_write_jail_cfg(actions=[2])
|
||||
|
||||
# write new failures:
|
||||
self.pruneLog("[test-phase 2b]")
|
||||
|
@ -913,7 +923,8 @@ class Fail2banServerTest(Fail2banClientServerBase):
|
|||
"[test-jail2] Found 192.0.2.2",
|
||||
"[test-jail2] Ban 192.0.2.2",
|
||||
"[test-jail2] Found 192.0.2.3",
|
||||
"[test-jail2] Ban 192.0.2.3", all=True)
|
||||
"[test-jail2] Ban 192.0.2.3",
|
||||
all=True)
|
||||
|
||||
# rotate logs:
|
||||
_write_file(test1log, "w+")
|
||||
|
@ -936,6 +947,19 @@ class Fail2banServerTest(Fail2banClientServerBase):
|
|||
"[test-jail2] Restore Ban 192.0.2.4",
|
||||
"[test-jail2] Restore Ban 192.0.2.8", all=True
|
||||
)
|
||||
# test restored is 1:
|
||||
self.assertLogged(
|
||||
"stdout: '[test-jail2] test-action2: ++ ban 192.0.2.4 restored: 1'",
|
||||
"stdout: '[test-jail2] test-action2: ++ ban 192.0.2.8 restored: 1'",
|
||||
all=True, wait=MID_WAITTIME)
|
||||
self.assertNotLogged(
|
||||
"stdout: '[test-jail2] test-action2: ++ ban 192.0.2.4 restored: 0'",
|
||||
"stdout: '[test-jail2] test-action2: ++ ban 192.0.2.8 restored: 0'",
|
||||
all=True)
|
||||
|
||||
# don't need actions anymore:
|
||||
_write_action_cfg(actname="test-action2", allow=False)
|
||||
_write_jail_cfg(actions=[])
|
||||
|
||||
# restart jail with unban all:
|
||||
self.pruneLog("[test-phase 2d]")
|
||||
|
|
Loading…
Reference in New Issue