mirror of https://github.com/fail2ban/fail2ban
ENH: Add <ipmatches> and <ipjailmatches> tags
Example use filter also added for sendmail-whois with ipmatches rather than grepped linespull/491/head
parent
6dde1d5429
commit
0bcff771b8
1
MANIFEST
1
MANIFEST
|
@ -228,6 +228,7 @@ config/action.d/mynetwatchman.conf
|
||||||
config/action.d/pf.conf
|
config/action.d/pf.conf
|
||||||
config/action.d/sendmail.conf
|
config/action.d/sendmail.conf
|
||||||
config/action.d/sendmail-buffered.conf
|
config/action.d/sendmail-buffered.conf
|
||||||
|
config/action.d/sendmail-whois-ipmatches.conf
|
||||||
config/action.d/sendmail-whois.conf
|
config/action.d/sendmail-whois.conf
|
||||||
config/action.d/sendmail-whois-lines.conf
|
config/action.d/sendmail-whois-lines.conf
|
||||||
config/action.d/shorewall.conf
|
config/action.d/shorewall.conf
|
||||||
|
|
|
@ -0,0 +1,77 @@
|
||||||
|
# Fail2Ban configuration file
|
||||||
|
#
|
||||||
|
# Author: Cyril Jaquier
|
||||||
|
#
|
||||||
|
#
|
||||||
|
|
||||||
|
[INCLUDES]
|
||||||
|
|
||||||
|
before = sendmail-common.conf
|
||||||
|
|
||||||
|
[Definition]
|
||||||
|
|
||||||
|
# Option: actionstart
|
||||||
|
# Notes.: command executed once at the start of Fail2Ban.
|
||||||
|
# Values: CMD
|
||||||
|
#
|
||||||
|
actionstart = printf %%b "Subject: [Fail2Ban] <name>: started on `uname -n`
|
||||||
|
Date: `LC_TIME=C date -u +"%%a, %%d %%h %%Y %%T +0000"`
|
||||||
|
From: <sendername> <<sender>>
|
||||||
|
To: <dest>\n
|
||||||
|
Hi,\n
|
||||||
|
The jail <name> has been started successfully.\n
|
||||||
|
Regards,\n
|
||||||
|
Fail2Ban" | /usr/sbin/sendmail -f <sender> <dest>
|
||||||
|
|
||||||
|
# Option: actionstop
|
||||||
|
# Notes.: command executed once at the end of Fail2Ban
|
||||||
|
# Values: CMD
|
||||||
|
#
|
||||||
|
actionstop = printf %%b "Subject: [Fail2Ban] <name>: stopped on `uname -n`
|
||||||
|
Date: `LC_TIME=C date -u +"%%a, %%d %%h %%Y %%T +0000"`
|
||||||
|
From: <sendername> <<sender>>
|
||||||
|
To: <dest>\n
|
||||||
|
Hi,\n
|
||||||
|
The jail <name> has been stopped.\n
|
||||||
|
Regards,\n
|
||||||
|
Fail2Ban" | /usr/sbin/sendmail -f <sender> <dest>
|
||||||
|
|
||||||
|
# Option: actioncheck
|
||||||
|
# Notes.: command executed once before each actionban command
|
||||||
|
# Values: CMD
|
||||||
|
#
|
||||||
|
actioncheck =
|
||||||
|
|
||||||
|
# Option: actionban
|
||||||
|
# Notes.: command executed when banning an IP. Take care that the
|
||||||
|
# command is executed with Fail2Ban user rights.
|
||||||
|
# Tags: See jail.conf(5) man page
|
||||||
|
# Values: CMD
|
||||||
|
#
|
||||||
|
actionban = printf %%b "Subject: [Fail2Ban] <name>: banned <ip> from `uname -n`
|
||||||
|
Date: `LC_TIME=C date -u +"%%a, %%d %%h %%Y %%T +0000"`
|
||||||
|
From: <sendername> <<sender>>
|
||||||
|
To: <dest>\n
|
||||||
|
Hi,\n
|
||||||
|
The IP <ip> has just been banned by Fail2Ban after
|
||||||
|
<failures> attempts against <name>.\n\n
|
||||||
|
Here are more information about <ip>:\n
|
||||||
|
`/usr/bin/whois <ip>`\n\n
|
||||||
|
Matches for IP:<ip>\n
|
||||||
|
<ipmatches>\n\n
|
||||||
|
Regards,\n
|
||||||
|
Fail2Ban" | /usr/sbin/sendmail -f <sender> <dest>
|
||||||
|
|
||||||
|
# Option: actionunban
|
||||||
|
# Notes.: command executed when unbanning an IP. Take care that the
|
||||||
|
# command is executed with Fail2Ban user rights.
|
||||||
|
# Tags: See jail.conf(5) man page
|
||||||
|
# Values: CMD
|
||||||
|
#
|
||||||
|
actionunban =
|
||||||
|
|
||||||
|
[Init]
|
||||||
|
|
||||||
|
# Default name of the chain
|
||||||
|
#
|
||||||
|
name = default
|
|
@ -295,7 +295,7 @@ class Action:
|
||||||
|
|
||||||
#@staticmethod
|
#@staticmethod
|
||||||
def escapeTag(tag):
|
def escapeTag(tag):
|
||||||
for c in '\\#&;`|*?~<>^()[]{}$\n\'"':
|
for c in '\\#&;`|*?~<>^()[]{}$\'"':
|
||||||
if c in tag:
|
if c in tag:
|
||||||
tag = tag.replace(c, '\\' + c)
|
tag = tag.replace(c, '\\' + c)
|
||||||
return tag
|
return tag
|
||||||
|
@ -314,8 +314,11 @@ class Action:
|
||||||
"""
|
"""
|
||||||
string = query
|
string = query
|
||||||
for tag, value in aInfo.iteritems():
|
for tag, value in aInfo.iteritems():
|
||||||
|
if "<%s>" % tag in query:
|
||||||
|
if callable(value):
|
||||||
|
value = value()
|
||||||
value = str(value) # assure string
|
value = str(value) # assure string
|
||||||
if tag == 'matches':
|
if tag.endswith('matches'):
|
||||||
# That one needs to be escaped since its content is
|
# That one needs to be escaped since its content is
|
||||||
# out of our control
|
# out of our control
|
||||||
value = Action.escapeTag(value)
|
value = Action.escapeTag(value)
|
||||||
|
|
|
@ -183,7 +183,14 @@ class Actions(JailThread):
|
||||||
aInfo["ip"] = bTicket.getIP()
|
aInfo["ip"] = bTicket.getIP()
|
||||||
aInfo["failures"] = bTicket.getAttempt()
|
aInfo["failures"] = bTicket.getAttempt()
|
||||||
aInfo["time"] = bTicket.getTime()
|
aInfo["time"] = bTicket.getTime()
|
||||||
aInfo["matches"] = "".join(bTicket.getMatches())
|
aInfo["matches"] = "\n".join(bTicket.getMatches())
|
||||||
|
if self.jail.getDatabase() is not None:
|
||||||
|
aInfo["ipmatches"] = lambda: "\n".join(
|
||||||
|
self.jail.getDatabase().getBansMerged(
|
||||||
|
bTicket.getIP()).getMatches())
|
||||||
|
aInfo["ipjailmatches"] = lambda: "\n".join(
|
||||||
|
self.jail.getDatabase().getBansMerged(
|
||||||
|
bTicket.getIP(), jail=self.jail).getMatches())
|
||||||
if self.__banManager.addBanTicket(bTicket):
|
if self.__banManager.addBanTicket(bTicket):
|
||||||
logSys.warning("[%s] Ban %s" % (self.jail.getName(), aInfo["ip"]))
|
logSys.warning("[%s] Ban %s" % (self.jail.getName(), aInfo["ip"]))
|
||||||
for action in self.__actions:
|
for action in self.__actions:
|
||||||
|
|
|
@ -102,8 +102,28 @@ class ExecuteAction(unittest.TestCase):
|
||||||
"Text 890 text 123 ABC")
|
"Text 890 text 123 ABC")
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
self.__action.replaceTag("<matches>",
|
self.__action.replaceTag("<matches>",
|
||||||
{'matches': "some >char< should \< be[ escap}ed&"}),
|
{'matches': "some >char< should \< be[ escap}ed&\n"}),
|
||||||
r"some \>char\< should \\\< be\[ escap\}ed\&")
|
"some \\>char\\< should \\\\\\< be\\[ escap\\}ed\\&\n")
|
||||||
|
self.assertEqual(
|
||||||
|
self.__action.replaceTag("<ipmatches>",
|
||||||
|
{'ipmatches': "some >char< should \< be[ escap}ed&\n"}),
|
||||||
|
"some \\>char\\< should \\\\\\< be\\[ escap\\}ed\\&\n")
|
||||||
|
self.assertEqual(
|
||||||
|
self.__action.replaceTag("<ipjailmatches>",
|
||||||
|
{'ipjailmatches': "some >char< should \< be[ escap}ed&\n"}),
|
||||||
|
"some \\>char\\< should \\\\\\< be\\[ escap\\}ed\\&\n")
|
||||||
|
|
||||||
|
# Callable
|
||||||
|
self.assertEqual(
|
||||||
|
self.__action.replaceTag("09 <callable> 11",
|
||||||
|
{'callable': lambda: str(10)}),
|
||||||
|
"09 10 11")
|
||||||
|
|
||||||
|
# As tag not present, therefore callable should not be called
|
||||||
|
# Will raise ValueError if it is
|
||||||
|
self.assertEqual(
|
||||||
|
self.__action.replaceTag("abc",
|
||||||
|
{'callable': lambda: int("a")}), "abc")
|
||||||
|
|
||||||
def testExecuteActionBan(self):
|
def testExecuteActionBan(self):
|
||||||
self.__action.setActionStart("touch /tmp/fail2ban.test")
|
self.__action.setActionStart("touch /tmp/fail2ban.test")
|
||||||
|
|
Loading…
Reference in New Issue