mirror of https://github.com/fail2ban/fail2ban
Merge pull request #401 from bes-internal/ignorecommand
ENH: New ignorecommand with path to external command for dynamic ignoreip listpull/522/head
commit
dfb6c45297
|
@ -54,7 +54,9 @@ class FilterReader(ConfigReader):
|
|||
|
||||
def getOptions(self, pOpts):
|
||||
opts = [["string", "ignoreregex", ""],
|
||||
["string", "failregex", ""]]
|
||||
["string", "failregex", ""],
|
||||
["string", "ignorecommand", ""]
|
||||
]
|
||||
self.__opts = ConfigReader.getOptions(self, "Definition", opts, pOpts)
|
||||
|
||||
def convert(self):
|
||||
|
|
|
@ -80,6 +80,7 @@ class JailReader(ConfigReader):
|
|||
["string", "usedns", "warn"],
|
||||
["string", "failregex", None],
|
||||
["string", "ignoreregex", None],
|
||||
["string", "ignorecommand", None],
|
||||
["string", "ignoreip", None],
|
||||
["string", "filter", ""],
|
||||
["string", "action", ""]]
|
||||
|
@ -164,6 +165,8 @@ class JailReader(ConfigReader):
|
|||
stream.append(["set", self.__name, "usedns", self.__opts[opt]])
|
||||
elif opt == "failregex":
|
||||
stream.append(["set", self.__name, "addfailregex", self.__opts[opt]])
|
||||
elif opt == "ignorecommand":
|
||||
stream.append(["set", self.__name, "ignorecommand", self.__opts[opt]])
|
||||
elif opt == "ignoreregex":
|
||||
for regex in self.__opts[opt].split('\n'):
|
||||
# Do not send a command if the rule is empty.
|
||||
|
|
|
@ -57,6 +57,7 @@ protocol = [
|
|||
["set <JAIL> dellogpath <FILE>", "removes <FILE> from the monitoring list of <JAIL>"],
|
||||
["set <JAIL> addfailregex <REGEX>", "adds the regular expression <REGEX> which must match failures for <JAIL>"],
|
||||
["set <JAIL> delfailregex <INDEX>", "removes the regular expression at <INDEX> for failregex"],
|
||||
["set <JAIL> ignorecommand <VALUE>", "sets ignorecommand of <JAIL>"],
|
||||
["set <JAIL> addignoreregex <REGEX>", "adds the regular expression <REGEX> which should match pattern to exclude for <JAIL>"],
|
||||
["set <JAIL> delignoreregex <INDEX>", "removes the regular expression at <INDEX> for ignoreregex"],
|
||||
["set <JAIL> findtime <TIME>", "sets the number of seconds <TIME> for which the filter will look back for <JAIL>"],
|
||||
|
@ -77,6 +78,7 @@ protocol = [
|
|||
['', "JAIL INFORMATION", ""],
|
||||
["get <JAIL> logpath", "gets the list of the monitored files for <JAIL>"],
|
||||
["get <JAIL> ignoreip", "gets the list of ignored IP addresses for <JAIL>"],
|
||||
["get <JAIL> ignorecommand", "gets ignorecommand of <JAIL>"],
|
||||
["get <JAIL> failregex", "gets the list of regular expressions which matches the failures for <JAIL>"],
|
||||
["get <JAIL> ignoreregex", "gets the list of regular expressions which matches patterns to ignore for <JAIL>"],
|
||||
["get <JAIL> findtime", "gets the time for which the filter will look back for failures for <JAIL>"],
|
||||
|
|
|
@ -31,6 +31,11 @@
|
|||
# defined using space separator.
|
||||
ignoreip = 127.0.0.1/8
|
||||
|
||||
# External command that will take an tagged arguments to ignore, e.g. <ip>,
|
||||
# and return true if the IP is to be ignored. False otherwise.
|
||||
#
|
||||
# ignorecommand = /path/to/command <ip>
|
||||
|
||||
# "bantime" is the number of seconds that a host is banned.
|
||||
bantime = 600
|
||||
|
||||
|
|
|
@ -128,6 +128,9 @@ for <JAIL>
|
|||
removes the regular expression at
|
||||
<INDEX> for failregex
|
||||
.TP
|
||||
\fBset <JAIL> ignorecommand <VALUE>\fR
|
||||
sets ignorecommand of <JAIL>
|
||||
.TP
|
||||
\fBset <JAIL> addignoreregex <REGEX>\fR
|
||||
adds the regular expression
|
||||
<REGEX> which should match pattern
|
||||
|
@ -206,6 +209,9 @@ files for <JAIL>
|
|||
gets the list of ignored IP
|
||||
addresses for <JAIL>
|
||||
.TP
|
||||
\fBget <JAIL> ignorecommand\fR
|
||||
gets ignorecommand of <JAIL>
|
||||
.TP
|
||||
\fBget <JAIL> failregex\fR
|
||||
gets the list of regular
|
||||
expressions which matches the
|
||||
|
|
|
@ -70,6 +70,11 @@ The following options are applicable to all jails. Their meaning is described in
|
|||
\fBaction\fR
|
||||
.TP
|
||||
\fBignoreip\fR
|
||||
A space separated list of IPs not to ban.
|
||||
.TP
|
||||
\fBignorecommand\fR
|
||||
A command that is executed to determine if the current ban's actionban is to be executed. This command will return true if the current ban should be ignored. A false return value will result in the ban's actionban executed.
|
||||
Like ACTION FILES, tags like <ip> are can be included in the ignore command value and will be substitued before execution. Currently only <ip> is supported however more will be added later.
|
||||
.TP
|
||||
\fBbantime\fR
|
||||
.TP
|
||||
|
|
|
@ -30,8 +30,9 @@ from jailthread import JailThread
|
|||
from datedetector import DateDetector
|
||||
from mytime import MyTime
|
||||
from failregex import FailRegex, Regex, RegexException
|
||||
from action import Action
|
||||
|
||||
import logging, re, os, fcntl, time
|
||||
import logging, re, os, fcntl, time, shlex, subprocess
|
||||
|
||||
# Gets the instance of the logger.
|
||||
logSys = logging.getLogger("fail2ban.filter")
|
||||
|
@ -67,6 +68,8 @@ class Filter(JailThread):
|
|||
self.__findTime = 6000
|
||||
## The ignore IP list.
|
||||
self.__ignoreIpList = []
|
||||
## External command
|
||||
self.__ignoreCommand = False
|
||||
|
||||
self.dateDetector = DateDetector()
|
||||
self.dateDetector.addDefaultTemplate()
|
||||
|
@ -212,6 +215,20 @@ class Filter(JailThread):
|
|||
def run(self): # pragma: no cover
|
||||
raise Exception("run() is abstract")
|
||||
|
||||
##
|
||||
# Set external command, for ignoredips
|
||||
#
|
||||
|
||||
def setIgnoreCommand(self, command):
|
||||
self.__ignoreCommand = command
|
||||
|
||||
##
|
||||
# Get external command, for ignoredips
|
||||
#
|
||||
|
||||
def getIgnoreCommand(self):
|
||||
return self.__ignoreCommand
|
||||
|
||||
##
|
||||
# Ban an IP - http://blogs.buanzo.com.ar/2009/04/fail2ban-patch-ban-ip-address-manually.html
|
||||
# Arturo 'Buanzo' Busleiman <buanzo@buanzo.com.ar>
|
||||
|
@ -284,6 +301,12 @@ class Filter(JailThread):
|
|||
continue
|
||||
if a == b:
|
||||
return True
|
||||
|
||||
if self.__ignoreCommand:
|
||||
command = Action.replaceTag(self.__ignoreCommand, { 'ip': ip } )
|
||||
logSys.debug('ignore command: ' + command)
|
||||
return Action.executeCmd(command)
|
||||
|
||||
return False
|
||||
|
||||
|
||||
|
|
|
@ -184,6 +184,12 @@ class Server:
|
|||
def getFindTime(self, name):
|
||||
return self.__jails.getFilter(name).getFindTime()
|
||||
|
||||
def setIgnoreCommand(self, name, value):
|
||||
self.__jails.getFilter(name).setIgnoreCommand(value)
|
||||
|
||||
def getIgnoreCommand(self, name):
|
||||
return self.__jails.getFilter(name).getIgnoreCommand()
|
||||
|
||||
def addFailRegex(self, name, value):
|
||||
self.__jails.getFilter(name).addFailRegex(value)
|
||||
|
||||
|
|
|
@ -142,6 +142,10 @@ class Transmitter:
|
|||
value = command[2]
|
||||
self.__server.delLogPath(name, value)
|
||||
return self.__server.getLogPath(name)
|
||||
elif command[1] == "ignorecommand":
|
||||
value = command[2]
|
||||
self.__server.setIgnoreCommand(name, value)
|
||||
return self.__server.getIgnoreCommand(name)
|
||||
elif command[1] == "addfailregex":
|
||||
value = command[2]
|
||||
self.__server.addFailRegex(name, value)
|
||||
|
@ -239,6 +243,8 @@ class Transmitter:
|
|||
return self.__server.getLogPath(name)
|
||||
elif command[1] == "ignoreip":
|
||||
return self.__server.getIgnoreIP(name)
|
||||
elif command[1] == "ignorecommand":
|
||||
return self.__server.getIgnoreCommand(name)
|
||||
elif command[1] == "failregex":
|
||||
return self.__server.getFailRegex(name)
|
||||
elif command[1] == "ignoreregex":
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
#!/usr/bin/python
|
||||
import sys
|
||||
if sys.argv[1] == "10.0.0.1":
|
||||
exit(0)
|
||||
exit(1)
|
|
@ -171,7 +171,6 @@ class IgnoreIP(LogCaptureTestCase):
|
|||
ipList = "127.0.0.1", "192.168.0.1", "255.255.255.255", "99.99.99.99"
|
||||
for ip in ipList:
|
||||
self.filter.addIgnoreIP(ip)
|
||||
|
||||
self.assertTrue(self.filter.inIgnoreIPList(ip))
|
||||
|
||||
def testIgnoreIPNOK(self):
|
||||
|
@ -201,6 +200,11 @@ class IgnoreIP(LogCaptureTestCase):
|
|||
self.assertFalse(self._is_logged('Ignore 192.168.1.32'))
|
||||
self.assertTrue(self._is_logged('Requested to manually ban an ignored IP 192.168.1.32. User knows best. Proceeding to ban it.'))
|
||||
|
||||
def testIgnoreCommand(self):
|
||||
self.filter.setIgnoreCommand("testcases/files/ignorecommand.py <ip>")
|
||||
self.assertTrue(self.filter.inIgnoreIPList("10.0.0.1"))
|
||||
self.assertFalse(self.filter.inIgnoreIPList("10.0.0.0"))
|
||||
|
||||
|
||||
class IgnoreIPDNS(IgnoreIP):
|
||||
|
||||
|
|
|
@ -337,6 +337,9 @@ class Transmitter(TransmitterBase):
|
|||
self.transm.proceed(["set", self.jailName, "delignoreip", value]),
|
||||
(0, [value]))
|
||||
|
||||
def testJailIgnoreCommand(self):
|
||||
self.setGetTest("ignorecommand", "bin ", jail=self.jailName)
|
||||
|
||||
def testJailRegex(self):
|
||||
self.jailAddDelRegexTest("failregex",
|
||||
[
|
||||
|
|
Loading…
Reference in New Issue