mirror of https://github.com/fail2ban/fail2ban
- Improved date detector
git-svn-id: https://fail2ban.svn.sourceforge.net/svnroot/fail2ban/trunk@340 a942ae1a-1317-0410-a47c-b1dcaea8d6050.x
parent
5c020b99da
commit
77eef14ed8
|
@ -24,26 +24,45 @@ __date__ = "$Date: 2006-09-04 21:19:58 +0200 (Mon, 04 Sep 2006) $"
|
||||||
__copyright__ = "Copyright (c) 2004 Cyril Jaquier"
|
__copyright__ = "Copyright (c) 2004 Cyril Jaquier"
|
||||||
__license__ = "GPL"
|
__license__ = "GPL"
|
||||||
|
|
||||||
import time
|
import time, logging
|
||||||
|
|
||||||
from datetemplate import DateTemplate
|
from datetemplate import DateTemplate
|
||||||
|
from datestrptime import DateStrptime
|
||||||
|
from datetai64n import DateTai64n
|
||||||
|
from dateepoch import DateEpoch
|
||||||
|
from threading import Lock
|
||||||
|
|
||||||
|
# Gets the instance of the logger.
|
||||||
|
logSys = logging.getLogger("fail2ban.filter.datedetector")
|
||||||
|
|
||||||
class DateDetector:
|
class DateDetector:
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
|
self.lock = Lock()
|
||||||
self.templates = list()
|
self.templates = list()
|
||||||
self.defTemplate = DateTemplate()
|
self.defTemplate = DateTemplate()
|
||||||
|
|
||||||
def addDefaultTemplate(self):
|
def addDefaultTemplate(self):
|
||||||
template = DateTemplate()
|
# standard
|
||||||
template.setRegex("\S{3}\s{1,2}\d{1,2} \d{2}:\d{2}:\d{2}")
|
template = DateStrptime()
|
||||||
|
template.setName("Month Day Hour:Minute:Second")
|
||||||
|
template.setRegex("^\S{3}\s{1,2}\d{1,2} \d{2}:\d{2}:\d{2}")
|
||||||
template.setPattern("%b %d %H:%M:%S")
|
template.setPattern("%b %d %H:%M:%S")
|
||||||
self.templates.append(template)
|
self.templates.append(template)
|
||||||
|
# asctime
|
||||||
template = DateTemplate()
|
template = DateStrptime()
|
||||||
template.setRegex("\S{3} \S{3} \d{2} \d{2}:\d{2}:\d{2} \d{4}")
|
template.setName("Weekday Month Day Hour:Minute:Second Year")
|
||||||
|
template.setRegex("^\S{3} \S{3} \d{2} \d{2}:\d{2}:\d{2} \d{4}")
|
||||||
template.setPattern("%a %b %d %H:%M:%S %Y")
|
template.setPattern("%a %b %d %H:%M:%S %Y")
|
||||||
self.templates.append(template)
|
self.templates.append(template)
|
||||||
|
# TAI64N
|
||||||
|
template = DateTai64n()
|
||||||
|
template.setName("TAI64N")
|
||||||
|
self.templates.append(template)
|
||||||
|
# Epoch
|
||||||
|
template = DateEpoch()
|
||||||
|
template.setName("Epoch")
|
||||||
|
self.templates.append(template)
|
||||||
|
|
||||||
def setDefaultRegex(self, value):
|
def setDefaultRegex(self, value):
|
||||||
self.defTemplate.setRegex(value)
|
self.defTemplate.setRegex(value)
|
||||||
|
@ -57,18 +76,17 @@ class DateDetector:
|
||||||
def getDefaultPattern(self):
|
def getDefaultPattern(self):
|
||||||
return self.defTemplate.getPattern()
|
return self.defTemplate.getPattern()
|
||||||
|
|
||||||
#def addTemplate(self, template):
|
|
||||||
# self.templates.append(template)
|
|
||||||
|
|
||||||
def matchTime(self, line):
|
def matchTime(self, line):
|
||||||
if self.defTemplate.isValid():
|
if self.defTemplate.isValid():
|
||||||
return self.defTemplate.matchDate(line)
|
return self.defTemplate.matchDate(line)
|
||||||
else:
|
else:
|
||||||
# TODO Should be called from outside. Add locking
|
self.lock.acquire()
|
||||||
for template in self.templates:
|
for template in self.templates:
|
||||||
match = template.matchDate(line)
|
match = template.matchDate(line)
|
||||||
if match <> None:
|
if match <> None:
|
||||||
|
self.lock.release()
|
||||||
return match
|
return match
|
||||||
|
self.lock.release()
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def getTime(self, line):
|
def getTime(self, line):
|
||||||
|
@ -79,15 +97,18 @@ class DateDetector:
|
||||||
except ValueError:
|
except ValueError:
|
||||||
return None
|
return None
|
||||||
else:
|
else:
|
||||||
# TODO Should be called from outside. Add locking
|
self.lock.acquire()
|
||||||
self.sortTemplate()
|
|
||||||
for template in self.templates:
|
for template in self.templates:
|
||||||
try:
|
try:
|
||||||
date = template.getDate(line)
|
date = template.getDate(line)
|
||||||
|
if date == None:
|
||||||
|
continue
|
||||||
template.incHits()
|
template.incHits()
|
||||||
|
self.lock.release()
|
||||||
return date
|
return date
|
||||||
except ValueError:
|
except ValueError:
|
||||||
pass
|
pass
|
||||||
|
self.lock.release()
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def getUnixTime(self, line):
|
def getUnixTime(self, line):
|
||||||
|
@ -97,7 +118,13 @@ class DateDetector:
|
||||||
else:
|
else:
|
||||||
return time.mktime(date)
|
return time.mktime(date)
|
||||||
|
|
||||||
|
##
|
||||||
|
# Sort the template lists using the hits score. This method is not called
|
||||||
|
# in this object and thus should be called from time to time.
|
||||||
|
|
||||||
def sortTemplate(self):
|
def sortTemplate(self):
|
||||||
|
self.lock.acquire()
|
||||||
|
logSys.debug("Sorting the template list")
|
||||||
self.templates.sort(cmp = lambda x, y: cmp(x.getHits(), y.getHits()),
|
self.templates.sort(cmp = lambda x, y: cmp(x.getHits(), y.getHits()),
|
||||||
reverse=True)
|
reverse=True)
|
||||||
|
self.lock.release()
|
||||||
|
|
|
@ -0,0 +1,44 @@
|
||||||
|
# This file is part of Fail2Ban.
|
||||||
|
#
|
||||||
|
# Fail2Ban is free software; you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation; either version 2 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# Fail2Ban is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with Fail2Ban; if not, write to the Free Software
|
||||||
|
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
|
# Author: Cyril Jaquier
|
||||||
|
#
|
||||||
|
# $Revision: 321 $
|
||||||
|
|
||||||
|
__author__ = "Cyril Jaquier"
|
||||||
|
__version__ = "$Revision: 321 $"
|
||||||
|
__date__ = "$Date: 2006-09-04 21:19:58 +0200 (Mon, 04 Sep 2006) $"
|
||||||
|
__copyright__ = "Copyright (c) 2004 Cyril Jaquier"
|
||||||
|
__license__ = "GPL"
|
||||||
|
|
||||||
|
import re, time
|
||||||
|
|
||||||
|
from datetemplate import DateTemplate
|
||||||
|
|
||||||
|
class DateEpoch(DateTemplate):
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
DateTemplate.__init__(self)
|
||||||
|
# We already know the format for TAI64N
|
||||||
|
self.setRegex("^\d{10}(\.\d{6})?")
|
||||||
|
|
||||||
|
def getDate(self, line):
|
||||||
|
date = None
|
||||||
|
dateMatch = self.matchDate(line)
|
||||||
|
if dateMatch:
|
||||||
|
# extract part of format which represents seconds since epoch
|
||||||
|
date = list(time.gmtime(float(dateMatch.group())))
|
||||||
|
return date
|
|
@ -0,0 +1,49 @@
|
||||||
|
# This file is part of Fail2Ban.
|
||||||
|
#
|
||||||
|
# Fail2Ban is free software; you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation; either version 2 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# Fail2Ban is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with Fail2Ban; if not, write to the Free Software
|
||||||
|
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
|
# Author: Cyril Jaquier
|
||||||
|
#
|
||||||
|
# $Revision: 321 $
|
||||||
|
|
||||||
|
__author__ = "Cyril Jaquier"
|
||||||
|
__version__ = "$Revision: 321 $"
|
||||||
|
__date__ = "$Date: 2006-09-04 21:19:58 +0200 (Mon, 04 Sep 2006) $"
|
||||||
|
__copyright__ = "Copyright (c) 2004 Cyril Jaquier"
|
||||||
|
__license__ = "GPL"
|
||||||
|
|
||||||
|
import re, time
|
||||||
|
|
||||||
|
from datetemplate import DateTemplate
|
||||||
|
|
||||||
|
class DateStrptime(DateTemplate):
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
DateTemplate.__init__(self)
|
||||||
|
|
||||||
|
def getDate(self, line):
|
||||||
|
date = None
|
||||||
|
dateMatch = self.matchDate(line)
|
||||||
|
if dateMatch:
|
||||||
|
date = list(time.strptime(dateMatch.group(), self.pattern))
|
||||||
|
if date[0] < 2000:
|
||||||
|
# There is probably no year field in the logs
|
||||||
|
date[0] = time.gmtime()[0]
|
||||||
|
# Bug fix for #1241756
|
||||||
|
# If the date is greater than the current time, we suppose
|
||||||
|
# that the log is not from this year but from the year before
|
||||||
|
if time.mktime(date) > time.time():
|
||||||
|
date[0] -= 1
|
||||||
|
return date
|
|
@ -0,0 +1,46 @@
|
||||||
|
# This file is part of Fail2Ban.
|
||||||
|
#
|
||||||
|
# Fail2Ban is free software; you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation; either version 2 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# Fail2Ban is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with Fail2Ban; if not, write to the Free Software
|
||||||
|
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
|
# Author: Cyril Jaquier
|
||||||
|
#
|
||||||
|
# $Revision: 321 $
|
||||||
|
|
||||||
|
__author__ = "Cyril Jaquier"
|
||||||
|
__version__ = "$Revision: 321 $"
|
||||||
|
__date__ = "$Date: 2006-09-04 21:19:58 +0200 (Mon, 04 Sep 2006) $"
|
||||||
|
__copyright__ = "Copyright (c) 2004 Cyril Jaquier"
|
||||||
|
__license__ = "GPL"
|
||||||
|
|
||||||
|
import re, time
|
||||||
|
|
||||||
|
from datetemplate import DateTemplate
|
||||||
|
|
||||||
|
class DateTai64n(DateTemplate):
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
DateTemplate.__init__(self)
|
||||||
|
# We already know the format for TAI64N
|
||||||
|
self.setRegex("@[0-9a-f]{24}")
|
||||||
|
|
||||||
|
def getDate(self, line):
|
||||||
|
date = None
|
||||||
|
dateMatch = self.matchDate(line)
|
||||||
|
if dateMatch:
|
||||||
|
# extract part of format which represents seconds since epoch
|
||||||
|
value = dateMatch.group()
|
||||||
|
seconds_since_epoch = value[2:17]
|
||||||
|
date = list(time.gmtime(int(seconds_since_epoch, 16)))
|
||||||
|
return date
|
|
@ -29,12 +29,21 @@ import re, time
|
||||||
class DateTemplate:
|
class DateTemplate:
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
|
self.name = ""
|
||||||
self.regex = ""
|
self.regex = ""
|
||||||
|
self.cRegex = None
|
||||||
self.pattern = ""
|
self.pattern = ""
|
||||||
self.hits = 0
|
self.hits = 0
|
||||||
|
|
||||||
|
def setName(self, name):
|
||||||
|
self.name = name
|
||||||
|
|
||||||
|
def getName(self):
|
||||||
|
return self.name
|
||||||
|
|
||||||
def setRegex(self, regex):
|
def setRegex(self, regex):
|
||||||
self.regex = regex
|
self.regex = regex
|
||||||
|
self.cRegex = re.compile(regex)
|
||||||
|
|
||||||
def getRegex(self):
|
def getRegex(self):
|
||||||
return self.regex
|
return self.regex
|
||||||
|
@ -55,20 +64,8 @@ class DateTemplate:
|
||||||
return self.hits
|
return self.hits
|
||||||
|
|
||||||
def matchDate(self, line):
|
def matchDate(self, line):
|
||||||
dateMatch = re.search(self.regex, line)
|
dateMatch = self.cRegex.search(line)
|
||||||
return dateMatch
|
return dateMatch
|
||||||
|
|
||||||
def getDate(self, line):
|
def getDate(self, line):
|
||||||
date = None
|
raise Exception("matchDate() is abstract")
|
||||||
dateMatch = self.matchDate(line)
|
|
||||||
if dateMatch:
|
|
||||||
date = list(time.strptime(dateMatch.group(), self.pattern))
|
|
||||||
if date[0] < 2000:
|
|
||||||
# There is probably no year field in the logs
|
|
||||||
date[0] = time.gmtime()[0]
|
|
||||||
# Bug fix for #1241756
|
|
||||||
# If the date is greater than the current time, we suppose
|
|
||||||
# that the log is not from this year but from the year before
|
|
||||||
if time.mktime(date) > time.time():
|
|
||||||
date[0] -= 1
|
|
||||||
return date
|
|
||||||
|
|
|
@ -217,6 +217,7 @@ class Filter(JailThread):
|
||||||
if not self.isIdle:
|
if not self.isIdle:
|
||||||
if self.isModified():
|
if self.isModified():
|
||||||
self.getFailures()
|
self.getFailures()
|
||||||
|
self.dateDetector.sortTemplate()
|
||||||
try:
|
try:
|
||||||
ticket = self.failManager.toBan()
|
ticket = self.failManager.toBan()
|
||||||
self.jail.putFailTicket(ticket)
|
self.jail.putFailTicket(ticket)
|
||||||
|
|
Loading…
Reference in New Issue