- Added file support to fail2ban-regex. Benchmark feature has been removed

git-svn-id: https://fail2ban.svn.sourceforge.net/svnroot/fail2ban/trunk@523 a942ae1a-1317-0410-a47c-b1dcaea8d605
0.x
Cyril Jaquier 2007-01-21 22:21:13 +00:00
parent a257fdc87d
commit 7bcfd2ace9
5 changed files with 225 additions and 78 deletions

View File

@ -1,4 +1,4 @@
#!/usr/bin/env python #!/usr/bin/python -O
# This file is part of Fail2Ban. # This file is part of Fail2Ban.
# #
# Fail2Ban is free software; you can redistribute it and/or modify # Fail2Ban is free software; you can redistribute it and/or modify
@ -25,12 +25,14 @@ __date__ = "$Date$"
__copyright__ = "Copyright (c) 2004 Cyril Jaquier" __copyright__ = "Copyright (c) 2004 Cyril Jaquier"
__license__ = "GPL" __license__ = "GPL"
import locale, getopt, sys, time, logging, gc import getopt, sys, time, logging, os
# Inserts our own modules path first in the list # Inserts our own modules path first in the list
# fix for bug #343821 # fix for bug #343821
sys.path.insert(1, "/usr/share/fail2ban") sys.path.insert(1, "/usr/share/fail2ban")
from ConfigParser import SafeConfigParser
from ConfigParser import NoOptionError, NoSectionError, MissingSectionHeaderError
from common.version import version from common.version import version
from server.filter import Filter from server.filter import Filter
from server.regex import RegexException from server.regex import RegexException
@ -38,13 +40,38 @@ from server.regex import RegexException
# Gets the instance of the logger. # Gets the instance of the logger.
logSys = logging.getLogger("fail2ban.regex") logSys = logging.getLogger("fail2ban.regex")
class RegexStat:
def __init__(self, failregex):
self.__stats = 0
self.__failregex = failregex
self.__ipList = list()
def inc(self):
self.__stats += 1
def getStats(self):
return self.__stats
def getFailRegex(self):
return self.__failregex
def appendIP(self, value):
self.__ipList.extend(value)
def getIPList(self):
return self.__ipList
class Fail2banRegex: class Fail2banRegex:
test = None
def __init__(self): def __init__(self):
self.__filter = Filter(None) self.__filter = Filter(None)
self.__failregex = list()
# Setup logging # Setup logging
logging.getLogger("fail2ban").handlers = [] logging.getLogger("fail2ban").handlers = []
self.__hdlr = logging.StreamHandler(sys.stdout) self.__hdlr = logging.StreamHandler(Fail2banRegex.test)
# set a format which is simpler for console use # set a format which is simpler for console use
formatter = logging.Formatter("%(message)s") formatter = logging.Formatter("%(message)s")
# tell the handler to use this format # tell the handler to use this format
@ -52,7 +79,8 @@ class Fail2banRegex:
logging.getLogger("fail2ban").addHandler(self.__hdlr) logging.getLogger("fail2ban").addHandler(self.__hdlr)
logging.getLogger("fail2ban").setLevel(logging.ERROR) logging.getLogger("fail2ban").setLevel(logging.ERROR)
def dispVersion(self): @staticmethod
def dispVersion():
print "Fail2Ban v" + version print "Fail2Ban v" + version
print print
print "Copyright (c) 2004-2006 Cyril Jaquier" print "Copyright (c) 2004-2006 Cyril Jaquier"
@ -62,14 +90,26 @@ class Fail2banRegex:
print "Written by Cyril Jaquier <lostcontrol@users.sourceforge.net>." print "Written by Cyril Jaquier <lostcontrol@users.sourceforge.net>."
print "Many contributions by Yaroslav O. Halchenko <debian@onerussian.com>." print "Many contributions by Yaroslav O. Halchenko <debian@onerussian.com>."
def dispUsage(self): @staticmethod
print "Usage: "+sys.argv[0]+" <logline> <failregex>" def dispUsage():
print "Usage: "+sys.argv[0]+" [OPTIONS] <LOG> <REGEX>"
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."
print print
print "This tools can test and benchmark your regular expressions for the \"failregex\"" print "This tools can test regular expressions for \"fail2ban\"."
print "option." print
print "Options:"
print " -h, --help display this help message"
print " -V, --version print the version"
print
print "Log:"
print " string a string representing a log line"
print " filename path to a log file (/var/log/auth.log)"
print
print "Regex:"
print " string a string representing a 'failregex'"
print " filename path to a filter file (filter.d/sshd.conf)"
print print
print "Report bugs to <lostcontrol@users.sourceforge.net>" print "Report bugs to <lostcontrol@users.sourceforge.net>"
@ -78,87 +118,149 @@ class Fail2banRegex:
""" """
for opt in optList: for opt in optList:
if opt[0] in ["-h", "--help"]: if opt[0] in ["-h", "--help"]:
self.dispUsage() self.dispUsage()
sys.exit(0) sys.exit(0)
elif opt[0] in ["-V", "--version"]: elif opt[0] in ["-V", "--version"]:
self.dispVersion() self.dispVersion()
sys.exit(0) sys.exit(0)
@staticmethod
def logIsFile(value):
return os.path.isfile(value)
def readRegex(self, value):
if os.path.isfile(value):
reader = SafeConfigParser()
try:
reader.read(value)
self.__failregex = [RegexStat(m)
for m in reader.get("Definition", "failregex").split('\n')]
except NoSectionError:
print "No [Definition] section in " + value
return False
except NoOptionError:
print "No failregex option in " + value
return False
except MissingSectionHeaderError:
print "No section headers in " + value
return False
else:
self.__failregex = [RegexStat(value)]
return True
def testRegex(self, line, regex): def testRegex(self, line):
print for regex in self.__failregex:
try:
logging.getLogger("fail2ban").setLevel(logging.DEBUG) logging.getLogger("fail2ban").setLevel(logging.DEBUG)
self.__filter.addFailRegex(regex) try:
ret = self.__filter.findFailure(line) self.__filter.addFailRegex(regex.getFailRegex())
print try:
logging.getLogger("fail2ban").setLevel(logging.CRITICAL) ret = self.__filter.findFailure(line)
except RegexException, e: if not len(ret) == 0:
print e regex.inc()
return False regex.appendIP(ret)
except IndexError: except RegexException, e:
print "Sorry, but no <host> found in regex" print e
return False return False
if len(ret) == 0: except IndexError:
print "Sorry, but no <host> found in regex"
return False
finally:
self.__filter.delFailRegex(0)
logging.getLogger("fail2ban").setLevel(logging.CRITICAL)
def printStats(self):
print
print "Results"
print "======="
print
# Print title
cnt = 1
print "Failregex:"
for failregex in self.__failregex:
print "[" + str(cnt) + "] " + failregex.getFailRegex()
cnt += 1
print
# Print stats
cnt = 1
total = 0
print "Number of matches:"
for failregex in self.__failregex:
match = failregex.getStats()
total += match
print "[" + str(cnt) + "] " + str(match) + " match(es)"
cnt += 1
print
if total == 0:
print "Sorry, no match" print "Sorry, no match"
print
print "Look at the above section 'Running tests' which could contain important"
print "information."
return False return False
else: else:
print "Success, the following data were found:" # Print stats
timeTuple = time.localtime(ret[0][1]) cnt = 1
print "Date: " + time.strftime("%a %b %d %H:%M:%S %Y", timeTuple) print "Addresses found:"
ipList = "" for failregex in self.__failregex:
for i in ret: print "[" + str(cnt) + "]"
ipList = ipList + " " + i[0] for ip in failregex.getIPList():
print "IP :" + ipList timeTuple = time.localtime(ip[1])
timeString = time.strftime("%a %b %d %H:%M:%S %Y", timeTuple)
print " " + ip[0] + " (" + timeString + ")"
cnt += 1
print print
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: " + template.getName()
print print
print "Benchmark. Executing 1000..."
gc.disable() print "Success, the total number of match is " + str(total)
total = 0 print
maxValue = 0 print "However, look at the above section 'Running tests' which could contain important"
maxPos = 0 print "information."
minValue = 99999999
minPos = 0
for i in range(1000):
start = time.time()
ret = self.__filter.findFailure(line)
end = time.time()
diff = (end - start) * 1000
total = total + diff
minValue = min(minValue, diff)
if minValue == diff:
minPos = i
maxValue = max(maxValue, diff)
if maxValue == diff:
maxPos = i
gc.enable()
print "Performance"
print "Avg: " + `total / 1000` + " ms"
print "Max: " + `maxValue` + " ms (Run " + `maxPos` + ")"
print "Min: " + `minValue` + " ms (Run " + `minPos` + ")"
return True return True
if __name__ == "__main__": if __name__ == "__main__":
regex = Fail2banRegex() fail2banRegex = Fail2banRegex()
# Reads the command line options. # Reads the command line options.
try: try:
cmdOpts = 'hV' cmdOpts = 'hV'
cmdLongOpts = ['help', 'version'] cmdLongOpts = ['help', 'version']
optList, args = getopt.getopt(sys.argv[1:], cmdOpts, cmdLongOpts) optList, args = getopt.getopt(sys.argv[1:], cmdOpts, cmdLongOpts)
except getopt.GetoptError: except getopt.GetoptError:
regex.dispUsage() fail2banRegex.dispUsage()
sys.exit(-1) sys.exit(-1)
# Process command line # Process command line
regex.getCmdLineOptions(optList) fail2banRegex.getCmdLineOptions(optList)
# We need exactly 3 parameters # We need exactly 3 parameters
if len(sys.argv) <> 3: if not len(sys.argv) == 3:
regex.dispUsage() fail2banRegex.dispUsage()
sys.exit(-1) sys.exit(-1)
else: else:
ret = regex.testRegex(sys.argv[1], sys.argv[2]) if fail2banRegex.readRegex(sys.argv[2]) == False:
if ret: sys.exit(-1)
print
print "Running tests"
print "============="
print
if fail2banRegex.logIsFile(sys.argv[1]):
hdlr = open(sys.argv[1])
for line in hdlr:
fail2banRegex.testRegex(line)
else:
fail2banRegex.testRegex(sys.argv[1])
if fail2banRegex.printStats():
sys.exit(0) sys.exit(0)
else: else:
sys.exit(-1) sys.exit(-1)

View File

@ -1,12 +1,11 @@
.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.36. .\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.36.
.TH FAIL2BAN-CLIENT "1" "January 2007" "fail2ban-client v0.7.6" "User Commands" .TH FAIL2BAN-CLIENT "1" "January 2007" "fail2ban-client v0.7.6-SVN" "User Commands"
.SH NAME .SH NAME
fail2ban-client \- configure and control the server fail2ban-client \- configure and control the server
.SH SYNOPSIS
.B fail2ban-client
[\fIOPTIONS\fR]... \fI<COMMAND>\fR
.SH DESCRIPTION .SH DESCRIPTION
Fail2Ban v0.7.6 reads log file that contains password failure report [?1034hUsage: ../fail2ban\-client [OPTIONS]... <COMMAND>
.PP
Fail2Ban v0.7.6\-SVN reads log file that contains password failure report
and bans the corresponding IP addresses using firewall rules. and bans the corresponding IP addresses using firewall rules.
.SH OPTIONS .SH OPTIONS
.TP .TP

View File

@ -1,16 +1,36 @@
.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.36. .\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.36.
.TH FAIL2BAN-REGEX "1" "January 2007" "fail2ban-regex v0.7.6" "User Commands" .TH FAIL2BAN-REGEX "1" "January 2007" "fail2ban-regex v0.7.6-SVN" "User Commands"
.SH NAME .SH NAME
fail2ban-regex \- test Fail2ban "failregex" option fail2ban-regex \- test Fail2ban "failregex" option
.SH SYNOPSIS .SH SYNOPSIS
.B fail2ban-regex .B fail2ban-regex
\fI<logline> <failregex>\fR [\fIOPTIONS\fR] \fI<LOG> <REGEX>\fR
.SH DESCRIPTION .SH DESCRIPTION
Fail2Ban v0.7.6 reads log file that contains password failure report Fail2Ban v0.7.6\-SVN reads log file that contains password failure report
and bans the corresponding IP addresses using firewall rules. and bans the corresponding IP addresses using firewall rules.
.PP .PP
This tools can test and benchmark your regular expressions for the "failregex" This tools can test regular expressions for "fail2ban".
option. .SH OPTIONS
.TP
\fB\-h\fR, \fB\-\-help\fR
display this help message
.TP
\fB\-V\fR, \fB\-\-version\fR
print the version
.SH LOG
.TP
\fBstring\fR
a string representing a log line
.TP
\fBfilename\fR
path to a log file (/var/log/auth.log)
.SH REGEX
.TP
\fBstring\fR
a string representing a 'failregex'
.TP
\fBfilename\fR
path to a filter file (filter.d/sshd.conf)
.SH AUTHOR .SH AUTHOR
Written by Cyril Jaquier <lostcontrol@users.sourceforge.net>. Written by Cyril Jaquier <lostcontrol@users.sourceforge.net>.
Many contributions by Yaroslav O. Halchenko <debian@onerussian.com>. Many contributions by Yaroslav O. Halchenko <debian@onerussian.com>.

View File

@ -1,12 +1,12 @@
.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.36. .\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.36.
.TH FAIL2BAN-SERVER "1" "January 2007" "fail2ban-server v0.7.6" "User Commands" .TH FAIL2BAN-SERVER "1" "January 2007" "fail2ban-server v0.7.6-SVN" "User Commands"
.SH NAME .SH NAME
fail2ban-server \- start the server fail2ban-server \- start the server
.SH SYNOPSIS .SH SYNOPSIS
.B fail2ban-server .B fail2ban-server
[\fIOPTIONS\fR] [\fIOPTIONS\fR]
.SH DESCRIPTION .SH DESCRIPTION
Fail2Ban v0.7.6 reads log file that contains password failure report Fail2Ban v0.7.6\-SVN reads log file that contains password failure report
and bans the corresponding IP addresses using firewall rules. and bans the corresponding IP addresses using firewall rules.
.PP .PP
Only use this command for debugging purpose. Start the server with Only use this command for debugging purpose. Start the server with

View File

@ -40,4 +40,30 @@ echo "[done]"
echo -n "Generating fail2ban-regex " echo -n "Generating fail2ban-regex "
help2man --section=1 --no-info --include=fail2ban-regex.h2m --output fail2ban-regex.1 ../fail2ban-regex help2man --section=1 --no-info --include=fail2ban-regex.h2m --output fail2ban-regex.1 ../fail2ban-regex
echo "[done]" echo "[done]"
echo -n "Patching fail2ban-regex "
# Changes the title.
sed -i -e 's/.SS "Log:"/.SH LOG/' fail2ban-regex.1
sed -i -e 's/.SS "Regex:"/.SH REGEX/' fail2ban-regex.1
# Sets bold font for commands.
IFS="
"
NEXT=0
FOUND=0
LINES=$( cat fail2ban-regex.1 )
echo -n "" > fail2ban-regex.1
for LINE in $LINES; do
if [ "$LINE" = ".SH LOG" ]; then
FOUND=1
fi
if [ $NEXT -eq 1 ] && [ $FOUND -eq 1 ]; then
echo "\fB$LINE\fR" >> fail2ban-regex.1
else
echo "$LINE" >> fail2ban-regex.1
fi
if [ "$LINE" = ".TP" ]; then
NEXT=1
else
NEXT=0
fi
done
echo "[done]"