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.py
debian-releases/squeeze
Yaroslav Halchenko 2008-03-05 22:30:10 -05:00
commit 9ab6db30c7
74 changed files with 1358 additions and 983 deletions

View File

@ -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

View File

@ -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
View File

@ -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
View File

@ -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?

View File

@ -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"

108
client/configparserinc.py Normal file
View File

@ -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)

View File

@ -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")

View File

@ -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()

View File

@ -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)

View File

@ -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)

View File

@ -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):

View File

@ -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>"],

View File

@ -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"

View File

@ -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

View File

@ -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]

View File

@ -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
#

View File

@ -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

View File

@ -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
#

View File

@ -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
#

View File

@ -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
#

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -2,7 +2,7 @@
#
# Author: Cyril Jaquier
#
# $Revision: 510 $
# $Revision: 658 $
#
[Definition]

View File

@ -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 =

View File

@ -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*

View File

@ -4,7 +4,7 @@
#
# Author: Yaroslav Halchenko
#
# $Revision: 608 $
# $Revision: 616 $
#
[Definition]

View File

@ -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.

View File

@ -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.

View File

@ -2,7 +2,7 @@
#
# Author: Cyril Jaquier
#
# $Revision: 610 $
# $Revision: 658 $
#
[Definition]

View File

@ -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 =

View File

@ -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

2
debian/watch vendored
View File

@ -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

View File

@ -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):

View File

@ -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)

View File

@ -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

View File

@ -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:
--------

19
files/macosx-initd Normal file
View File

@ -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>

View File

@ -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).

View File

@ -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).

View File

@ -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).

View File

@ -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)

155
server/asyncserver.py Normal file
View File

@ -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

View File

@ -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.

View File

@ -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)

View File

@ -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()

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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)

View File

@ -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)

View File

@ -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

View File

@ -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:

View File

@ -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)

View File

@ -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

View File

@ -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)

View File

@ -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)

View File

@ -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":

View File

@ -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 = [

View File

@ -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):

View File

@ -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)

View File

@ -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):

View File

@ -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}")