mirror of https://github.com/fail2ban/fail2ban
- Added "ignoreregex" support to fail2ban-regex
git-svn-id: https://fail2ban.svn.sourceforge.net/svnroot/fail2ban/branches/FAIL2BAN-0_8@596 a942ae1a-1317-0410-a47c-b1dcaea8d605_tent/ipv6_via_aInfo
parent
08c2c55742
commit
ada2d7234e
|
@ -14,6 +14,7 @@ ver. 0.8.1 (2007/??/??) - stable
|
||||||
- Improved regular expressions. Thanks to Yaroslav Halchenko
|
- Improved regular expressions. Thanks to Yaroslav Halchenko
|
||||||
- Added sendmail actions. The action started with "mail" are
|
- Added sendmail actions. The action started with "mail" are
|
||||||
now deprecated. Thanks to Raphaël Marichez
|
now deprecated. Thanks to Raphaël Marichez
|
||||||
|
- Added "ignoreregex" support to fail2ban-regex
|
||||||
|
|
||||||
ver. 0.8.0 (2007/05/03) - stable
|
ver. 0.8.0 (2007/05/03) - stable
|
||||||
----------
|
----------
|
||||||
|
|
103
fail2ban-regex
103
fail2ban-regex
|
@ -68,6 +68,7 @@ class Fail2banRegex:
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.__filter = Filter(None)
|
self.__filter = Filter(None)
|
||||||
|
self.__ignoreregex = list()
|
||||||
self.__failregex = list()
|
self.__failregex = list()
|
||||||
# Setup logging
|
# Setup logging
|
||||||
logging.getLogger("fail2ban").handlers = []
|
logging.getLogger("fail2ban").handlers = []
|
||||||
|
@ -92,7 +93,7 @@ class Fail2banRegex:
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def dispUsage():
|
def dispUsage():
|
||||||
print "Usage: "+sys.argv[0]+" [OPTIONS] <LOG> <REGEX>"
|
print "Usage: "+sys.argv[0]+" [OPTIONS] <LOG> <REGEX> [IGNOREREGEX]"
|
||||||
print
|
print
|
||||||
print "Fail2Ban v" + version + " reads log file that contains password failure report"
|
print "Fail2Ban v" + version + " reads log file that contains password failure report"
|
||||||
print "and bans the corresponding IP addresses using firewall rules."
|
print "and bans the corresponding IP addresses using firewall rules."
|
||||||
|
@ -111,6 +112,10 @@ class Fail2banRegex:
|
||||||
print " string a string representing a 'failregex'"
|
print " string a string representing a 'failregex'"
|
||||||
print " filename path to a filter file (filter.d/sshd.conf)"
|
print " filename path to a filter file (filter.d/sshd.conf)"
|
||||||
print
|
print
|
||||||
|
print "IgnoreRegex:"
|
||||||
|
print " string a string representing an 'ignoreregex'"
|
||||||
|
print " filename path to a filter file (filter.d/sshd.conf)"
|
||||||
|
print
|
||||||
print "Report bugs to <lostcontrol@users.sourceforge.net>"
|
print "Report bugs to <lostcontrol@users.sourceforge.net>"
|
||||||
|
|
||||||
def getCmdLineOptions(self, optList):
|
def getCmdLineOptions(self, optList):
|
||||||
|
@ -128,6 +133,35 @@ class Fail2banRegex:
|
||||||
def logIsFile(value):
|
def logIsFile(value):
|
||||||
return os.path.isfile(value)
|
return os.path.isfile(value)
|
||||||
|
|
||||||
|
def readIgnoreRegex(self, value):
|
||||||
|
if os.path.isfile(value):
|
||||||
|
reader = SafeConfigParser()
|
||||||
|
try:
|
||||||
|
reader.read(value)
|
||||||
|
print "Use ignoreregex file : " + value
|
||||||
|
self.__ignoreregex = [RegexStat(m)
|
||||||
|
for m in reader.get("Definition", "ignoreregex").split('\n')]
|
||||||
|
except NoSectionError:
|
||||||
|
print "No [Definition] section in " + value
|
||||||
|
print
|
||||||
|
return False
|
||||||
|
except NoOptionError:
|
||||||
|
print "No failregex option in " + value
|
||||||
|
print
|
||||||
|
return False
|
||||||
|
except MissingSectionHeaderError:
|
||||||
|
print "No section headers in " + value
|
||||||
|
print
|
||||||
|
return False
|
||||||
|
else:
|
||||||
|
if len(value) > 53:
|
||||||
|
stripReg = value[0:50] + "..."
|
||||||
|
else:
|
||||||
|
stripReg = value
|
||||||
|
print "Use ignoreregex line : " + stripReg
|
||||||
|
self.__ignoreregex = [RegexStat(value)]
|
||||||
|
return True
|
||||||
|
|
||||||
def readRegex(self, value):
|
def readRegex(self, value):
|
||||||
if os.path.isfile(value):
|
if os.path.isfile(value):
|
||||||
reader = SafeConfigParser()
|
reader = SafeConfigParser()
|
||||||
|
@ -157,8 +191,27 @@ class Fail2banRegex:
|
||||||
self.__failregex = [RegexStat(value)]
|
self.__failregex = [RegexStat(value)]
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
def testIgnoreRegex(self, line):
|
||||||
|
found = False
|
||||||
|
for regex in self.__ignoreregex:
|
||||||
|
logging.getLogger("fail2ban").setLevel(logging.DEBUG)
|
||||||
|
try:
|
||||||
|
self.__filter.addIgnoreRegex(regex.getFailRegex())
|
||||||
|
try:
|
||||||
|
ret = self.__filter.ignoreLine(line)
|
||||||
|
if ret:
|
||||||
|
regex.inc()
|
||||||
|
except RegexException, e:
|
||||||
|
print e
|
||||||
|
return False
|
||||||
|
finally:
|
||||||
|
self.__filter.delIgnoreRegex(0)
|
||||||
|
logging.getLogger("fail2ban").setLevel(logging.CRITICAL)
|
||||||
|
|
||||||
def testRegex(self, line):
|
def testRegex(self, line):
|
||||||
found = False
|
found = False
|
||||||
|
for regex in self.__ignoreregex:
|
||||||
|
self.__filter.addIgnoreRegex(regex.getFailRegex())
|
||||||
for regex in self.__failregex:
|
for regex in self.__failregex:
|
||||||
logging.getLogger("fail2ban").setLevel(logging.DEBUG)
|
logging.getLogger("fail2ban").setLevel(logging.DEBUG)
|
||||||
try:
|
try:
|
||||||
|
@ -182,6 +235,8 @@ class Fail2banRegex:
|
||||||
finally:
|
finally:
|
||||||
self.__filter.delFailRegex(0)
|
self.__filter.delFailRegex(0)
|
||||||
logging.getLogger("fail2ban").setLevel(logging.CRITICAL)
|
logging.getLogger("fail2ban").setLevel(logging.CRITICAL)
|
||||||
|
for regex in self.__ignoreregex:
|
||||||
|
self.__filter.delIgnoreRegex(0)
|
||||||
|
|
||||||
def printStats(self):
|
def printStats(self):
|
||||||
print
|
print
|
||||||
|
@ -191,25 +246,51 @@ class Fail2banRegex:
|
||||||
|
|
||||||
# Print title
|
# Print title
|
||||||
cnt = 1
|
cnt = 1
|
||||||
print "Failregex:"
|
print "Failregex"
|
||||||
|
print "|- Regular expressions:"
|
||||||
for failregex in self.__failregex:
|
for failregex in self.__failregex:
|
||||||
print "[" + str(cnt) + "] " + failregex.getFailRegex()
|
print "| [" + str(cnt) + "] " + failregex.getFailRegex()
|
||||||
cnt += 1
|
cnt += 1
|
||||||
|
cnt = 1
|
||||||
|
|
||||||
print
|
print "|"
|
||||||
|
|
||||||
# Print stats
|
# Print stats
|
||||||
cnt = 1
|
cnt = 1
|
||||||
total = 0
|
total = 0
|
||||||
print "Number of matches:"
|
print "`- Number of matches:"
|
||||||
for failregex in self.__failregex:
|
for failregex in self.__failregex:
|
||||||
match = failregex.getStats()
|
match = failregex.getStats()
|
||||||
total += match
|
total += match
|
||||||
print "[" + str(cnt) + "] " + str(match) + " match(es)"
|
print " [" + str(cnt) + "] " + str(match) + " match(es)"
|
||||||
cnt += 1
|
cnt += 1
|
||||||
|
|
||||||
print
|
print
|
||||||
|
|
||||||
|
# Print title
|
||||||
|
cnt = 1
|
||||||
|
print "Ignoreregex"
|
||||||
|
print "|- Regular expressions:"
|
||||||
|
for failregex in self.__ignoreregex:
|
||||||
|
print "| [" + str(cnt) + "] " + failregex.getFailRegex()
|
||||||
|
cnt += 1
|
||||||
|
cnt = 1
|
||||||
|
|
||||||
|
print "|"
|
||||||
|
|
||||||
|
# Print stats
|
||||||
|
cnt = 1
|
||||||
|
print "`- Number of matches:"
|
||||||
|
for failregex in self.__ignoreregex:
|
||||||
|
match = failregex.getStats()
|
||||||
|
print " [" + str(cnt) + "] " + str(match) + " match(es)"
|
||||||
|
cnt += 1
|
||||||
|
|
||||||
|
print
|
||||||
|
print "Summary"
|
||||||
|
print "======="
|
||||||
|
print
|
||||||
|
|
||||||
if total == 0:
|
if total == 0:
|
||||||
print "Sorry, no match"
|
print "Sorry, no match"
|
||||||
print
|
print
|
||||||
|
@ -236,7 +317,7 @@ class Fail2banRegex:
|
||||||
|
|
||||||
print "Date template hits:"
|
print "Date template hits:"
|
||||||
for template in self.__filter.dateDetector.getTemplates():
|
for template in self.__filter.dateDetector.getTemplates():
|
||||||
print `template.getHits()` + " hit: " + template.getName()
|
print `template.getHits()` + " hit(s): " + template.getName()
|
||||||
|
|
||||||
print
|
print
|
||||||
|
|
||||||
|
@ -260,7 +341,7 @@ if __name__ == "__main__":
|
||||||
# Process command line
|
# Process command line
|
||||||
fail2banRegex.getCmdLineOptions(optList)
|
fail2banRegex.getCmdLineOptions(optList)
|
||||||
# We need exactly 3 parameters
|
# We need exactly 3 parameters
|
||||||
if not len(sys.argv) == 3:
|
if not len(sys.argv) in (3, 4):
|
||||||
fail2banRegex.dispUsage()
|
fail2banRegex.dispUsage()
|
||||||
sys.exit(-1)
|
sys.exit(-1)
|
||||||
else:
|
else:
|
||||||
|
@ -269,6 +350,10 @@ if __name__ == "__main__":
|
||||||
print "============="
|
print "============="
|
||||||
print
|
print
|
||||||
|
|
||||||
|
if len(sys.argv) == 4:
|
||||||
|
if fail2banRegex.readIgnoreRegex(sys.argv[3]) == False:
|
||||||
|
sys.exit(-1)
|
||||||
|
|
||||||
if fail2banRegex.readRegex(sys.argv[2]) == False:
|
if fail2banRegex.readRegex(sys.argv[2]) == False:
|
||||||
sys.exit(-1)
|
sys.exit(-1)
|
||||||
|
|
||||||
|
@ -278,6 +363,7 @@ if __name__ == "__main__":
|
||||||
print "Use log file : " + sys.argv[1]
|
print "Use log file : " + sys.argv[1]
|
||||||
print
|
print
|
||||||
for line in hdlr:
|
for line in hdlr:
|
||||||
|
fail2banRegex.testIgnoreRegex(line)
|
||||||
fail2banRegex.testRegex(line)
|
fail2banRegex.testRegex(line)
|
||||||
except IOError, e:
|
except IOError, e:
|
||||||
print e
|
print e
|
||||||
|
@ -290,6 +376,7 @@ if __name__ == "__main__":
|
||||||
stripLog = sys.argv[1]
|
stripLog = sys.argv[1]
|
||||||
print "Use single line: " + stripLog
|
print "Use single line: " + stripLog
|
||||||
print
|
print
|
||||||
|
fail2banRegex.testIgnoreRegex(sys.argv[1])
|
||||||
fail2banRegex.testRegex(sys.argv[1])
|
fail2banRegex.testRegex(sys.argv[1])
|
||||||
|
|
||||||
if fail2banRegex.printStats():
|
if fail2banRegex.printStats():
|
||||||
|
|
|
@ -413,6 +413,20 @@ class Filter(JailThread):
|
||||||
self.__closeLogFile()
|
self.__closeLogFile()
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
##
|
||||||
|
# Returns true if the line should be ignored.
|
||||||
|
#
|
||||||
|
# Uses ignoreregex.
|
||||||
|
# @param line: the line
|
||||||
|
# @return: a boolean
|
||||||
|
|
||||||
|
def ignoreLine(self, line):
|
||||||
|
for ignoreRegex in self.__ignoreRegex:
|
||||||
|
ignoreRegex.search(line)
|
||||||
|
if ignoreRegex.hasMatched():
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
##
|
##
|
||||||
# Finds the failure in a line.
|
# Finds the failure in a line.
|
||||||
#
|
#
|
||||||
|
@ -423,12 +437,9 @@ class Filter(JailThread):
|
||||||
def findFailure(self, line):
|
def findFailure(self, line):
|
||||||
failList = list()
|
failList = list()
|
||||||
# Checks if we must ignore this line.
|
# Checks if we must ignore this line.
|
||||||
for ignoreRegex in self.__ignoreRegex:
|
if self.ignoreLine(line):
|
||||||
ignoreRegex.search(line)
|
# The ignoreregex matched. Return.
|
||||||
if ignoreRegex.hasMatched():
|
return failList
|
||||||
# The ignoreregex matched. Return.
|
|
||||||
logSys.debug("Ignoring this line")
|
|
||||||
return failList
|
|
||||||
# Iterates over all the regular expressions.
|
# Iterates over all the regular expressions.
|
||||||
for failRegex in self.__failRegex:
|
for failRegex in self.__failRegex:
|
||||||
failRegex.search(line)
|
failRegex.search(line)
|
||||||
|
|
Loading…
Reference in New Issue