mirror of https://github.com/fail2ban/fail2ban
Merge branch 'debian' into build
* debian: (56 commits) Imported upstream version 0.8.2 debian/watch: switched to git-import-orig - Tag for 0.8.2 - Updated for 0.8.2 - Updated e-mail - Changed homepage and e-mail - Updated copyright. - readline is now optional in fail2ban-client (not needed in fail2ban-server). - Added svn:keywords - Fixed Debian bug #461426 - Fixed Debian bug #462060 - Fixed Debian bug #468477 - Fixed Debian bug #456567 - Added revision. - Added "reload <JAIL>" - Replaced "reject" with "drop" in shorwall action. Fix #1854875 - Replaced "echo" with "printf" in actions. Fix #1839673 - Catch Exception instead of AttributeError. - Absorbed some Debian patches. Thanks to Yaroslav Halchenko. - Updated. ... Conflicts: config/fail2ban.conf config/filter.d/proftpd.conf config/filter.d/sshd.conf man/fail2ban-client.1 man/fail2ban-server.1 server/datestrptime.py server/server.pydebian-releases/squeeze
commit
9ab6db30c7
|
@ -4,9 +4,46 @@
|
|||
|_| \__,_|_|_/___|_.__/\__,_|_||_|
|
||||
|
||||
=============================================================
|
||||
Fail2Ban (version 0.8.1) 2007/08/14
|
||||
Fail2Ban (version 0.8.2) 2008/03/06
|
||||
=============================================================
|
||||
|
||||
ver. 0.8.2 (2008/03/06) - stable
|
||||
----------
|
||||
- Fixed named filter. Thanks to Yaroslav Halchenko
|
||||
- Fixed wrong path for apache-auth in jail.conf. Thanks to
|
||||
Vincent Deffontaines
|
||||
- Fixed timezone bug with epoch date template. Thanks to
|
||||
Michael Hanselmann
|
||||
- Added "full line failregex" patch. Thanks to Yaroslav
|
||||
Halchenko. It will be possible to create stronger failregex
|
||||
against log injection
|
||||
- Fixed ipfw action script. Thanks to Nick Munger
|
||||
- Removed date from logging message when using SYSLOG. Thanks
|
||||
to Iain Lea
|
||||
- Fixed "ignore IPs". Only the first value was taken into
|
||||
account. Thanks to Adrien Clerc
|
||||
- Moved socket to /var/run/fail2ban.
|
||||
- Rewrote the communication server.
|
||||
- Refactoring. Reduced number of files.
|
||||
- Removed Python 2.4. Minimum required version is now Python
|
||||
2.3.
|
||||
- New log rotation detection algorithm.
|
||||
- Print monitored files in status.
|
||||
- Create a PID file in /var/run/fail2ban/. Thanks to Julien
|
||||
Perez.
|
||||
- Fixed "Feb 29" bug. Thanks to James Andrewartha who pointed
|
||||
this out. Thanks to Yaroslav Halchenko for the fix.
|
||||
- "reload <jail>" reloads a single jail and the parameters in
|
||||
fail2ban.conf.
|
||||
- Added Mac OS/X startup script. Thanks to Bill Heaton.
|
||||
- Absorbed some Debian patches. Thanks to Yaroslav Halchenko.
|
||||
- Replaced "echo" with "printf" in actions. Fix #1839673
|
||||
- Replaced "reject" with "drop" in shorwall action. Fix
|
||||
#1854875
|
||||
- Fixed Debian bug #456567, #468477, #462060, #461426
|
||||
- readline is now optional in fail2ban-client (not needed in
|
||||
fail2ban-server).
|
||||
|
||||
ver. 0.8.1 (2007/08/14) - stable
|
||||
----------
|
||||
- Fixed vulnerability in sshd.conf. Thanks to Daniel B. Cid
|
6
PKG-INFO
6
PKG-INFO
|
@ -1,10 +1,10 @@
|
|||
Metadata-Version: 1.0
|
||||
Name: fail2ban
|
||||
Version: 0.8.1
|
||||
Version: 0.8.2
|
||||
Summary: Ban IPs that make too many password failure
|
||||
Home-page: http://fail2ban.sourceforge.net
|
||||
Home-page: http://www.fail2ban.org
|
||||
Author: Cyril Jaquier
|
||||
Author-email: lostcontrol@users.sourceforge.net
|
||||
Author-email: cyril.jaquier@fail2ban.org
|
||||
License: GPL
|
||||
Description:
|
||||
Fail2Ban scans log files like /var/log/pwdfail or
|
||||
|
|
13
README
13
README
|
@ -4,7 +4,7 @@
|
|||
|_| \__,_|_|_/___|_.__/\__,_|_||_|
|
||||
|
||||
=============================================================
|
||||
Fail2Ban (version 0.8.1) 2007/08/14
|
||||
Fail2Ban (version 0.8.2) 2008/03/06
|
||||
=============================================================
|
||||
|
||||
Fail2Ban scans log files like /var/log/pwdfail and bans IP
|
||||
|
@ -21,15 +21,15 @@ Installation:
|
|||
-------------
|
||||
|
||||
Required:
|
||||
>=python-2.4 (http://www.python.org)
|
||||
>=python-2.3 (http://www.python.org)
|
||||
|
||||
Optional:
|
||||
>=gamin-0.0.21 (http://www.gnome.org/~veillard/gamin)
|
||||
|
||||
To install, just do:
|
||||
|
||||
> tar xvfj fail2ban-0.8.1.tar.bz2
|
||||
> cd fail2ban-0.8.1
|
||||
> tar xvfj fail2ban-0.8.2.tar.bz2
|
||||
> cd fail2ban-0.8.2
|
||||
> python setup.py install
|
||||
|
||||
This will install Fail2Ban into /usr/share/fail2ban. The
|
||||
|
@ -62,7 +62,7 @@ appreciate this program, you can contact me at:
|
|||
|
||||
Website: http://www.fail2ban.org
|
||||
|
||||
Cyril Jaquier: <lostcontrol@users.sourceforge.net>
|
||||
Cyril Jaquier: <cyril.jaquier@fail2ban.org>
|
||||
|
||||
Thanks:
|
||||
-------
|
||||
|
@ -75,7 +75,8 @@ Nick Munger, Christoph Haas, Justin Shore, Joël Bertrand,
|
|||
René Berber, mEDI, Axel Thimm, Eric Gerbier, Christian Rauch,
|
||||
Michael C. Haller, Jonathan Underwood, Hanno 'Rince' Wagner,
|
||||
Daniel B. Cid, David Nutter, Raphaël Marichez, Guillaume
|
||||
Delvit, Vaclav Misek
|
||||
Delvit, Vaclav Misek, Adrien Clerc, Michael Hanselmann,
|
||||
Vincent Deffontaines, Bill Heaton and many others.
|
||||
|
||||
License:
|
||||
--------
|
||||
|
|
9
TODO
9
TODO
|
@ -4,7 +4,7 @@
|
|||
|_| \__,_|_|_/___|_.__/\__,_|_||_|
|
||||
|
||||
=============================================================
|
||||
ToDo $Revision: 557 $
|
||||
ToDo $Revision: 653 $
|
||||
=============================================================
|
||||
|
||||
Legend:
|
||||
|
@ -15,9 +15,6 @@ Legend:
|
|||
|
||||
- Removed relative imports
|
||||
|
||||
- Discuss where Fail2ban should be installed (/usr/share,
|
||||
/usr/lib/python/site-packages/, etc)
|
||||
|
||||
- Cleanup fail2ban-client and fail2ban-server. Move code to
|
||||
server/ and client/
|
||||
|
||||
|
@ -45,12 +42,8 @@ Legend:
|
|||
|
||||
- Add gettext support (I18N)
|
||||
|
||||
- Fix the cPickle issue with Python 2.5
|
||||
|
||||
- Multiline log reading
|
||||
|
||||
- Improve communication. (asyncore, asynchat??)
|
||||
|
||||
- Improve execution of action. Why does subprocess.call
|
||||
deadlock with multi-jails?
|
||||
|
||||
|
|
|
@ -16,11 +16,11 @@
|
|||
|
||||
# Author: Cyril Jaquier
|
||||
#
|
||||
# $Revision: 547 $
|
||||
# $Revision: 644 $
|
||||
|
||||
__author__ = "Cyril Jaquier"
|
||||
__version__ = "$Revision: 547 $"
|
||||
__date__ = "$Date: 2007-02-12 00:21:56 +0100 (Mon, 12 Feb 2007) $"
|
||||
__version__ = "$Revision: 644 $"
|
||||
__date__ = "$Date: 2008-01-15 00:12:21 +0100 (Tue, 15 Jan 2008) $"
|
||||
__copyright__ = "Copyright (c) 2004 Cyril Jaquier"
|
||||
__license__ = "GPL"
|
||||
|
||||
|
@ -72,9 +72,14 @@ class Beautifier:
|
|||
ipList = ""
|
||||
for ip in response[1][1][2][1]:
|
||||
ipList += ip + " "
|
||||
# Creates file list.
|
||||
fileList = ""
|
||||
for f in response[0][1][2][1]:
|
||||
fileList += f + " "
|
||||
# Display information
|
||||
msg = "Status for the jail: " + inC[1] + "\n"
|
||||
msg = msg + "|- " + response[0][0] + "\n"
|
||||
msg = msg + "| |- " + response[0][1][2][0] + ":\t" + fileList + "\n"
|
||||
msg = msg + "| |- " + response[0][1][0][0] + ":\t" + `response[0][1][0][1]` + "\n"
|
||||
msg = msg + "| `- " + response[0][1][1][0] + ":\t" + `response[0][1][1][1]` + "\n"
|
||||
msg = msg + "`- " + response[1][0] + "\n"
|
||||
|
|
|
@ -0,0 +1,108 @@
|
|||
# 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: Yaroslav Halchenko
|
||||
# Modified: Cyril Jaquier
|
||||
# $Revision: 656 $
|
||||
|
||||
__author__ = 'Yaroslav Halhenko'
|
||||
__revision__ = '$Revision: $'
|
||||
__date__ = '$Date: $'
|
||||
__copyright__ = 'Copyright (c) 2007 Yaroslav Halchenko'
|
||||
__license__ = 'GPL'
|
||||
|
||||
import logging, os
|
||||
from ConfigParser import SafeConfigParser
|
||||
|
||||
# Gets the instance of the logger.
|
||||
logSys = logging.getLogger("fail2ban.client.config")
|
||||
|
||||
class SafeConfigParserWithIncludes(SafeConfigParser):
|
||||
"""
|
||||
Class adds functionality to SafeConfigParser to handle included
|
||||
other configuration files (or may be urls, whatever in the future)
|
||||
|
||||
File should have section [includes] and only 2 options implemented
|
||||
are 'files_before' and 'files_after' where files are listed 1 per
|
||||
line.
|
||||
|
||||
Example:
|
||||
|
||||
[INCLUDES]
|
||||
before = 1.conf
|
||||
3.conf
|
||||
|
||||
after = 1.conf
|
||||
|
||||
It is a simple implementation, so just basic care is taken about
|
||||
recursion. Includes preserve right order, ie new files are
|
||||
inserted to the list of read configs before original, and their
|
||||
includes correspondingly so the list should follow the leaves of
|
||||
the tree.
|
||||
|
||||
I wasn't sure what would be the right way to implement generic (aka c++
|
||||
template) so we could base at any *configparser class... so I will
|
||||
leave it for the future
|
||||
|
||||
"""
|
||||
|
||||
SECTION_NAME = "INCLUDES"
|
||||
|
||||
#@staticmethod
|
||||
def getIncludes(resource, seen = []):
|
||||
"""
|
||||
Given 1 config resource returns list of included files
|
||||
(recursively) with the original one as well
|
||||
Simple loops are taken care about
|
||||
"""
|
||||
|
||||
# Use a short class name ;)
|
||||
SCPWI = SafeConfigParserWithIncludes
|
||||
|
||||
parser = SafeConfigParser()
|
||||
parser.read(resource)
|
||||
|
||||
resourceDir = os.path.dirname(resource)
|
||||
|
||||
newFiles = [ ('before', []), ('after', []) ]
|
||||
if SCPWI.SECTION_NAME in parser.sections():
|
||||
for option_name, option_list in newFiles:
|
||||
if option_name in parser.options(SCPWI.SECTION_NAME):
|
||||
newResources = parser.get(SCPWI.SECTION_NAME, option_name)
|
||||
for newResource in newResources.split('\n'):
|
||||
if os.path.isabs(newResource):
|
||||
r = newResource
|
||||
else:
|
||||
r = "%s/%s" % (resourceDir, newResource)
|
||||
if r in seen:
|
||||
continue
|
||||
s = seen + [resource]
|
||||
option_list += SCPWI.getIncludes(r, s)
|
||||
# combine lists
|
||||
return newFiles[0][1] + [resource] + newFiles[1][1]
|
||||
#print "Includes list for " + resource + " is " + `resources`
|
||||
getIncludes = staticmethod(getIncludes)
|
||||
|
||||
|
||||
def read(self, filenames):
|
||||
fileNamesFull = []
|
||||
if not isinstance(filenames, list):
|
||||
filenames = [ filenames ]
|
||||
for filename in filenames:
|
||||
fileNamesFull += SafeConfigParserWithIncludes.getIncludes(filename)
|
||||
logSys.debug("Reading files: %s" % fileNamesFull)
|
||||
return SafeConfigParser.read(self, fileNamesFull)
|
||||
|
|
@ -15,38 +15,40 @@
|
|||
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
# Author: Cyril Jaquier
|
||||
#
|
||||
# $Revision: 458 $
|
||||
# Modified by: Yaroslav Halchenko (SafeConfigParserWithIncludes)
|
||||
# $Revision: 656 $
|
||||
|
||||
__author__ = "Cyril Jaquier"
|
||||
__version__ = "$Revision: 458 $"
|
||||
__date__ = "$Date: 2006-11-12 15:52:36 +0100 (Sun, 12 Nov 2006) $"
|
||||
__version__ = "$Revision: 656 $"
|
||||
__date__ = "$Date: 2008-03-04 01:17:56 +0100 (Tue, 04 Mar 2008) $"
|
||||
__copyright__ = "Copyright (c) 2004 Cyril Jaquier"
|
||||
__license__ = "GPL"
|
||||
|
||||
import logging, os
|
||||
from ConfigParser import SafeConfigParser
|
||||
from configparserinc import SafeConfigParserWithIncludes
|
||||
from ConfigParser import NoOptionError, NoSectionError
|
||||
|
||||
# Gets the instance of the logger.
|
||||
logSys = logging.getLogger("fail2ban.client.config")
|
||||
|
||||
class ConfigReader(SafeConfigParser):
|
||||
class ConfigReader(SafeConfigParserWithIncludes):
|
||||
|
||||
BASE_DIRECTORY = "/etc/fail2ban/"
|
||||
|
||||
def __init__(self):
|
||||
SafeConfigParser.__init__(self)
|
||||
SafeConfigParserWithIncludes.__init__(self)
|
||||
self.__opts = None
|
||||
|
||||
@staticmethod
|
||||
#@staticmethod
|
||||
def setBaseDir(folderName):
|
||||
path = folderName.rstrip('/')
|
||||
ConfigReader.BASE_DIRECTORY = path + '/'
|
||||
setBaseDir = staticmethod(setBaseDir)
|
||||
|
||||
@staticmethod
|
||||
#@staticmethod
|
||||
def getBaseDir():
|
||||
return ConfigReader.BASE_DIRECTORY
|
||||
getBaseDir = staticmethod(getBaseDir)
|
||||
|
||||
def read(self, filename):
|
||||
basename = ConfigReader.BASE_DIRECTORY + filename
|
||||
|
@ -54,7 +56,7 @@ class ConfigReader(SafeConfigParser):
|
|||
bConf = basename + ".conf"
|
||||
bLocal = basename + ".local"
|
||||
if os.path.exists(bConf) or os.path.exists(bLocal):
|
||||
SafeConfigParser.read(self, [bConf, bLocal])
|
||||
SafeConfigParserWithIncludes.read(self, [bConf, bLocal])
|
||||
return True
|
||||
else:
|
||||
logSys.error(bConf + " and " + bLocal + " do not exist")
|
||||
|
|
|
@ -16,11 +16,11 @@
|
|||
|
||||
# Author: Cyril Jaquier
|
||||
#
|
||||
# $Revision: 518 $
|
||||
# $Revision: 655 $
|
||||
|
||||
__author__ = "Cyril Jaquier"
|
||||
__version__ = "$Revision: 518 $"
|
||||
__date__ = "$Date: 2007-01-08 22:15:47 +0100 (Mon, 08 Jan 2007) $"
|
||||
__version__ = "$Revision: 655 $"
|
||||
__date__ = "$Date: 2008-03-04 01:13:39 +0100 (Tue, 04 Mar 2008) $"
|
||||
__copyright__ = "Copyright (c) 2004 Cyril Jaquier"
|
||||
__license__ = "GPL"
|
||||
|
||||
|
@ -40,13 +40,15 @@ class Configurator:
|
|||
self.__fail2ban = Fail2banReader()
|
||||
self.__jails = JailsReader()
|
||||
|
||||
@staticmethod
|
||||
#@staticmethod
|
||||
def setBaseDir(folderName):
|
||||
ConfigReader.setBaseDir(folderName)
|
||||
setBaseDir = staticmethod(setBaseDir)
|
||||
|
||||
@staticmethod
|
||||
#@staticmethod
|
||||
def getBaseDir():
|
||||
return ConfigReader.getBaseDir()
|
||||
getBaseDir = staticmethod(getBaseDir)
|
||||
|
||||
def readEarly(self):
|
||||
self.__fail2ban.read()
|
||||
|
@ -54,13 +56,13 @@ class Configurator:
|
|||
def readAll(self):
|
||||
self.readEarly()
|
||||
self.__jails.read()
|
||||
|
||||
|
||||
def getEarlyOptions(self):
|
||||
return self.__fail2ban.getEarlyOptions()
|
||||
|
||||
def getAllOptions(self):
|
||||
|
||||
def getOptions(self, jail = None):
|
||||
self.__fail2ban.getOptions()
|
||||
return self.__jails.getOptions()
|
||||
return self.__jails.getOptions(jail)
|
||||
|
||||
def convertToProtocol(self):
|
||||
self.__streams["general"] = self.__fail2ban.convert()
|
||||
|
|
|
@ -16,11 +16,11 @@
|
|||
|
||||
# Author: Cyril Jaquier
|
||||
#
|
||||
# $Revision: 459 $
|
||||
# $Revision: 635 $
|
||||
|
||||
__author__ = "Cyril Jaquier"
|
||||
__version__ = "$Revision: 459 $"
|
||||
__date__ = "$Date: 2006-11-12 22:55:57 +0100 (Sun, 12 Nov 2006) $"
|
||||
__version__ = "$Revision: 635 $"
|
||||
__date__ = "$Date: 2007-12-16 22:38:04 +0100 (Sun, 16 Dec 2007) $"
|
||||
__copyright__ = "Copyright (c) 2004 Cyril Jaquier"
|
||||
__license__ = "GPL"
|
||||
|
||||
|
@ -32,7 +32,7 @@ class CSocket:
|
|||
|
||||
END_STRING = "<F2B_END_COMMAND>"
|
||||
|
||||
def __init__(self, sock = "/tmp/fail2ban.sock"):
|
||||
def __init__(self, sock = "/var/run/fail2ban/fail2ban.sock"):
|
||||
# Create an INET, STREAMing socket
|
||||
#self.csock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||
self.__csock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
|
||||
|
@ -47,7 +47,7 @@ class CSocket:
|
|||
self.__csock.close()
|
||||
return ret
|
||||
|
||||
@staticmethod
|
||||
#@staticmethod
|
||||
def receive(sock):
|
||||
msg = ''
|
||||
while msg.rfind(CSocket.END_STRING) == -1:
|
||||
|
@ -56,3 +56,4 @@ class CSocket:
|
|||
raise RuntimeError, "socket connection broken"
|
||||
msg = msg + chunk
|
||||
return loads(msg)
|
||||
receive = staticmethod(receive)
|
||||
|
|
|
@ -16,11 +16,11 @@
|
|||
|
||||
# Author: Cyril Jaquier
|
||||
#
|
||||
# $Revision: 509 $
|
||||
# $Revision: 659 $
|
||||
|
||||
__author__ = "Cyril Jaquier"
|
||||
__version__ = "$Revision: 509 $"
|
||||
__date__ = "$Date: 2007-01-04 12:58:58 +0100 (Thu, 04 Jan 2007) $"
|
||||
__version__ = "$Revision: 659 $"
|
||||
__date__ = "$Date: 2008-03-05 00:09:30 +0100 (Wed, 05 Mar 2008) $"
|
||||
__copyright__ = "Copyright (c) 2004 Cyril Jaquier"
|
||||
__license__ = "GPL"
|
||||
|
||||
|
@ -90,7 +90,7 @@ class JailReader(ConfigReader):
|
|||
self.__actions.append(action)
|
||||
else:
|
||||
raise AttributeError("Unable to read action")
|
||||
except AttributeError, e:
|
||||
except Exception, e:
|
||||
logSys.error("Error in action definition " + act)
|
||||
logSys.debug(e)
|
||||
return False
|
||||
|
@ -129,7 +129,7 @@ class JailReader(ConfigReader):
|
|||
stream.insert(0, ["add", self.__name, backend])
|
||||
return stream
|
||||
|
||||
@staticmethod
|
||||
#@staticmethod
|
||||
def splitAction(action):
|
||||
m = JailReader.actionCRE.match(action)
|
||||
d = dict()
|
||||
|
@ -165,3 +165,4 @@ class JailReader(ConfigReader):
|
|||
except IndexError:
|
||||
logSys.error("Invalid argument %s in '%s'" % (p, m.group(2)))
|
||||
return [m.group(1), d]
|
||||
splitAction = staticmethod(splitAction)
|
||||
|
|
|
@ -16,11 +16,11 @@
|
|||
|
||||
# Author: Cyril Jaquier
|
||||
#
|
||||
# $Revision: 518 $
|
||||
# $Revision: 655 $
|
||||
|
||||
__author__ = "Cyril Jaquier"
|
||||
__version__ = "$Revision: 518 $"
|
||||
__date__ = "$Date: 2007-01-08 22:15:47 +0100 (Mon, 08 Jan 2007) $"
|
||||
__version__ = "$Revision: 655 $"
|
||||
__date__ = "$Date: 2008-03-04 01:13:39 +0100 (Tue, 04 Mar 2008) $"
|
||||
__copyright__ = "Copyright (c) 2004 Cyril Jaquier"
|
||||
__license__ = "GPL"
|
||||
|
||||
|
@ -40,12 +40,13 @@ class JailsReader(ConfigReader):
|
|||
def read(self):
|
||||
ConfigReader.read(self, "jail")
|
||||
|
||||
def getOptions(self):
|
||||
def getOptions(self, section = None):
|
||||
opts = []
|
||||
self.__opts = ConfigReader.getOptions(self, "Definition", opts)
|
||||
|
||||
for sec in self.sections():
|
||||
jail = JailReader(sec)
|
||||
if section:
|
||||
# Get the options of a specific jail.
|
||||
jail = JailReader(section)
|
||||
jail.read()
|
||||
ret = jail.getOptions()
|
||||
if ret:
|
||||
|
@ -53,8 +54,21 @@ class JailsReader(ConfigReader):
|
|||
# We only add enabled jails
|
||||
self.__jails.append(jail)
|
||||
else:
|
||||
logSys.error("Errors in jail '" + sec + "'. Skipping...")
|
||||
logSys.error("Errors in jail '%s'. Skipping..." % section)
|
||||
return False
|
||||
else:
|
||||
# Get the options of all jails.
|
||||
for sec in self.sections():
|
||||
jail = JailReader(sec)
|
||||
jail.read()
|
||||
ret = jail.getOptions()
|
||||
if ret:
|
||||
if jail.isEnabled():
|
||||
# We only add enabled jails
|
||||
self.__jails.append(jail)
|
||||
else:
|
||||
logSys.error("Errors in jail '" + sec + "'. Skipping...")
|
||||
return False
|
||||
return True
|
||||
|
||||
def convert(self):
|
||||
|
|
|
@ -16,11 +16,11 @@
|
|||
|
||||
# Author: Cyril Jaquier
|
||||
#
|
||||
# $Revision: 529 $
|
||||
# $Revision: 662 $
|
||||
|
||||
__author__ = "Cyril Jaquier"
|
||||
__version__ = "$Revision: 529 $"
|
||||
__date__ = "$Date: 2007-01-29 21:27:51 +0100 (Mon, 29 Jan 2007) $"
|
||||
__version__ = "$Revision: 662 $"
|
||||
__date__ = "$Date: 2008-03-05 00:41:58 +0100 (Wed, 05 Mar 2008) $"
|
||||
__copyright__ = "Copyright (c) 2004 Cyril Jaquier"
|
||||
__license__ = "GPL"
|
||||
|
||||
|
@ -33,6 +33,7 @@ protocol = [
|
|||
['', "BASIC", ""],
|
||||
["start", "starts the server and the jails"],
|
||||
["reload", "reloads the configuration"],
|
||||
["reload <JAIL>", "reloads the jail <JAIL>"],
|
||||
["stop", "stops all jails and terminate the server"],
|
||||
["status", "gets the current status of the server"],
|
||||
["ping", "tests if the server is alive"],
|
||||
|
@ -51,9 +52,7 @@ protocol = [
|
|||
["set <JAIL> addignoreip <IP>", "adds <IP> to the ignore list of <JAIL>"],
|
||||
["set <JAIL> delignoreip <IP>", "removes <IP> from the ignore list of <JAIL>"],
|
||||
["set <JAIL> addlogpath <FILE>", "adds <FILE> to the monitoring list of <JAIL>"],
|
||||
["set <JAIL> dellogpath <FILE>", "removes <FILE> to the monitoring list of <JAIL>"],
|
||||
["set <JAIL> timeregex <REGEX>", "sets the regular expression <REGEX> to match the date format for <JAIL>. This will disable the autodetection feature."],
|
||||
["set <JAIL> timepattern <PATTERN>", "sets the pattern <PATTERN> to match the date format for <JAIL>. This will disable the autodetection feature."],
|
||||
["set <JAIL> dellogpath <FILE>", "removes <FILE> to 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> addignoreregex <REGEX>", "adds the regular expression <REGEX> which should match pattern to exclude for <JAIL>"],
|
||||
|
|
|
@ -16,12 +16,12 @@
|
|||
|
||||
# Author: Cyril Jaquier
|
||||
#
|
||||
# $Revision: 614 $
|
||||
# $Revision: 673 $
|
||||
|
||||
__author__ = "Cyril Jaquier"
|
||||
__version__ = "$Revision: 614 $"
|
||||
__date__ = "$Date: 2007-08-14 23:39:15 +0200 (Tue, 14 Aug 2007) $"
|
||||
__version__ = "$Revision: 673 $"
|
||||
__date__ = "$Date: 2008-03-06 00:19:45 +0100 (Thu, 06 Mar 2008) $"
|
||||
__copyright__ = "Copyright (c) 2004 Cyril Jaquier"
|
||||
__license__ = "GPL"
|
||||
|
||||
version = "0.8.1"
|
||||
version = "0.8.2"
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
#
|
||||
# Author: Cyril Jaquier
|
||||
#
|
||||
# $Revision: 554 $
|
||||
# $Revision: 660 $
|
||||
#
|
||||
|
||||
[Definition]
|
||||
|
@ -13,7 +13,7 @@
|
|||
#
|
||||
actionstart =
|
||||
|
||||
# Option: actionend
|
||||
# Option: actionstop
|
||||
# Notes.: command executed once at the end of Fail2Ban
|
||||
# Values: CMD
|
||||
#
|
||||
|
@ -34,7 +34,7 @@ actioncheck =
|
|||
# Values: CMD
|
||||
#
|
||||
actionban = IP=<ip> &&
|
||||
echo "ALL: $IP" >> <file>
|
||||
printf %%b "ALL: $IP\n" >> <file>
|
||||
|
||||
# Option: actionunban
|
||||
# Notes.: command executed when unbanning an IP. Take care that the
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
# Author: Nick Munger
|
||||
# Modified by: Cyril Jaquier
|
||||
#
|
||||
# $Revision: 510 $
|
||||
# $Revision: 658 $
|
||||
#
|
||||
|
||||
[Definition]
|
||||
|
@ -15,7 +15,7 @@
|
|||
actionstart =
|
||||
|
||||
|
||||
# Option: actionend
|
||||
# Option: actionstop
|
||||
# Notes.: command executed once at the end of Fail2Ban
|
||||
# Values: CMD
|
||||
#
|
||||
|
@ -37,7 +37,7 @@ actioncheck =
|
|||
# <time> unix timestamp of the ban time
|
||||
# Values: CMD
|
||||
#
|
||||
actionban = ipaction add deny tcp from <ip> to <localhost> <port>
|
||||
actionban = ipfw add deny tcp from <ip> to <localhost> <port>
|
||||
|
||||
|
||||
# Option: actionunban
|
||||
|
@ -48,7 +48,7 @@ actionban = ipaction add deny tcp from <ip> to <localhost> <port>
|
|||
# <time> unix timestamp of the ban time
|
||||
# Values: CMD
|
||||
#
|
||||
actionunban = ipaction delete `ipfw list | grep -i <ip> | awk '{print $1;}'`
|
||||
actionunban = ipfw delete `ipfw list | grep -i <ip> | awk '{print $1;}'`
|
||||
|
||||
[Init]
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
# Modified: Yaroslav O. Halchenko <debian@onerussian.com>
|
||||
# made active on all ports from original iptables.conf
|
||||
#
|
||||
# $Revision: 606 $
|
||||
# $Revision: 658 $
|
||||
#
|
||||
|
||||
[Definition]
|
||||
|
@ -17,7 +17,7 @@ actionstart = iptables -N fail2ban-<name>
|
|||
iptables -A fail2ban-<name> -j RETURN
|
||||
iptables -I INPUT -p <protocol> -j fail2ban-<name>
|
||||
|
||||
# Option: actionend
|
||||
# Option: actionstop
|
||||
# Notes.: command executed once at the end of Fail2Ban
|
||||
# Values: CMD
|
||||
#
|
||||
|
|
|
@ -0,0 +1,78 @@
|
|||
# Fail2Ban configuration file
|
||||
#
|
||||
# Author: Guido Bozzetto
|
||||
# Modified: Cyril Jaquier
|
||||
#
|
||||
# make "fail2ban-<name>" chain to match drop IP
|
||||
# make "fail2ban-<name>-log" chain to log and drop
|
||||
# insert a jump to fail2ban-<name> from -I INPUT if proto/port match
|
||||
#
|
||||
# $Revision: 668 $
|
||||
#
|
||||
|
||||
[Definition]
|
||||
|
||||
# Option: actionstart
|
||||
# Notes.: command executed once at the start of Fail2Ban.
|
||||
# Values: CMD
|
||||
#
|
||||
actionstart = iptables -N fail2ban-<name>
|
||||
iptables -A fail2ban-<name> -j RETURN
|
||||
iptables -I INPUT 1 -p <protocol> -m multiport --dports <port> -j fail2ban-<name>
|
||||
iptables -N fail2ban-<name>-log
|
||||
iptables -I fail2ban-<name>-log -j LOG --log-prefix "$(expr fail2ban-<name> : '\(.\{1,23\}\)'):DROP " --log-level warning -m limit --limit 6/m --limit-burst 2
|
||||
iptables -A fail2ban-<name>-log -j DROP
|
||||
|
||||
# Option: actionstop
|
||||
# Notes.: command executed once at the end of Fail2Ban
|
||||
# Values: CMD
|
||||
#
|
||||
actionstop = iptables -D INPUT -p <protocol> -m multiport --dports <port> -j fail2ban-<name>
|
||||
iptables -F fail2ban-<name>
|
||||
iptables -F fail2ban-<name>-log
|
||||
iptables -X fail2ban-<name>
|
||||
iptables -X fail2ban-<name>-log
|
||||
|
||||
# Option: actioncheck
|
||||
# Notes.: command executed once before each actionban command
|
||||
# Values: CMD
|
||||
#
|
||||
actioncheck = iptables -n -L fail2ban-<name>-log >/dev/null
|
||||
|
||||
# Option: actionban
|
||||
# Notes.: command executed when banning an IP. Take care that the
|
||||
# command is executed with Fail2Ban user rights.
|
||||
# Tags: <ip> IP address
|
||||
# <failures> number of failures
|
||||
# <time> unix timestamp of the ban time
|
||||
# Values: CMD
|
||||
#
|
||||
actionban = iptables -I fail2ban-<name> 1 -s <ip> -j fail2ban-<name>-log
|
||||
|
||||
# Option: actionunban
|
||||
# Notes.: command executed when unbanning an IP. Take care that the
|
||||
# command is executed with Fail2Ban user rights.
|
||||
# Tags: <ip> IP address
|
||||
# <failures> number of failures
|
||||
# <time> unix timestamp of the ban time
|
||||
# Values: CMD
|
||||
#
|
||||
actionunban = iptables -D fail2ban-<name> -s <ip> -j fail2ban-<name>-log
|
||||
|
||||
[Init]
|
||||
|
||||
# Defaut name of the chain
|
||||
#
|
||||
name = default
|
||||
|
||||
# Option: port
|
||||
# Notes.: specifies port to monitor
|
||||
# Values: [ NUM | STRING ] Default:
|
||||
#
|
||||
port = ssh
|
||||
|
||||
# Option: protocol
|
||||
# Notes.: internally used by config reader for interpolations.
|
||||
# Values: [ tcp | udp | icmp | all ] Default: tcp
|
||||
#
|
||||
protocol = tcp
|
|
@ -2,7 +2,7 @@
|
|||
#
|
||||
# Author: Cyril Jaquier
|
||||
# Modified by Yaroslav Halchenko for multiport banning
|
||||
# $Revision: 520 $
|
||||
# $Revision: 658 $
|
||||
#
|
||||
|
||||
[Definition]
|
||||
|
@ -15,7 +15,7 @@ actionstart = iptables -N fail2ban-<name>
|
|||
iptables -A fail2ban-<name> -j RETURN
|
||||
iptables -I INPUT -p <protocol> -m multiport --dports <port> -j fail2ban-<name>
|
||||
|
||||
# Option: actionend
|
||||
# Option: actionstop
|
||||
# Notes.: command executed once at the end of Fail2Ban
|
||||
# Values: CMD
|
||||
#
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
# Copied from iptables.conf and modified by Yaroslav Halchenko
|
||||
# to fullfill the needs of bugreporter dbts#350746.
|
||||
#
|
||||
# $Revision: 520 $
|
||||
# $Revision: 658 $
|
||||
#
|
||||
|
||||
[Definition]
|
||||
|
@ -17,7 +17,7 @@ actionstart = iptables -N fail2ban-<name>
|
|||
iptables -A fail2ban-<name> -j RETURN
|
||||
iptables -I INPUT -m state --state NEW -p <protocol> --dport <port> -j fail2ban-<name>
|
||||
|
||||
# Option: actionend
|
||||
# Option: actionstop
|
||||
# Notes.: command executed once at the end of Fail2Ban
|
||||
# Values: CMD
|
||||
#
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
#
|
||||
# Author: Cyril Jaquier
|
||||
#
|
||||
# $Revision: 494 $
|
||||
# $Revision: 658 $
|
||||
#
|
||||
|
||||
[Definition]
|
||||
|
@ -15,7 +15,7 @@ actionstart = iptables -N fail2ban-<name>
|
|||
iptables -A fail2ban-<name> -j RETURN
|
||||
iptables -I INPUT -p <protocol> --dport <port> -j fail2ban-<name>
|
||||
|
||||
# Option: actionend
|
||||
# Option: actionstop
|
||||
# Notes.: command executed once at the end of Fail2Ban
|
||||
# Values: CMD
|
||||
#
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
#
|
||||
# Author: Cyril Jaquier
|
||||
#
|
||||
# $Revision: 510 $
|
||||
# $Revision: 668 $
|
||||
#
|
||||
|
||||
[Definition]
|
||||
|
@ -11,25 +11,25 @@
|
|||
# Notes.: command executed once at the start of Fail2Ban.
|
||||
# Values: CMD
|
||||
#
|
||||
actionstart = echo -en "Hi,\n
|
||||
actionstart = printf %%b "Hi,\n
|
||||
The jail <name> has been started successfully.\n
|
||||
Output will be buffered until <lines> lines are available.\n
|
||||
Regards,\n
|
||||
Fail2Ban"|mail -s "[Fail2Ban] <name>: started" <dest>
|
||||
|
||||
# Option: actionend
|
||||
# Option: actionstop
|
||||
# Notes.: command executed once at the end of Fail2Ban
|
||||
# Values: CMD
|
||||
#
|
||||
actionstop = if [ -f <tmpfile> ]; then
|
||||
echo -en "Hi,\n
|
||||
printf %%b "Hi,\n
|
||||
These hosts have been banned by Fail2Ban.\n
|
||||
`cat <tmpfile>`
|
||||
Regards,\n
|
||||
Fail2Ban"|mail -s "[Fail2Ban] <name>: Summary" <dest>
|
||||
rm <tmpfile>
|
||||
fi
|
||||
echo -en "Hi,\n
|
||||
printf %%b "Hi,\n
|
||||
The jail <name> has been stopped.\n
|
||||
Regards,\n
|
||||
Fail2Ban"|mail -s "[Fail2Ban] <name>: stopped" <dest>
|
||||
|
@ -48,10 +48,10 @@ actioncheck =
|
|||
# <time> unix timestamp of the ban time
|
||||
# Values: CMD
|
||||
#
|
||||
actionban = echo `date`": <ip> (<failures> failures)" >> <tmpfile>
|
||||
actionban = printf %%b "`date`: <ip> (<failures> failures)\n" >> <tmpfile>
|
||||
LINE=$( wc -l <tmpfile> | awk '{ print $1 }' )
|
||||
if [ $LINE -eq <lines> ]; then
|
||||
echo -en "Hi,\n
|
||||
printf %%b "Hi,\n
|
||||
These hosts have been banned by Fail2Ban.\n
|
||||
`cat <tmpfile>`
|
||||
\nRegards,\n
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
#
|
||||
# Author: Cyril Jaquier
|
||||
# Modified-By: Yaroslav Halchenko to include grepping on IP over log files
|
||||
# $Revision: 595 $
|
||||
# $Revision: 660 $
|
||||
#
|
||||
|
||||
[Definition]
|
||||
|
@ -11,7 +11,7 @@
|
|||
# Notes.: command executed once at the start of Fail2Ban.
|
||||
# Values: CMD
|
||||
#
|
||||
actionstart = echo -en "Hi,\n
|
||||
actionstart = printf %%b "Hi,\n
|
||||
The jail <name> has been started successfully.\n
|
||||
Regards,\n
|
||||
Fail2Ban"|mail -s "[Fail2Ban] <name>: started" <dest>
|
||||
|
@ -20,7 +20,7 @@ actionstart = echo -en "Hi,\n
|
|||
# Notes.: command executed once at the end of Fail2Ban
|
||||
# Values: CMD
|
||||
#
|
||||
actionstop = echo -en "Hi,\n
|
||||
actionstop = printf %%b "Hi,\n
|
||||
The jail <name> has been stopped.\n
|
||||
Regards,\n
|
||||
Fail2Ban"|mail -s "[Fail2Ban] <name>: stopped" <dest>
|
||||
|
@ -40,7 +40,7 @@ actioncheck =
|
|||
# <bantime> unix timestamp of the ban time
|
||||
# Values: CMD
|
||||
#
|
||||
actionban = echo -en "Hi,\n
|
||||
actionban = printf %%b "Hi,\n
|
||||
The IP <ip> has just been banned by Fail2Ban after
|
||||
<failures> attempts against <name>.\n\n
|
||||
Here are more information about <ip>:\n
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
#
|
||||
# Author: Cyril Jaquier
|
||||
#
|
||||
# $Revision: 595 $
|
||||
# $Revision: 660 $
|
||||
#
|
||||
|
||||
[Definition]
|
||||
|
@ -11,16 +11,16 @@
|
|||
# Notes.: command executed once at the start of Fail2Ban.
|
||||
# Values: CMD
|
||||
#
|
||||
actionstart = echo -en "Hi,\n
|
||||
actionstart = printf %%b "Hi,\n
|
||||
The jail <name> has been started successfully.\n
|
||||
Regards,\n
|
||||
Fail2Ban"|mail -s "[Fail2Ban] <name>: started" <dest>
|
||||
|
||||
# Option: actionend
|
||||
# Option: actionstop
|
||||
# Notes.: command executed once at the end of Fail2Ban
|
||||
# Values: CMD
|
||||
#
|
||||
actionstop = echo -en "Hi,\n
|
||||
actionstop = printf %%b "Hi,\n
|
||||
The jail <name> has been stopped.\n
|
||||
Regards,\n
|
||||
Fail2Ban"|mail -s "[Fail2Ban] <name>: stopped" <dest>
|
||||
|
@ -39,7 +39,7 @@ actioncheck =
|
|||
# <time> unix timestamp of the ban time
|
||||
# Values: CMD
|
||||
#
|
||||
actionban = echo -en "Hi,\n
|
||||
actionban = printf %%b "Hi,\n
|
||||
The IP <ip> has just been banned by Fail2Ban after
|
||||
<failures> attempts against <name>.\n\n
|
||||
Here are more information about <ip>:\n
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
#
|
||||
# Author: Cyril Jaquier
|
||||
#
|
||||
# $Revision: 595 $
|
||||
# $Revision: 660 $
|
||||
#
|
||||
|
||||
[Definition]
|
||||
|
@ -11,16 +11,16 @@
|
|||
# Notes.: command executed once at the start of Fail2Ban.
|
||||
# Values: CMD
|
||||
#
|
||||
actionstart = echo -en "Hi,\n
|
||||
actionstart = printf %%b "Hi,\n
|
||||
The jail <name> has been started successfully.\n
|
||||
Regards,\n
|
||||
Fail2Ban"|mail -s "[Fail2Ban] <name>: started" <dest>
|
||||
|
||||
# Option: actionend
|
||||
# Option: actionstop
|
||||
# Notes.: command executed once at the end of Fail2Ban
|
||||
# Values: CMD
|
||||
#
|
||||
actionstop = echo -en "Hi,\n
|
||||
actionstop = printf %%b "Hi,\n
|
||||
The jail <name> has been stopped.\n
|
||||
Regards,\n
|
||||
Fail2Ban"|mail -s "[Fail2Ban] <name>: stopped" <dest>
|
||||
|
@ -39,7 +39,7 @@ actioncheck =
|
|||
# <time> unix timestamp of the ban time
|
||||
# Values: CMD
|
||||
#
|
||||
actionban = echo -en "Hi,\n
|
||||
actionban = printf %%b "Hi,\n
|
||||
The IP <ip> has just been banned by Fail2Ban after
|
||||
<failures> attempts against <name>.\n
|
||||
Regards,\n
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
#
|
||||
# Author: Cyril Jaquier
|
||||
#
|
||||
# $Revision: 604 $
|
||||
# $Revision: 660 $
|
||||
#
|
||||
|
||||
[Definition]
|
||||
|
@ -11,7 +11,7 @@
|
|||
# Notes.: command executed once at the start of Fail2Ban.
|
||||
# Values: CMD
|
||||
#
|
||||
actionstart = echo -en "Subject: [Fail2Ban] <name>: started
|
||||
actionstart = printf %%b "Subject: [Fail2Ban] <name>: started
|
||||
From: Fail2Ban <<sender>>
|
||||
To: <dest>\n
|
||||
Hi,\n
|
||||
|
@ -20,12 +20,12 @@ actionstart = echo -en "Subject: [Fail2Ban] <name>: started
|
|||
Regards,\n
|
||||
Fail2Ban" | /usr/sbin/sendmail -f <sender> <dest>
|
||||
|
||||
# Option: actionend
|
||||
# Option: actionstop
|
||||
# Notes.: command executed once at the end of Fail2Ban
|
||||
# Values: CMD
|
||||
#
|
||||
actionstop = if [ -f <tmpfile> ]; then
|
||||
echo -en "Subject: [Fail2Ban] <name>: summary
|
||||
printf %%b "Subject: [Fail2Ban] <name>: summary
|
||||
From: Fail2Ban <<sender>>
|
||||
To: <dest>\n
|
||||
Hi,\n
|
||||
|
@ -35,7 +35,7 @@ actionstop = if [ -f <tmpfile> ]; then
|
|||
Fail2Ban" | /usr/sbin/sendmail -f <sender> <dest>
|
||||
rm <tmpfile>
|
||||
fi
|
||||
echo -en "Subject: [Fail2Ban] <name>: stopped
|
||||
printf %%b "Subject: [Fail2Ban] <name>: stopped
|
||||
From: Fail2Ban <<sender>>
|
||||
To: <dest>\n
|
||||
Hi,\n
|
||||
|
@ -57,10 +57,10 @@ actioncheck =
|
|||
# <time> unix timestamp of the ban time
|
||||
# Values: CMD
|
||||
#
|
||||
actionban = echo `date`": <ip> (<failures> failures)" >> <tmpfile>
|
||||
actionban = printf %%b "`date`: <ip> (<failures> failures)\n" >> <tmpfile>
|
||||
LINE=$( wc -l <tmpfile> | awk '{ print $1 }' )
|
||||
if [ $LINE -eq <lines> ]; then
|
||||
echo -en "Subject: [Fail2Ban] <name>: summary
|
||||
printf %%b "Subject: [Fail2Ban] <name>: summary
|
||||
From: Fail2Ban <<sender>>
|
||||
To: <dest>\n
|
||||
Hi,\n
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
#
|
||||
# Author: Cyril Jaquier
|
||||
#
|
||||
# $Revision: 595 $
|
||||
# $Revision: 660 $
|
||||
#
|
||||
|
||||
[Definition]
|
||||
|
@ -11,7 +11,7 @@
|
|||
# Notes.: command executed once at the start of Fail2Ban.
|
||||
# Values: CMD
|
||||
#
|
||||
actionstart = echo -en "Subject: [Fail2Ban] <name>: started
|
||||
actionstart = printf %%b "Subject: [Fail2Ban] <name>: started
|
||||
From: Fail2Ban <<sender>>
|
||||
To: <dest>\n
|
||||
Hi,\n
|
||||
|
@ -19,11 +19,11 @@ actionstart = echo -en "Subject: [Fail2Ban] <name>: started
|
|||
Regards,\n
|
||||
Fail2Ban" | /usr/sbin/sendmail -f <sender> <dest>
|
||||
|
||||
# Option: actionend
|
||||
# Option: actionstop
|
||||
# Notes.: command executed once at the end of Fail2Ban
|
||||
# Values: CMD
|
||||
#
|
||||
actionstop = echo -en "Subject: [Fail2Ban] <name>: stopped
|
||||
actionstop = printf %%b "Subject: [Fail2Ban] <name>: stopped
|
||||
From: Fail2Ban <<sender>>
|
||||
To: <dest>\n
|
||||
Hi,\n
|
||||
|
@ -45,7 +45,7 @@ actioncheck =
|
|||
# <time> unix timestamp of the ban time
|
||||
# Values: CMD
|
||||
#
|
||||
actionban = echo -en "Subject: [Fail2Ban] <name>: banned <ip>
|
||||
actionban = printf %%b "Subject: [Fail2Ban] <name>: banned <ip>
|
||||
From: Fail2Ban <<sender>>
|
||||
To: <dest>\n
|
||||
Hi,\n
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
#
|
||||
# Author: Cyril Jaquier
|
||||
#
|
||||
# $Revision: 595 $
|
||||
# $Revision: 660 $
|
||||
#
|
||||
|
||||
[Definition]
|
||||
|
@ -11,7 +11,7 @@
|
|||
# Notes.: command executed once at the start of Fail2Ban.
|
||||
# Values: CMD
|
||||
#
|
||||
actionstart = echo -en "Subject: [Fail2Ban] <name>: started
|
||||
actionstart = printf %%b "Subject: [Fail2Ban] <name>: started
|
||||
From: Fail2Ban <<sender>>
|
||||
To: <dest>\n
|
||||
Hi,\n
|
||||
|
@ -19,11 +19,11 @@ actionstart = echo -en "Subject: [Fail2Ban] <name>: started
|
|||
Regards,\n
|
||||
Fail2Ban" | /usr/sbin/sendmail -f <sender> <dest>
|
||||
|
||||
# Option: actionend
|
||||
# Option: actionstop
|
||||
# Notes.: command executed once at the end of Fail2Ban
|
||||
# Values: CMD
|
||||
#
|
||||
actionstop = echo -en "Subject: [Fail2Ban] <name>: stopped
|
||||
actionstop = printf %%b "Subject: [Fail2Ban] <name>: stopped
|
||||
From: Fail2Ban <<sender>>
|
||||
To: <dest>\n
|
||||
Hi,\n
|
||||
|
@ -45,7 +45,7 @@ actioncheck =
|
|||
# <time> unix timestamp of the ban time
|
||||
# Values: CMD
|
||||
#
|
||||
actionban = echo -en "Subject: [Fail2Ban] <name>: banned <ip>
|
||||
actionban = printf %%b "Subject: [Fail2Ban] <name>: banned <ip>
|
||||
From: Fail2Ban <<sender>>
|
||||
To: <dest>\n
|
||||
Hi,\n
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
#
|
||||
# Author: Cyril Jaquier
|
||||
#
|
||||
# $Revision: 595 $
|
||||
# $Revision: 660 $
|
||||
#
|
||||
|
||||
[Definition]
|
||||
|
@ -11,7 +11,7 @@
|
|||
# Notes.: command executed once at the start of Fail2Ban.
|
||||
# Values: CMD
|
||||
#
|
||||
actionstart = echo -en "Subject: [Fail2Ban] <name>: started
|
||||
actionstart = printf %%b "Subject: [Fail2Ban] <name>: started
|
||||
From: Fail2Ban <<sender>>
|
||||
To: <dest>\n
|
||||
Hi,\n
|
||||
|
@ -19,11 +19,11 @@ actionstart = echo -en "Subject: [Fail2Ban] <name>: started
|
|||
Regards,\n
|
||||
Fail2Ban" | /usr/sbin/sendmail -f <sender> <dest>
|
||||
|
||||
# Option: actionend
|
||||
# Option: actionstop
|
||||
# Notes.: command executed once at the end of Fail2Ban
|
||||
# Values: CMD
|
||||
#
|
||||
actionstop = echo -en "Subject: [Fail2Ban] <name>: stopped
|
||||
actionstop = printf %%b "Subject: [Fail2Ban] <name>: stopped
|
||||
From: Fail2Ban <<sender>>
|
||||
To: <dest>\n
|
||||
Hi,\n
|
||||
|
@ -45,7 +45,7 @@ actioncheck =
|
|||
# <time> unix timestamp of the ban time
|
||||
# Values: CMD
|
||||
#
|
||||
actionban = echo -en "Subject: [Fail2Ban] <name>: banned <ip>
|
||||
actionban = printf %%b "Subject: [Fail2Ban] <name>: banned <ip>
|
||||
From: Fail2Ban <<sender>>
|
||||
To: <dest>\n
|
||||
Hi,\n
|
||||
|
|
|
@ -2,8 +2,16 @@
|
|||
#
|
||||
# Author: Cyril Jaquier
|
||||
#
|
||||
# $Revision: 510 $
|
||||
# $Revision: 661 $
|
||||
#
|
||||
# The default Shorewall configuration is with "BLACKLISTNEWONLY=Yes" (see
|
||||
# file /etc/shorewall/shorewall.conf). This means that when Fail2ban adds a
|
||||
# new shorewall rule to ban an IP address, that rule will affect only new
|
||||
# connections. So if the attempter goes on trying using the same connection
|
||||
# he could even log in. In order to get the same behavior of the iptable
|
||||
# action (so that the ban is immediate) the /etc/shorewall/shorewall.conf
|
||||
# file should me modified with "BLACKLISTNEWONLY=No".
|
||||
#
|
||||
|
||||
[Definition]
|
||||
|
||||
|
@ -13,7 +21,7 @@
|
|||
#
|
||||
actionstart =
|
||||
|
||||
# Option: actionend
|
||||
# Option: actionstop
|
||||
# Notes.: command executed once at the end of Fail2Ban
|
||||
# Values: CMD
|
||||
#
|
||||
|
@ -33,7 +41,7 @@ actioncheck =
|
|||
# <time> unix timestamp of the ban time
|
||||
# Values: CMD
|
||||
#
|
||||
actionban = shorewall reject <ip>
|
||||
actionban = shorewall drop <ip>
|
||||
|
||||
# Option: actionunban
|
||||
# Notes.: command executed when unbanning an IP. Take care that the
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
#
|
||||
# Author: Cyril Jaquier
|
||||
#
|
||||
# $Revision: 494 $
|
||||
# $Revision: 629 $
|
||||
#
|
||||
|
||||
[Definition]
|
||||
|
@ -28,7 +28,7 @@ logtarget = /var/log/fail2ban.log
|
|||
# Notes.: Set the socket file. This is used to communicate with the daemon. Do
|
||||
# not remove this file when Fail2ban runs. It will not be possible to
|
||||
# communicate with the server afterwards.
|
||||
# Values: FILE Default: /var/run/fail2ban.sock
|
||||
# Values: FILE Default: /var/run/fail2ban/fail2ban.sock
|
||||
#
|
||||
socket = /var/run/fail2ban.sock
|
||||
socket = /var/run/fail2ban/fail2ban.sock
|
||||
|
||||
|
|
|
@ -5,10 +5,12 @@
|
|||
#
|
||||
# Author: Yaroslav Halchenko
|
||||
#
|
||||
# $Revision: 668 $
|
||||
#
|
||||
|
||||
[Definition]
|
||||
|
||||
badbotscustom = EmailCollector|WebEMailExtrac|TrackBack/1\.02
|
||||
badbotscustom = EmailCollector|WebEMailExtrac|TrackBack/1\.02|sogou music spider
|
||||
badbots = atSpider/1\.0|autoemailspider|China Local Browse 2\.6|ContentSmartz|DataCha0s/2\.0|DataCha0s/2\.0|DBrowse 1\.4b|DBrowse 1\.4d|Demo Bot DOT 16b|Demo Bot Z 16b|DSurf15a 01|DSurf15a 71|DSurf15a 81|DSurf15a VA|EBrowse 1\.4b|Educate Search VxB|EmailSiphon|EmailWolf 1\.00|ESurf15a 15|ExtractorPro|Franklin Locator 1\.8|FSurf15a 01|Full Web Bot 0416B|Full Web Bot 0516B|Full Web Bot 2816B|Industry Program 1\.0\.x|ISC Systems iRc Search 2\.1|IUPUI Research Bot v 1\.9a|LARBIN-EXPERIMENTAL \(efp@gmx\.net\)|LetsCrawl\.com/1\.0 +http\://letscrawl\.com/|Lincoln State Web Browser|LWP\:\:Simple/5\.803|Mac Finder 1\.0\.xx|MFC Foundation Class Library 4\.0|Microsoft URL Control - 6\.00\.8xxx|Missauga Locate 1\.0\.0|Missigua Locator 1\.9|Missouri College Browse|Mizzu Labs 2\.2|Mo College 1\.9|Mozilla/2\.0 \(compatible; NEWT ActiveX; Win32\)|Mozilla/3\.0 \(compatible; Indy Library\)|Mozilla/4\.0 \(compatible; Advanced Email Extractor v2\.xx\)|Mozilla/4\.0 \(compatible; Iplexx Spider/1\.0 http\://www\.iplexx\.at\)|Mozilla/4\.0 \(compatible; MSIE 5\.0; Windows NT; DigExt; DTS Agent|Mozilla/4\.0 efp@gmx\.net|Mozilla/5\.0 \(Version\: xxxx Type\:xx\)|MVAClient|NASA Search 1\.0|Nsauditor/1\.x|PBrowse 1\.4b|PEval 1\.4b|Poirot|Port Huron Labs|Production Bot 0116B|Production Bot 2016B|Production Bot DOT 3016B|Program Shareware 1\.0\.2|PSurf15a 11|PSurf15a 51|PSurf15a VA|psycheclone|RSurf15a 41|RSurf15a 51|RSurf15a 81|searchbot admin@google\.com|sogou spider|sohu agent|SSurf15a 11 |TSurf15a 11|Under the Rainbow 2\.2|User-Agent\: Mozilla/4\.0 \(compatible; MSIE 6\.0; Windows NT 5\.1\)|WebVulnCrawl\.blogspot\.com/1\.0 libwww-perl/5\.803|Wells Search II|WEP Search 00
|
||||
|
||||
# Option: failregex
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
#
|
||||
# Author: Cyril Jaquier
|
||||
#
|
||||
# $Revision: 510 $
|
||||
# $Revision: 658 $
|
||||
#
|
||||
|
||||
[Definition]
|
||||
|
|
|
@ -0,0 +1,20 @@
|
|||
# Fail2Ban configuration file
|
||||
#
|
||||
# Author: Tim Connors
|
||||
#
|
||||
# $Revision: 668 $
|
||||
#
|
||||
|
||||
[Definition]
|
||||
|
||||
# Option: failregex
|
||||
# Notes.: Regexp to catch Apache overflow attempts.
|
||||
# Values: TEXT
|
||||
#
|
||||
failregex = [[]client <HOST>[]] (Invalid method in request|request failed: URI too long|erroneous characters after protocol string)
|
||||
|
||||
# Option: ignoreregex
|
||||
# Notes.: regex to ignore. If this regex matches, the line is ignored.
|
||||
# Values: TEXT
|
||||
#
|
||||
ignoreregex =
|
|
@ -0,0 +1,41 @@
|
|||
# Generic configuration items (to be used as interpolations) in other
|
||||
# filters or actions configurations
|
||||
#
|
||||
# Author: Yaroslav Halchenko
|
||||
#
|
||||
# $Revision: $
|
||||
#
|
||||
|
||||
[INCLUDES]
|
||||
|
||||
# Load customizations if any available
|
||||
after = common.local
|
||||
|
||||
|
||||
[DEFAULT]
|
||||
|
||||
# Daemon definition is to be specialized (if needed) in .conf file
|
||||
_daemon = \S*
|
||||
|
||||
#
|
||||
# Shortcuts for easier comprehension of the failregex
|
||||
#
|
||||
# PID.
|
||||
# EXAMPLES: [123]
|
||||
__pid_re = (?:\[\d+\])
|
||||
|
||||
# Daemon name (with optional source_file:line or whatever)
|
||||
# EXAMPLES: pam_rhosts_auth, [sshd], pop(pam_unix)
|
||||
__daemon_re = [\[\(]?%(_daemon)s(?:\(\S+\))?[\]\)]?:?
|
||||
|
||||
# Combinations of daemon name and PID
|
||||
# EXAMPLES: sshd[31607], pop(pam_unix)[4920]
|
||||
__daemon_combs_re = (?:%(__pid_re)s?:\s+%(__daemon_re)s|%(__daemon_re)s%(__pid_re)s?:)
|
||||
|
||||
#
|
||||
# Common line prefixes (beginnings) which could be used in filters
|
||||
#
|
||||
# [hostname] [vserver tag] daemon_id spaces
|
||||
# this can be optional (for instance if we match named native log files)
|
||||
__prefix_line = \s*(?:\S+ )?(?:@vserver_\S+ )?%(__daemon_combs_re)s?\s*
|
||||
|
|
@ -4,7 +4,7 @@
|
|||
#
|
||||
# Author: Yaroslav Halchenko
|
||||
#
|
||||
# $Revision: 608 $
|
||||
# $Revision: 616 $
|
||||
#
|
||||
|
||||
[Definition]
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
#
|
||||
# Author: Yaroslav Halchenko
|
||||
#
|
||||
# $Revision: 603 $
|
||||
# $Revision: 665 $
|
||||
#
|
||||
|
||||
[Definition]
|
||||
|
@ -14,10 +14,10 @@
|
|||
# (?:::f{4,6}:)?(?P<host>\S+)
|
||||
# Values: TEXT
|
||||
#
|
||||
failregex = \(\S+\[<HOST>\]\): USER \S+: no such user found from \S+ \[[0-9.]+\] to \S+:\S+$
|
||||
\(\S+\[<HOST>\]\): USER \S+ \(Login failed\): Incorrect password\.$
|
||||
\(\S+\[<HOST>\]\): SECURITY VIOLATION: \S+ login attempted\.$
|
||||
\(\S+\[<HOST>\]\): Maximum login attempts \(\d+\) exceeded$
|
||||
failregex = \(\S+\[<HOST>\]\)[: -]+ USER \S+: no such user found from \S+ \[[0-9.]+\] to \S+:\S+$
|
||||
\(\S+\[<HOST>\]\)[: -]+ USER \S+ \(Login failed\): Incorrect password\.$
|
||||
\(\S+\[<HOST>\]\)[: -]+ SECURITY VIOLATION: \S+ login attempted\.$
|
||||
\(\S+\[<HOST>\]\)[: -]+ Maximum login attempts \(\d+\) exceeded$
|
||||
|
||||
# Option: ignoreregex
|
||||
# Notes.: regex to ignore. If this regex matches, the line is ignored.
|
||||
|
|
|
@ -2,11 +2,20 @@
|
|||
#
|
||||
# Author: Cyril Jaquier
|
||||
#
|
||||
# $Revision: 613 $
|
||||
# $Revision: 663 $
|
||||
#
|
||||
|
||||
[INCLUDES]
|
||||
|
||||
# Read common prefixes. If any customizations available -- read them from
|
||||
# common.local
|
||||
before = common.conf
|
||||
|
||||
|
||||
[Definition]
|
||||
|
||||
_daemon = sshd
|
||||
|
||||
# Option: failregex
|
||||
# Notes.: regex to match the password failures messages in the logfile. The
|
||||
# host must be matched by a group named "host". The tag "<HOST>" can
|
||||
|
@ -14,13 +23,15 @@
|
|||
# (?:::f{4,6}:)?(?P<host>\S+)
|
||||
# Values: TEXT
|
||||
#
|
||||
failregex = (?:error: PAM: )?Authentication failure for .* from <HOST>\s*$
|
||||
Failed [-/\w]+ for .* from <HOST>(?: port \d*)?(?: ssh\d*)?\s*$
|
||||
ROOT LOGIN REFUSED.* FROM <HOST>\s*$
|
||||
[iI](?:llegal|nvalid) user .* from <HOST>\s*$
|
||||
User .+ from <HOST> not allowed because not listed in AllowUsers\s*$
|
||||
User .+ from <HOST> not allowed because none of user's groups are listed in AllowGroups\s*$
|
||||
sshd(?:\[\d+\])?: refused connect from \S+ \(<HOST>\)\s*$
|
||||
failregex = ^%(__prefix_line)s(?:error: PAM: )?Authentication failure for .* from <HOST>\s*$
|
||||
^%(__prefix_line)sFailed [-/\w]+ for .* from <HOST>(?: port \d*)?(?: ssh\d*)?$
|
||||
^%(__prefix_line)sROOT LOGIN REFUSED.* FROM <HOST>\s*$
|
||||
^%(__prefix_line)s[iI](?:llegal|nvalid) user .* from <HOST>\s*$
|
||||
^%(__prefix_line)sUser .+ from <HOST> not allowed because not listed in AllowUsers$
|
||||
^%(__prefix_line)sUser .+ from <HOST> not allowed because none of user's groups are listed in AllowGroups\s*$
|
||||
^%(__prefix_line)sauthentication failure; logname=\S* uid=\S* euid=\S* tty=\S* ruser=\S* rhost=<HOST>(?:\s+user=.*)?\s*$
|
||||
^%(__prefix_line)srefused connect from \S+ \(<HOST>\)\s*$
|
||||
^%(__prefix_line)sAddress <HOST> .* POSSIBLE BREAK-IN ATTEMPT\s*$
|
||||
|
||||
# Option: ignoreregex
|
||||
# Notes.: regex to ignore. If this regex matches, the line is ignored.
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
#
|
||||
# Author: Cyril Jaquier
|
||||
#
|
||||
# $Revision: 610 $
|
||||
# $Revision: 658 $
|
||||
#
|
||||
|
||||
[Definition]
|
||||
|
|
|
@ -0,0 +1,30 @@
|
|||
# Fail2Ban configuration file
|
||||
#
|
||||
# Author: Guido Bozzetto
|
||||
#
|
||||
# $Revision: 668 $
|
||||
#
|
||||
|
||||
[Definition]
|
||||
|
||||
# Option: failregex
|
||||
# Notes.: regex to match the password failures messages in the logfile. The
|
||||
# host must be matched by a group named "host". The tag "<HOST>" can
|
||||
# be used for standard IP/hostname matching and is only an alias for
|
||||
# (?:::f{4,6}:)?(?P<host>\S+)
|
||||
# Values: TEXT
|
||||
#
|
||||
# Cfr.: /var/log/(daemon\.|sys)log
|
||||
# libwrap => tcp wrappers: hosts.(allow|deny)
|
||||
# address => xinetd: deny_from|only_from
|
||||
# load => xinetd: max_load (temporary problem)
|
||||
#
|
||||
|
||||
failregex = xinetd(?:\[\d{1,5}\])?: FAIL: \S+ address from=<HOST>$
|
||||
xinetd(?:\[\d{1,5}\])?: FAIL: \S+ libwrap from=<HOST>$
|
||||
|
||||
# Option: ignoreregex
|
||||
# Notes.: regex to ignore. If this regex matches, the line is ignored.
|
||||
# Values: TEXT
|
||||
#
|
||||
ignoreregex =
|
|
@ -2,7 +2,7 @@
|
|||
#
|
||||
# Author: Cyril Jaquier
|
||||
#
|
||||
# $Revision: 611 $
|
||||
# $Revision: 617 $
|
||||
#
|
||||
|
||||
# The DEFAULT allows a global definition of the options. They can be override
|
||||
|
@ -89,8 +89,8 @@ logpath = /var/log/sshd.log
|
|||
enabled = false
|
||||
filter = apache-auth
|
||||
action = hostsdeny
|
||||
logpath = /var/log/apache*/*access.log
|
||||
/home/www/myhomepage/access.log
|
||||
logpath = /var/log/apache*/*error.log
|
||||
/home/www/myhomepage/error.log
|
||||
maxretry = 6
|
||||
|
||||
# The hosts.deny path can be defined with the "file" argument if it is
|
||||
|
|
|
@ -3,4 +3,4 @@
|
|||
# Site Directory Pattern Version Script
|
||||
version=3
|
||||
|
||||
http://sf.net/fail2ban/ fail2ban-(.*)\.tar\.bz2 debian svn-upgrade
|
||||
http://sf.net/fail2ban/ fail2ban-(.*)\.tar\.bz2 debian git-import-orig
|
||||
|
|
|
@ -17,16 +17,16 @@
|
|||
|
||||
# Author: Cyril Jaquier
|
||||
#
|
||||
# $Revision: 528 $
|
||||
# $Revision: 672 $
|
||||
|
||||
__author__ = "Cyril Jaquier"
|
||||
__version__ = "$Revision: 528 $"
|
||||
__date__ = "$Date: 2007-01-29 21:27:01 +0100 (Mon, 29 Jan 2007) $"
|
||||
__version__ = "$Revision: 672 $"
|
||||
__date__ = "$Date: 2008-03-06 00:18:06 +0100 (Thu, 06 Mar 2008) $"
|
||||
__copyright__ = "Copyright (c) 2004 Cyril Jaquier"
|
||||
__license__ = "GPL"
|
||||
|
||||
import sys, string, os, pickle, re, logging, signal
|
||||
import getopt, time, readline, shlex, socket
|
||||
import getopt, time, shlex, socket
|
||||
|
||||
# Inserts our own modules path first in the list
|
||||
# fix for bug #343821
|
||||
|
@ -48,7 +48,8 @@ logSys = logging.getLogger("fail2ban.client")
|
|||
|
||||
class Fail2banClient:
|
||||
|
||||
prompt = "fail2ban> "
|
||||
SERVER = "fail2ban-server"
|
||||
PROMPT = "fail2ban> "
|
||||
|
||||
def __init__(self):
|
||||
self.__argv = None
|
||||
|
@ -65,11 +66,11 @@ class Fail2banClient:
|
|||
def dispVersion(self):
|
||||
print "Fail2Ban v" + version
|
||||
print
|
||||
print "Copyright (c) 2004-2006 Cyril Jaquier"
|
||||
print "Copyright (c) 2004-2008 Cyril Jaquier"
|
||||
print "Copyright of modifications held by their respective authors."
|
||||
print "Licensed under the GNU General Public License v2 (GPL)."
|
||||
print
|
||||
print "Written by Cyril Jaquier <lostcontrol@users.sourceforge.net>."
|
||||
print "Written by Cyril Jaquier <cyril.jaquier@fail2ban.org>."
|
||||
print "Many contributions by Yaroslav O. Halchenko <debian@onerussian.com>."
|
||||
|
||||
def dispUsage(self):
|
||||
|
@ -97,7 +98,7 @@ class Fail2banClient:
|
|||
printFormatted()
|
||||
|
||||
print
|
||||
print "Report bugs to <lostcontrol@users.sourceforge.net>"
|
||||
print "Report bugs to <cyril.jaquier@fail2ban.org>"
|
||||
|
||||
def dispInteractive(self):
|
||||
print "Fail2Ban v" + version + " reads log file that contains password failure report"
|
||||
|
@ -208,6 +209,19 @@ class Fail2banClient:
|
|||
else:
|
||||
logSys.error("Could not find server")
|
||||
return False
|
||||
elif len(cmd) == 2 and cmd[0] == "reload":
|
||||
if self.__ping():
|
||||
jail = cmd[1]
|
||||
ret = self.__readJailConfig(jail)
|
||||
# Do not continue if configuration is not 100% valid
|
||||
if not ret:
|
||||
return False
|
||||
self.__processCmd([['stop', jail]], False)
|
||||
# Configure the server
|
||||
return self.__processCmd(self.__stream, False)
|
||||
else:
|
||||
logSys.error("Could not find server")
|
||||
return False
|
||||
else:
|
||||
return self.__processCmd([cmd])
|
||||
|
||||
|
@ -222,7 +236,7 @@ class Fail2banClient:
|
|||
pid = os.fork()
|
||||
if pid == 0:
|
||||
args = list()
|
||||
args.append("fail2ban-server")
|
||||
args.append(self.SERVER)
|
||||
# Start in background mode.
|
||||
args.append("-b")
|
||||
# Set the socket path.
|
||||
|
@ -232,14 +246,15 @@ class Fail2banClient:
|
|||
if force:
|
||||
args.append("-x")
|
||||
try:
|
||||
# Use the PATH env
|
||||
os.execvp("fail2ban-server", args)
|
||||
# Use the current directory.
|
||||
exe = os.path.abspath(os.path.join(sys.path[0], self.SERVER))
|
||||
os.execv(exe, args)
|
||||
except OSError:
|
||||
try:
|
||||
# Use the current directory
|
||||
os.execv("fail2ban-server", args)
|
||||
# Use the PATH env.
|
||||
os.execvp(self.SERVER, args)
|
||||
except OSError:
|
||||
print "Could not find fail2ban-server"
|
||||
print "Could not find %s" % self.SERVER
|
||||
os.exit(-1)
|
||||
|
||||
|
||||
|
@ -325,6 +340,11 @@ class Fail2banClient:
|
|||
|
||||
# Interactive mode
|
||||
if self.__conf["interactive"]:
|
||||
try:
|
||||
import readline
|
||||
except ImportError:
|
||||
logSys.error("Readline not available")
|
||||
return False
|
||||
try:
|
||||
ret = True
|
||||
if len(args) > 0:
|
||||
|
@ -333,7 +353,7 @@ class Fail2banClient:
|
|||
readline.parse_and_bind("tab: complete")
|
||||
self.dispInteractive()
|
||||
while True:
|
||||
cmd = raw_input(self.prompt)
|
||||
cmd = raw_input(self.PROMPT)
|
||||
if cmd == "exit" or cmd == "quit":
|
||||
# Exit
|
||||
return True
|
||||
|
@ -352,16 +372,24 @@ class Fail2banClient:
|
|||
def __readConfig(self):
|
||||
# Read the configuration
|
||||
self.__configurator.readAll()
|
||||
ret = self.__configurator.getAllOptions()
|
||||
ret = self.__configurator.getOptions()
|
||||
self.__configurator.convertToProtocol()
|
||||
self.__stream = self.__configurator.getConfigStream()
|
||||
return ret
|
||||
|
||||
@staticmethod
|
||||
def __readJailConfig(self, jail):
|
||||
self.__configurator.readAll()
|
||||
ret = self.__configurator.getOptions(jail)
|
||||
self.__configurator.convertToProtocol()
|
||||
self.__stream = self.__configurator.getConfigStream()
|
||||
return ret
|
||||
|
||||
#@staticmethod
|
||||
def dumpConfig(cmd):
|
||||
for c in cmd:
|
||||
print c
|
||||
return True
|
||||
dumpConfig = staticmethod(dumpConfig)
|
||||
|
||||
|
||||
class ServerExecutionException(Exception):
|
||||
|
|
|
@ -17,11 +17,11 @@
|
|||
|
||||
# Author: Cyril Jaquier
|
||||
#
|
||||
# $Revision: 596 $
|
||||
# $Revision: 672 $
|
||||
|
||||
__author__ = "Cyril Jaquier"
|
||||
__version__ = "$Revision: 596 $"
|
||||
__date__ = "$Date: 2007-07-10 21:54:01 +0200 (Tue, 10 Jul 2007) $"
|
||||
__version__ = "$Revision: 672 $"
|
||||
__date__ = "$Date: 2008-03-06 00:18:06 +0100 (Thu, 06 Mar 2008) $"
|
||||
__copyright__ = "Copyright (c) 2004 Cyril Jaquier"
|
||||
__license__ = "GPL"
|
||||
|
||||
|
@ -31,11 +31,11 @@ import getopt, sys, time, logging, os
|
|||
# fix for bug #343821
|
||||
sys.path.insert(1, "/usr/share/fail2ban")
|
||||
|
||||
from ConfigParser import SafeConfigParser
|
||||
from client.configparserinc import SafeConfigParserWithIncludes
|
||||
from ConfigParser import NoOptionError, NoSectionError, MissingSectionHeaderError
|
||||
from common.version import version
|
||||
from server.filter import Filter
|
||||
from server.regex import RegexException
|
||||
from server.failregex import RegexException
|
||||
|
||||
# Gets the instance of the logger.
|
||||
logSys = logging.getLogger("fail2ban.regex")
|
||||
|
@ -65,7 +65,9 @@ class RegexStat:
|
|||
class Fail2banRegex:
|
||||
|
||||
test = None
|
||||
|
||||
|
||||
CONFIG_DEFAULTS = {'configpath' : "/etc/fail2ban/"}
|
||||
|
||||
def __init__(self):
|
||||
self.__filter = Filter(None)
|
||||
self.__ignoreregex = list()
|
||||
|
@ -80,18 +82,19 @@ class Fail2banRegex:
|
|||
logging.getLogger("fail2ban").addHandler(self.__hdlr)
|
||||
logging.getLogger("fail2ban").setLevel(logging.ERROR)
|
||||
|
||||
@staticmethod
|
||||
#@staticmethod
|
||||
def dispVersion():
|
||||
print "Fail2Ban v" + version
|
||||
print
|
||||
print "Copyright (c) 2004-2006 Cyril Jaquier"
|
||||
print "Copyright (c) 2004-2008 Cyril Jaquier"
|
||||
print "Copyright of modifications held by their respective authors."
|
||||
print "Licensed under the GNU General Public License v2 (GPL)."
|
||||
print
|
||||
print "Written by Cyril Jaquier <lostcontrol@users.sourceforge.net>."
|
||||
print "Written by Cyril Jaquier <cyril.jaquier@fail2ban.org>."
|
||||
print "Many contributions by Yaroslav O. Halchenko <debian@onerussian.com>."
|
||||
dispVersion = staticmethod(dispVersion)
|
||||
|
||||
@staticmethod
|
||||
#@staticmethod
|
||||
def dispUsage():
|
||||
print "Usage: "+sys.argv[0]+" [OPTIONS] <LOG> <REGEX> [IGNOREREGEX]"
|
||||
print
|
||||
|
@ -116,7 +119,8 @@ class Fail2banRegex:
|
|||
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 <cyril.jaquier@fail2ban.org>"
|
||||
dispUsage = staticmethod(dispUsage)
|
||||
|
||||
def getCmdLineOptions(self, optList):
|
||||
""" Gets the command line options
|
||||
|
@ -129,13 +133,14 @@ class Fail2banRegex:
|
|||
self.dispVersion()
|
||||
sys.exit(0)
|
||||
|
||||
@staticmethod
|
||||
#@staticmethod
|
||||
def logIsFile(value):
|
||||
return os.path.isfile(value)
|
||||
logIsFile = staticmethod(logIsFile)
|
||||
|
||||
def readIgnoreRegex(self, value):
|
||||
if os.path.isfile(value):
|
||||
reader = SafeConfigParser()
|
||||
reader = SafeConfigParserWithIncludes(defaults=self.CONFIG_DEFAULTS)
|
||||
try:
|
||||
reader.read(value)
|
||||
print "Use ignoreregex file : " + value
|
||||
|
@ -164,7 +169,7 @@ class Fail2banRegex:
|
|||
|
||||
def readRegex(self, value):
|
||||
if os.path.isfile(value):
|
||||
reader = SafeConfigParser()
|
||||
reader = SafeConfigParserWithIncludes(defaults=self.CONFIG_DEFAULTS)
|
||||
try:
|
||||
reader.read(value)
|
||||
print "Use regex file : " + value
|
||||
|
@ -217,7 +222,7 @@ class Fail2banRegex:
|
|||
try:
|
||||
self.__filter.addFailRegex(regex.getFailRegex())
|
||||
try:
|
||||
ret = self.__filter.findFailure(line)
|
||||
ret = self.__filter.processLine(line)
|
||||
if not len(ret) == 0:
|
||||
if found == True:
|
||||
ret[0].append(True)
|
||||
|
|
|
@ -17,15 +17,15 @@
|
|||
|
||||
# Author: Cyril Jaquier
|
||||
#
|
||||
# $Revision: 522 $
|
||||
# $Revision: 672 $
|
||||
|
||||
__author__ = "Cyril Jaquier"
|
||||
__version__ = "$Revision: 522 $"
|
||||
__date__ = "$Date: 2007-01-21 23:19:57 +0100 (Sun, 21 Jan 2007) $"
|
||||
__version__ = "$Revision: 672 $"
|
||||
__date__ = "$Date: 2008-03-06 00:18:06 +0100 (Thu, 06 Mar 2008) $"
|
||||
__copyright__ = "Copyright (c) 2004 Cyril Jaquier"
|
||||
__license__ = "GPL"
|
||||
|
||||
import getopt, sys
|
||||
import getopt, sys, logging
|
||||
|
||||
# Inserts our own modules path first in the list
|
||||
# fix for bug #343821
|
||||
|
@ -34,6 +34,9 @@ sys.path.insert(1, "/usr/share/fail2ban")
|
|||
from common.version import version
|
||||
from server.server import Server
|
||||
|
||||
# Gets the instance of the logger.
|
||||
logSys = logging.getLogger("fail2ban")
|
||||
|
||||
##
|
||||
# \mainpage Fail2Ban
|
||||
#
|
||||
|
@ -50,16 +53,16 @@ class Fail2banServer:
|
|||
self.__conf = dict()
|
||||
self.__conf["background"] = True
|
||||
self.__conf["force"] = False
|
||||
self.__conf["socket"] = "/tmp/fail2ban.sock"
|
||||
self.__conf["socket"] = "/var/run/fail2ban/fail2ban.sock"
|
||||
|
||||
def dispVersion(self):
|
||||
print "Fail2Ban v" + version
|
||||
print
|
||||
print "Copyright (c) 2004-2006 Cyril Jaquier"
|
||||
print "Copyright (c) 2004-2008 Cyril Jaquier"
|
||||
print "Copyright of modifications held by their respective authors."
|
||||
print "Licensed under the GNU General Public License v2 (GPL)."
|
||||
print
|
||||
print "Written by Cyril Jaquier <lostcontrol@users.sourceforge.net>."
|
||||
print "Written by Cyril Jaquier <cyril.jaquier@fail2ban.org>."
|
||||
print "Many contributions by Yaroslav O. Halchenko <debian@onerussian.com>."
|
||||
|
||||
def dispUsage(self):
|
||||
|
@ -82,7 +85,7 @@ class Fail2banServer:
|
|||
print " -h, --help display this help message"
|
||||
print " -V, --version print the version"
|
||||
print
|
||||
print "Report bugs to <lostcontrol@users.sourceforge.net>"
|
||||
print "Report bugs to <cyril.jaquier@fail2ban.org>"
|
||||
|
||||
def __getCmdLineOptions(self, optList):
|
||||
""" Gets the command line options
|
||||
|
@ -123,7 +126,7 @@ class Fail2banServer:
|
|||
self.__server.start(self.__conf["socket"], self.__conf["force"])
|
||||
return True
|
||||
except Exception, e:
|
||||
print e
|
||||
logSys.exception(e)
|
||||
self.__server.quit()
|
||||
return False
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
|_| \__,_|_|_/___|_.__/\__,_|_||_|
|
||||
|
||||
=============================================================
|
||||
Fail2Ban (version 0.7.7) 2007/??/??
|
||||
Fail2Ban (version 0.8.2) 2008/03/06
|
||||
=============================================================
|
||||
|
||||
Cacti is a graphing solution using RRDTool. It is possible to
|
||||
|
@ -13,7 +13,7 @@ use Cacti to display statistics about Fail2ban.
|
|||
Installation:
|
||||
-------------
|
||||
|
||||
1/ Install Fail2ban version 0.7 or higher and ensure that it
|
||||
1/ Install Fail2ban version 0.8 or higher and ensure that it
|
||||
works properly.
|
||||
2/ The user running poller.php must have read and write
|
||||
access to the socket used by Fail2ban.
|
||||
|
@ -30,7 +30,7 @@ appreciate this program, you can contact me at:
|
|||
|
||||
Website: http://www.fail2ban.org
|
||||
|
||||
Cyril Jaquier: <lostcontrol@users.sourceforge.net>
|
||||
Cyril Jaquier: <cyril.jaquier@fail2ban.org>
|
||||
|
||||
License:
|
||||
--------
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
/Library/LaunchDaemonsm/org.fail2ban.plist
|
||||
===================================
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>Disabled</key>
|
||||
<false/>
|
||||
<key>Label</key>
|
||||
<string>fail2ban</string>
|
||||
<key>ProgramArguments</key>
|
||||
<array>
|
||||
<string>/usr/local/bin/fail2ban-client</string>
|
||||
<string>start</string>
|
||||
</array>
|
||||
<key>RunAtLoad</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</plist>
|
|
@ -1,11 +1,12 @@
|
|||
.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.36.
|
||||
.TH FAIL2BAN-CLIENT "1" "August 2007" "fail2ban-client v0.8.1" "User Commands"
|
||||
.TH FAIL2BAN-CLIENT "1" "March 2008" "fail2ban-client v0.8.2" "User Commands"
|
||||
.SH NAME
|
||||
fail2ban-client \- configure and control the server
|
||||
.SH SYNOPSIS
|
||||
.B fail2ban-client
|
||||
[\fIOPTIONS\fR] \fI<COMMAND>\fR
|
||||
.SH DESCRIPTION
|
||||
[?1034hUsage: ../fail2ban\-client [OPTIONS] <COMMAND>
|
||||
.PP
|
||||
Fail2Ban v0.8.1 reads log file that contains password failure report
|
||||
Fail2Ban v0.8.2 reads log file that contains password failure report
|
||||
and bans the corresponding IP addresses using firewall rules.
|
||||
.SH OPTIONS
|
||||
.TP
|
||||
|
@ -45,6 +46,9 @@ starts the server and the jails
|
|||
\fBreload\fR
|
||||
reloads the configuration
|
||||
.TP
|
||||
\fBreload <JAIL>\fR
|
||||
reloads the jail <JAIL>
|
||||
.TP
|
||||
\fBstop\fR
|
||||
stops all jails and terminate the
|
||||
server
|
||||
|
@ -109,18 +113,6 @@ of <JAIL>
|
|||
removes <FILE> to the monitoring
|
||||
list of <JAIL>
|
||||
.TP
|
||||
\fBset <JAIL> timeregex <REGEX>\fR
|
||||
sets the regular expression
|
||||
<REGEX> to match the date format
|
||||
for <JAIL>. This will disable the
|
||||
autodetection feature.
|
||||
.TP
|
||||
\fBset <JAIL> timepattern <PATTERN>\fR
|
||||
sets the pattern <PATTERN> to
|
||||
match the date format for <JAIL>.
|
||||
This will disable the
|
||||
autodetection feature.
|
||||
.TP
|
||||
\fBset <JAIL> addfailregex <REGEX>\fR
|
||||
adds the regular expression
|
||||
<REGEX> which must match failures
|
||||
|
@ -256,13 +248,13 @@ action <ACT> for <JAIL>
|
|||
.SH FILES
|
||||
\fI/etc/fail2ban/*\fR
|
||||
.SH AUTHOR
|
||||
Written by Cyril Jaquier <lostcontrol@users.sourceforge.net>.
|
||||
Written by Cyril Jaquier <cyril.jaquier@fail2ban.org>.
|
||||
Many contributions by Yaroslav O. Halchenko <debian@onerussian.com>.
|
||||
.SH "REPORTING BUGS"
|
||||
Please report bugs via Debian bug tracking system
|
||||
http://www.debian.org/Bugs/.
|
||||
.SH COPYRIGHT
|
||||
Copyright \(co 2004-2006 Cyril Jaquier
|
||||
Copyright \(co 2004-2008 Cyril Jaquier
|
||||
.br
|
||||
Copyright of modifications held by their respective authors.
|
||||
Licensed under the GNU General Public License v2 (GPL).
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.36.
|
||||
.TH FAIL2BAN-REGEX "1" "August 2007" "fail2ban-regex v0.8.1" "User Commands"
|
||||
.TH FAIL2BAN-REGEX "1" "March 2008" "fail2ban-regex v0.8.2" "User Commands"
|
||||
.SH NAME
|
||||
fail2ban-regex \- test Fail2ban "failregex" option
|
||||
.SH SYNOPSIS
|
||||
.B fail2ban-regex
|
||||
[\fIOPTIONS\fR] \fI<LOG> <REGEX> \fR[\fIIGNOREREGEX\fR]
|
||||
.SH DESCRIPTION
|
||||
Fail2Ban v0.8.1 reads log file that contains password failure report
|
||||
Fail2Ban v0.8.2 reads log file that contains password failure report
|
||||
and bans the corresponding IP addresses using firewall rules.
|
||||
.PP
|
||||
This tools can test regular expressions for "fail2ban".
|
||||
|
@ -39,12 +39,12 @@ a string representing an 'ignoreregex'
|
|||
\fBfilename\fR
|
||||
path to a filter file (filter.d/sshd.conf)
|
||||
.SH AUTHOR
|
||||
Written by Cyril Jaquier <lostcontrol@users.sourceforge.net>.
|
||||
Written by Cyril Jaquier <cyril.jaquier@fail2ban.org>.
|
||||
Many contributions by Yaroslav O. Halchenko <debian@onerussian.com>.
|
||||
.SH "REPORTING BUGS"
|
||||
Report bugs to <lostcontrol@users.sourceforge.net>
|
||||
Report bugs to <cyril.jaquier@fail2ban.org>
|
||||
.SH COPYRIGHT
|
||||
Copyright \(co 2004-2006 Cyril Jaquier
|
||||
Copyright \(co 2004-2008 Cyril Jaquier
|
||||
.br
|
||||
Copyright of modifications held by their respective authors.
|
||||
Licensed under the GNU General Public License v2 (GPL).
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.36.
|
||||
.TH FAIL2BAN-SERVER "1" "August 2007" "fail2ban-server v0.8.1" "User Commands"
|
||||
.TH FAIL2BAN-SERVER "1" "March 2008" "fail2ban-server v0.8.2" "User Commands"
|
||||
.SH NAME
|
||||
fail2ban-server \- start the server
|
||||
.SH SYNOPSIS
|
||||
.B fail2ban-server
|
||||
[\fIOPTIONS\fR]
|
||||
.SH DESCRIPTION
|
||||
Fail2Ban v0.8.1 reads log file that contains password failure report
|
||||
Fail2Ban v0.8.2 reads log file that contains password failure report
|
||||
and bans the corresponding IP addresses using firewall rules.
|
||||
.PP
|
||||
Only use this command for debugging purpose. Start the server with
|
||||
|
@ -32,13 +32,13 @@ display this help message
|
|||
\fB\-V\fR, \fB\-\-version\fR
|
||||
print the version
|
||||
.SH AUTHOR
|
||||
Written by Cyril Jaquier <lostcontrol@users.sourceforge.net>.
|
||||
Written by Cyril Jaquier <cyril.jaquier@fail2ban.org>.
|
||||
Many contributions by Yaroslav O. Halchenko <debian@onerussian.com>.
|
||||
.SH "REPORTING BUGS"
|
||||
Please report bugs via Debian bug tracking system
|
||||
http://www.debian.org/Bugs/.
|
||||
.SH COPYRIGHT
|
||||
Copyright \(co 2004-2006 Cyril Jaquier
|
||||
Copyright \(co 2004-2008 Cyril Jaquier
|
||||
.br
|
||||
Copyright of modifications held by their respective authors.
|
||||
Licensed under the GNU General Public License v2 (GPL).
|
||||
|
|
|
@ -16,11 +16,11 @@
|
|||
|
||||
# Author: Cyril Jaquier
|
||||
#
|
||||
# $Revision: 556 $
|
||||
# $Revision: 635 $
|
||||
|
||||
__author__ = "Cyril Jaquier"
|
||||
__version__ = "$Revision: 556 $"
|
||||
__date__ = "$Date: 2007-03-07 21:54:32 +0100 (Wed, 07 Mar 2007) $"
|
||||
__version__ = "$Revision: 635 $"
|
||||
__date__ = "$Date: 2007-12-16 22:38:04 +0100 (Sun, 16 Dec 2007) $"
|
||||
__copyright__ = "Copyright (c) 2004 Cyril Jaquier"
|
||||
__license__ = "GPL"
|
||||
|
||||
|
@ -231,7 +231,7 @@ class Action:
|
|||
# @param aInfo the properties
|
||||
# @return a string
|
||||
|
||||
@staticmethod
|
||||
#@staticmethod
|
||||
def replaceTag(query, aInfo):
|
||||
""" Replace tags in query
|
||||
"""
|
||||
|
@ -241,6 +241,7 @@ class Action:
|
|||
# New line
|
||||
string = string.replace("<br>", '\n')
|
||||
return string
|
||||
replaceTag = staticmethod(replaceTag)
|
||||
|
||||
##
|
||||
# Executes a command with preliminary checks and substitutions.
|
||||
|
@ -297,7 +298,7 @@ class Action:
|
|||
# @param realCmd the command to execute
|
||||
# @return True if the command succeeded
|
||||
|
||||
@staticmethod
|
||||
#@staticmethod
|
||||
def executeCmd(realCmd):
|
||||
logSys.debug(realCmd)
|
||||
try:
|
||||
|
@ -312,3 +313,5 @@ class Action:
|
|||
except OSError, e:
|
||||
logSys.error("%s failed with %s" % (realCmd, e))
|
||||
return False
|
||||
executeCmd = staticmethod(executeCmd)
|
||||
|
||||
|
|
|
@ -0,0 +1,155 @@
|
|||
# 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: 567 $
|
||||
|
||||
__author__ = "Cyril Jaquier"
|
||||
__version__ = "$Revision: 567 $"
|
||||
__date__ = "$Date: 2007-03-26 23:17:31 +0200 (Mon, 26 Mar 2007) $"
|
||||
__copyright__ = "Copyright (c) 2004 Cyril Jaquier"
|
||||
__license__ = "GPL"
|
||||
|
||||
from pickle import dumps, loads, HIGHEST_PROTOCOL
|
||||
import asyncore, asynchat, socket, os, logging
|
||||
|
||||
# Gets the instance of the logger.
|
||||
logSys = logging.getLogger("fail2ban.server")
|
||||
|
||||
##
|
||||
# Request handler class.
|
||||
#
|
||||
# This class extends asynchat in order to provide a request handler for
|
||||
# incoming query.
|
||||
|
||||
class RequestHandler(asynchat.async_chat):
|
||||
|
||||
END_STRING = "<F2B_END_COMMAND>"
|
||||
|
||||
def __init__(self, conn, transmitter):
|
||||
asynchat.async_chat.__init__(self, conn)
|
||||
self.__transmitter = transmitter
|
||||
self.__buffer = []
|
||||
# Sets the terminator.
|
||||
self.set_terminator(RequestHandler.END_STRING)
|
||||
|
||||
def collect_incoming_data(self, data):
|
||||
#logSys.debug("Received raw data: " + str(data))
|
||||
self.__buffer.append(data)
|
||||
|
||||
##
|
||||
# Handles a new request.
|
||||
#
|
||||
# This method is called once we have a complete request.
|
||||
|
||||
def found_terminator(self):
|
||||
# Joins the buffer items.
|
||||
message = loads("".join(self.__buffer))
|
||||
# Gives the message to the transmitter.
|
||||
message = self.__transmitter.proceed(message)
|
||||
# Serializes the response.
|
||||
message = dumps(message, HIGHEST_PROTOCOL)
|
||||
# Sends the response to the client.
|
||||
self.send(message + RequestHandler.END_STRING)
|
||||
# Closes the channel.
|
||||
self.close_when_done()
|
||||
|
||||
def handle_error(self):
|
||||
logSys.error("Unexpected communication error")
|
||||
self.close()
|
||||
|
||||
##
|
||||
# Asynchronous server class.
|
||||
#
|
||||
# This class extends asyncore and dispatches connection requests to
|
||||
# RequestHandler.
|
||||
|
||||
class AsyncServer(asyncore.dispatcher):
|
||||
|
||||
def __init__(self, transmitter):
|
||||
asyncore.dispatcher.__init__(self)
|
||||
self.__transmitter = transmitter
|
||||
self.__sock = "/var/run/fail2ban/fail2ban.sock"
|
||||
self.__init = False
|
||||
|
||||
##
|
||||
# Returns False as we only read the socket first.
|
||||
|
||||
def writable(self):
|
||||
return False
|
||||
|
||||
def handle_accept(self):
|
||||
try:
|
||||
conn, addr = self.accept()
|
||||
except socket.error:
|
||||
logSys.warning("Socket error")
|
||||
return
|
||||
except TypeError:
|
||||
logSys.warning("Type error")
|
||||
return
|
||||
# Creates an instance of the handler class to handle the
|
||||
# request/response on the incoming connection.
|
||||
RequestHandler(conn, self.__transmitter)
|
||||
|
||||
##
|
||||
# Starts the communication server.
|
||||
#
|
||||
# @param sock: socket file.
|
||||
# @param force: remove the socket file if exists.
|
||||
|
||||
def start(self, sock, force):
|
||||
self.__sock = sock
|
||||
# Remove socket
|
||||
if os.path.exists(sock):
|
||||
logSys.error("Fail2ban seems to be already running")
|
||||
if force:
|
||||
logSys.warn("Forcing execution of the server")
|
||||
os.remove(sock)
|
||||
else:
|
||||
raise AsyncServerException("Server already running")
|
||||
# Creates the socket.
|
||||
self.create_socket(socket.AF_UNIX, socket.SOCK_STREAM)
|
||||
self.set_reuse_addr()
|
||||
try:
|
||||
self.bind(sock)
|
||||
except Exception:
|
||||
raise AsyncServerException("Unable to bind socket %s" % self.__sock)
|
||||
self.listen(1)
|
||||
# Sets the init flag.
|
||||
self.__init = True
|
||||
# TODO Add try..catch
|
||||
asyncore.loop()
|
||||
|
||||
##
|
||||
# Stops the communication server.
|
||||
|
||||
def stop(self):
|
||||
if self.__init:
|
||||
# Only closes the socket if it was initialized first.
|
||||
self.close()
|
||||
# Remove socket
|
||||
if os.path.exists(self.__sock):
|
||||
logSys.debug("Removed socket file " + self.__sock)
|
||||
os.remove(self.__sock)
|
||||
logSys.debug("Socket shutdown")
|
||||
|
||||
|
||||
##
|
||||
# AsyncServerException is used to wrap communication exceptions.
|
||||
|
||||
class AsyncServerException(Exception):
|
||||
pass
|
|
@ -16,15 +16,15 @@
|
|||
|
||||
# Author: Cyril Jaquier
|
||||
#
|
||||
# $Revision: 553 $
|
||||
# $Revision: 638 $
|
||||
|
||||
__author__ = "Cyril Jaquier"
|
||||
__version__ = "$Revision: 553 $"
|
||||
__date__ = "$Date: 2007-02-26 00:53:22 +0100 (Mon, 26 Feb 2007) $"
|
||||
__version__ = "$Revision: 638 $"
|
||||
__date__ = "$Date: 2007-12-17 21:00:36 +0100 (Mon, 17 Dec 2007) $"
|
||||
__copyright__ = "Copyright (c) 2004 Cyril Jaquier"
|
||||
__license__ = "GPL"
|
||||
|
||||
from banticket import BanTicket
|
||||
from ticket import BanTicket
|
||||
from threading import Lock
|
||||
from mytime import MyTime
|
||||
import logging
|
||||
|
@ -125,7 +125,7 @@ class BanManager:
|
|||
# @param ticket the FailTicket
|
||||
# @return a BanTicket
|
||||
|
||||
@staticmethod
|
||||
#@staticmethod
|
||||
def createBanTicket(ticket):
|
||||
ip = ticket.getIP()
|
||||
#lastTime = ticket.getTime()
|
||||
|
@ -133,6 +133,7 @@ class BanManager:
|
|||
banTicket = BanTicket(ip, lastTime)
|
||||
banTicket.setAttempt(ticket.getAttempt())
|
||||
return banTicket
|
||||
createBanTicket = staticmethod(createBanTicket)
|
||||
|
||||
##
|
||||
# Add a ban ticket.
|
||||
|
|
|
@ -1,50 +0,0 @@
|
|||
# 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: 382 $
|
||||
|
||||
__author__ = "Cyril Jaquier"
|
||||
__version__ = "$Revision: 382 $"
|
||||
__date__ = "$Date: 2006-09-25 19:03:48 +0200 (Mon, 25 Sep 2006) $"
|
||||
__copyright__ = "Copyright (c) 2004 Cyril Jaquier"
|
||||
__license__ = "GPL"
|
||||
|
||||
import logging
|
||||
from ticket import Ticket
|
||||
|
||||
# Gets the instance of the logger.
|
||||
logSys = logging.getLogger("fail2ban")
|
||||
|
||||
##
|
||||
# Ban Ticket.
|
||||
#
|
||||
# This class extends the Ticket class. It is mainly used by the BanManager.
|
||||
|
||||
class BanTicket(Ticket):
|
||||
|
||||
##
|
||||
# Constructor.
|
||||
#
|
||||
# Call the Ticket (parent) constructor and initialize default
|
||||
# values.
|
||||
# @param ip the IP address
|
||||
# @param time the ban time
|
||||
|
||||
def __init__(self, ip, time):
|
||||
Ticket.__init__(self, ip, time)
|
||||
|
|
@ -16,19 +16,19 @@
|
|||
|
||||
# Author: Cyril Jaquier
|
||||
#
|
||||
# $Revision: 607 $
|
||||
# $Revision: 645 $
|
||||
|
||||
__author__ = "Cyril Jaquier"
|
||||
__version__ = "$Revision: 607 $"
|
||||
__date__ = "$Date: 2007-08-09 00:16:22 +0200 (Thu, 09 Aug 2007) $"
|
||||
__version__ = "$Revision: 645 $"
|
||||
__date__ = "$Date: 2008-01-16 23:55:04 +0100 (Wed, 16 Jan 2008) $"
|
||||
__copyright__ = "Copyright (c) 2004 Cyril Jaquier"
|
||||
__license__ = "GPL"
|
||||
|
||||
import time, logging
|
||||
|
||||
from datestrptime import DateStrptime
|
||||
from datetai64n import DateTai64n
|
||||
from dateepoch import DateEpoch
|
||||
from datetemplate import DateStrptime
|
||||
from datetemplate import DateTai64n
|
||||
from datetemplate import DateEpoch
|
||||
from threading import Lock
|
||||
|
||||
# Gets the instance of the logger.
|
||||
|
@ -39,11 +39,10 @@ class DateDetector:
|
|||
def __init__(self):
|
||||
self.__lock = Lock()
|
||||
self.__templates = list()
|
||||
self.__defTemplate = DateStrptime()
|
||||
|
||||
def addDefaultTemplate(self):
|
||||
self.__lock.acquire()
|
||||
try:
|
||||
self.__lock.acquire()
|
||||
# standard
|
||||
template = DateStrptime()
|
||||
template.setName("Month Day Hour:Minute:Second")
|
||||
|
@ -100,54 +99,31 @@ class DateDetector:
|
|||
def getTemplates(self):
|
||||
return self.__templates
|
||||
|
||||
def setDefaultRegex(self, value):
|
||||
self.__defTemplate.setRegex(value)
|
||||
|
||||
def getDefaultRegex(self):
|
||||
return self.__defTemplate.getRegex()
|
||||
|
||||
def setDefaultPattern(self, value):
|
||||
self.__defTemplate.setPattern(value)
|
||||
|
||||
def getDefaultPattern(self):
|
||||
return self.__defTemplate.getPattern()
|
||||
|
||||
def matchTime(self, line):
|
||||
if self.__defTemplate.isValid():
|
||||
return self.__defTemplate.matchDate(line)
|
||||
else:
|
||||
try:
|
||||
self.__lock.acquire()
|
||||
for template in self.__templates:
|
||||
match = template.matchDate(line)
|
||||
if not match == None:
|
||||
return match
|
||||
return None
|
||||
finally:
|
||||
self.__lock.release()
|
||||
self.__lock.acquire()
|
||||
try:
|
||||
for template in self.__templates:
|
||||
match = template.matchDate(line)
|
||||
if not match == None:
|
||||
return match
|
||||
return None
|
||||
finally:
|
||||
self.__lock.release()
|
||||
|
||||
def getTime(self, line):
|
||||
if self.__defTemplate.isValid():
|
||||
try:
|
||||
date = self.__defTemplate.getDate(line)
|
||||
return date
|
||||
except ValueError:
|
||||
return None
|
||||
else:
|
||||
try:
|
||||
self.__lock.acquire()
|
||||
for template in self.__templates:
|
||||
try:
|
||||
date = template.getDate(line)
|
||||
if date == None:
|
||||
continue
|
||||
template.incHits()
|
||||
return date
|
||||
except ValueError:
|
||||
pass
|
||||
return None
|
||||
finally:
|
||||
self.__lock.release()
|
||||
self.__lock.acquire()
|
||||
try:
|
||||
for template in self.__templates:
|
||||
try:
|
||||
date = template.getDate(line)
|
||||
if date == None:
|
||||
continue
|
||||
return date
|
||||
except ValueError:
|
||||
pass
|
||||
return None
|
||||
finally:
|
||||
self.__lock.release()
|
||||
|
||||
def getUnixTime(self, line):
|
||||
date = self.getTime(line)
|
||||
|
@ -161,11 +137,10 @@ class DateDetector:
|
|||
# in this object and thus should be called from time to time.
|
||||
|
||||
def sortTemplate(self):
|
||||
self.__lock.acquire()
|
||||
try:
|
||||
self.__lock.acquire()
|
||||
logSys.debug("Sorting the template list")
|
||||
self.__templates.sort(cmp = lambda x, y:
|
||||
cmp(x.getHits(), y.getHits()),
|
||||
reverse = True)
|
||||
self.__templates.sort(lambda x, y: cmp(x.getHits(), y.getHits()))
|
||||
self.__templates.reverse()
|
||||
finally:
|
||||
self.__lock.release()
|
||||
|
|
|
@ -1,44 +0,0 @@
|
|||
# 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: 504 $
|
||||
|
||||
__author__ = "Cyril Jaquier"
|
||||
__version__ = "$Revision: 504 $"
|
||||
__date__ = "$Date: 2006-12-23 17:37:17 +0100 (Sat, 23 Dec 2006) $"
|
||||
__copyright__ = "Copyright (c) 2004 Cyril Jaquier"
|
||||
__license__ = "GPL"
|
||||
|
||||
import 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
|
|
@ -1,91 +0,0 @@
|
|||
# -*- coding: utf8 -*-
|
||||
# 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: 504 $
|
||||
|
||||
__author__ = "Cyril Jaquier"
|
||||
__version__ = "$Revision: 504 $"
|
||||
__date__ = "$Date: 2006-12-23 17:37:17 +0100 (Sat, 23 Dec 2006) $"
|
||||
__copyright__ = "Copyright (c) 2004 Cyril Jaquier"
|
||||
__license__ = "GPL"
|
||||
|
||||
from mytime import MyTime
|
||||
import time
|
||||
|
||||
from datetemplate import DateTemplate
|
||||
|
||||
##
|
||||
# Use strptime() to parse a date. Our current locale is the 'C'
|
||||
# one because we do not set the locale explicitly. This is POSIX
|
||||
# standard.
|
||||
|
||||
class DateStrptime(DateTemplate):
|
||||
|
||||
TABLE = dict()
|
||||
TABLE["Jan"] = []
|
||||
TABLE["Feb"] = [u"Fév"]
|
||||
TABLE["Mar"] = [u"Mär"]
|
||||
TABLE["Apr"] = ["Avr"]
|
||||
TABLE["May"] = ["Mai"]
|
||||
TABLE["Jun"] = []
|
||||
TABLE["Jul"] = []
|
||||
TABLE["Aug"] = ["Aou"]
|
||||
TABLE["Sep"] = []
|
||||
TABLE["Oct"] = ["Okt"]
|
||||
TABLE["Nov"] = []
|
||||
TABLE["Dec"] = [u"Déc", "Dez"]
|
||||
|
||||
def __init__(self):
|
||||
DateTemplate.__init__(self)
|
||||
|
||||
@staticmethod
|
||||
def convertLocale(date):
|
||||
for t in DateStrptime.TABLE:
|
||||
for m in DateStrptime.TABLE[t]:
|
||||
if date.find(m) >= 0:
|
||||
return date.replace(m, t)
|
||||
return date
|
||||
|
||||
def getDate(self, line):
|
||||
date = None
|
||||
dateMatch = self.matchDate(line)
|
||||
if dateMatch:
|
||||
try:
|
||||
# Try first with 'C' locale
|
||||
date = list(time.strptime(dateMatch.group(), self.getPattern()))
|
||||
except ValueError:
|
||||
# Try to convert date string to 'C' locale
|
||||
conv = self.convertLocale(dateMatch.group())
|
||||
try:
|
||||
date = list(time.strptime(conv, self.getPattern()))
|
||||
except ValueError:
|
||||
# Try to add the current year to the pattern. Should fix
|
||||
# the "Feb 29" issue.
|
||||
conv += " %s" % MyTime.gmtime()[0]
|
||||
pattern = "%s %%Y" % self.getPattern()
|
||||
date = list(time.strptime(conv, pattern))
|
||||
if date[0] < 2000:
|
||||
# There is probably no year field in the logs
|
||||
date[0] = MyTime.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) > MyTime.time():
|
||||
date[0] -= 1
|
||||
return date
|
|
@ -1,46 +0,0 @@
|
|||
# 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: 504 $
|
||||
|
||||
__author__ = "Cyril Jaquier"
|
||||
__version__ = "$Revision: 504 $"
|
||||
__date__ = "$Date: 2006-12-23 17:37:17 +0100 (Sat, 23 Dec 2006) $"
|
||||
__copyright__ = "Copyright (c) 2004 Cyril Jaquier"
|
||||
__license__ = "GPL"
|
||||
|
||||
import 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
|
|
@ -1,3 +1,4 @@
|
|||
# -*- coding: utf8 -*-
|
||||
# This file is part of Fail2Ban.
|
||||
#
|
||||
# Fail2Ban is free software; you can redistribute it and/or modify
|
||||
|
@ -16,15 +17,17 @@
|
|||
|
||||
# Author: Cyril Jaquier
|
||||
#
|
||||
# $Revision: 504 $
|
||||
# $Revision: 652 $
|
||||
|
||||
__author__ = "Cyril Jaquier"
|
||||
__version__ = "$Revision: 504 $"
|
||||
__date__ = "$Date: 2006-12-23 17:37:17 +0100 (Sat, 23 Dec 2006) $"
|
||||
__version__ = "$Revision: 652 $"
|
||||
__date__ = "$Date: 2008-02-29 00:01:30 +0100 (Fri, 29 Feb 2008) $"
|
||||
__copyright__ = "Copyright (c) 2004 Cyril Jaquier"
|
||||
__license__ = "GPL"
|
||||
|
||||
import re
|
||||
import re, time
|
||||
|
||||
from mytime import MyTime
|
||||
|
||||
class DateTemplate:
|
||||
|
||||
|
@ -32,7 +35,6 @@ class DateTemplate:
|
|||
self.__name = ""
|
||||
self.__regex = ""
|
||||
self.__cRegex = None
|
||||
self.__pattern = ""
|
||||
self.__hits = 0
|
||||
|
||||
def setName(self, name):
|
||||
|
@ -48,24 +50,117 @@ class DateTemplate:
|
|||
def getRegex(self):
|
||||
return self.__regex
|
||||
|
||||
def getHits(self):
|
||||
return self.__hits
|
||||
|
||||
def matchDate(self, line):
|
||||
dateMatch = self.__cRegex.search(line)
|
||||
if not dateMatch == None:
|
||||
self.__hits += 1
|
||||
return dateMatch
|
||||
|
||||
def getDate(self, line):
|
||||
raise Exception("matchDate() is abstract")
|
||||
|
||||
|
||||
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.localtime(float(dateMatch.group())))
|
||||
return date
|
||||
|
||||
|
||||
##
|
||||
# Use strptime() to parse a date. Our current locale is the 'C'
|
||||
# one because we do not set the locale explicitly. This is POSIX
|
||||
# standard.
|
||||
|
||||
class DateStrptime(DateTemplate):
|
||||
|
||||
TABLE = dict()
|
||||
TABLE["Jan"] = []
|
||||
TABLE["Feb"] = [u"Fév"]
|
||||
TABLE["Mar"] = [u"Mär"]
|
||||
TABLE["Apr"] = ["Avr"]
|
||||
TABLE["May"] = ["Mai"]
|
||||
TABLE["Jun"] = []
|
||||
TABLE["Jul"] = []
|
||||
TABLE["Aug"] = ["Aou"]
|
||||
TABLE["Sep"] = []
|
||||
TABLE["Oct"] = ["Okt"]
|
||||
TABLE["Nov"] = []
|
||||
TABLE["Dec"] = [u"Déc", "Dez"]
|
||||
|
||||
def __init__(self):
|
||||
DateTemplate.__init__(self)
|
||||
self.__pattern = ""
|
||||
|
||||
def setPattern(self, pattern):
|
||||
self.__pattern = pattern.strip()
|
||||
|
||||
def getPattern(self):
|
||||
return self.__pattern
|
||||
|
||||
def isValid(self):
|
||||
return self.__regex != "" and self.__pattern != ""
|
||||
|
||||
def incHits(self):
|
||||
self.__hits = self.__hits + 1
|
||||
|
||||
def getHits(self):
|
||||
return self.__hits
|
||||
|
||||
def matchDate(self, line):
|
||||
dateMatch = self.__cRegex.search(line)
|
||||
return dateMatch
|
||||
#@staticmethod
|
||||
def convertLocale(date):
|
||||
for t in DateStrptime.TABLE:
|
||||
for m in DateStrptime.TABLE[t]:
|
||||
if date.find(m) >= 0:
|
||||
return date.replace(m, t)
|
||||
return date
|
||||
convertLocale = staticmethod(convertLocale)
|
||||
|
||||
def getDate(self, line):
|
||||
raise Exception("matchDate() is abstract")
|
||||
date = None
|
||||
dateMatch = self.matchDate(line)
|
||||
if dateMatch:
|
||||
try:
|
||||
# Try first with 'C' locale
|
||||
date = list(time.strptime(dateMatch.group(), self.getPattern()))
|
||||
except ValueError:
|
||||
# Try to convert date string to 'C' locale
|
||||
conv = self.convertLocale(dateMatch.group())
|
||||
try:
|
||||
date = list(time.strptime(conv, self.getPattern()))
|
||||
except ValueError:
|
||||
# Try to add the current year to the pattern. Should fix
|
||||
# the "Feb 29" issue.
|
||||
conv += " %s" % MyTime.gmtime()[0]
|
||||
pattern = "%s %%Y" % self.getPattern()
|
||||
date = list(time.strptime(conv, pattern))
|
||||
if date[0] < 2000:
|
||||
# There is probably no year field in the logs
|
||||
date[0] = MyTime.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) > MyTime.time():
|
||||
date[0] -= 1
|
||||
return date
|
||||
|
||||
|
||||
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
|
|
@ -16,16 +16,16 @@
|
|||
|
||||
# Author: Cyril Jaquier
|
||||
#
|
||||
# $Revision: 553 $
|
||||
# $Revision: 638 $
|
||||
|
||||
__author__ = "Cyril Jaquier"
|
||||
__version__ = "$Revision: 553 $"
|
||||
__date__ = "$Date: 2007-02-26 00:53:22 +0100 (Mon, 26 Feb 2007) $"
|
||||
__version__ = "$Revision: 638 $"
|
||||
__date__ = "$Date: 2007-12-17 21:00:36 +0100 (Mon, 17 Dec 2007) $"
|
||||
__copyright__ = "Copyright (c) 2004 Cyril Jaquier"
|
||||
__license__ = "GPL"
|
||||
|
||||
from faildata import FailData
|
||||
from failticket import FailTicket
|
||||
from ticket import FailTicket
|
||||
from threading import Lock
|
||||
import logging
|
||||
|
||||
|
|
|
@ -16,15 +16,82 @@
|
|||
|
||||
# Author: Cyril Jaquier
|
||||
#
|
||||
# $Revision: 589 $
|
||||
# $Revision: 642 $
|
||||
|
||||
__author__ = "Cyril Jaquier"
|
||||
__version__ = "$Revision: 589 $"
|
||||
__date__ = "$Date: 2007-06-25 23:43:25 +0200 (Mon, 25 Jun 2007) $"
|
||||
__version__ = "$Revision: 642 $"
|
||||
__date__ = "$Date: 2008-01-05 23:33:44 +0100 (Sat, 05 Jan 2008) $"
|
||||
__copyright__ = "Copyright (c) 2004 Cyril Jaquier"
|
||||
__license__ = "GPL"
|
||||
|
||||
from regex import Regex, RegexException
|
||||
import re, sre_constants
|
||||
|
||||
##
|
||||
# Regular expression class.
|
||||
#
|
||||
# This class represents a regular expression with its compiled version.
|
||||
|
||||
class Regex:
|
||||
|
||||
##
|
||||
# Constructor.
|
||||
#
|
||||
# Creates a new object. This method can throw RegexException in order to
|
||||
# avoid construction of invalid object.
|
||||
# @param value the regular expression
|
||||
|
||||
def __init__(self, regex):
|
||||
self._matchCache = None
|
||||
# Perform shortcuts expansions.
|
||||
# Replace "<HOST>" with default regular expression for host.
|
||||
regex = regex.replace("<HOST>", "(?:::f{4,6}:)?(?P<host>\S+)")
|
||||
if regex.lstrip() == '':
|
||||
raise RegexException("Cannot add empty regex")
|
||||
try:
|
||||
self._regexObj = re.compile(regex)
|
||||
self._regex = regex
|
||||
except sre_constants.error:
|
||||
raise RegexException("Unable to compile regular expression '%s'" %
|
||||
regex)
|
||||
|
||||
##
|
||||
# Gets the regular expression.
|
||||
#
|
||||
# The effective regular expression used is returned.
|
||||
# @return the regular expression
|
||||
|
||||
def getRegex(self):
|
||||
return self._regex
|
||||
|
||||
##
|
||||
# Searches the regular expression.
|
||||
#
|
||||
# Sets an internal cache (match object) in order to avoid searching for
|
||||
# the pattern again. This method must be called before calling any other
|
||||
# method of this object.
|
||||
# @param value the line
|
||||
|
||||
def search(self, value):
|
||||
self._matchCache = self._regexObj.search(value)
|
||||
|
||||
##
|
||||
# Checks if the previous call to search() matched.
|
||||
#
|
||||
# @return True if a match was found, False otherwise
|
||||
|
||||
def hasMatched(self):
|
||||
if self._matchCache:
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
|
||||
##
|
||||
# Exception dedicated to the class Regex.
|
||||
|
||||
class RegexException(Exception):
|
||||
pass
|
||||
|
||||
|
||||
##
|
||||
# Regular expression class.
|
||||
|
@ -56,5 +123,8 @@ class FailRegex(Regex):
|
|||
def getHost(self):
|
||||
host = self._matchCache.group("host")
|
||||
if host == None:
|
||||
raise RegexException("Unexpected error. Please check your regex")
|
||||
# Gets a few information.
|
||||
s = self._matchCache.string
|
||||
r = self._matchCache.re
|
||||
raise RegexException("No 'host' found in '%s' using '%s'" % (s, r))
|
||||
return host
|
||||
|
|
|
@ -1,37 +0,0 @@
|
|||
# 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: 382 $
|
||||
|
||||
__author__ = "Cyril Jaquier"
|
||||
__version__ = "$Revision: 382 $"
|
||||
__date__ = "$Date: 2006-09-25 19:03:48 +0200 (Mon, 25 Sep 2006) $"
|
||||
__copyright__ = "Copyright (c) 2004 Cyril Jaquier"
|
||||
__license__ = "GPL"
|
||||
|
||||
import logging
|
||||
from ticket import Ticket
|
||||
|
||||
# Gets the instance of the logger.
|
||||
logSys = logging.getLogger("fail2ban")
|
||||
|
||||
class FailTicket(Ticket):
|
||||
|
||||
def __init__(self, ip, time):
|
||||
Ticket.__init__(self, ip, time)
|
||||
|
403
server/filter.py
403
server/filter.py
|
@ -16,21 +16,20 @@
|
|||
|
||||
# Author: Cyril Jaquier
|
||||
#
|
||||
# $Revision: 605 $
|
||||
# $Revision: 656 $
|
||||
|
||||
__author__ = "Cyril Jaquier"
|
||||
__version__ = "$Revision: 605 $"
|
||||
__date__ = "$Date: 2007-08-08 00:11:34 +0200 (Wed, 08 Aug 2007) $"
|
||||
__version__ = "$Revision: 656 $"
|
||||
__date__ = "$Date: 2008-03-04 01:17:56 +0100 (Tue, 04 Mar 2008) $"
|
||||
__copyright__ = "Copyright (c) 2004 Cyril Jaquier"
|
||||
__license__ = "GPL"
|
||||
|
||||
from failmanager import FailManager
|
||||
from failticket import FailTicket
|
||||
from ticket import FailTicket
|
||||
from jailthread import JailThread
|
||||
from datedetector import DateDetector
|
||||
from mytime import MyTime
|
||||
from regex import Regex, RegexException
|
||||
from failregex import FailRegex
|
||||
from failregex import FailRegex, Regex, RegexException
|
||||
|
||||
import logging, re
|
||||
|
||||
|
@ -58,11 +57,6 @@ class Filter(JailThread):
|
|||
self.jail = jail
|
||||
## The failures manager.
|
||||
self.failManager = FailManager()
|
||||
## The log file handler.
|
||||
self.__crtHandler = None
|
||||
self.__crtFilename = None
|
||||
## The log file path.
|
||||
self.__logPath = []
|
||||
## The regular expression list matching the failures.
|
||||
self.__failRegex = list()
|
||||
## The regular expression list with expressions to ignore.
|
||||
|
@ -71,92 +65,12 @@ class Filter(JailThread):
|
|||
self.__findTime = 6000
|
||||
## The ignore IP list.
|
||||
self.__ignoreIpList = []
|
||||
## The last position of the file.
|
||||
self.__lastPos = dict()
|
||||
## The last date in tht log file.
|
||||
self.__lastDate = dict()
|
||||
|
||||
self.dateDetector = DateDetector()
|
||||
self.dateDetector.addDefaultTemplate()
|
||||
logSys.info("Created Filter")
|
||||
|
||||
|
||||
##
|
||||
# Add a log file path
|
||||
#
|
||||
# @param path log file path
|
||||
|
||||
def addLogPath(self, path):
|
||||
self.getLogPath().append(path)
|
||||
# Initialize default values
|
||||
self.__lastDate[path] = 0
|
||||
self.__lastPos[path] = 0
|
||||
|
||||
##
|
||||
# Delete a log path
|
||||
#
|
||||
# @param path the log file to delete
|
||||
|
||||
def delLogPath(self, path):
|
||||
self.getLogPath().remove(path)
|
||||
del self.__lastDate[path]
|
||||
del self.__lastPos[path]
|
||||
|
||||
##
|
||||
# Get the log file path
|
||||
#
|
||||
# @return log file path
|
||||
|
||||
def getLogPath(self):
|
||||
return self.__logPath
|
||||
|
||||
##
|
||||
# Check whether path is already monitored.
|
||||
#
|
||||
# @param path The path
|
||||
# @return True if the path is already monitored else False
|
||||
|
||||
def containsLogPath(self, path):
|
||||
try:
|
||||
self.getLogPath().index(path)
|
||||
return True
|
||||
except ValueError:
|
||||
return False
|
||||
|
||||
##
|
||||
# Set the regular expression which matches the time.
|
||||
#
|
||||
# @param value the regular expression
|
||||
|
||||
def setTimeRegex(self, value):
|
||||
self.dateDetector.setDefaultRegex(value)
|
||||
logSys.info("Set default regex = %s" % value)
|
||||
|
||||
##
|
||||
# Get the regular expression which matches the time.
|
||||
#
|
||||
# @return the regular expression
|
||||
|
||||
def getTimeRegex(self):
|
||||
return self.dateDetector.getDefaultRegex()
|
||||
|
||||
##
|
||||
# Set the time pattern.
|
||||
#
|
||||
# @param value the time pattern
|
||||
|
||||
def setTimePattern(self, value):
|
||||
self.dateDetector.setDefaultPattern(value)
|
||||
logSys.info("Set default pattern = %s" % value)
|
||||
|
||||
##
|
||||
# Get the time pattern.
|
||||
#
|
||||
# @return the time pattern
|
||||
|
||||
def getTimePattern(self):
|
||||
return self.dateDetector.getDefaultPattern()
|
||||
|
||||
##
|
||||
# Add a regular expression which matches the failure.
|
||||
#
|
||||
|
@ -299,7 +213,7 @@ class Filter(JailThread):
|
|||
for i in self.__ignoreIpList:
|
||||
# An empty string is always false
|
||||
if i == "":
|
||||
return False
|
||||
continue
|
||||
s = i.split('/', 1)
|
||||
# IP address without CIDR mask
|
||||
if len(s) == 1:
|
||||
|
@ -314,104 +228,41 @@ class Filter(JailThread):
|
|||
if ip in ips:
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
continue
|
||||
if a == b:
|
||||
return True
|
||||
return False
|
||||
|
||||
##
|
||||
# Open the log file.
|
||||
|
||||
def __openLogFile(self, filename):
|
||||
""" Opens the log file specified on init.
|
||||
"""
|
||||
|
||||
def processLine(self, line):
|
||||
try:
|
||||
self.__crtFilename = filename
|
||||
self.__crtHandler = open(filename)
|
||||
logSys.debug("Opened " + filename)
|
||||
return True
|
||||
except OSError:
|
||||
logSys.error("Unable to open " + filename)
|
||||
except IOError:
|
||||
logSys.error("Unable to read " + filename +
|
||||
". Please check permissions")
|
||||
return False
|
||||
|
||||
##
|
||||
# Close the log file.
|
||||
|
||||
def __closeLogFile(self):
|
||||
self.__crtFilename = None
|
||||
self.__crtHandler.close()
|
||||
# Decode line to UTF-8
|
||||
l = line.decode('utf-8')
|
||||
except UnicodeDecodeError:
|
||||
l = line
|
||||
timeMatch = self.dateDetector.matchTime(l)
|
||||
if not timeMatch:
|
||||
# There is no valid time in this line
|
||||
return []
|
||||
# Lets split into time part and log part of the line
|
||||
timeLine = timeMatch.group()
|
||||
# Lets leave the beginning in as well, so if there is no
|
||||
# anchore at the beginning of the time regexp, we don't
|
||||
# at least allow injection. Should be harmless otherwise
|
||||
logLine = l[:timeMatch.start()] + l[timeMatch.end():]
|
||||
return self.findFailure(timeLine, logLine)
|
||||
|
||||
##
|
||||
# Set the file position.
|
||||
#
|
||||
# Sets the file position. We must take care of log file rotation
|
||||
# and reset the position to 0 in that case. Use the log message
|
||||
# timestamp in order to detect this.
|
||||
|
||||
def __setFilePos(self):
|
||||
line = self.__crtHandler.readline()
|
||||
lastDate = self.__lastDate[self.__crtFilename]
|
||||
lineDate = self.dateDetector.getUnixTime(line)
|
||||
if lastDate < lineDate:
|
||||
logSys.debug("Date " + `lastDate` + " is smaller than " + `lineDate`)
|
||||
logSys.debug("Log rotation detected for " + self.__crtFilename)
|
||||
self.__lastPos[self.__crtFilename] = 0
|
||||
lastPos = self.__lastPos[self.__crtFilename]
|
||||
logSys.debug("Setting file position to " + `lastPos` + " for " +
|
||||
self.__crtFilename)
|
||||
self.__crtHandler.seek(lastPos)
|
||||
|
||||
##
|
||||
# Get the file position.
|
||||
|
||||
def __getFilePos(self):
|
||||
return self.__crtHandler.tell()
|
||||
|
||||
##
|
||||
# Gets all the failure in the log file.
|
||||
#
|
||||
# Gets all the failure in the log file which are newer than
|
||||
# MyTime.time()-self.findTime. When a failure is detected, a FailTicket
|
||||
# is created and is added to the FailManager.
|
||||
|
||||
def getFailures(self, filename):
|
||||
# Try to open log file.
|
||||
if not self.__openLogFile(filename):
|
||||
logSys.error("Unable to get failures in " + filename)
|
||||
return False
|
||||
self.__setFilePos()
|
||||
lastLine = None
|
||||
for line in self.__crtHandler:
|
||||
if not self._isActive():
|
||||
# The jail has been stopped
|
||||
def processLineAndAdd(self, line):
|
||||
for element in self.processLine(line):
|
||||
ip = element[0]
|
||||
unixTime = element[1]
|
||||
if unixTime < MyTime.time() - self.getFindTime():
|
||||
break
|
||||
try:
|
||||
# Decode line to UTF-8
|
||||
line = line.decode('utf-8')
|
||||
except UnicodeDecodeError:
|
||||
pass
|
||||
if not self.dateDetector.matchTime(line):
|
||||
# There is no valid time in this line
|
||||
if self.inIgnoreIPList(ip):
|
||||
logSys.debug("Ignore %s" % ip)
|
||||
continue
|
||||
lastLine = line
|
||||
for element in self.findFailure(line):
|
||||
ip = element[0]
|
||||
unixTime = element[1]
|
||||
if unixTime < MyTime.time()-self.__findTime:
|
||||
break
|
||||
if self.inIgnoreIPList(ip):
|
||||
logSys.debug("Ignore "+ip)
|
||||
continue
|
||||
logSys.debug("Found "+ip)
|
||||
self.failManager.addFailure(FailTicket(ip, unixTime))
|
||||
self.__lastPos[filename] = self.__getFilePos()
|
||||
if lastLine:
|
||||
self.__lastDate[filename] = self.dateDetector.getUnixTime(lastLine)
|
||||
self.__closeLogFile()
|
||||
return True
|
||||
logSys.debug("Found %s" % ip)
|
||||
self.failManager.addFailure(FailTicket(ip, unixTime))
|
||||
|
||||
##
|
||||
# Returns true if the line should be ignored.
|
||||
|
@ -428,27 +279,28 @@ class Filter(JailThread):
|
|||
return False
|
||||
|
||||
##
|
||||
# Finds the failure in a line.
|
||||
# Finds the failure in a line given split into time and log parts.
|
||||
#
|
||||
# Uses the failregex pattern to find it and timeregex in order
|
||||
# to find the logging time.
|
||||
# @return a dict with IP and timestamp.
|
||||
|
||||
def findFailure(self, line):
|
||||
def findFailure(self, timeLine, logLine):
|
||||
failList = list()
|
||||
# Checks if we must ignore this line.
|
||||
if self.ignoreLine(line):
|
||||
if self.ignoreLine(logLine):
|
||||
# The ignoreregex matched. Return.
|
||||
return failList
|
||||
# Iterates over all the regular expressions.
|
||||
for failRegex in self.__failRegex:
|
||||
failRegex.search(line)
|
||||
failRegex.search(logLine)
|
||||
if failRegex.hasMatched():
|
||||
# The failregex matched.
|
||||
date = self.dateDetector.getUnixTime(line)
|
||||
date = self.dateDetector.getUnixTime(timeLine)
|
||||
if date == None:
|
||||
logSys.debug("Found a match but no valid date/time found "
|
||||
+ "for " + line + ". Please contact the "
|
||||
logSys.debug("Found a match for '" + logLine +"' but no "
|
||||
+ "valid date/time found for '"
|
||||
+ timeLine + "'. Please contact the "
|
||||
+ "author in order to get support for this "
|
||||
+ "format")
|
||||
else:
|
||||
|
@ -478,6 +330,157 @@ class Filter(JailThread):
|
|||
return ret
|
||||
|
||||
|
||||
class FileFilter(Filter):
|
||||
|
||||
def __init__(self, jail):
|
||||
Filter.__init__(self, jail)
|
||||
## The log file path.
|
||||
self.__logPath = []
|
||||
|
||||
##
|
||||
# Add a log file path
|
||||
#
|
||||
# @param path log file path
|
||||
|
||||
def addLogPath(self, path, tail = False):
|
||||
container = FileContainer(path, tail)
|
||||
self.__logPath.append(container)
|
||||
|
||||
##
|
||||
# Delete a log path
|
||||
#
|
||||
# @param path the log file to delete
|
||||
|
||||
def delLogPath(self, path):
|
||||
for log in self.__logPath:
|
||||
if log.getFileName() == path:
|
||||
self.__logPath.remove(log)
|
||||
return
|
||||
|
||||
##
|
||||
# Get the log file path
|
||||
#
|
||||
# @return log file path
|
||||
|
||||
def getLogPath(self):
|
||||
return self.__logPath
|
||||
|
||||
##
|
||||
# Check whether path is already monitored.
|
||||
#
|
||||
# @param path The path
|
||||
# @return True if the path is already monitored else False
|
||||
|
||||
def containsLogPath(self, path):
|
||||
for log in self.__logPath:
|
||||
if log.getFileName() == path:
|
||||
return True
|
||||
return False
|
||||
|
||||
def getFileContainer(self, path):
|
||||
for log in self.__logPath:
|
||||
if log.getFileName() == path:
|
||||
return log
|
||||
return None
|
||||
|
||||
##
|
||||
# Gets all the failure in the log file.
|
||||
#
|
||||
# Gets all the failure in the log file which are newer than
|
||||
# MyTime.time()-self.findTime. When a failure is detected, a FailTicket
|
||||
# is created and is added to the FailManager.
|
||||
|
||||
def getFailures(self, filename):
|
||||
container = self.getFileContainer(filename)
|
||||
if container == None:
|
||||
logSys.error("Unable to get failures in " + filename)
|
||||
return False
|
||||
# Try to open log file.
|
||||
try:
|
||||
container.open()
|
||||
except Exception, e:
|
||||
logSys.error("Unable to open %s" % filename)
|
||||
logSys.exception(e)
|
||||
return False
|
||||
|
||||
line = container.readline()
|
||||
while not line == "":
|
||||
if not self._isActive():
|
||||
# The jail has been stopped
|
||||
break
|
||||
self.processLineAndAdd(line)
|
||||
# Read a new line.
|
||||
line = container.readline()
|
||||
container.close()
|
||||
return True
|
||||
|
||||
def status(self):
|
||||
ret = Filter.status(self)
|
||||
path = [m.getFileName() for m in self.getLogPath()]
|
||||
ret.append(("File list", path))
|
||||
return ret
|
||||
|
||||
##
|
||||
# FileContainer class.
|
||||
#
|
||||
# This class manages a file handler and takes care of log rotation detection.
|
||||
# In order to detect log rotation, the hash (MD5) of the first line of the file
|
||||
# is computed and compared to the previous hash of this line.
|
||||
|
||||
import md5
|
||||
|
||||
class FileContainer:
|
||||
|
||||
def __init__(self, filename, tail = False):
|
||||
self.__filename = filename
|
||||
self.__tail = tail
|
||||
self.__handler = None
|
||||
# Try to open the file. Raises an exception if an error occured.
|
||||
handler = open(filename)
|
||||
try:
|
||||
firstLine = handler.readline()
|
||||
# Computes the MD5 of the first line.
|
||||
self.__hash = md5.new(firstLine).digest()
|
||||
# Start at the beginning of file if tail mode is off.
|
||||
if tail:
|
||||
handler.seek(0, 2)
|
||||
self.__pos = handler.tell()
|
||||
else:
|
||||
self.__pos = 0
|
||||
finally:
|
||||
handler.close()
|
||||
|
||||
def getFileName(self):
|
||||
return self.__filename
|
||||
|
||||
def open(self):
|
||||
self.__handler = open(self.__filename)
|
||||
firstLine = self.__handler.readline()
|
||||
# Computes the MD5 of the first line.
|
||||
myHash = md5.new(firstLine).digest()
|
||||
# Compare hash.
|
||||
if not self.__hash == myHash:
|
||||
logSys.info("Log rotation detected for %s" % self.__filename)
|
||||
self.__hash = myHash
|
||||
self.__pos = 0
|
||||
# Sets the file pointer to the last position.
|
||||
self.__handler.seek(self.__pos)
|
||||
|
||||
def readline(self):
|
||||
if self.__handler == None:
|
||||
return ""
|
||||
return self.__handler.readline()
|
||||
|
||||
def close(self):
|
||||
if not self.__handler == None:
|
||||
# Saves the last position.
|
||||
self.__pos = self.__handler.tell()
|
||||
# Closes the file.
|
||||
self.__handler.close()
|
||||
self.__handler = None
|
||||
|
||||
|
||||
|
||||
##
|
||||
# Utils class for DNS and IP handling.
|
||||
#
|
||||
|
@ -488,10 +491,9 @@ import socket, struct
|
|||
|
||||
class DNSUtils:
|
||||
|
||||
DNS_CRE = re.compile("(?:(?:\w|-)+\.){2,}\w+")
|
||||
IP_CRE = re.compile("(?:\d{1,3}\.){3}\d{1,3}")
|
||||
|
||||
@staticmethod
|
||||
#@staticmethod
|
||||
def dnsToIp(dns):
|
||||
""" Convert a DNS into an IP address using the Python socket module.
|
||||
Thanks to Kevin Drapel.
|
||||
|
@ -502,8 +504,9 @@ class DNSUtils:
|
|||
logSys.warn("Unable to find a corresponding IP address for %s"
|
||||
% dns)
|
||||
return list()
|
||||
dnsToIp = staticmethod(dnsToIp)
|
||||
|
||||
@staticmethod
|
||||
#@staticmethod
|
||||
def searchIP(text):
|
||||
""" Search if an IP address if directly available and return
|
||||
it.
|
||||
|
@ -513,8 +516,9 @@ class DNSUtils:
|
|||
return match
|
||||
else:
|
||||
return None
|
||||
searchIP = staticmethod(searchIP)
|
||||
|
||||
@staticmethod
|
||||
#@staticmethod
|
||||
def isValidIP(string):
|
||||
""" Return true if str is a valid IP
|
||||
"""
|
||||
|
@ -524,8 +528,9 @@ class DNSUtils:
|
|||
return True
|
||||
except socket.error:
|
||||
return False
|
||||
isValidIP = staticmethod(isValidIP)
|
||||
|
||||
@staticmethod
|
||||
#@staticmethod
|
||||
def textToIp(text):
|
||||
""" Return the IP of DNS found in a given text.
|
||||
"""
|
||||
|
@ -542,8 +547,9 @@ class DNSUtils:
|
|||
for e in ip:
|
||||
ipList.append(e)
|
||||
return ipList
|
||||
textToIp = staticmethod(textToIp)
|
||||
|
||||
@staticmethod
|
||||
#@staticmethod
|
||||
def cidr(i, n):
|
||||
""" Convert an IP address string with a CIDR mask into a 32-bit
|
||||
integer.
|
||||
|
@ -551,15 +557,18 @@ class DNSUtils:
|
|||
# 32-bit IPv4 address mask
|
||||
MASK = 0xFFFFFFFFL
|
||||
return ~(MASK >> n) & MASK & DNSUtils.addr2bin(i)
|
||||
cidr = staticmethod(cidr)
|
||||
|
||||
@staticmethod
|
||||
#@staticmethod
|
||||
def addr2bin(string):
|
||||
""" Convert a string IPv4 address into an unsigned integer.
|
||||
"""
|
||||
return struct.unpack("!L", socket.inet_aton(string))[0]
|
||||
addr2bin = staticmethod(addr2bin)
|
||||
|
||||
@staticmethod
|
||||
#@staticmethod
|
||||
def bin2addr(addr):
|
||||
""" Convert a numeric IPv4 address into string n.n.n.n form.
|
||||
"""
|
||||
return socket.inet_ntoa(struct.pack("!L", addr))
|
||||
bin2addr = staticmethod(bin2addr)
|
||||
|
|
|
@ -16,16 +16,16 @@
|
|||
|
||||
# Author: Cyril Jaquier
|
||||
#
|
||||
# $Revision: 567 $
|
||||
# $Revision: 649 $
|
||||
|
||||
__author__ = "Cyril Jaquier"
|
||||
__version__ = "$Revision: 567 $"
|
||||
__date__ = "$Date: 2007-03-26 23:17:31 +0200 (Mon, 26 Mar 2007) $"
|
||||
__version__ = "$Revision: 649 $"
|
||||
__date__ = "$Date: 2008-02-02 18:04:11 +0100 (Sat, 02 Feb 2008) $"
|
||||
__copyright__ = "Copyright (c) 2004 Cyril Jaquier"
|
||||
__license__ = "GPL"
|
||||
|
||||
from failmanager import FailManagerEmpty
|
||||
from filter import Filter
|
||||
from filter import FileFilter
|
||||
from mytime import MyTime
|
||||
|
||||
import time, logging, gamin
|
||||
|
@ -40,7 +40,7 @@ logSys = logging.getLogger("fail2ban.filter")
|
|||
# that matches a given regular expression. This class is instanciated by
|
||||
# a Jail object.
|
||||
|
||||
class FilterGamin(Filter):
|
||||
class FilterGamin(FileFilter):
|
||||
|
||||
##
|
||||
# Constructor.
|
||||
|
@ -49,7 +49,7 @@ class FilterGamin(Filter):
|
|||
# @param jail the jail object
|
||||
|
||||
def __init__(self, jail):
|
||||
Filter.__init__(self, jail)
|
||||
FileFilter.__init__(self, jail)
|
||||
self.__modified = False
|
||||
# Gamin monitor
|
||||
self.monitor = gamin.WatchMonitor()
|
||||
|
@ -69,12 +69,12 @@ class FilterGamin(Filter):
|
|||
#
|
||||
# @param path log file path
|
||||
|
||||
def addLogPath(self, path):
|
||||
def addLogPath(self, path, tail = False):
|
||||
if self.containsLogPath(path):
|
||||
logSys.error(path + " already exists")
|
||||
else:
|
||||
self.monitor.watch_file(path, self.callback)
|
||||
Filter.addLogPath(self, path)
|
||||
FileFilter.addLogPath(self, path, tail)
|
||||
logSys.info("Added logfile = %s" % path)
|
||||
|
||||
##
|
||||
|
@ -87,7 +87,7 @@ class FilterGamin(Filter):
|
|||
logSys.error(path + " is not monitored")
|
||||
else:
|
||||
self.monitor.stop_watch(path)
|
||||
Filter.delLogPath(self, path)
|
||||
FileFilter.delLogPath(self, path)
|
||||
logSys.info("Removed logfile = %s" % path)
|
||||
|
||||
##
|
||||
|
@ -126,6 +126,6 @@ class FilterGamin(Filter):
|
|||
# Desallocates the resources used by Gamin.
|
||||
|
||||
def __cleanup(self):
|
||||
for path in Filter.getLogPath(self):
|
||||
self.monitor.stop_watch(path)
|
||||
for path in self.getLogPath():
|
||||
self.monitor.stop_watch(path.getFileName())
|
||||
del self.monitor
|
||||
|
|
|
@ -16,16 +16,16 @@
|
|||
|
||||
# Author: Cyril Jaquier
|
||||
#
|
||||
# $Revision: 567 $
|
||||
# $Revision: 649 $
|
||||
|
||||
__author__ = "Cyril Jaquier"
|
||||
__version__ = "$Revision: 567 $"
|
||||
__date__ = "$Date: 2007-03-26 23:17:31 +0200 (Mon, 26 Mar 2007) $"
|
||||
__version__ = "$Revision: 649 $"
|
||||
__date__ = "$Date: 2008-02-02 18:04:11 +0100 (Sat, 02 Feb 2008) $"
|
||||
__copyright__ = "Copyright (c) 2004 Cyril Jaquier"
|
||||
__license__ = "GPL"
|
||||
|
||||
from failmanager import FailManagerEmpty
|
||||
from filter import Filter
|
||||
from filter import FileFilter
|
||||
from mytime import MyTime
|
||||
|
||||
import time, logging, os
|
||||
|
@ -40,7 +40,7 @@ logSys = logging.getLogger("fail2ban.filter")
|
|||
# that matches a given regular expression. This class is instanciated by
|
||||
# a Jail object.
|
||||
|
||||
class FilterPoll(Filter):
|
||||
class FilterPoll(FileFilter):
|
||||
|
||||
##
|
||||
# Constructor.
|
||||
|
@ -49,7 +49,7 @@ class FilterPoll(Filter):
|
|||
# @param jail the jail object
|
||||
|
||||
def __init__(self, jail):
|
||||
Filter.__init__(self, jail)
|
||||
FileFilter.__init__(self, jail)
|
||||
self.__modified = False
|
||||
## The time of the last modification of the file.
|
||||
self.__lastModTime = dict()
|
||||
|
@ -61,13 +61,13 @@ class FilterPoll(Filter):
|
|||
#
|
||||
# @param path log file path
|
||||
|
||||
def addLogPath(self, path):
|
||||
def addLogPath(self, path, tail = False):
|
||||
if self.containsLogPath(path):
|
||||
logSys.error(path + " already exists")
|
||||
else:
|
||||
self.__lastModTime[path] = 0
|
||||
self.__file404Cnt[path] = 0
|
||||
Filter.addLogPath(self, path)
|
||||
FileFilter.addLogPath(self, path, tail)
|
||||
logSys.info("Added logfile = %s" % path)
|
||||
|
||||
##
|
||||
|
@ -81,7 +81,7 @@ class FilterPoll(Filter):
|
|||
else:
|
||||
del self.__lastModTime[path]
|
||||
del self.__file404Cnt[path]
|
||||
Filter.delLogPath(self, path)
|
||||
FileFilter.delLogPath(self, path)
|
||||
logSys.info("Removed logfile = %s" % path)
|
||||
|
||||
##
|
||||
|
@ -96,9 +96,9 @@ class FilterPoll(Filter):
|
|||
while self._isActive():
|
||||
if not self.getIdle():
|
||||
# Get file modification
|
||||
for f in self.getLogPath():
|
||||
if self.isModified(f):
|
||||
self.getFailures(f)
|
||||
for container in self.getLogPath():
|
||||
if self.isModified(container.getFileName()):
|
||||
self.getFailures(container.getFileName())
|
||||
self.__modified = True
|
||||
|
||||
if self.__modified:
|
||||
|
|
|
@ -16,11 +16,11 @@
|
|||
|
||||
# Author: Cyril Jaquier
|
||||
#
|
||||
# $Revision: 556 $
|
||||
# $Revision: 635 $
|
||||
|
||||
__author__ = "Cyril Jaquier"
|
||||
__version__ = "$Revision: 556 $"
|
||||
__date__ = "$Date: 2007-03-07 21:54:32 +0100 (Wed, 07 Mar 2007) $"
|
||||
__version__ = "$Revision: 635 $"
|
||||
__date__ = "$Date: 2007-12-16 22:38:04 +0100 (Sun, 16 Dec 2007) $"
|
||||
__copyright__ = "Copyright (c) 2004 Cyril Jaquier"
|
||||
__license__ = "GPL"
|
||||
|
||||
|
@ -46,31 +46,34 @@ class MyTime:
|
|||
#
|
||||
# @param t the time to set or None
|
||||
|
||||
@staticmethod
|
||||
#@staticmethod
|
||||
def setTime(t):
|
||||
MyTime.myTime = t
|
||||
setTime = staticmethod(setTime)
|
||||
|
||||
##
|
||||
# Equivalent to time.time()
|
||||
#
|
||||
# @return time.time() if setTime was called with None
|
||||
|
||||
@staticmethod
|
||||
#@staticmethod
|
||||
def time():
|
||||
if MyTime.myTime == None:
|
||||
return time.time()
|
||||
else:
|
||||
return MyTime.myTime
|
||||
time = staticmethod(time)
|
||||
|
||||
##
|
||||
# Equivalent to time.gmtime()
|
||||
#
|
||||
# @return time.gmtime() if setTime was called with None
|
||||
|
||||
@staticmethod
|
||||
#@staticmethod
|
||||
def gmtime():
|
||||
if MyTime.myTime == None:
|
||||
return time.gmtime()
|
||||
else:
|
||||
return time.gmtime(MyTime.myTime)
|
||||
gmtime = staticmethod(gmtime)
|
||||
|
|
@ -1,93 +0,0 @@
|
|||
# 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: 589 $
|
||||
|
||||
__author__ = "Cyril Jaquier"
|
||||
__version__ = "$Revision: 589 $"
|
||||
__date__ = "$Date: 2007-06-25 23:43:25 +0200 (Mon, 25 Jun 2007) $"
|
||||
__copyright__ = "Copyright (c) 2004 Cyril Jaquier"
|
||||
__license__ = "GPL"
|
||||
|
||||
import re, sre_constants
|
||||
|
||||
##
|
||||
# Regular expression class.
|
||||
#
|
||||
# This class represents a regular expression with its compiled version.
|
||||
|
||||
class Regex:
|
||||
|
||||
##
|
||||
# Constructor.
|
||||
#
|
||||
# Creates a new object. This method can throw RegexException in order to
|
||||
# avoid construction of invalid object.
|
||||
# @param value the regular expression
|
||||
|
||||
def __init__(self, regex):
|
||||
self._matchCache = None
|
||||
# Perform shortcuts expansions.
|
||||
# Replace "<HOST>" with default regular expression for host.
|
||||
regex = regex.replace("<HOST>", "(?:::f{4,6}:)?(?P<host>\S+)")
|
||||
if regex.lstrip() == '':
|
||||
raise RegexException("Cannot add empty regex")
|
||||
try:
|
||||
self._regexObj = re.compile(regex)
|
||||
self._regex = regex
|
||||
except sre_constants.error:
|
||||
raise RegexException("Unable to compile regular expression '%s'" %
|
||||
regex)
|
||||
|
||||
##
|
||||
# Gets the regular expression.
|
||||
#
|
||||
# The effective regular expression used is returned.
|
||||
# @return the regular expression
|
||||
|
||||
def getRegex(self):
|
||||
return self._regex
|
||||
|
||||
##
|
||||
# Searches the regular expression.
|
||||
#
|
||||
# Sets an internal cache (match object) in order to avoid searching for
|
||||
# the pattern again. This method must be called before calling any other
|
||||
# method of this object.
|
||||
# @param value the line
|
||||
|
||||
def search(self, value):
|
||||
self._matchCache = self._regexObj.search(value)
|
||||
|
||||
##
|
||||
# Checks if the previous call to search() matched.
|
||||
#
|
||||
# @return True if a match was found, False otherwise
|
||||
|
||||
def hasMatched(self):
|
||||
if self._matchCache:
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
|
||||
##
|
||||
# Exception dedicated to the class Regex.
|
||||
|
||||
class RegexException(Exception):
|
||||
pass
|
|
@ -16,25 +16,28 @@
|
|||
|
||||
# Author: Cyril Jaquier
|
||||
#
|
||||
# $Revision: 567 $
|
||||
# $Revision: 647 $
|
||||
|
||||
__author__ = "Cyril Jaquier"
|
||||
__version__ = "$Revision: 567 $"
|
||||
__date__ = "$Date: 2007-03-26 23:17:31 +0200 (Mon, 26 Mar 2007) $"
|
||||
__version__ = "$Revision: 647 $"
|
||||
__date__ = "$Date: 2008-01-20 17:30:35 +0100 (Sun, 20 Jan 2008) $"
|
||||
__copyright__ = "Copyright (c) 2004 Cyril Jaquier"
|
||||
__license__ = "GPL"
|
||||
|
||||
from threading import Lock, RLock
|
||||
from jails import Jails
|
||||
from transmitter import Transmitter
|
||||
from communication.asyncserver import AsyncServer
|
||||
from communication.asyncserver import AsyncServerException
|
||||
from asyncserver import AsyncServer
|
||||
from asyncserver import AsyncServerException
|
||||
from common import version
|
||||
import logging, logging.handlers, sys, os, signal
|
||||
|
||||
# Gets the instance of the logger.
|
||||
logSys = logging.getLogger("fail2ban.server")
|
||||
|
||||
class Server:
|
||||
|
||||
PID_FILE = "/var/run/fail2ban/fail2ban.pid"
|
||||
|
||||
def __init__(self, daemon = False):
|
||||
self.__loggingLock = Lock()
|
||||
|
@ -54,7 +57,16 @@ class Server:
|
|||
self.quit()
|
||||
|
||||
def start(self, sock, force = False):
|
||||
logSys.info("Starting Fail2ban")
|
||||
logSys.info("Starting Fail2ban v" + version.version)
|
||||
|
||||
# Creates a PID file.
|
||||
try:
|
||||
logSys.debug("Creating PID file %s" % Server.PID_FILE)
|
||||
pidFile = open(Server.PID_FILE, 'w')
|
||||
pidFile.write("%s\n" % os.getpid())
|
||||
pidFile.close()
|
||||
except IOError, e:
|
||||
logSys.error("Unable to create PID file: %s" % e)
|
||||
|
||||
# Install signal handlers
|
||||
signal.signal(signal.SIGTERM, self.__sigTERMhandler)
|
||||
|
@ -73,14 +85,26 @@ class Server:
|
|||
logSys.debug("Starting communication")
|
||||
try:
|
||||
self.__asyncServer.start(sock, force)
|
||||
except AsyncServerException:
|
||||
logSys.error("Could not start server")
|
||||
except AsyncServerException, e:
|
||||
logSys.error("Could not start server: %s", e)
|
||||
# Removes the PID file.
|
||||
try:
|
||||
logSys.debug("Remove PID file %s" % Server.PID_FILE)
|
||||
os.remove(Server.PID_FILE)
|
||||
except OSError, e:
|
||||
logSys.error("Unable to remove PID file: %s" % e)
|
||||
logSys.info("Exiting Fail2ban")
|
||||
|
||||
def quit(self):
|
||||
self.stopAllJail()
|
||||
# Stop communication
|
||||
self.__asyncServer.stop()
|
||||
# Shutdowns the logging.
|
||||
try:
|
||||
self.__loggingLock.acquire()
|
||||
logging.shutdown()
|
||||
finally:
|
||||
self.__loggingLock.release()
|
||||
|
||||
def addJail(self, name, backend):
|
||||
self.__jails.add(name, backend)
|
||||
|
@ -142,18 +166,6 @@ class Server:
|
|||
def getLogPath(self, name):
|
||||
return self.__jails.getFilter(name).getLogPath()
|
||||
|
||||
def setTimeRegex(self, name, value):
|
||||
self.__jails.getFilter(name).setTimeRegex(value)
|
||||
|
||||
def getTimeRegex(self, name):
|
||||
return self.__jails.getFilter(name).getTimeRegex()
|
||||
|
||||
def setTimePattern(self, name, value):
|
||||
self.__jails.getFilter(name).setTimePattern(value)
|
||||
|
||||
def getTimePattern(self, name):
|
||||
return self.__jails.getFilter(name).getTimePattern()
|
||||
|
||||
def setFindTime(self, name, value):
|
||||
self.__jails.getFilter(name).setFindTime(value)
|
||||
|
||||
|
@ -310,7 +322,11 @@ class Server:
|
|||
def setLogTarget(self, target):
|
||||
try:
|
||||
self.__loggingLock.acquire()
|
||||
# set a format which is simpler for console use
|
||||
formatter = logging.Formatter("%(asctime)s %(name)-16s: %(levelname)-6s %(message)s")
|
||||
if target == "SYSLOG":
|
||||
# Syslog daemons already add date to the message.
|
||||
formatter = logging.Formatter("%(name)-16s: %(levelname)-6s %(message)s")
|
||||
facility = logging.handlers.SysLogHandler.LOG_DAEMON
|
||||
hdlr = logging.handlers.SysLogHandler("/dev/log",
|
||||
facility = facility)
|
||||
|
@ -331,10 +347,8 @@ class Server:
|
|||
# Removes previous handlers
|
||||
for handler in logging.getLogger("fail2ban").handlers:
|
||||
# Closes the handler.
|
||||
handler.close()
|
||||
logging.getLogger("fail2ban").removeHandler(handler)
|
||||
# set a format which is simpler for console use
|
||||
formatter = logging.Formatter("%(asctime)s %(name)-16s: %(levelname)-6s %(message)s")
|
||||
handler.close()
|
||||
# tell the handler to use this format
|
||||
hdlr.setFormatter(formatter)
|
||||
logging.getLogger("fail2ban").addHandler(hdlr)
|
||||
|
|
|
@ -16,11 +16,11 @@
|
|||
|
||||
# Author: Cyril Jaquier
|
||||
#
|
||||
# $Revision: 382 $
|
||||
# $Revision: 638 $
|
||||
|
||||
__author__ = "Cyril Jaquier"
|
||||
__version__ = "$Revision: 382 $"
|
||||
__date__ = "$Date: 2006-09-25 19:03:48 +0200 (Mon, 25 Sep 2006) $"
|
||||
__version__ = "$Revision: 638 $"
|
||||
__date__ = "$Date: 2007-12-17 21:00:36 +0100 (Mon, 17 Dec 2007) $"
|
||||
__copyright__ = "Copyright (c) 2004 Cyril Jaquier"
|
||||
__license__ = "GPL"
|
||||
|
||||
|
@ -53,4 +53,28 @@ class Ticket:
|
|||
|
||||
def getAttempt(self):
|
||||
return self.__attempt
|
||||
|
||||
|
||||
|
||||
class FailTicket(Ticket):
|
||||
|
||||
def __init__(self, ip, time):
|
||||
Ticket.__init__(self, ip, time)
|
||||
|
||||
|
||||
##
|
||||
# Ban Ticket.
|
||||
#
|
||||
# This class extends the Ticket class. It is mainly used by the BanManager.
|
||||
|
||||
class BanTicket(Ticket):
|
||||
|
||||
##
|
||||
# Constructor.
|
||||
#
|
||||
# Call the Ticket (parent) constructor and initialize default
|
||||
# values.
|
||||
# @param ip the IP address
|
||||
# @param time the ban time
|
||||
|
||||
def __init__(self, ip, time):
|
||||
Ticket.__init__(self, ip, time)
|
||||
|
|
|
@ -16,11 +16,11 @@
|
|||
|
||||
# Author: Cyril Jaquier
|
||||
#
|
||||
# $Revision: 503 $
|
||||
# $Revision: 639 $
|
||||
|
||||
__author__ = "Cyril Jaquier"
|
||||
__version__ = "$Revision: 503 $"
|
||||
__date__ = "$Date: 2006-12-23 17:31:00 +0100 (Sat, 23 Dec 2006) $"
|
||||
__version__ = "$Revision: 639 $"
|
||||
__date__ = "$Date: 2007-12-17 21:04:29 +0100 (Mon, 17 Dec 2007) $"
|
||||
__copyright__ = "Copyright (c) 2004 Cyril Jaquier"
|
||||
__license__ = "GPL"
|
||||
|
||||
|
@ -135,14 +135,6 @@ class Transmitter:
|
|||
value = command[2]
|
||||
self.__server.delLogPath(name, value)
|
||||
return self.__server.getLogPath(name)
|
||||
elif command[1] == "timeregex":
|
||||
value = command[2]
|
||||
self.__server.setTimeRegex(name, value)
|
||||
return self.__server.getTimeRegex(name)
|
||||
elif command[1] == "timepattern":
|
||||
value = command[2]
|
||||
self.__server.setTimePattern(name, value)
|
||||
return self.__server.getTimePattern(name)
|
||||
elif command[1] == "addfailregex":
|
||||
value = command[2]
|
||||
self.__server.addFailRegex(name, value)
|
||||
|
@ -229,10 +221,6 @@ class Transmitter:
|
|||
return self.__server.getLogPath(name)
|
||||
elif command[1] == "ignoreip":
|
||||
return self.__server.getIgnoreIP(name)
|
||||
elif command[1] == "timeregex":
|
||||
return self.__server.getTimeRegex(name)
|
||||
elif command[1] == "timepattern":
|
||||
return self.__server.getTimePattern(name)
|
||||
elif command[1] == "failregex":
|
||||
return self.__server.getFailRegex(name)
|
||||
elif command[1] == "ignoreregex":
|
||||
|
|
10
setup.py
10
setup.py
|
@ -18,11 +18,11 @@
|
|||
|
||||
# Author: Cyril Jaquier
|
||||
#
|
||||
# $Revision: 522 $
|
||||
# $Revision: 671 $
|
||||
|
||||
__author__ = "Cyril Jaquier"
|
||||
__version__ = "$Revision: 522 $"
|
||||
__date__ = "$Date: 2007-01-21 23:19:57 +0100 (Sun, 21 Jan 2007) $"
|
||||
__version__ = "$Revision: 671 $"
|
||||
__date__ = "$Date: 2008-03-06 00:12:41 +0100 (Thu, 06 Mar 2008) $"
|
||||
__copyright__ = "Copyright (c) 2004 Cyril Jaquier"
|
||||
__license__ = "GPL"
|
||||
|
||||
|
@ -45,8 +45,8 @@ setup(
|
|||
description = "Ban IPs that make too many password failure",
|
||||
long_description = longdesc,
|
||||
author = "Cyril Jaquier",
|
||||
author_email = "lostcontrol@users.sourceforge.net",
|
||||
url = "http://fail2ban.sourceforge.net",
|
||||
author_email = "cyril.jaquier@fail2ban.org",
|
||||
url = "http://www.fail2ban.org",
|
||||
license = "GPL",
|
||||
platforms = "Posix",
|
||||
scripts = [
|
||||
|
|
|
@ -16,17 +16,17 @@
|
|||
|
||||
# Author: Cyril Jaquier
|
||||
#
|
||||
# $Revision: 382 $
|
||||
# $Revision: 638 $
|
||||
|
||||
__author__ = "Cyril Jaquier"
|
||||
__version__ = "$Revision: 382 $"
|
||||
__date__ = "$Date: 2006-09-25 19:03:48 +0200 (Mon, 25 Sep 2006) $"
|
||||
__version__ = "$Revision: 638 $"
|
||||
__date__ = "$Date: 2007-12-17 21:00:36 +0100 (Mon, 17 Dec 2007) $"
|
||||
__copyright__ = "Copyright (c) 2004 Cyril Jaquier"
|
||||
__license__ = "GPL"
|
||||
|
||||
import unittest, socket, time, pickle
|
||||
import unittest
|
||||
from server.banmanager import BanManager
|
||||
from server.banticket import BanTicket
|
||||
from server.ticket import BanTicket
|
||||
|
||||
class AddFailure(unittest.TestCase):
|
||||
|
||||
|
|
|
@ -16,11 +16,11 @@
|
|||
|
||||
# Author: Cyril Jaquier
|
||||
#
|
||||
# $Revision: 504 $
|
||||
# $Revision: 650 $
|
||||
|
||||
__author__ = "Cyril Jaquier"
|
||||
__version__ = "$Revision: 504 $"
|
||||
__date__ = "$Date: 2006-12-23 17:37:17 +0100 (Sat, 23 Dec 2006) $"
|
||||
__version__ = "$Revision: 650 $"
|
||||
__date__ = "$Date: 2008-02-02 21:07:06 +0100 (Sat, 02 Feb 2008) $"
|
||||
__copyright__ = "Copyright (c) 2004 Cyril Jaquier"
|
||||
__license__ = "GPL"
|
||||
|
||||
|
@ -40,8 +40,8 @@ class DateDetectorTest(unittest.TestCase):
|
|||
|
||||
def testGetEpochTime(self):
|
||||
log = "1138049999 [sshd] error: PAM: Authentication failure"
|
||||
date = [2006, 1, 23, 20, 59, 59, 0, 23, 0]
|
||||
dateUnix = 1138046399.0
|
||||
date = [2006, 1, 23, 21, 59, 59, 0, 23, 0]
|
||||
dateUnix = 1138049999.0
|
||||
|
||||
self.assertEqual(self.__datedetector.getTime(log), date)
|
||||
self.assertEqual(self.__datedetector.getUnixTime(log), dateUnix)
|
||||
|
@ -54,14 +54,14 @@ class DateDetectorTest(unittest.TestCase):
|
|||
self.assertEqual(self.__datedetector.getTime(log), date)
|
||||
self.assertEqual(self.__datedetector.getUnixTime(log), dateUnix)
|
||||
|
||||
def testDefaultTempate(self):
|
||||
self.__datedetector.setDefaultRegex("^\S{3}\s{1,2}\d{1,2} \d{2}:\d{2}:\d{2}")
|
||||
self.__datedetector.setDefaultPattern("%b %d %H:%M:%S")
|
||||
|
||||
log = "Jan 23 21:59:59 [sshd] error: PAM: Authentication failure"
|
||||
date = [2005, 1, 23, 21, 59, 59, 1, 23, -1]
|
||||
dateUnix = 1106513999.0
|
||||
|
||||
self.assertEqual(self.__datedetector.getTime(log), date)
|
||||
self.assertEqual(self.__datedetector.getUnixTime(log), dateUnix)
|
||||
# def testDefaultTempate(self):
|
||||
# self.__datedetector.setDefaultRegex("^\S{3}\s{1,2}\d{1,2} \d{2}:\d{2}:\d{2}")
|
||||
# self.__datedetector.setDefaultPattern("%b %d %H:%M:%S")
|
||||
#
|
||||
# log = "Jan 23 21:59:59 [sshd] error: PAM: Authentication failure"
|
||||
# date = [2005, 1, 23, 21, 59, 59, 1, 23, -1]
|
||||
# dateUnix = 1106513999.0
|
||||
#
|
||||
# self.assertEqual(self.__datedetector.getTime(log), date)
|
||||
# self.assertEqual(self.__datedetector.getUnixTime(log), dateUnix)
|
||||
|
|
@ -16,18 +16,17 @@
|
|||
|
||||
# Author: Cyril Jaquier
|
||||
#
|
||||
# $Revision: 382 $
|
||||
# $Revision: 638 $
|
||||
|
||||
__author__ = "Cyril Jaquier"
|
||||
__version__ = "$Revision: 382 $"
|
||||
__date__ = "$Date: 2006-09-25 19:03:48 +0200 (Mon, 25 Sep 2006) $"
|
||||
__version__ = "$Revision: 638 $"
|
||||
__date__ = "$Date: 2007-12-17 21:00:36 +0100 (Mon, 17 Dec 2007) $"
|
||||
__copyright__ = "Copyright (c) 2004 Cyril Jaquier"
|
||||
__license__ = "GPL"
|
||||
|
||||
import unittest, socket, time, pickle
|
||||
from server.failmanager import FailManager
|
||||
from server.failmanager import FailManagerEmpty
|
||||
from server.failticket import FailTicket
|
||||
from server.failmanager import FailManager, FailManagerEmpty
|
||||
from server.ticket import FailTicket
|
||||
|
||||
class AddFailure(unittest.TestCase):
|
||||
|
||||
|
|
|
@ -16,17 +16,17 @@
|
|||
|
||||
# Author: Cyril Jaquier
|
||||
#
|
||||
# $Revision: 503 $
|
||||
# $Revision: 641 $
|
||||
|
||||
__author__ = "Cyril Jaquier"
|
||||
__version__ = "$Revision: 503 $"
|
||||
__date__ = "$Date: 2006-12-23 17:31:00 +0100 (Sat, 23 Dec 2006) $"
|
||||
__version__ = "$Revision: 641 $"
|
||||
__date__ = "$Date: 2007-12-26 12:46:22 +0100 (Wed, 26 Dec 2007) $"
|
||||
__copyright__ = "Copyright (c) 2004 Cyril Jaquier"
|
||||
__license__ = "GPL"
|
||||
|
||||
import unittest
|
||||
from server.filterpoll import FilterPoll
|
||||
from server.filter import Filter
|
||||
from server.filter import FileFilter
|
||||
from server.failmanager import FailManager
|
||||
from server.failmanager import FailManagerEmpty
|
||||
|
||||
|
@ -34,7 +34,7 @@ class IgnoreIP(unittest.TestCase):
|
|||
|
||||
def setUp(self):
|
||||
"""Call before every test case."""
|
||||
self.__filter = Filter(None)
|
||||
self.__filter = FileFilter(None)
|
||||
|
||||
def tearDown(self):
|
||||
"""Call after every test case."""
|
||||
|
@ -86,7 +86,7 @@ class GetFailures(unittest.TestCase):
|
|||
|
||||
def setUp(self):
|
||||
"""Call before every test case."""
|
||||
self.__filter = Filter(None)
|
||||
self.__filter = FileFilter(None)
|
||||
self.__filter.setActive(True)
|
||||
# TODO Test this
|
||||
#self.__filter.setTimeRegex("\S{3}\s{1,2}\d{1,2} \d{2}:\d{2}:\d{2}")
|
||||
|
|
Loading…
Reference in New Issue