|
|
@ -72,6 +72,7 @@ class Fail2banRegex:
|
|
|
|
self.__filter = Filter(None)
|
|
|
|
self.__filter = Filter(None)
|
|
|
|
self.__ignoreregex = list()
|
|
|
|
self.__ignoreregex = list()
|
|
|
|
self.__failregex = list()
|
|
|
|
self.__failregex = list()
|
|
|
|
|
|
|
|
self.__verbose = False
|
|
|
|
# Setup logging
|
|
|
|
# Setup logging
|
|
|
|
logging.getLogger("fail2ban").handlers = []
|
|
|
|
logging.getLogger("fail2ban").handlers = []
|
|
|
|
self.__hdlr = logging.StreamHandler(Fail2banRegex.test)
|
|
|
|
self.__hdlr = logging.StreamHandler(Fail2banRegex.test)
|
|
|
@ -79,6 +80,7 @@ class Fail2banRegex:
|
|
|
|
formatter = logging.Formatter("%(message)s")
|
|
|
|
formatter = logging.Formatter("%(message)s")
|
|
|
|
# tell the handler to use this format
|
|
|
|
# tell the handler to use this format
|
|
|
|
self.__hdlr.setFormatter(formatter)
|
|
|
|
self.__hdlr.setFormatter(formatter)
|
|
|
|
|
|
|
|
self.__logging_level = self.__verbose and logging.DEBUG or logging.WARN
|
|
|
|
logging.getLogger("fail2ban").addHandler(self.__hdlr)
|
|
|
|
logging.getLogger("fail2ban").addHandler(self.__hdlr)
|
|
|
|
logging.getLogger("fail2ban").setLevel(logging.ERROR)
|
|
|
|
logging.getLogger("fail2ban").setLevel(logging.ERROR)
|
|
|
|
|
|
|
|
|
|
|
@ -106,6 +108,7 @@ class Fail2banRegex:
|
|
|
|
print "Options:"
|
|
|
|
print "Options:"
|
|
|
|
print " -h, --help display this help message"
|
|
|
|
print " -h, --help display this help message"
|
|
|
|
print " -V, --version print the version"
|
|
|
|
print " -V, --version print the version"
|
|
|
|
|
|
|
|
print " -v, --verbose verbose output"
|
|
|
|
print
|
|
|
|
print
|
|
|
|
print "Log:"
|
|
|
|
print "Log:"
|
|
|
|
print " string a string representing a log line"
|
|
|
|
print " string a string representing a log line"
|
|
|
@ -132,6 +135,8 @@ class Fail2banRegex:
|
|
|
|
elif opt[0] in ["-V", "--version"]:
|
|
|
|
elif opt[0] in ["-V", "--version"]:
|
|
|
|
self.dispVersion()
|
|
|
|
self.dispVersion()
|
|
|
|
sys.exit(0)
|
|
|
|
sys.exit(0)
|
|
|
|
|
|
|
|
elif opt[0] in ["-v", "--verbose"]:
|
|
|
|
|
|
|
|
self.__verbose = True
|
|
|
|
|
|
|
|
|
|
|
|
#@staticmethod
|
|
|
|
#@staticmethod
|
|
|
|
def logIsFile(value):
|
|
|
|
def logIsFile(value):
|
|
|
@ -199,7 +204,7 @@ class Fail2banRegex:
|
|
|
|
def testIgnoreRegex(self, line):
|
|
|
|
def testIgnoreRegex(self, line):
|
|
|
|
found = False
|
|
|
|
found = False
|
|
|
|
for regex in self.__ignoreregex:
|
|
|
|
for regex in self.__ignoreregex:
|
|
|
|
logging.getLogger("fail2ban").setLevel(logging.DEBUG)
|
|
|
|
logging.getLogger("fail2ban").setLevel(self.__logging_level)
|
|
|
|
try:
|
|
|
|
try:
|
|
|
|
self.__filter.addIgnoreRegex(regex.getFailRegex())
|
|
|
|
self.__filter.addIgnoreRegex(regex.getFailRegex())
|
|
|
|
try:
|
|
|
|
try:
|
|
|
@ -211,7 +216,7 @@ class Fail2banRegex:
|
|
|
|
return False
|
|
|
|
return False
|
|
|
|
finally:
|
|
|
|
finally:
|
|
|
|
self.__filter.delIgnoreRegex(0)
|
|
|
|
self.__filter.delIgnoreRegex(0)
|
|
|
|
logging.getLogger("fail2ban").setLevel(logging.CRITICAL)
|
|
|
|
logging.getLogger("fail2ban").setLevel(self.__logging_level)
|
|
|
|
|
|
|
|
|
|
|
|
def testRegex(self, line):
|
|
|
|
def testRegex(self, line):
|
|
|
|
found = False
|
|
|
|
found = False
|
|
|
@ -251,19 +256,17 @@ class Fail2banRegex:
|
|
|
|
|
|
|
|
|
|
|
|
def print_failregexes(title, failregexes):
|
|
|
|
def print_failregexes(title, failregexes):
|
|
|
|
# Print title
|
|
|
|
# Print title
|
|
|
|
print title
|
|
|
|
total, out = 0, []
|
|
|
|
print "|- Regular expressions:"
|
|
|
|
|
|
|
|
for cnt, failregex in enumerate(failregexes):
|
|
|
|
|
|
|
|
print "| [%d] %s" % (cnt+1, failregex.getFailRegex())
|
|
|
|
|
|
|
|
print "|"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Print stats
|
|
|
|
|
|
|
|
total = 0
|
|
|
|
|
|
|
|
print "`- Number of matches:"
|
|
|
|
|
|
|
|
for cnt, failregex in enumerate(failregexes):
|
|
|
|
for cnt, failregex in enumerate(failregexes):
|
|
|
|
match = failregex.getStats()
|
|
|
|
match = failregex.getStats()
|
|
|
|
total += match
|
|
|
|
total += match
|
|
|
|
print " [%d] %s match(es)" % (cnt+1, match)
|
|
|
|
if (match or self.__verbose):
|
|
|
|
|
|
|
|
out.append("| %d) [%d] %s" % (cnt+1, match, failregex.getFailRegex()))
|
|
|
|
|
|
|
|
print "%s: %d total" % (title, total)
|
|
|
|
|
|
|
|
if len(out):
|
|
|
|
|
|
|
|
print "|- #) [# of hits] regular expression"
|
|
|
|
|
|
|
|
print '\n'.join(out)
|
|
|
|
|
|
|
|
print '`-'
|
|
|
|
print
|
|
|
|
print
|
|
|
|
return total
|
|
|
|
return total
|
|
|
|
|
|
|
|
|
|
|
@ -285,17 +288,19 @@ class Fail2banRegex:
|
|
|
|
# Print stats
|
|
|
|
# Print stats
|
|
|
|
print "Addresses found:"
|
|
|
|
print "Addresses found:"
|
|
|
|
for cnt, failregex in enumerate(self.__failregex):
|
|
|
|
for cnt, failregex in enumerate(self.__failregex):
|
|
|
|
print "[%d]" % (cnt+1)
|
|
|
|
if self.__verbose or len(failregex.getIPList()):
|
|
|
|
for ip in failregex.getIPList():
|
|
|
|
print "[%d]" % (cnt+1)
|
|
|
|
timeTuple = time.localtime(ip[1])
|
|
|
|
for ip in failregex.getIPList():
|
|
|
|
timeString = time.strftime("%a %b %d %H:%M:%S %Y", timeTuple)
|
|
|
|
timeTuple = time.localtime(ip[1])
|
|
|
|
print " %s (%s)%s" % (
|
|
|
|
timeString = time.strftime("%a %b %d %H:%M:%S %Y", timeTuple)
|
|
|
|
ip[0], timeString, ip[2] and " (already matched)" or "")
|
|
|
|
print " %s (%s)%s" % (
|
|
|
|
|
|
|
|
ip[0], timeString, ip[2] and " (already matched)" or "")
|
|
|
|
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(s): " + template.getName()
|
|
|
|
if self.__verbose or template.getHits():
|
|
|
|
|
|
|
|
print `template.getHits()` + " hit(s): " + template.getName()
|
|
|
|
print
|
|
|
|
print
|
|
|
|
|
|
|
|
|
|
|
|
print "Success, the total number of match is " + str(total)
|
|
|
|
print "Success, the total number of match is " + str(total)
|
|
|
@ -309,16 +314,17 @@ if __name__ == "__main__":
|
|
|
|
fail2banRegex = Fail2banRegex()
|
|
|
|
fail2banRegex = Fail2banRegex()
|
|
|
|
# Reads the command line options.
|
|
|
|
# Reads the command line options.
|
|
|
|
try:
|
|
|
|
try:
|
|
|
|
cmdOpts = 'hV'
|
|
|
|
cmdOpts = 'hVc'
|
|
|
|
cmdLongOpts = ['help', 'version']
|
|
|
|
cmdLongOpts = ['help', 'version', 'verbose']
|
|
|
|
optList, args = getopt.getopt(sys.argv[1:], cmdOpts, cmdLongOpts)
|
|
|
|
optList, args = getopt.getopt(sys.argv[1:], cmdOpts, cmdLongOpts)
|
|
|
|
except getopt.GetoptError:
|
|
|
|
except getopt.GetoptError:
|
|
|
|
fail2banRegex.dispUsage()
|
|
|
|
fail2banRegex.dispUsage()
|
|
|
|
sys.exit(-1)
|
|
|
|
sys.exit(-1)
|
|
|
|
# Process command line
|
|
|
|
# Process command line
|
|
|
|
fail2banRegex.getCmdLineOptions(optList)
|
|
|
|
fail2banRegex.getCmdLineOptions(optList)
|
|
|
|
# We need exactly 3 parameters
|
|
|
|
|
|
|
|
if not len(sys.argv) in (3, 4):
|
|
|
|
# We need 2 or 3 parameters
|
|
|
|
|
|
|
|
if not len(args) in (2, 3):
|
|
|
|
fail2banRegex.dispUsage()
|
|
|
|
fail2banRegex.dispUsage()
|
|
|
|
sys.exit(-1)
|
|
|
|
sys.exit(-1)
|
|
|
|
else:
|
|
|
|
else:
|
|
|
@ -327,17 +333,17 @@ if __name__ == "__main__":
|
|
|
|
print "============="
|
|
|
|
print "============="
|
|
|
|
print
|
|
|
|
print
|
|
|
|
|
|
|
|
|
|
|
|
if len(sys.argv) == 4:
|
|
|
|
cmd_log, cmd_regex = args[:2]
|
|
|
|
if fail2banRegex.readIgnoreRegex(sys.argv[3]) == False:
|
|
|
|
|
|
|
|
sys.exit(-1)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if fail2banRegex.readRegex(sys.argv[2]) == False:
|
|
|
|
if len(args) == 3:
|
|
|
|
sys.exit(-1)
|
|
|
|
fail2banRegex.readIgnoreRegex(args[2]) or sys.exit(-1)
|
|
|
|
|
|
|
|
|
|
|
|
if fail2banRegex.logIsFile(sys.argv[1]):
|
|
|
|
fail2banRegex.readRegex(cmd_regex) or sys.exit(-1)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if fail2banRegex.logIsFile(cmd_log):
|
|
|
|
try:
|
|
|
|
try:
|
|
|
|
hdlr = open(sys.argv[1])
|
|
|
|
hdlr = open(cmd_log)
|
|
|
|
print "Use log file : " + sys.argv[1]
|
|
|
|
print "Use log file : " + cmd_log
|
|
|
|
print
|
|
|
|
print
|
|
|
|
for line in hdlr:
|
|
|
|
for line in hdlr:
|
|
|
|
fail2banRegex.testIgnoreRegex(line)
|
|
|
|
fail2banRegex.testIgnoreRegex(line)
|
|
|
@ -348,15 +354,12 @@ if __name__ == "__main__":
|
|
|
|
sys.exit(-1)
|
|
|
|
sys.exit(-1)
|
|
|
|
else:
|
|
|
|
else:
|
|
|
|
if len(sys.argv[1]) > 53:
|
|
|
|
if len(sys.argv[1]) > 53:
|
|
|
|
stripLog = sys.argv[1][0:50] + "..."
|
|
|
|
stripLog = cmd_log[0:50] + "..."
|
|
|
|
else:
|
|
|
|
else:
|
|
|
|
stripLog = sys.argv[1]
|
|
|
|
stripLog = cmd_log
|
|
|
|
print "Use single line: " + stripLog
|
|
|
|
print "Use single line: " + stripLog
|
|
|
|
print
|
|
|
|
print
|
|
|
|
fail2banRegex.testIgnoreRegex(sys.argv[1])
|
|
|
|
fail2banRegex.testIgnoreRegex(cmd_log)
|
|
|
|
fail2banRegex.testRegex(sys.argv[1])
|
|
|
|
fail2banRegex.testRegex(cmd_log)
|
|
|
|
|
|
|
|
|
|
|
|
if fail2banRegex.printStats():
|
|
|
|
fail2banRegex.printStats() or sys.exit(-1)
|
|
|
|
sys.exit(0)
|
|
|
|
|
|
|
|
else:
|
|
|
|
|
|
|
|
sys.exit(-1)
|
|
|
|
|
|
|
|