- Overwrote head with some of 0.8.

git-svn-id: https://fail2ban.svn.sourceforge.net/svnroot/fail2ban/trunk@686 a942ae1a-1317-0410-a47c-b1dcaea8d605
0.x
Cyril Jaquier 2008-04-13 17:48:52 +00:00
parent cc57497f5b
commit b070dc89aa
72 changed files with 1761 additions and 932 deletions

View File

@ -1,5 +1,5 @@
README
CHANGELOG
ChangeLog
TODO
COPYING
fail2ban-client
@ -7,6 +7,7 @@ fail2ban-server
fail2ban-testcases
fail2ban-regex
client/configreader.py
client/configparserinc.py
client/jailreader.py
client/fail2banreader.py
client/jailsreader.py
@ -16,15 +17,12 @@ client/actionreader.py
client/__init__.py
client/configurator.py
client/csocket.py
server/banticket.py
server/asyncserver.py
server/filter.py
server/filtergamin.py
server/filterpoll.py
server/server.py
server/datestrptime.py
server/failticket.py
server/actions.py
server/datetai64n.py
server/faildata.py
server/failmanager.py
server/datedetector.py
@ -35,14 +33,10 @@ server/ticket.py
server/jail.py
server/jails.py
server/__init__.py
server/dateepoch.py
server/banmanager.py
server/datetemplate.py
server/mytime.py
server/regex.py
server/failregex.py
server/communication/__init__.py
server/communication/asyncserver.py
testcases/banmanagertestcase.py
testcases/failmanagertestcase.py
testcases/clientreadertestcase.py
@ -61,30 +55,43 @@ common/__init__.py
common/version.py
common/protocol.py
config/jail.conf
config/filter.d/common.conf
config/filter.d/apache-auth.conf
config/filter.d/apache-badbots.conf
config/filter.d/apache-noscript.conf
config/filter.d/apache-overflows.conf
config/filter.d/courierlogin.conf
config/filter.d/couriersmtp.conf
config/filter.d/exim.conf
config/filter.d/gssftpd.conf
config/filter.d/named-refused.conf
config/filter.d/postfix.conf
config/filter.d/proftpd.conf
config/filter.d/pure-ftpd.conf
config/filter.d/qmail.conf
config/filter.d/pam-generic.conf
config/filter.d/sasl.conf
config/filter.d/sshd.conf
config/filter.d/sshd-ddos.conf
config/filter.d/vsftpd.conf
config/filter.d/webmin-auth.conf
config/filter.d/wuftpd.conf
config/filter.d/xinetd-fail.conf
config/action.d/hostsdeny.conf
config/action.d/ipfw.conf
config/action.d/iptables.conf
config/action.d/iptables-allports.conf
config/action.d/iptables-multiport.conf
config/action.d/iptables-multiport-log.conf
config/action.d/iptables-new.conf
config/action.d/mail.conf
config/action.d/mail-buffered.conf
config/action.d/mail-whois.conf
config/action.d/mail-whois-lines.conf
config/action.d/sendmail.conf
config/action.d/sendmail-buffered.conf
config/action.d/sendmail-whois.conf
config/action.d/sendmail-whois-lines.conf
config/action.d/shorewall.conf
config/fail2ban.conf
man/fail2ban-client.1
@ -97,8 +104,10 @@ man/generate-man
files/gentoo-initd
files/gentoo-confd
files/redhat-initd
files/macosx-initd
files/solaris-fail2ban.xml
files/solaris-svc-fail2ban
files/suse-initd
files/cacti/fail2ban_stats.sh
files/cacti/cacti_host_template_fail2ban.xml
files/cacti/README

15
README
View File

@ -4,7 +4,7 @@
|_| \__,_|_|_/___|_.__/\__,_|_||_|
=============================================================
Fail2Ban (version 0.8.0) 2007/05/03
Fail2Ban (version 0.8.3) 2008/??/??
=============================================================
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.0.tar.bz2
> cd fail2ban-0.8.0
> tar xvfj fail2ban-0.8.3.tar.bz2
> cd fail2ban-0.8.3
> 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:
-------
@ -73,7 +73,10 @@ Jonathan Kamens, Stephen Gildea, Markus Hoffmann, Mark
Edgington, Patrick Börjesson, kojiro, zugeschmiert, Tyler,
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
Michael C. Haller, Jonathan Underwood, Hanno 'Rince' Wagner,
Daniel B. Cid, David Nutter, Raphaël Marichez, Guillaume
Delvit, Vaclav Misek, Adrien Clerc, Michael Hanselmann,
Vincent Deffontaines, Bill Heaton and many others.
License:
--------

12
TODO
View File

@ -13,16 +13,8 @@ Legend:
# partially done
* done
- <HOST> should not be mandatory. It should be possible to
start an action without an host
- Use Python 2.3
- 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/
@ -50,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

@ -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,7 +15,7 @@
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
# Author: Cyril Jaquier
#
# Modified by: Yaroslav Halchenko (SafeConfigParserWithIncludes)
# $Revision$
__author__ = "Cyril Jaquier"
@ -25,18 +25,18 @@ __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
@ -56,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

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

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

View File

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

View File

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

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

@ -24,4 +24,4 @@ __date__ = "$Date$"
__copyright__ = "Copyright (c) 2004 Cyril Jaquier"
__license__ = "GPL"
version = "0.9.0-SVN"
version = "0.8.2-SVN"

View File

@ -12,9 +12,9 @@
# Values: CMD
#
actionstart = touch /tmp/fail2ban.dummy
echo "<init>" >> /tmp/fail2ban.dummy
printf %%b "<init>\n" >> /tmp/fail2ban.dummy
# Option: actionend
# Option: actionstop
# Notes.: command executed once at the end of Fail2Ban
# Values: CMD
#
@ -34,7 +34,7 @@ actioncheck =
# <time> unix timestamp of the ban time
# Values: CMD
#
actionban = echo "+<ip>" >> /tmp/fail2ban.dummy
actionban = printf %%b "+<ip>\n" >> /tmp/fail2ban.dummy
# Option: actionunban
# Notes.: command executed when unbanning an IP. Take care that the
@ -44,7 +44,7 @@ actionban = echo "+<ip>" >> /tmp/fail2ban.dummy
# <time> unix timestamp of the ban time
# Values: CMD
#
actionunban = echo "-<ip>" >> /tmp/fail2ban.dummy
actionunban = printf %%b "-<ip>\n" >> /tmp/fail2ban.dummy
[Init]

View File

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

@ -15,7 +15,7 @@
actionstart =
# Option: actionend
# Option: actionstop
# Notes.: command executed once at the end of Fail2Ban
# Values: CMD
#

View File

@ -0,0 +1,65 @@
# Fail2Ban configuration file
#
# Author: Cyril Jaquier
# Modified: Yaroslav O. Halchenko <debian@onerussian.com>
# made active on all ports from original iptables.conf
#
# $Revision: 658 $
#
[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 -p <protocol> -j fail2ban-<name>
# Option: actionstop
# Notes.: command executed once at the end of Fail2Ban
# Values: CMD
#
actionstop = iptables -D INPUT -p <protocol> -j fail2ban-<name>
iptables -F fail2ban-<name>
iptables -X fail2ban-<name>
# Option: actioncheck
# Notes.: command executed once before each actionban command
# Values: CMD
#
actioncheck = iptables -n -L INPUT | grep -q fail2ban-<name>
# 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 DROP
# 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 DROP
[Init]
# Defaut name of the chain
#
name = default
# Option: protocol
# Notes.: internally used by config reader for interpolations.
# Values: [ tcp | udp | icmp | all ] Default: tcp
#
protocol = tcp

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

@ -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: 510 $
# $Revision: 668 $
#
[Definition]
@ -11,25 +11,25 @@
# Notes.: command executed once at the start of Fail2Ban.
# Values: CMD
#
actionstart = echo -en "Hi,\n
The jail <name> has been started successfuly.\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

@ -7,31 +7,31 @@
[Definition]
# Option: fwstart
# Option: actionstart
# Notes.: command executed once at the start of Fail2Ban.
# Values: CMD
#
actionstart = echo -en "Hi,\n
The jail <name> has been started successfuly.\n
actionstart = printf %%b "Hi,\n
The jail <name> has been started successfully.\n
Regards,\n
Fail2Ban"|mail -s "[Fail2Ban] <name>: started" <dest>
# Option: fwend
# 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>
# Option: fwcheck
# Notes.: command executed once before each fwban command
# Option: actioncheck
# Notes.: command executed once before each actionban command
# Values: CMD
#
actioncheck =
# Option: fwban
# Option: actionban
# Notes.: command executed when banning an IP. Take care that the
# command is executed with Fail2Ban user rights.
# Tags: <ip> IP address
@ -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
@ -50,7 +50,7 @@ actionban = echo -en "Hi,\n
Regards,\n
Fail2Ban"|mail -s "[Fail2Ban] <name>: banned <ip>" <dest>
# Option: fwunban
# Option: actionunban
# Notes.: command executed when unbanning an IP. Take care that the
# command is executed with Fail2Ban user rights.
# Tags: <ip> IP address

View File

@ -0,0 +1,105 @@
# Fail2Ban configuration file
#
# Author: Cyril Jaquier
#
# $Revision: 660 $
#
[Definition]
# Option: actionstart
# Notes.: command executed once at the start of Fail2Ban.
# Values: CMD
#
actionstart = printf %%b "Subject: [Fail2Ban] <name>: started
From: Fail2Ban <<sender>>
To: <dest>\n
Hi,\n
The jail <name> has been started successfully.\n
Output will be buffered until <lines> lines are available.\n
Regards,\n
Fail2Ban" | /usr/sbin/sendmail -f <sender> <dest>
# Option: actionstop
# Notes.: command executed once at the end of Fail2Ban
# Values: CMD
#
actionstop = if [ -f <tmpfile> ]; then
printf %%b "Subject: [Fail2Ban] <name>: summary
From: Fail2Ban <<sender>>
To: <dest>\n
Hi,\n
These hosts have been banned by Fail2Ban.\n
`cat <tmpfile>`
Regards,\n
Fail2Ban" | /usr/sbin/sendmail -f <sender> <dest>
rm <tmpfile>
fi
printf %%b "Subject: [Fail2Ban] <name>: stopped
From: Fail2Ban <<sender>>
To: <dest>\n
Hi,\n
The jail <name> has been stopped.\n
Regards,\n
Fail2Ban" | /usr/sbin/sendmail -f <sender> <dest>
# Option: actioncheck
# Notes.: command executed once before each actionban command
# Values: CMD
#
actioncheck =
# 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 = printf %%b "`date`: <ip> (<failures> failures)\n" >> <tmpfile>
LINE=$( wc -l <tmpfile> | awk '{ print $1 }' )
if [ $LINE -eq <lines> ]; then
printf %%b "Subject: [Fail2Ban] <name>: summary
From: Fail2Ban <<sender>>
To: <dest>\n
Hi,\n
These hosts have been banned by Fail2Ban.\n
`cat <tmpfile>`
Regards,\n
Fail2Ban" | /usr/sbin/sendmail -f <sender> <dest>
rm <tmpfile>
fi
# 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 =
[Init]
# Defaut name of the chain
#
name = default
# Destination/Addressee of the mail
#
dest = root
# Sender of the mail
#
sender = fail2ban
# Default number of lines that are buffered
#
lines = 5
# Default temporary file
#
tmpfile = /tmp/fail2ban-mail.txt

View File

@ -0,0 +1,88 @@
# Fail2Ban configuration file
#
# Author: Cyril Jaquier
#
# $Revision: 660 $
#
[Definition]
# Option: actionstart
# Notes.: command executed once at the start of Fail2Ban.
# Values: CMD
#
actionstart = printf %%b "Subject: [Fail2Ban] <name>: started
From: Fail2Ban <<sender>>
To: <dest>\n
Hi,\n
The jail <name> has been started successfully.\n
Regards,\n
Fail2Ban" | /usr/sbin/sendmail -f <sender> <dest>
# Option: actionstop
# Notes.: command executed once at the end of Fail2Ban
# Values: CMD
#
actionstop = printf %%b "Subject: [Fail2Ban] <name>: stopped
From: Fail2Ban <<sender>>
To: <dest>\n
Hi,\n
The jail <name> has been stopped.\n
Regards,\n
Fail2Ban" | /usr/sbin/sendmail -f <sender> <dest>
# Option: actioncheck
# Notes.: command executed once before each actionban command
# Values: CMD
#
actioncheck =
# 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 = printf %%b "Subject: [Fail2Ban] <name>: banned <ip>
From: Fail2Ban <<sender>>
To: <dest>\n
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
`/usr/bin/whois <ip>`\n\n
Lines containing IP:<ip> in <logpath>\n
`/bin/grep '\<<ip>\>' <logpath>`\n\n
Regards,\n
Fail2Ban" | /usr/sbin/sendmail -f <sender> <dest>
# 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 =
[Init]
# Defaut name of the chain
#
name = default
# Destination/Addressee of the mail
#
dest = root
# Sender of the mail
#
sender = fail2ban
# Path to the log files which contain relevant lines for the abuser IP
#
logpath = /dev/null

View File

@ -0,0 +1,82 @@
# Fail2Ban configuration file
#
# Author: Cyril Jaquier
#
# $Revision: 660 $
#
[Definition]
# Option: actionstart
# Notes.: command executed once at the start of Fail2Ban.
# Values: CMD
#
actionstart = printf %%b "Subject: [Fail2Ban] <name>: started
From: Fail2Ban <<sender>>
To: <dest>\n
Hi,\n
The jail <name> has been started successfully.\n
Regards,\n
Fail2Ban" | /usr/sbin/sendmail -f <sender> <dest>
# Option: actionstop
# Notes.: command executed once at the end of Fail2Ban
# Values: CMD
#
actionstop = printf %%b "Subject: [Fail2Ban] <name>: stopped
From: Fail2Ban <<sender>>
To: <dest>\n
Hi,\n
The jail <name> has been stopped.\n
Regards,\n
Fail2Ban" | /usr/sbin/sendmail -f <sender> <dest>
# Option: actioncheck
# Notes.: command executed once before each actionban command
# Values: CMD
#
actioncheck =
# 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 = printf %%b "Subject: [Fail2Ban] <name>: banned <ip>
From: Fail2Ban <<sender>>
To: <dest>\n
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
`/usr/bin/whois <ip>`\n
Regards,\n
Fail2Ban" | /usr/sbin/sendmail -f <sender> <dest>
# 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 =
[Init]
# Defaut name of the chain
#
name = default
# Destination/Addressee of the mail
#
dest = root
# Sender of the mail
#
sender = fail2ban

View File

@ -0,0 +1,80 @@
# Fail2Ban configuration file
#
# Author: Cyril Jaquier
#
# $Revision: 660 $
#
[Definition]
# Option: actionstart
# Notes.: command executed once at the start of Fail2Ban.
# Values: CMD
#
actionstart = printf %%b "Subject: [Fail2Ban] <name>: started
From: Fail2Ban <<sender>>
To: <dest>\n
Hi,\n
The jail <name> has been started successfully.\n
Regards,\n
Fail2Ban" | /usr/sbin/sendmail -f <sender> <dest>
# Option: actionstop
# Notes.: command executed once at the end of Fail2Ban
# Values: CMD
#
actionstop = printf %%b "Subject: [Fail2Ban] <name>: stopped
From: Fail2Ban <<sender>>
To: <dest>\n
Hi,\n
The jail <name> has been stopped.\n
Regards,\n
Fail2Ban" | /usr/sbin/sendmail -f <sender> <dest>
# Option: actioncheck
# Notes.: command executed once before each actionban command
# Values: CMD
#
actioncheck =
# 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 = printf %%b "Subject: [Fail2Ban] <name>: banned <ip>
From: Fail2Ban <<sender>>
To: <dest>\n
Hi,\n
The IP <ip> has just been banned by Fail2Ban after
<failures> attempts against <name>.\n
Regards,\n
Fail2Ban" | /usr/sbin/sendmail -f <sender> <dest>
# 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 =
[Init]
# Defaut name of the chain
#
name = default
# Destination/Addressee of the mail
#
dest = root
# Sender of the mail
#
sender = fail2ban

View File

@ -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: /tmp/fail2ban.sock
# Values: FILE Default: /var/run/fail2ban/fail2ban.sock
#
socket = /tmp/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

@ -14,7 +14,7 @@
# (?:::f{4,6}:)?(?P<host>\S+)
# Values: TEXT
#
failregex = [[]client <HOST>[]] File does not exist: .*(\.php|\.asp)
failregex = [[]client <HOST>[]] (File does not exist|script not found or unable to stat): .*(\.php|\.asp|\.exe|\.pl)
# Option: ignoreregex
# Notes.: regex to ignore. If this regex matches, the line is ignored.

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

@ -0,0 +1,14 @@
# Fail2Ban configuration file for wuftpd
#
# Author: Kevin Zembower (copied from wsftpd.conf)
#
# $Revision: 684 $
#
[Definition]
# Option: failregex
# Notes.: regex to match the password failures messages in the logfile.
# Values: TEXT
#
failregex = ftpd(?:\[\d+\])?:\s+repeated login failures from <HOST> \(\S+\)$

View File

@ -0,0 +1,31 @@
# Fail2Ban configuration file for named (bind9). Trying to generalize the
# structure which is general to capture general patterns in log
# lines to cover different configurations/distributions
#
# Author: Yaroslav Halchenko
#
# $Revision: 616 $
#
[Definition]
#
# Daemon name
_daemon=named
#
# Shortcuts for easier comprehension of the failregex
__pid_re=(?:\[\d+\])
__daemon_re=\(?%(_daemon)s(?:\(\S+\))?\)?:?
__daemon_combs_re=(?:%(__pid_re)s?:\s+%(__daemon_re)s|%(__daemon_re)s%(__pid_re)s?:)
# hostname daemon_id spaces
# this can be optional (for instance if we match named native log files)
__line_prefix=(?:\s\S+ %(__daemon_combs_re)s\s+)?
# Option: failregex
# Notes.: regex to match the password failures messages in the logfile.
# Values: TEXT
#
failregex = %(__line_prefix)sclient <HOST>#\S+: query(?: \(cache\))? '.*' denied\s*$

View File

@ -0,0 +1,25 @@
# Fail2Ban configuration file for generic PAM authentication errors
#
# Author: Yaroslav Halchenko
#
# $Revision: $
#
[Definition]
# if you want to catch only login erros from specific daemons, use smth like
#_ttys_re=(?:ssh|pure-ftpd|ftp)
# To catch all failed logins
_ttys_re=\S*
#
# Shortcuts for easier comprehension of the failregex
__pid_re=(?:\[\d+\])
__pam_re=\(?pam_unix(?:\(\S+\))?\)?:?
__pam_combs_re=(?:%(__pid_re)s?:\s+%(__pam_re)s|%(__pam_re)s%(__pid_re)s?:)
# Option: failregex
# Notes.: regex to match the password failures messages in the logfile.
# Values: TEXT
#
failregex = \s\S+ \S+%(__pam_combs_re)s\s+authentication failure; logname=\S* uid=\S* euid=\S* tty=%(_ttys_re)s ruser=\S* rhost=<HOST>(?:\s+user=.*)?\s*$

View File

@ -14,7 +14,10 @@
# (?:::f{4,6}:)?(?P<host>\S+)
# Values: TEXT
#
failregex = USER \S+: no such user found from \S* ?\[<HOST>\] to \S+\s*$
failregex = \(\S+\[<HOST>\]\)[: -]+ USER \S+: no such user found from \S+ \[\S+\] 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

@ -5,8 +5,17 @@
# $Revision$
#
[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,11 +23,14 @@
# (?:::f{4,6}:)?(?P<host>\S+)
# Values: TEXT
#
failregex = Authentication failure for .* from <HOST>$
Failed [-/\w]+ for .* from <HOST>$
ROOT LOGIN REFUSED .* FROM <HOST>$
[iI](?:llegal|nvalid) user .* from <HOST>$
User .* from <HOST> not allowed because not listed in AllowUsers$
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 \S+ from <HOST> not allowed because not listed in AllowUsers$
^%(__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

@ -14,8 +14,8 @@
# (?:::f{4,6}:)?(?P<host>\S+)
# Values: TEXT
#
failregex = vsftpd(?:\[\d+\])?: .* authentication failure; .* rhost=<HOST>$
\[.+\] FAIL LOGIN: Client "<HOST>"$
failregex = vsftpd(?:\(pam_unix\))?(?:\[\d+\])?:.* authentication failure; .* rhost=<HOST>(?:\s+user=\S*)?\s*$
\[.+\] FAIL LOGIN: Client "<HOST>"\s*$
# Option: ignoreregex
# Notes.: regex to ignore. If this regex matches, the line is ignored.

View File

@ -0,0 +1,28 @@
# Fail2Ban configuration file
#
# Author: Cyril Jaquier
# Rule by : Delvit Guillaume
#
# $Revision: 601 $
#
[Definition]
# patern : webmin[15673]: Non-existent login as toto from 86.0.6.217
# webmin[29544]: Invalid login as root from 86.0.6.217
#
# Option: failregex
# Notes.: regex to match the password failure 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
#
failregex = webmin.* Non-existent login as .+ from <HOST>$
webmin.* Invalid login as .+ from <HOST>$
# Option: ignoreregex
# Notes.: regex to ignore. If this regex matches, the line is ignored.
# Values: TEXT
#
ignoreregex =

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

@ -45,7 +45,7 @@ backend = auto
enabled = false
filter = sshd
action = iptables[name=SSH, port=ssh, protocol=tcp]
mail-whois[name=SSH, dest=yourmail@mail.com]
sendmail-whois[name=SSH, dest=you@mail.com, sender=fail2ban@mail.com]
logpath = /var/log/sshd.log
maxretry = 5
@ -54,7 +54,7 @@ maxretry = 5
enabled = false
filter = proftpd
action = iptables[name=ProFTPD, port=ftp, protocol=tcp]
mail-whois[name=ProFTPD, dest=yourmail@mail.com]
sendmail-whois[name=ProFTPD, dest=you@mail.com]
logpath = /var/log/proftpd/proftpd.log
maxretry = 6
@ -66,7 +66,7 @@ enabled = false
filter = sasl
backend = polling
action = iptables[name=sasl, port=smtp, protocol=tcp]
mail-whois[name=sasl, dest=yourmail@mail.com]
sendmail-whois[name=sasl, dest=you@mail.com]
logpath = /var/log/mail.log
# Here we use TCP-Wrappers instead of Netfilter/Iptables. "ignoreregex" is
@ -77,7 +77,7 @@ logpath = /var/log/mail.log
enabled = false
filter = sshd
action = hostsdeny
mail-whois[name=SSH, dest=yourmail@mail.com]
sendmail-whois[name=SSH, dest=you@mail.com]
ignoreregex = for myuser from
logpath = /var/log/sshd.log
@ -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
@ -101,7 +101,7 @@ maxretry = 6
enabled = false
filter = postfix
action = hostsdeny[file=/not/a/standard/path/hosts.deny]
mail[name=Postfix, dest=yourmail@mail.com]
sendmail[name=Postfix, dest=you@mail.com]
logpath = /var/log/postfix.log
bantime = 300
@ -112,7 +112,7 @@ bantime = 300
enabled = false
filter = vsftpd
action = mail-whois[name=VSFTPD, dest=yourmail@mail.com]
action = sendmail-whois[name=VSFTPD, dest=you@mail.com]
logpath = /var/log/vsftpd.log
maxretry = 5
bantime = 1800
@ -124,7 +124,7 @@ bantime = 1800
enabled = false
filter = vsftpd
action = iptables[name=VSFTPD, port=ftp, protocol=tcp]
mail-whois[name=VSFTPD, dest=yourmail@mail.com]
sendmail-whois[name=VSFTPD, dest=you@mail.com]
logpath = /var/log/vsftpd.log
maxretry = 5
bantime = 1800
@ -137,7 +137,7 @@ bantime = 1800
enabled = false
filter = apache-badbots
action = iptables-multiport[name=BadBots, port="http,https"]
mail-buffered[name=BadBots, lines=5, dest=yourmail@mail.com]
sendmail-buffered[name=BadBots, lines=5, dest=you@mail.com]
logpath = /var/www/*/logs/access_log
bantime = 172800
maxretry = 1
@ -149,7 +149,7 @@ maxretry = 1
enabled = false
filter = apache-noscript
action = shorewall
mail[name=Postfix, dest=yourmail@mail.com]
sendmail[name=Postfix, dest=you@mail.com]
logpath = /var/log/apache2/error_log
# This jail uses ipfw, the standard firewall on FreeBSD. The "ignoreip"
@ -162,6 +162,44 @@ logpath = /var/log/apache2/error_log
enabled = false
filter = sshd
action = ipfw[localhost=192.168.0.1]
mail-whois[name="SSH,IPFW", dest=yourmail@mail.com]
sendmail-whois[name="SSH,IPFW", dest=you@mail.com]
logpath = /var/log/auth.log
ignoreip = 168.192.0.1
# These jails block attacks against named (bind9). By default, logging is off
# with bind9 installation. You will need something like this:
#
# logging {
# channel security_file {
# file "/var/log/named/security.log" versions 3 size 30m;
# severity dynamic;
# print-time yes;
# };
# category security {
# security_file;
# };
# }
#
# in your named.conf to provide proper logging.
# This jail blocks UDP traffic for DNS requests.
[named-refused-udp]
enabled = false
filter = named-refused
action = iptables-multiport[name=Named, port="domain,953", protocol=udp]
sendmail-whois[name=Named, dest=you@mail.com]
logpath = /var/log/named/security.log
ignoreip = 168.192.0.1
# This jail blocks TCP traffic for DNS requests.
[named-refused-tcp]
enabled = false
filter = named-refused
action = iptables-multiport[name=Named, port="domain,953", protocol=tcp]
sendmail-whois[name=Named, dest=you@mail.com]
logpath = /var/log/named/security.log
ignoreip = 168.192.0.1

View File

@ -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)
@ -338,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
@ -357,7 +372,14 @@ 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
def __readJailConfig(self, jail):
self.__configurator.readAll()
ret = self.__configurator.getOptions(jail)
self.__configurator.convertToProtocol()
self.__stream = self.__configurator.getConfigStream()
return ret

View File

@ -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,9 +65,12 @@ class RegexStat:
class Fail2banRegex:
test = None
CONFIG_DEFAULTS = {'configpath' : "/etc/fail2ban/"}
def __init__(self):
self.__filter = Filter(None)
self.__ignoreregex = list()
self.__failregex = list()
# Setup logging
logging.getLogger("fail2ban").handlers = []
@ -83,17 +86,17 @@ class Fail2banRegex:
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
def dispUsage():
print "Usage: "+sys.argv[0]+" [OPTIONS] <LOG> <REGEX>"
print "Usage: "+sys.argv[0]+" [OPTIONS] <LOG> <REGEX> [IGNOREREGEX]"
print
print "Fail2Ban v" + version + " reads log file that contains password failure report"
print "and bans the corresponding IP addresses using firewall rules."
@ -112,7 +115,11 @@ class Fail2banRegex:
print " string a string representing a 'failregex'"
print " filename path to a filter file (filter.d/sshd.conf)"
print
print "Report bugs to <lostcontrol@users.sourceforge.net>"
print "IgnoreRegex:"
print " string a string representing an 'ignoreregex'"
print " filename path to a filter file (filter.d/sshd.conf)"
print
print "Report bugs to <cyril.jaquier@fail2ban.org>"
dispUsage = staticmethod(dispUsage)
def getCmdLineOptions(self, optList):
@ -131,9 +138,38 @@ class Fail2banRegex:
return os.path.isfile(value)
logIsFile = staticmethod(logIsFile)
def readIgnoreRegex(self, value):
if os.path.isfile(value):
reader = SafeConfigParserWithIncludes(defaults=self.CONFIG_DEFAULTS)
try:
reader.read(value)
print "Use ignoreregex file : " + value
self.__ignoreregex = [RegexStat(m)
for m in reader.get("Definition", "ignoreregex").split('\n')]
except NoSectionError:
print "No [Definition] section in " + value
print
return False
except NoOptionError:
print "No failregex option in " + value
print
return False
except MissingSectionHeaderError:
print "No section headers in " + value
print
return False
else:
if len(value) > 53:
stripReg = value[0:50] + "..."
else:
stripReg = value
print "Use ignoreregex line : " + stripReg
self.__ignoreregex = [RegexStat(value)]
return True
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
@ -160,14 +196,33 @@ class Fail2banRegex:
self.__failregex = [RegexStat(value)]
return True
def testIgnoreRegex(self, line):
found = False
for regex in self.__ignoreregex:
logging.getLogger("fail2ban").setLevel(logging.DEBUG)
try:
self.__filter.addIgnoreRegex(regex.getFailRegex())
try:
ret = self.__filter.ignoreLine(line)
if ret:
regex.inc()
except RegexException, e:
print e
return False
finally:
self.__filter.delIgnoreRegex(0)
logging.getLogger("fail2ban").setLevel(logging.CRITICAL)
def testRegex(self, line):
found = False
for regex in self.__ignoreregex:
self.__filter.addIgnoreRegex(regex.getFailRegex())
for regex in self.__failregex:
logging.getLogger("fail2ban").setLevel(logging.DEBUG)
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)
@ -185,6 +240,8 @@ class Fail2banRegex:
finally:
self.__filter.delFailRegex(0)
logging.getLogger("fail2ban").setLevel(logging.CRITICAL)
for regex in self.__ignoreregex:
self.__filter.delIgnoreRegex(0)
def printStats(self):
print
@ -194,25 +251,51 @@ class Fail2banRegex:
# Print title
cnt = 1
print "Failregex:"
print "Failregex"
print "|- Regular expressions:"
for failregex in self.__failregex:
print "[" + str(cnt) + "] " + failregex.getFailRegex()
print "| [" + str(cnt) + "] " + failregex.getFailRegex()
cnt += 1
cnt = 1
print
print "|"
# Print stats
cnt = 1
total = 0
print "Number of matches:"
print "`- Number of matches:"
for failregex in self.__failregex:
match = failregex.getStats()
total += match
print "[" + str(cnt) + "] " + str(match) + " match(es)"
print " [" + str(cnt) + "] " + str(match) + " match(es)"
cnt += 1
print
# Print title
cnt = 1
print "Ignoreregex"
print "|- Regular expressions:"
for failregex in self.__ignoreregex:
print "| [" + str(cnt) + "] " + failregex.getFailRegex()
cnt += 1
cnt = 1
print "|"
# Print stats
cnt = 1
print "`- Number of matches:"
for failregex in self.__ignoreregex:
match = failregex.getStats()
print " [" + str(cnt) + "] " + str(match) + " match(es)"
cnt += 1
print
print "Summary"
print "======="
print
if total == 0:
print "Sorry, no match"
print
@ -239,7 +322,7 @@ class Fail2banRegex:
print "Date template hits:"
for template in self.__filter.dateDetector.getTemplates():
print `template.getHits()` + " hit: " + template.getName()
print `template.getHits()` + " hit(s): " + template.getName()
print
@ -263,7 +346,7 @@ if __name__ == "__main__":
# Process command line
fail2banRegex.getCmdLineOptions(optList)
# We need exactly 3 parameters
if not len(sys.argv) == 3:
if not len(sys.argv) in (3, 4):
fail2banRegex.dispUsage()
sys.exit(-1)
else:
@ -272,6 +355,10 @@ if __name__ == "__main__":
print "============="
print
if len(sys.argv) == 4:
if fail2banRegex.readIgnoreRegex(sys.argv[3]) == False:
sys.exit(-1)
if fail2banRegex.readRegex(sys.argv[2]) == False:
sys.exit(-1)
@ -281,6 +368,7 @@ if __name__ == "__main__":
print "Use log file : " + sys.argv[1]
print
for line in hdlr:
fail2banRegex.testIgnoreRegex(line)
fail2banRegex.testRegex(line)
except IOError, e:
print e
@ -293,6 +381,7 @@ if __name__ == "__main__":
stripLog = sys.argv[1]
print "Use single line: " + stripLog
print
fail2banRegex.testIgnoreRegex(sys.argv[1])
fail2banRegex.testRegex(sys.argv[1])
if fail2banRegex.printStats():

View File

@ -25,7 +25,7 @@ __date__ = "$Date$"
__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

@ -20,14 +20,14 @@ FAIL2BAN="/usr/bin/fail2ban-client"
RETVAL=0
getpid() {
pid=`ps -ef | grep fail2ban-|grep -v grep|awk '{print $2}'`
pid=`ps -eo pid,comm | grep fail2ban- | awk '{ print $1 }'`
}
start() {
echo -n $"Starting fail2ban: "
getpid
if [ -z "$pid" ]; then
rm -rf /tmp/fail2ban.sock # in case of unclean shutdown
rm -rf /var/run/fail2ban/fail2ban.sock # in case of unclean shutdown
$FAIL2BAN start > /dev/null
RETVAL=$?
fi

View File

@ -6,26 +6,26 @@
#
### BEGIN INIT INFO
# Provides: fail2ban
# Required-Start: $syslog $remote_fs postfix
# Required-Start: $syslog $remote_fs sendmail
# Required-Stop: $syslog $remote_fs
# Should-Stop: $time ypbind sendmail
# Default-Start: 3 5
# Default-Stop: 0 1 2 6
# Description: startup Fail2Ban
### END INIT INFO
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/sbin:/usr/bin
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/sbin:/usr/sbin:/usr/bin:/bin
FAIL2BAN_BIN=/usr/local/bin/fail2ban-client
FAIL2BAN_SERVER=/usr/local/bin/fail2ban-server
FAIL2BAN_SOCKET=/tmp/fail2ban.sock
test -x $FAIL2BAN_BIN || { echo "$FAIL2BAN_BIN not installed";
if [ "$1" = "stop" ]; then exit 0;
else exit 5; fi; }
FAIL2BAN_SOCKET=/var/run/fail2ban/fail2ban.sock
test -x $FAIL2BAN_BIN || { echo "$FAIL2BAN_BIN not installed";
if [ "$1" = "stop" ]; then exit 0;
else exit 5; fi; }
# Check for existence of needed config file and read it
FAIL2BAN_CONFIG=/etc/fail2ban/fail2ban.conf
test -r $FAIL2BAN_CONFIG || { echo "$FAIL2BAN_CONFIG not existing";
if [ "$1" = "stop" ]; then exit 0;
else exit 6; fi; }
if [ "$1" = "stop" ]; then exit 0;
else exit 6; fi; }
. /etc/rc.status
@ -34,54 +34,63 @@ rc_reset
case "$1" in
start)
echo -n "Starting Fail2Ban "
/sbin/startproc $FAIL2BAN_BIN -q start 2>1 > /dev/null
rc_status -v
;;
echo -n "Starting Fail2Ban "
/sbin/startproc $FAIL2BAN_BIN start &>/dev/null
rc_status -v
;;
stop)
echo -n "Shutting down Fail2ban "
/sbin/startproc $FAIL2BAN_BIN -q stop
rc_status -v
;;
echo -n "Shutting down Fail2ban "
/sbin/startproc $FAIL2BAN_BIN -q stop
rc_status -v
;;
try-restart|condrestart)
if test "$1" = "condrestart"; then
echo "${attn} Use try-restart ${done}(LSB)${attn} rather than condrestart ${warn}(RH)${norm}"
fi
$0 status
if test $? = 0; then
$0 restart
else
rc_reset # Not running is not a failure.
fi
rc_status
;;
if test "$1" = "condrestart"; then
echo "${attn} Use try-restart ${done}(LSB)${attn} rather than condrestart ${warn}(RH)${norm}"
fi
$0 status
if test $? = 0; then
$0 restart
else
rc_reset # Not running is not a failure.
fi
rc_status
;;
restart)
$0 stop
i=60
while [ -e $FAIL2BAN_SOCKET ] && [ $i -gt 60 ]
sleep 1
i=$[i-1]
echo -n "."
done
echo "."
$0 start
$0 stop
echo -n "-wait a minute "
i=60
while [ -e $FAIL2BAN_SOCKET ] && [ $i -gt 0 ]; do
sleep 1
i=$[$i-1]
echo -n "."
done
echo "."
$0 start
# Remember status and be quiet
rc_status
;;
# Remember status and be quiet
rc_status
;;
force-reload)
echo -n "Reload service Fail2ban "
/sbin/startproc $FAIL2BAN_BIN -q reload
rc_status -v
;;
echo -n "Reload service Fail2ban "
/sbin/startproc $FAIL2BAN_BIN -q reload
rc_status -v
;;
reload)
echo -n "Reload service Fail2ban "
/sbin/startproc $FAIL2BAN_BIN -q reload
rc_status -v
;;
echo -n "Reload service Fail2ban "
/sbin/startproc $FAIL2BAN_BIN -q reload
rc_status -v
;;
status)
echo -n "Checking for service Fail2ban "
/sbin/checkproc $FAIL2BAN_SERVER
rc_status -v
;;
echo -n "Checking for service Fail2ban "
/sbin/checkproc $FAIL2BAN_SERVER
rc_status -v
;;
probe)
test /etc/fail2ban/fail2ban.conf -nt /var/run/fail2ban.pid && echo reload
;;
*)
echo "Usage: $0 {start|stop|status|try-restart|restart|force-reload|reload|probe}"
exit 1
;;
esac
rc_exit

View File

@ -106,7 +106,7 @@ class Action:
def setActionStart(self, value):
self.__actionStart = value
logSys.info("Set actionStart = %s" % value)
logSys.debug("Set actionStart = %s" % value)
##
# Get the "start" command.
@ -135,7 +135,7 @@ class Action:
def setActionBan(self, value):
self.__actionBan = value
logSys.info("Set actionBan = %s" % value)
logSys.debug("Set actionBan = %s" % value)
##
# Get the "ban" command.
@ -160,7 +160,7 @@ class Action:
def setActionUnban(self, value):
self.__actionUnban = value
logSys.info("Set actionUnban = %s" % value)
logSys.debug("Set actionUnban = %s" % value)
##
# Get the "unban" command.
@ -185,7 +185,7 @@ class Action:
def setActionCheck(self, value):
self.__actionCheck = value
logSys.info("Set actionCheck = %s" % value)
logSys.debug("Set actionCheck = %s" % value)
##
# Get the "check" command.
@ -202,7 +202,7 @@ class Action:
def setActionStop(self, value):
self.__actionStop = value
logSys.info("Set actionStop = %s" % value)
logSys.debug("Set actionStop = %s" % value)
##
# Get the "stop" command.
@ -314,3 +314,4 @@ class Action:
logSys.error("%s failed with %s" % (realCmd, e))
return False
executeCmd = staticmethod(executeCmd)

View File

@ -25,10 +25,10 @@ __copyright__ = "Copyright (c) 2004 Cyril Jaquier"
__license__ = "GPL"
from pickle import dumps, loads, HIGHEST_PROTOCOL
import asyncore, asynchat, socket, os, logging, sys
import asyncore, asynchat, socket, os, logging
# Gets the instance of the logger.
logSys = logging.getLogger("fail2ban.server.communication")
logSys = logging.getLogger("fail2ban.server")
##
# Request handler class.
@ -46,10 +46,9 @@ class RequestHandler(asynchat.async_chat):
self.__buffer = []
# Sets the terminator.
self.set_terminator(RequestHandler.END_STRING)
self.found_terminator = self.handle_request_line
def collect_incoming_data(self, data):
logSys.debug("Received raw data: " + str(data))
#logSys.debug("Received raw data: " + str(data))
self.__buffer.append(data)
##
@ -57,7 +56,7 @@ class RequestHandler(asynchat.async_chat):
#
# This method is called once we have a complete request.
def handle_request_line(self):
def found_terminator(self):
# Joins the buffer items.
message = loads("".join(self.__buffer))
# Gives the message to the transmitter.
@ -84,7 +83,7 @@ class AsyncServer(asyncore.dispatcher):
def __init__(self, transmitter):
asyncore.dispatcher.__init__(self)
self.__transmitter = transmitter
self.__sock = "/tmp/fail2ban.sock"
self.__sock = "/var/run/fail2ban/fail2ban.sock"
self.__init = False
##
@ -125,12 +124,15 @@ class AsyncServer(asyncore.dispatcher):
# Creates the socket.
self.create_socket(socket.AF_UNIX, socket.SOCK_STREAM)
self.set_reuse_addr()
self.bind(sock)
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(timeout = 2)
asyncore.loop()
##
# Stops the communication server.

View File

@ -24,7 +24,7 @@ __date__ = "$Date$"
__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

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$
__author__ = "Cyril Jaquier"
__version__ = "$Revision$"
__date__ = "$Date$"
__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

@ -1,25 +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: 433 $
__author__ = "Cyril Jaquier"
__version__ = "$Revision: 433 $"
__date__ = "$Date: 2006-10-24 21:40:51 +0200 (Tue, 24 Oct 2006) $"
__copyright__ = "Copyright (c) 2004 Cyril Jaquier"
__license__ = "GPL"

View File

@ -26,9 +26,9 @@ __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")
@ -68,6 +67,12 @@ class DateDetector:
template.setRegex("\d{4}/\d{2}/\d{2} \d{2}:\d{2}:\d{2}")
template.setPattern("%Y/%m/%d %H:%M:%S")
self.__templates.append(template)
# simple date too (from x11vnc)
template = DateStrptime()
template.setName("Day/Month/Year Hour:Minute:Second")
template.setRegex("\d{2}/\d{2}/\d{4} \d{2}:\d{2}:\d{2}")
template.setPattern("%d/%m/%Y %H:%M:%S")
self.__templates.append(template)
# Apache format [31/Oct/2006:09:22:55 -0000]
template = DateStrptime()
template.setName("Day/Month/Year:Hour:Minute:Second")
@ -80,6 +85,12 @@ class DateDetector:
template.setRegex("\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}")
template.setPattern("%Y-%m-%d %H:%M:%S")
self.__templates.append(template)
# named 26-Jul-2007 15:20:52.252
template = DateStrptime()
template.setName("Day-Month-Year Hour:Minute:Second[.Millisecond]")
template.setRegex("\d{2}-\S{3}-\d{4} \d{2}:\d{2}:\d{2}")
template.setPattern("%d-%b-%Y %H:%M:%S")
self.__templates.append(template)
# TAI64N
template = DateTai64n()
template.setName("TAI64N")
@ -94,54 +105,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)
@ -155,8 +143,8 @@ 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(lambda x, y: cmp(x.getHits(), y.getHits()))
self.__templates.reverse()

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$
__author__ = "Cyril Jaquier"
__version__ = "$Revision$"
__date__ = "$Date$"
__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.localtime(float(dateMatch.group())))
return date

View File

@ -1,85 +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$
__author__ = "Cyril Jaquier"
__version__ = "$Revision$"
__date__ = "$Date$"
__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
convertLocale = staticmethod(convertLocale)
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())
date = list(time.strptime(conv, self.getPattern()))
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$
__author__ = "Cyril Jaquier"
__version__ = "$Revision$"
__date__ = "$Date$"
__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
@ -24,7 +25,9 @@ __date__ = "$Date$"
__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

@ -25,7 +25,7 @@ __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

@ -24,7 +24,74 @@ __date__ = "$Date$"
__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$
__author__ = "Cyril Jaquier"
__version__ = "$Revision$"
__date__ = "$Date$"
__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

@ -25,12 +25,11 @@ __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.
#
@ -267,7 +181,7 @@ class Filter(JailThread):
# @return True when the thread exits nicely
def run(self):
raise NotImplementedException("run() is abstract")
raise Exception("run() is abstract")
##
# Add an IP/DNS to the ignore list.
@ -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,130 +228,79 @@ 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))
##
# Finds the failure in a line.
# Returns true if the line should be ignored.
#
# Uses ignoreregex.
# @param line: the line
# @return: a boolean
def ignoreLine(self, line):
for ignoreRegex in self.__ignoreRegex:
ignoreRegex.search(line)
if ignoreRegex.hasMatched():
return True
return False
##
# 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.
for ignoreRegex in self.__ignoreRegex:
ignoreRegex.search(line)
if ignoreRegex.hasMatched():
# The ignoreregex matched. Return.
logSys.debug("Ignoring this line")
return failList
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:
@ -467,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.
#
@ -477,8 +491,6 @@ import socket, struct
class DNSUtils:
#DNS_CRE = re.compile("(?:(?:\w|-)+\.){2,}\w+")
DNS_CRE = re.compile("\S+")
IP_CRE = re.compile("(?:\d{1,3}\.){3}\d{1,3}")
#@staticmethod

View File

@ -25,7 +25,7 @@ __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)
##
@ -108,8 +108,9 @@ class FilterGamin(Filter):
if self.__modified:
try:
ticket = self.failManager.toBan()
self.jail.putFailTicket(ticket)
while True:
ticket = self.failManager.toBan()
self.jail.putFailTicket(ticket)
except FailManagerEmpty:
self.failManager.cleanup(MyTime.time())
self.dateDetector.sortTemplate()
@ -126,6 +127,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

@ -25,7 +25,7 @@ __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,15 +96,16 @@ 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:
try:
ticket = self.failManager.toBan()
self.jail.putFailTicket(ticket)
while True:
ticket = self.failManager.toBan()
self.jail.putFailTicket(ticket)
except FailManagerEmpty:
self.failManager.cleanup(MyTime.time())
self.dateDetector.sortTemplate()

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$
__author__ = "Cyril Jaquier"
__version__ = "$Revision$"
__date__ = "$Date$"
__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

@ -27,14 +27,17 @@ __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,7 @@ class Server:
self.quit()
def start(self, sock, force = False):
logSys.info("Starting Fail2ban")
logSys.info("Starting Fail2ban v" + version.version)
# Install signal handlers
signal.signal(signal.SIGTERM, self.__sigTERMhandler)
@ -69,18 +72,40 @@ class Server:
else:
logSys.error("Could not create daemon")
raise ServerInitializationError("Could not create daemon")
# 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)
# Start the communication
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)
@ -140,19 +165,8 @@ class Server:
self.__jails.getFilter(name).delLogPath(fileName)
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()
return [m.getFileName()
for m in self.__jails.getFilter(name).getLogPath()]
def setFindTime(self, name, value):
self.__jails.getFilter(name).setFindTime(value)
@ -310,7 +324,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 +349,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

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

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

@ -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 = [
@ -57,8 +57,7 @@ setup(
packages = [
'common',
'client',
'server',
'server/communication'
'server'
],
data_files = [
('/etc/fail2ban',
@ -69,6 +68,9 @@ setup(
),
('/etc/fail2ban/action.d',
glob("config/action.d/*.conf")
),
('/var/run/fail2ban',
''
)
]
)

View File

@ -43,5 +43,5 @@ class ExecuteAction(unittest.TestCase):
self.__action.setActionBan("echo -n")
self.__action.setActionCheck("[ -e /tmp/fail2ban.test ]")
self.failUnless(self.__action.execActionBan(None))
self.assertTrue(self.__action.execActionBan(None))

View File

@ -24,9 +24,9 @@ __date__ = "$Date$"
__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):
@ -34,7 +34,7 @@ class AddFailure(unittest.TestCase):
"""Call before every test case."""
self.__ticket = BanTicket('193.168.0.128', 1167605999.0)
self.__banManager = BanManager()
self.failUnless(self.__banManager.addBanTicket(self.__ticket))
self.assertTrue(self.__banManager.addBanTicket(self.__ticket))
def tearDown(self):
"""Call after every test case."""
@ -43,14 +43,14 @@ class AddFailure(unittest.TestCase):
self.assertEqual(self.__banManager.size(), 1)
def testAddDuplicate(self):
self.failIf(self.__banManager.addBanTicket(self.__ticket))
self.assertFalse(self.__banManager.addBanTicket(self.__ticket))
self.assertEqual(self.__banManager.size(), 1)
def _testInListOK(self):
ticket = BanTicket('193.168.0.128', 1167605999.0)
self.failUnless(self.__banManager.inBanList(ticket))
self.assertTrue(self.__banManager.inBanList(ticket))
def _testInListNOK(self):
ticket = BanTicket('111.111.1.111', 1167605999.0)
self.failIf(self.__banManager.inBanList(ticket))
self.assertFalse(self.__banManager.inBanList(ticket))

View File

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

@ -25,9 +25,8 @@ __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

@ -26,7 +26,7 @@ __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."""
@ -43,19 +43,19 @@ class IgnoreIP(unittest.TestCase):
ipList = "127.0.0.1", "192.168.0.1", "255.255.255.255", "99.99.99.99"
for ip in ipList:
self.__filter.addIgnoreIP(ip)
self.failUnless(self.__filter.inIgnoreIPList(ip))
self.assertTrue(self.__filter.inIgnoreIPList(ip))
# Test DNS
self.__filter.addIgnoreIP("www.epfl.ch")
self.failUnless(self.__filter.inIgnoreIPList("128.178.50.12"))
self.assertTrue(self.__filter.inIgnoreIPList("128.178.50.12"))
def testIgnoreIPNOK(self):
ipList = "", "999.999.999.999", "abcdef", "192.168.0."
for ip in ipList:
self.__filter.addIgnoreIP(ip)
self.failIf(self.__filter.inIgnoreIPList(ip))
self.assertFalse(self.__filter.inIgnoreIPList(ip))
# Test DNS
self.__filter.addIgnoreIP("www.epfl.ch")
self.failIf(self.__filter.inIgnoreIPList("127.177.50.10"))
self.assertFalse(self.__filter.inIgnoreIPList("127.177.50.10"))
class LogFile(unittest.TestCase):
@ -74,7 +74,7 @@ class LogFile(unittest.TestCase):
# self.__filter.openLogFile(LogFile.FILENAME)
def testIsModified(self):
self.failUnless(self.__filter.isModified(LogFile.FILENAME))
self.assertTrue(self.__filter.isModified(LogFile.FILENAME))
class GetFailures(unittest.TestCase):
@ -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}")