Merge branch '0.9' into py3

Conflicts:
	.travis.yml
	MANIFEST
	bin/fail2ban-regex
	fail2ban/server/filter.py
	fail2ban/tests/servertestcase.py
	setup.py
pull/171/head
Steven Hiscocks 2013-04-13 16:54:22 +01:00
commit fa0f8f9e6d
93 changed files with 1031 additions and 315 deletions

View File

@ -7,12 +7,16 @@ python:
- "2.7"
- "3.2"
- "3.3"
before_install:
- sudo apt-get update -qq
install:
- pip install pyinotify
- if [[ $TRAVIS_PYTHON_VERSION == 2.[6-7] ]] || [[ $TRAVIS_PYTHON_VERSION == 3.3 ]]; then pip install -q coveralls; fi
- if [[ $TRAVIS_PYTHON_VERSION == 2.7 ]]; then sudo apt-get install -qq python-gamin; fi
- if [[ $TRAVIS_PYTHON_VERSION == 2.7 ]]; then pip install -q coveralls; fi
before_script:
- if [[ $TRAVIS_PYTHON_VERSION == 3* ]]; then ./fail2ban-2to3; fi
script:
- if [[ $TRAVIS_PYTHON_VERSION == 2.[6-7] ]] || [[ $TRAVIS_PYTHON_VERSION == 3.3 ]]; then coverage run --rcfile=.travis_coveragerc fail2ban-testcases; else python ./fail2ban-testcases; fi
- if [[ $TRAVIS_PYTHON_VERSION == 2.7 ]]; then export PYTHONPATH="$PYTHONPATH:/usr/share/pyshared:/usr/lib/pyshared/python2.7"; fi
- if [[ $TRAVIS_PYTHON_VERSION == 2.7 ]]; then coverage run --rcfile=.travis_coveragerc bin/fail2ban-testcases; else python bin/fail2ban-testcases; fi
after_script:
- if [[ $TRAVIS_PYTHON_VERSION == 2.[6-7] ]] || [[ $TRAVIS_PYTHON_VERSION == 3.3 ]]; then coveralls; fi
- if [[ $TRAVIS_PYTHON_VERSION == 2.7 ]]; then coveralls; fi

View File

@ -4,4 +4,3 @@ branch = True
omit =
/usr/*
/home/travis/virtualenv/*
server/filtergamin.py

View File

@ -4,9 +4,21 @@
|_| \__,_|_|_/___|_.__/\__,_|_||_|
================================================================================
Fail2Ban (version 0.8.8) 2012/12/06
Fail2Ban (version 0.9.0a) 20??/??/??
================================================================================
ver. 0.9.0 (20??/??/??) - alpha
----------
Will carry all fixes in 0.8.x series and new features and enhancements
- Fixes:
- New features:
Steven Hiscocks
* Multiline failregex. Close gh-54
- Enhancements:
ver. 0.8.8 (2012/12/06) - stable
----------
- Fixes:

12
DEVELOP
View File

@ -24,9 +24,9 @@ Request feature. You can find more details on the Fail2Ban wiki
Testing
=======
Existing tests can be run by executing `fail2ban-testcases`. This has options
like --log-level that will probably be useful. `fail2ban-testcases --help` for
full options.
Existing tests can be run by executing `bin/fail2ban-testcases`. This has
options like --log-level that will probably be useful.
`bin/fail2ban-testcases --help` forfull options.
Test cases should cover all usual cases, all exception cases and all inside
/ outside boundary conditions.
@ -39,7 +39,7 @@ Install the package python-coverage to visualise your test coverage. Run the
following (note: on Debian-based systems, the script is called
`python-coverage`):
coverage run fail2ban-testcases
coverage run bin/fail2ban-testcases
coverage html
Then look at htmlcov/index.html and see how much coverage your test cases
@ -249,7 +249,7 @@ Takes care about executing start/check/ban/unban/stop commands
Releasing
=========
# Ensure the version is correct in ./common/version.py
# Ensure the version is correct in ./fail2ban/version.py
# Add/finalize the corresponding entry in the ChangeLog
@ -271,7 +271,7 @@ Releasing
# Run the following and update the wiki with output:
python -c 'import common.protocol; common.protocol.printWiki()'
python -c 'import fail2ban.protocol; fail2ban.protocol.printWiki()'
# Email users and development list of release

113
MANIFEST
View File

@ -5,65 +5,66 @@ THANKS
COPYING
DEVELOP
doc/run-rootless.txt
fail2ban-client
fail2ban-server
fail2ban-testcases
fail2ban-regex
fail2ban-2to3
client/configreader.py
client/configparserinc.py
client/jailreader.py
client/fail2banreader.py
client/jailsreader.py
client/beautifier.py
client/filterreader.py
client/actionreader.py
client/__init__.py
client/configurator.py
client/csocket.py
server/asyncserver.py
server/filter.py
server/filterpyinotify.py
server/filtergamin.py
server/filterpoll.py
server/iso8601.py
server/server.py
server/actions.py
server/faildata.py
server/failmanager.py
server/datedetector.py
server/jailthread.py
server/transmitter.py
server/action.py
server/ticket.py
server/jail.py
server/jails.py
server/__init__.py
server/banmanager.py
server/datetemplate.py
server/mytime.py
server/failregex.py
testcases/files/testcase-usedns.log
testcases/banmanagertestcase.py
testcases/failmanagertestcase.py
testcases/clientreadertestcase.py
testcases/filtertestcase.py
testcases/__init__.py
testcases/datedetectortestcase.py
testcases/actiontestcase.py
testcases/servertestcase.py
testcases/sockettestcase.py
testcases/files/testcase01.log
testcases/files/testcase02.log
testcases/files/testcase03.log
testcases/files/testcase04.log
bin/fail2ban-client
bin/fail2ban-server
bin/fail2ban-testcases
bin/fail2ban-regex
fail2ban/client/configreader.py
fail2ban/client/configparserinc.py
fail2ban/client/jailreader.py
fail2ban/client/fail2banreader.py
fail2ban/client/jailsreader.py
fail2ban/client/beautifier.py
fail2ban/client/filterreader.py
fail2ban/client/actionreader.py
fail2ban/client/__init__.py
fail2ban/client/configurator.py
fail2ban/client/csocket.py
fail2ban/server/asyncserver.py
fail2ban/server/filter.py
fail2ban/server/filterpyinotify.py
fail2ban/server/filtergamin.py
fail2ban/server/filterpoll.py
fail2ban/server/iso8601.py
fail2ban/server/server.py
fail2ban/server/actions.py
fail2ban/server/faildata.py
fail2ban/server/failmanager.py
fail2ban/server/datedetector.py
fail2ban/server/jailthread.py
fail2ban/server/transmitter.py
fail2ban/server/action.py
fail2ban/server/ticket.py
fail2ban/server/jail.py
fail2ban/server/jails.py
fail2ban/server/__init__.py
fail2ban/server/banmanager.py
fail2ban/server/datetemplate.py
fail2ban/server/mytime.py
fail2ban/server/failregex.py
fail2ban/tests/banmanagertestcase.py
fail2ban/tests/failmanagertestcase.py
fail2ban/tests/clientreadertestcase.py
fail2ban/tests/filtertestcase.py
fail2ban/tests/__init__.py
fail2ban/tests/datedetectortestcase.py
fail2ban/tests/actiontestcase.py
fail2ban/tests/servertestcase.py
fail2ban/tests/sockettestcase.py
fail2ban/tests/utils.py
fail2ban/tests/files/testcase01.log
fail2ban/tests/files/testcase02.log
fail2ban/tests/files/testcase03.log
fail2ban/tests/files/testcase04.log
fail2ban/tests/files/testcase-usedns.log
setup.py
setup.cfg
common/__init__.py
common/exceptions.py
common/helpers.py
common/version.py
common/protocol.py
fail2ban/__init__.py
fail2ban/exceptions.py
fail2ban/helpers.py
fail2ban/version.py
fail2ban/protocol.py
config/jail.conf
config/filter.d/common.conf
config/filter.d/apache-auth.conf

2
README
View File

@ -4,7 +4,7 @@
|_| \__,_|_|_/___|_.__/\__,_|_||_|
================================================================================
Fail2Ban (version 0.8.8) 2012/07/31
Fail2Ban (version 0.9.0a0) 20??/??/??
================================================================================
Fail2Ban scans log files like /var/log/pwdfail and bans IP that makes too many

View File

@ -25,19 +25,11 @@ __license__ = "GPL"
import sys, string, os, pickle, re, logging, signal
import getopt, time, shlex, socket
# Inserts our own modules path first in the list
# fix for bug #343821
try:
from common.version import version
except ImportError, e:
sys.path.insert(1, "/usr/share/fail2ban")
from common.version import version
# Now we can import the rest of modules
from common.protocol import printFormatted
from client.csocket import CSocket
from client.configurator import Configurator
from client.beautifier import Beautifier
from fail2ban.version import version
from fail2ban.protocol import printFormatted
from fail2ban.client.csocket import CSocket
from fail2ban.client.configurator import Configurator
from fail2ban.client.beautifier import Beautifier
# Gets the instance of the logger.
logSys = logging.getLogger("fail2ban.client")

View File

@ -23,19 +23,12 @@ __copyright__ = "Copyright (c) 2004 Cyril Jaquier, 2012 Yaroslav Halchenko"
__license__ = "GPL"
import getopt, sys, time, logging, os, locale
# Inserts our own modules path first in the list
# fix for bug #343821
try:
from common.version import version
except ImportError, e:
sys.path.insert(1, "/usr/share/fail2ban")
from common.version import version
from client.configparserinc import SafeConfigParserWithIncludes
from ConfigParser import NoOptionError, NoSectionError, MissingSectionHeaderError
from server.filter import Filter
from server.failregex import RegexException
from fail2ban.version import version
from fail2ban.client.configparserinc import SafeConfigParserWithIncludes
from fail2ban.server.filter import Filter
from fail2ban.server.failregex import RegexException
# Gets the instance of the logger.
logSys = logging.getLogger("fail2ban.regex")
@ -116,6 +109,7 @@ class Fail2banRegex:
print " -h, --help display this help message"
print " -V, --version print the version"
print " -v, --verbose verbose output"
print " -l INT, --maxlines=INT set maxlines for multi-line regex default: 1"
print
print "Log:"
print " string a string representing a log line"
@ -146,6 +140,14 @@ class Fail2banRegex:
self.__verbose = True
elif opt[0] in ["-e", "--encoding"]:
self.encoding = opt[1]
elif opt[0] in ["-l", "--maxlines"]:
try:
self.__filter.setMaxLines(int(opt[1]))
except ValueError:
print "Invlaid value for maxlines: %s" % (
opt[1])
fail2banRegex.dispUsage()
sys.exit(-1)
#@staticmethod
def logIsFile(value):
@ -323,8 +325,8 @@ if __name__ == "__main__":
fail2banRegex = Fail2banRegex()
# Reads the command line options.
try:
cmdOpts = 'e:hVcv'
cmdLongOpts = ['encoding=', 'help', 'version', 'verbose']
cmdOpts = 'hVcvl:e:'
cmdLongOpts = ['help', 'version', 'verbose', 'maxlines=', 'encoding=']
optList, args = getopt.getopt(sys.argv[1:], cmdOpts, cmdLongOpts)
except getopt.GetoptError:
fail2banRegex.dispUsage()

View File

@ -24,15 +24,8 @@ __license__ = "GPL"
import getopt, sys, logging, os
# Inserts our own modules path first in the list
# fix for bug #343821
try:
from common.version import version
except ImportError, e:
sys.path.insert(1, "/usr/share/fail2ban")
from common.version import version
from server.server import Server
from fail2ban.version import version
from fail2ban.server.server import Server
# Gets the instance of the logger.
logSys = logging.getLogger("fail2ban")

View File

@ -27,18 +27,23 @@ __license__ = "GPL"
import unittest, logging, sys, time, os
from common.version import version
from testcases import banmanagertestcase
from testcases import clientreadertestcase
from testcases import failmanagertestcase
from testcases import filtertestcase
from testcases import servertestcase
from testcases import datedetectortestcase
from testcases import actiontestcase
from testcases import sockettestcase
# Check if local fail2ban module exists, and use if it exists by
# modifying the path. This is such that tests can be used in dev
# environment.
if os.path.exists("fail2ban/__init__.py"):
sys.path.insert(0, ".")
from fail2ban.version import version
from fail2ban.tests import banmanagertestcase
from fail2ban.tests import clientreadertestcase
from fail2ban.tests import failmanagertestcase
from fail2ban.tests import filtertestcase
from fail2ban.tests import servertestcase
from fail2ban.tests import datedetectortestcase
from fail2ban.tests import actiontestcase
from fail2ban.tests import sockettestcase
from testcases.utils import FormatterWithTraceBack
from server.mytime import MyTime
from fail2ban.tests.utils import FormatterWithTraceBack
from fail2ban.server.mytime import MyTime
from optparse import OptionParser, Option
@ -147,6 +152,7 @@ tests.addTest(unittest.makeSuite(banmanagertestcase.AddFailure))
# ClientReaders
tests.addTest(unittest.makeSuite(clientreadertestcase.ConfigReaderTest))
tests.addTest(unittest.makeSuite(clientreadertestcase.JailReaderTest))
tests.addTest(unittest.makeSuite(clientreadertestcase.FilterReaderTest))
tests.addTest(unittest.makeSuite(clientreadertestcase.JailsReaderTest))
# CSocket and AsyncServer
tests.addTest(unittest.makeSuite(sockettestcase.Socket))
@ -168,20 +174,20 @@ tests.addTest(unittest.makeSuite(datedetectortestcase.DateDetectorTest))
# Extensive use-tests of different available filters backends
#
from server.filterpoll import FilterPoll
from fail2ban.server.filterpoll import FilterPoll
filters = [FilterPoll] # always available
# Additional filters available only if external modules are available
# yoh: Since I do not know better way for parametric tests
# with good old unittest
try:
from server.filtergamin import FilterGamin
from fail2ban.server.filtergamin import FilterGamin
filters.append(FilterGamin)
except Exception, e: # pragma: no cover
print "I: Skipping gamin backend testing. Got exception '%s'" % e
try:
from server.filterpyinotify import FilterPyinotify
from fail2ban.server.filterpyinotify import FilterPyinotify
filters.append(FilterPyinotify)
except Exception, e: # pragma: no cover
print "I: Skipping pyinotify backend testing. Got exception '%s'" % e

View File

@ -0,0 +1,31 @@
# Fail2Ban configuration file for unsuccesfull MySQL authentication attempts
#
# Authors: Artur Penttinen
# Yaroslav O. Halchenko
#
[INCLUDES]
# Read common prefixes. If any customizations available -- read them from
# common.local
before = common.conf
[Definition]
#_daemon = mysqld
# 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>[\w\-.^_]+)
# Values: TEXT
# 130322 11:26:54 [Warning] Access denied for user 'root'@'127.0.0.1' (using password: YES)
failregex = Access denied for user '\w+'@'<HOST>' (to database '[^']*'|\(using password: (YES|NO)\))*\s*$
# Option: ignoreregex
# Notes.: regex to ignore. If this regex matches, the line is ignored.
# Values: TEXT
#
ignoreregex =

View File

@ -352,6 +352,19 @@ action = iptables-multiport[name=asterisk-udp, port="5060,5061", protocol=udp]
logpath = /var/log/asterisk/messages
maxretry = 10
# To log wrong MySQL access attempts add to /etc/my.cnf:
# log-error=/var/log/mysqld.log
# log-warning = 2
[mysqld-iptables]
enabled = false
filter = mysqld-auth
action = iptables[name=mysql, port=3306, protocol=tcp]
sendmail-whois[name=MySQL, dest=root, sender=fail2ban@example.com]
logpath = /var/log/mysqld.log
maxretry = 5
# Jail for more extended banning of persistent abusers
# !!! WARNING !!!
# Make sure that your loglevel specified in fail2ban.conf/.local

View File

@ -9,7 +9,7 @@ for python in /usr/{,local/}bin/python2.[0-9]{,.*}{,-dbg}
do
[ -e "$python" ] || continue
echo "Testing using $python"
$python ./fail2ban-testcases "$@" || failed+=" $python"
$python bin/fail2ban-testcases "$@" || failed+=" $python"
done
if [ ! -z "$failed" ]; then

View File

@ -31,7 +31,7 @@ import logging
from configreader import ConfigReader
# Gets the instance of the logger.
logSys = logging.getLogger("fail2ban.client.config")
logSys = logging.getLogger(__name__)
class ActionReader(ConfigReader):

View File

@ -23,10 +23,10 @@ __license__ = "GPL"
import logging
from common.exceptions import UnknownJailException, DuplicateJailException
from fail2ban.exceptions import UnknownJailException, DuplicateJailException
# Gets the instance of the logger.
logSys = logging.getLogger("fail2ban.client.config")
logSys = logging.getLogger(__name__)
##
# Beautify the output of the client.

View File

@ -31,7 +31,7 @@ import logging, os
from ConfigParser import SafeConfigParser
# Gets the instance of the logger.
logSys = logging.getLogger("fail2ban.client.config")
logSys = logging.getLogger(__name__)
class SafeConfigParserWithIncludes(SafeConfigParser):
"""

View File

@ -32,7 +32,7 @@ from configparserinc import SafeConfigParserWithIncludes
from ConfigParser import NoOptionError, NoSectionError
# Gets the instance of the logger.
logSys = logging.getLogger("fail2ban.client.config")
logSys = logging.getLogger(__name__)
class ConfigReader(SafeConfigParserWithIncludes):

View File

@ -33,7 +33,7 @@ from fail2banreader import Fail2banReader
from jailsreader import JailsReader
# Gets the instance of the logger.
logSys = logging.getLogger("fail2ban.client.config")
logSys = logging.getLogger(__name__)
class Configurator:

View File

@ -31,7 +31,7 @@ import logging
from configreader import ConfigReader
# Gets the instance of the logger.
logSys = logging.getLogger("fail2ban.client.config")
logSys = logging.getLogger(__name__)
class Fail2banReader(ConfigReader):

View File

@ -31,7 +31,7 @@ import logging
from configreader import ConfigReader
# Gets the instance of the logger.
logSys = logging.getLogger("fail2ban.client.config")
logSys = logging.getLogger(__name__)
class FilterReader(ConfigReader):

View File

@ -34,7 +34,7 @@ from filterreader import FilterReader
from actionreader import ActionReader
# Gets the instance of the logger.
logSys = logging.getLogger("fail2ban.client.config")
logSys = logging.getLogger(__name__)
class JailReader(ConfigReader):
@ -65,6 +65,7 @@ class JailReader(ConfigReader):
["string", "logencoding", "auto"],
["string", "backend", "auto"],
["int", "maxretry", 3],
["int", "maxlines", 1],
["int", "findtime", 600],
["int", "bantime", 600],
["string", "usedns", "warn"],
@ -123,6 +124,8 @@ class JailReader(ConfigReader):
backend = self.__opts[opt]
elif opt == "maxretry":
stream.append(["set", self.__name, "maxretry", self.__opts[opt]])
elif opt == "maxlines":
stream.append(["set", self.__name, "maxlines", self.__opts[opt]])
elif opt == "ignoreip":
for ip in self.__opts[opt].split():
# Do not send a command if the rule is empty.

View File

@ -32,7 +32,7 @@ from configreader import ConfigReader
from jailreader import JailReader
# Gets the instance of the logger.
logSys = logging.getLogger("fail2ban.client.config")
logSys = logging.getLogger(__name__)
class JailsReader(ConfigReader):

View File

@ -68,6 +68,7 @@ protocol = [
["set <JAIL> banip <IP>", "manually Ban <IP> for <JAIL>"],
["set <JAIL> unbanip <IP>", "manually Unban <IP> in <JAIL>"],
["set <JAIL> maxretry <RETRY>", "sets the number of failures <RETRY> before banning the host for <JAIL>"],
["set <JAIL> maxlines <LINES>", "sets the number of <LINES> to buffer for regex search for <JAIL>"],
["set <JAIL> addaction <ACT>", "adds a new action named <NAME> for <JAIL>"],
["set <JAIL> delaction <ACT>", "removes the action <NAME> from <JAIL>"],
["set <JAIL> setcinfo <ACT> <KEY> <VALUE>", "sets <VALUE> for <KEY> of the action <NAME> for <JAIL>"],
@ -87,6 +88,7 @@ protocol = [
["get <JAIL> bantime", "gets the time a host is banned for <JAIL>"],
["get <JAIL> usedns", "gets the usedns setting for <JAIL>"],
["get <JAIL> maxretry", "gets the number of failures allowed for <JAIL>"],
["get <JAIL> maxlines", "gets the number of lines to buffer for <JAIL>"],
["get <JAIL> addaction", "gets the last action which has been added for <JAIL>"],
["get <JAIL> actionstart <ACT>", "gets the start command for the action <ACT> for <JAIL>"],
["get <JAIL> actionstop <ACT>", "gets the stop command for the action <ACT> for <JAIL>"],

View File

@ -32,7 +32,7 @@ import threading
#from subprocess import call
# Gets the instance of the logger.
logSys = logging.getLogger("fail2ban.actions.action")
logSys = logging.getLogger(__name__)
# Create a lock for running system commands
_cmd_lock = threading.Lock()

View File

@ -34,7 +34,7 @@ from mytime import MyTime
import time, logging
# Gets the instance of the logger.
logSys = logging.getLogger("fail2ban.actions")
logSys = logging.getLogger(__name__)
##
# Execute commands.

View File

@ -28,11 +28,12 @@ __copyright__ = "Copyright (c) 2004 Cyril Jaquier"
__license__ = "GPL"
from pickle import dumps, loads, HIGHEST_PROTOCOL
from common import helpers
import asyncore, asynchat, socket, os, logging, sys, traceback
from fail2ban import helpers
# Gets the instance of the logger.
logSys = logging.getLogger("fail2ban.server")
logSys = logging.getLogger(__name__)
##
# Request handler class.

View File

@ -33,7 +33,7 @@ from mytime import MyTime
import logging
# Gets the instance of the logger.
logSys = logging.getLogger("fail2ban.action")
logSys = logging.getLogger(__name__)
##
# Banning Manager.

View File

@ -33,7 +33,7 @@ from datetemplate import DateStrptime, DateTai64n, DateEpoch, DateISO8601
from threading import Lock
# Gets the instance of the logger.
logSys = logging.getLogger("fail2ban.filter.datedetector")
logSys = logging.getLogger(__name__)
class DateDetector:
@ -155,6 +155,12 @@ class DateDetector:
template.setRegex("^<\d{2}/\d{2}/\d{2}@\d{2}:\d{2}:\d{2}>")
template.setPattern("<%m/%d/%y@%H:%M:%S>")
self._appendTemplate(template)
# MySQL: 130322 11:46:11
template = DateStrptime()
template.setName("MonthDayYear Hour:Minute:Second")
template.setRegex("^\d{2}\d{2}\d{2} +\d{1,2}:\d{2}:\d{2}")
template.setPattern("%y%m%d %H:%M:%S")
self._appendTemplate(template)
finally:
self.__lock.release()

View File

@ -33,7 +33,7 @@ from mytime import MyTime
import iso8601
import logging
logSys = logging.getLogger("fail2ban.datetemplate")
logSys = logging.getLogger(__name__)
class DateTemplate:

View File

@ -30,7 +30,7 @@ __license__ = "GPL"
import logging
# Gets the instance of the logger.
logSys = logging.getLogger("fail2ban")
logSys = logging.getLogger(__name__)
class FailData:

View File

@ -33,7 +33,7 @@ from threading import Lock
import logging
# Gets the instance of the logger.
logSys = logging.getLogger("fail2ban.filter")
logSys = logging.getLogger(__name__)
class FailManager:

View File

@ -48,10 +48,15 @@ class Regex:
# Perform shortcuts expansions.
# Replace "<HOST>" with default regular expression for host.
regex = regex.replace("<HOST>", "(?:::f{4,6}:)?(?P<host>[\w\-.^_]+)")
# Replace "<SKIPLINES>" with regular expression for multiple lines.
regexSplit = regex.split("<SKIPLINES>")
regex = regexSplit[0]
for n, regexLine in enumerate(regexSplit[1:]):
regex += "\n(?P<skiplines%i>(?:(.*\n)*?))" % n + regexLine
if regex.lstrip() == '':
raise RegexException("Cannot add empty regex")
try:
self._regexObj = re.compile(regex)
self._regexObj = re.compile(regex, re.MULTILINE)
self._regex = regex
except sre_constants.error:
raise RegexException("Unable to compile regular expression '%s'" %
@ -76,6 +81,19 @@ class Regex:
def search(self, value):
self._matchCache = self._regexObj.search(value)
if self.hasMatched():
# Find start of the first line where the match was found
try:
self._matchLineStart = self._matchCache.string.rindex(
"\n", 0, self._matchCache.start() +1 ) + 1
except ValueError:
self._matchLineStart = 0
# Find end of the last line where the match was found
try:
self._matchLineEnd = self._matchCache.string.index(
"\n", self._matchCache.end() - 1) + 1
except ValueError:
self._matchLineEnd = len(self._matchCache.string)
##
# Checks if the previous call to search() matched.
@ -88,6 +106,54 @@ class Regex:
else:
return False
##
# Returns skipped lines.
#
# This returns skipped lines captured by the <SKIPLINES> tag.
# @return list of skipped lines
def getSkippedLines(self):
if not self._matchCache:
return []
skippedLines = ""
n = 0
while True:
try:
skippedLines += self._matchCache.group("skiplines%i" % n)
n += 1
except IndexError:
break
return skippedLines.splitlines(True)
##
# Returns unmatched lines.
#
# This returns unmatched lines including captured by the <SKIPLINES> tag.
# @return list of unmatched lines
def getUnmatchedLines(self):
if not self.hasMatched():
return []
unmatchedLines = (
self._matchCache.string[:self._matchLineStart].splitlines(True)
+ self.getSkippedLines()
+ self._matchCache.string[self._matchLineEnd:].splitlines(True))
return unmatchedLines
##
# Returns matched lines.
#
# This returns matched lines by excluding those captured
# by the <SKIPLINES> tag.
# @return list of matched lines
def getMatchedLines(self):
if not self.hasMatched():
return []
matchedLines = self._matchCache.string[
self._matchLineStart:self._matchLineEnd].splitlines(True)
return [line for line in matchedLines
if line not in self.getSkippedLines()]
##
# Exception dedicated to the class Regex.

View File

@ -38,7 +38,7 @@ from failregex import FailRegex, Regex, RegexException
import logging, re, os, fcntl, time, sys, locale, codecs
# Gets the instance of the logger.
logSys = logging.getLogger("fail2ban.filter")
logSys = logging.getLogger(__name__)
##
# Log reader class.
@ -71,6 +71,12 @@ class Filter(JailThread):
self.__findTime = 6000
## The ignore IP list.
self.__ignoreIpList = []
## Size of line buffer
self.__lineBufferSize = 1
## Line buffer
self.__lineBuffer = []
## Store last time stamp, applicable for multi-line
self.__lastTimeLine = ""
self.dateDetector = DateDetector()
self.dateDetector.addDefaultTemplate()
@ -206,6 +212,23 @@ class Filter(JailThread):
def getMaxRetry(self):
return self.failManager.getMaxRetry()
##
# Set the maximum line buffer size.
#
# @param value the line buffer size
def setMaxLines(self, value):
self.__lineBufferSize = max(1, value)
logSys.info("Set maxLines = %i" % self.__lineBufferSize)
##
# Get the maximum line buffer size.
#
# @return the line buffer size
def getMaxLines(self):
return self.__lineBufferSize
##
# Main loop.
#
@ -295,14 +318,17 @@ class Filter(JailThread):
if timeMatch:
# Lets split into time part and log part of the line
timeLine = timeMatch.group()
self.__lastTimeLine = timeLine
# 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 = line[:timeMatch.start()] + line[timeMatch.end():]
else:
timeLine = line
timeLine = self.__lastTimeLine or line
logLine = line
return self.findFailure(timeLine, logLine)
self.__lineBuffer = ((self.__lineBuffer +
[logLine])[-self.__lineBufferSize:])
return self.findFailure(timeLine, "".join(self.__lineBuffer))
def processLineAndAdd(self, line):
"""Processes the line for failures and populates failManager
@ -345,14 +371,15 @@ class Filter(JailThread):
def findFailure(self, timeLine, logLine):
failList = list()
# Checks if we must ignore this line.
if self.ignoreLine(logLine):
# The ignoreregex matched. Return.
return failList
# Iterates over all the regular expressions.
for failRegex in self.__failRegex:
failRegex.search(logLine)
if failRegex.hasMatched():
# Checks if we must ignore this match.
if self.ignoreLine("".join(failRegex.getMatchedLines())):
# The ignoreregex matched. Remove ignored match.
self.__lineBuffer = failRegex.getUnmatchedLines()
continue
# The failregex matched.
date = self.dateDetector.getUnixTime(timeLine)
if date == None:
@ -362,6 +389,7 @@ class Filter(JailThread):
"in order to get support for this format."
% (logLine, timeLine))
else:
self.__lineBuffer = failRegex.getUnmatchedLines()
try:
host = failRegex.getHost()
ipMatch = DNSUtils.textToIp(host, self.__useDns)

View File

@ -30,7 +30,7 @@ from mytime import MyTime
import time, logging, gamin
# Gets the instance of the logger.
logSys = logging.getLogger("fail2ban.filter")
logSys = logging.getLogger(__name__)
##
# Log reader class.

View File

@ -33,7 +33,7 @@ from mytime import MyTime
import time, logging, os
# Gets the instance of the logger.
logSys = logging.getLogger("fail2ban.filter")
logSys = logging.getLogger(__name__)
##
# Log reader class.

View File

@ -38,7 +38,7 @@ if not hasattr(pyinotify, '__version__') \
from os.path import dirname, sep as pathsep
# Gets the instance of the logger.
logSys = logging.getLogger("fail2ban.filter")
logSys = logging.getLogger(__name__)
##
# Log reader class.

View File

@ -28,7 +28,7 @@ import Queue, logging
from actions import Actions
# Gets the instance of the logger.
logSys = logging.getLogger("fail2ban.jail")
logSys = logging.getLogger(__name__)
class Jail:

View File

@ -21,7 +21,7 @@ __author__ = "Cyril Jaquier, Yaroslav Halchenko"
__copyright__ = "Copyright (c) 2004 Cyril Jaquier, 2013- Yaroslav Halchenko"
__license__ = "GPL"
from common.exceptions import DuplicateJailException, UnknownJailException
from fail2ban.exceptions import DuplicateJailException, UnknownJailException
from jail import Jail
from threading import Lock

View File

@ -31,7 +31,7 @@ from threading import Thread
import logging
# Gets the instance of the logger.
logSys = logging.getLogger("fail2ban.server")
logSys = logging.getLogger(__name__)
class JailThread(Thread):

View File

@ -32,11 +32,11 @@ from jails import Jails
from transmitter import Transmitter
from asyncserver import AsyncServer
from asyncserver import AsyncServerException
from common import version
from fail2ban import version
import logging, logging.handlers, sys, os, signal
# Gets the instance of the logger.
logSys = logging.getLogger("fail2ban.server")
logSys = logging.getLogger(__name__)
class Server:
@ -223,6 +223,12 @@ class Server:
def getMaxRetry(self, name):
return self.__jails.getFilter(name).getMaxRetry()
def setMaxLines(self, name, value):
self.__jails.getFilter(name).setMaxLines(value)
def getMaxLines(self, name):
return self.__jails.getFilter(name).getMaxLines()
# Action
def addAction(self, name, value):
self.__jails.getAction(name).addAction(value)
@ -326,7 +332,7 @@ class Server:
logLevel = logging.WARNING
elif value == 3:
logLevel = logging.INFO
logging.getLogger("fail2ban").setLevel(logLevel)
logging.getLogger(__name__).parent.parent.setLevel(logLevel)
finally:
self.__loggingLock.release()
@ -375,9 +381,10 @@ class Server:
return False
# Removes previous handlers -- in reverse order since removeHandler
# alter the list in-place and that can confuses the iterable
for handler in logging.getLogger("fail2ban").handlers[::-1]:
logger = logging.getLogger(__name__).parent.parent
for handler in logger.handlers[::-1]:
# Remove the handler.
logging.getLogger("fail2ban").removeHandler(handler)
logger.removeHandler(handler)
# And try to close -- it might be closed already
try:
handler.flush()
@ -390,7 +397,7 @@ class Server:
# with older Pythons -- seems to be safe to ignore there
# tell the handler to use this format
hdlr.setFormatter(formatter)
logging.getLogger("fail2ban").addHandler(hdlr)
logger.addHandler(hdlr)
# Does not display this message at startup.
if not self.__logTarget == None:
logSys.info("Changed logging target to %s for Fail2ban v%s" %

View File

@ -30,7 +30,7 @@ __license__ = "GPL"
import logging
# Gets the instance of the logger.
logSys = logging.getLogger("fail2ban")
logSys = logging.getLogger(__name__)
class Ticket:

View File

@ -30,7 +30,7 @@ __license__ = "GPL"
import logging, time
# Gets the instance of the logger.
logSys = logging.getLogger("fail2ban.comm")
logSys = logging.getLogger(__name__)
class Transmitter:
@ -175,6 +175,10 @@ class Transmitter:
value = command[2]
self.__server.setMaxRetry(name, int(value))
return self.__server.getMaxRetry(name)
elif command[1] == "maxlines":
value = command[2]
self.__server.setMaxLines(name, int(value))
return self.__server.getMaxLines(name)
# command
elif command[1] == "bantime":
value = command[2]
@ -256,6 +260,8 @@ class Transmitter:
return self.__server.getFindTime(name)
elif command[1] == "maxretry":
return self.__server.getMaxRetry(name)
elif command[1] == "maxlines":
return self.__server.getMaxLines(name)
# Action
elif command[1] == "bantime":
return self.__server.getBanTime(name)

View File

@ -29,9 +29,10 @@ __license__ = "GPL"
import unittest, time
import logging, sys
from server.action import Action
from StringIO import StringIO
from fail2ban.server.action import Action
class ExecuteAction(unittest.TestCase):
def setUp(self):

View File

@ -28,8 +28,9 @@ __copyright__ = "Copyright (c) 2004 Cyril Jaquier"
__license__ = "GPL"
import unittest
from server.banmanager import BanManager
from server.ticket import BanTicket
from fail2ban.server.banmanager import BanManager
from fail2ban.server.ticket import BanTicket
class AddFailure(unittest.TestCase):

View File

@ -22,10 +22,18 @@ __copyright__ = "Copyright (c) 2004 Cyril Jaquier, 2011-2013 Yaroslav Halchenko"
__license__ = "GPL"
import os, shutil, tempfile, unittest
from client.configreader import ConfigReader
from client.jailreader import JailReader
from client.jailsreader import JailsReader
from client.configurator import Configurator
from fail2ban.client.configreader import ConfigReader
from fail2ban.client.jailreader import JailReader
from fail2ban.client.filterreader import FilterReader
from fail2ban.client.jailsreader import JailsReader
from fail2ban.client.configurator import Configurator
TEST_FILES_DIR = os.path.join(os.path.dirname(__file__), "files")
if os.path.exists('config/fail2ban.conf'):
CONFIG_DIR='config'
else:
CONFIG_DIR='/etc/fail2ban'
class ConfigReaderTest(unittest.TestCase):
@ -98,7 +106,7 @@ option = %s
class JailReaderTest(unittest.TestCase):
def testStockSSHJail(self):
jail = JailReader('ssh-iptables', basedir='config') # we are running tests from root project dir atm
jail = JailReader('ssh-iptables', basedir=CONFIG_DIR) # we are running tests from root project dir atm
self.assertTrue(jail.read())
self.assertTrue(jail.getOptions())
self.assertFalse(jail.isEnabled())
@ -109,6 +117,36 @@ class JailReaderTest(unittest.TestCase):
expected = ['mail-whois', {'name': 'SSH'}]
result = JailReader.splitAction(action)
self.assertEquals(expected, result)
class FilterReaderTest(unittest.TestCase):
def testConvert(self):
output = [['set', 'testcase01', 'addfailregex',
"^\\s*(?:\\S+ )?(?:kernel: \\[\\d+\\.\\d+\\] )?(?:@vserver_\\S+ )"
"?(?:(?:\\[\\d+\\])?:\\s+[\\[\\(]?sshd(?:\\(\\S+\\))?[\\]\\)]?:?|"
"[\\[\\(]?sshd(?:\\(\\S+\\))?[\\]\\)]?:?(?:\\[\\d+\\])?:)?\\s*(?:"
"error: PAM: )?Authentication failure for .* from <HOST>\\s*$"],
['set', 'testcase01', 'addfailregex',
"^\\s*(?:\\S+ )?(?:kernel: \\[\\d+\\.\\d+\\] )?(?:@vserver_\\S+ )"
"?(?:(?:\\[\\d+\\])?:\\s+[\\[\\(]?sshd(?:\\(\\S+\\))?[\\]\\)]?:?|"
"[\\[\\(]?sshd(?:\\(\\S+\\))?[\\]\\)]?:?(?:\\[\\d+\\])?:)?\\s*(?:"
"error: PAM: )?User not known to the underlying authentication mo"
"dule for .* from <HOST>\\s*$"],
['set', 'testcase01', 'addfailregex',
"^\\s*(?:\\S+ )?(?:kernel: \\[\\d+\\.\\d+\\] )?(?:@vserver_\\S+ )"
"?(?:(?:\\[\\d+\\])?:\\s+[\\[\\(]?sshd(?:\\(\\S+\\))?[\\]\\)]?:?|"
"[\\[\\(]?sshd(?:\\(\\S+\\))?[\\]\\)]?:?(?:\\[\\d+\\])?:)?\\s*(?:"
"error: PAM: )?User not known to the\\nunderlying authentication."
"+$<SKIPLINES>^.+ module for .* from <HOST>\\s*$"],
['set', 'testcase01', 'addignoreregex',
"^.+ john from host 192.168.1.1\\s*$"]]
filterReader = FilterReader("testcase01", "testcase01")
filterReader.setBaseDir(TEST_FILES_DIR)
filterReader.read()
#filterReader.getOptions(["failregex", "ignoreregex"])
filterReader.getOptions(None)
self.assertEquals(filterReader.convert(), output)
class JailsReaderTest(unittest.TestCase):
@ -118,7 +156,7 @@ class JailsReaderTest(unittest.TestCase):
self.assertRaises(ValueError, reader.read)
def testReadStockJailConf(self):
jails = JailsReader(basedir='config') # we are running tests from root project dir atm
jails = JailsReader(basedir=CONFIG_DIR) # we are running tests from root project dir atm
self.assertTrue(jails.read()) # opens fine
self.assertTrue(jails.getOptions()) # reads fine
comm_commands = jails.convert()
@ -129,7 +167,7 @@ class JailsReaderTest(unittest.TestCase):
def testReadStockJailConfForceEnabled(self):
# more of a smoke test to make sure that no obvious surprises
# on users' systems when enabling shipped jails
jails = JailsReader(basedir='config', force_enable=True) # we are running tests from root project dir atm
jails = JailsReader(basedir=CONFIG_DIR, force_enable=True) # we are running tests from root project dir atm
self.assertTrue(jails.read()) # opens fine
self.assertTrue(jails.getOptions()) # reads fine
comm_commands = jails.convert()
@ -151,8 +189,8 @@ class JailsReaderTest(unittest.TestCase):
def testConfigurator(self):
configurator = Configurator()
configurator.setBaseDir('config')
self.assertEqual(configurator.getBaseDir(), 'config')
configurator.setBaseDir(CONFIG_DIR)
self.assertEqual(configurator.getBaseDir(), CONFIG_DIR)
configurator.readEarly()
opts = configurator.getEarlyOptions()
@ -165,4 +203,4 @@ class JailsReaderTest(unittest.TestCase):
# otherwise just a code smoke test)
configurator._Configurator__jails.setBaseDir('/tmp')
self.assertEqual(configurator._Configurator__jails.getBaseDir(), '/tmp')
self.assertEqual(configurator.getBaseDir(), 'config')
self.assertEqual(configurator.getBaseDir(), CONFIG_DIR)

View File

@ -28,8 +28,9 @@ __copyright__ = "Copyright (c) 2004 Cyril Jaquier"
__license__ = "GPL"
import unittest
from server.datedetector import DateDetector
from server.datetemplate import DateTemplate
from fail2ban.server.datedetector import DateDetector
from fail2ban.server.datetemplate import DateTemplate
class DateDetectorTest(unittest.TestCase):
@ -84,6 +85,7 @@ class DateDetectorTest(unittest.TestCase):
"2005-01-23T21:59:59.252Z", #ISO 8601
"2005-01-23T21:59:59-05:00Z", #ISO 8601 with TZ
"<01/23/05@21:59:59>",
"050123 21:59:59", # MySQL
):
log = sdate + "[sshd] error: PAM: Authentication failure"
# exclude

View File

@ -28,8 +28,9 @@ __copyright__ = "Copyright (c) 2004 Cyril Jaquier"
__license__ = "GPL"
import unittest, socket, time, pickle
from server.failmanager import FailManager, FailManagerEmpty
from server.ticket import FailTicket
from fail2ban.server.failmanager import FailManager, FailManagerEmpty
from fail2ban.server.ticket import FailTicket
class AddFailure(unittest.TestCase):

View File

@ -0,0 +1,41 @@
# Generic configuration items (to be used as interpolations) in other
# filters or actions configurations
#
# Author: Yaroslav Halchenko
#
# $Revision$
#
[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?:)
# Some messages have a kernel prefix with a timestamp
# EXAMPLES: kernel: [769570.846956]
__kernel_prefix = kernel: \[\d+\.\d+\]
__hostname = \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*(?:%(__hostname)s )?(?:%(__kernel_prefix)s )?(?:@vserver_\S+ )?%(__daemon_combs_re)s?\s*

View File

@ -0,0 +1,34 @@
# Fail2Ban configuration file
#
# Author: Cyril Jaquier
#
# $Revision$
#
[INCLUDES]
# Read common prefixes. If any customizations available -- read them from
# common.local
before = testcase-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
# be used for standard IP/hostname matching and is only an alias for
# (?:::f{4,6}:)?(?P<host>[\w\-.^_]+)
# Values: TEXT
#
failregex = ^%(__prefix_line)s(?:error: PAM: )?Authentication failure for .* from <HOST>\s*$
^%(__prefix_line)s(?:error: PAM: )?User not known to the underlying authentication module for .* from <HOST>\s*$
^%(__prefix_line)s(?:error: PAM: )?User not known to the\nunderlying authentication.+$<SKIPLINES>^.+ module for .* from <HOST>\s*$
# Option: ignoreregex
# Notes.: regex to ignore. If this regex matches, the line is ignored.
# Values: TEXT
#
ignoreregex = ^.+ john from host 192.168.1.1\s*$

View File

@ -0,0 +1,6 @@
130324 0:04:00 [Warning] Access denied for user 'root'@'192.168.1.35' (using password: NO)
130324 8:24:09 [Warning] Access denied for user 'root'@'220.95.238.171' (using password: NO)
130324 17:56:13 [Warning] Access denied for user 'root'@'61.160.223.112' (using password: NO)
130324 17:56:14 [Warning] Access denied for user 'root'@'61.160.223.112' (using password: YES)
130324 19:01:39 [Warning] Access denied for user 'root'@'61.147.108.35' (using password: NO)
130324 19:01:40 [Warning] Access denied for user 'root'@'61.147.108.35' (using password: YES)

View File

@ -0,0 +1,35 @@
Aug 14 11:58:58 yyyy rsyncd[9874]: connect from example.com (192.0.43.10)
Aug 14 11:58:58 yyyy rsyncd[23864]: connect from example.com (192.0.43.10)
Aug 14 11:59:58 yyyy rsyncd[23864]: rsync on xxx/ from example.com (192.0.43.10)
Aug 14 11:59:58 yyyy rsyncd[23864]: building file list
Aug 14 11:59:58 yyyy rsyncd[28101]: connect from irrelevant (192.0.43.11)
Aug 14 11:59:58 yyyy rsyncd[28101]: rsync on xxx/ from irrelevant (192.0.43.11)
Aug 14 11:59:58 yyyy rsyncd[28101]: building file list
Aug 14 11:59:58 yyyy rsyncd[28101]: sent 294382 bytes received 781 bytes total size 29221543998
Aug 14 11:59:58 yyyy rsyncd[18067]: sent 2833586339 bytes received 65115 bytes total size 29221543998
Aug 14 11:59:58 yyyy smartd[2635]: Device: /dev/sdb [SAT], SMART Usage Attribute: 194 Temperature_Celsius changed from 116 to 115
Aug 14 11:59:58 yyyy rsyncd[1762]: connect from irrelevant (192.0.43.11)
Aug 14 11:59:58 yyyy rsyncd[1762]: rsync on xxx/ from irrelevant (192.0.43.11)
Aug 14 11:59:58 yyyy rsyncd[1762]: building file list
Aug 14 11:59:58 yyyy rsyncd[1762]: sent 294382 bytes received 781 bytes total size 29221543998
Aug 14 11:59:58 yyyy sendmail[30222]: r0NNNlC0030222: from=<bounce-25497-9881290652-user=example.com@example.com>, size=6420, class=0, nrcpts=1, msgid=<0.0.9881290652.3772024cf8879cycvau18081.0@example.com>, bodytype=8BITMIME, proto=ESMTP, daemon=MTA, relay=[192.0.43.15] (may be forged)
Aug 14 11:59:58 yyyy smartd[2635]: Device: /dev/sda [SAT], starting scheduled Short Self-Test.
Aug 14 11:59:58 yyyy smartd[2635]: Device: /dev/sdb [SAT], SMART Usage Attribute: 194 Temperature_Celsius changed from 115 to 116
Aug 14 11:59:58 yyyy smartd[2635]: Device: /dev/sdb [SAT], starting scheduled Short Self-Test.
Aug 14 11:59:58 yyyy smartd[2635]: Device: /dev/sda [SAT], previous self-test completed without error
Aug 14 11:59:58 yyyy smartd[2635]: Device: /dev/sdb [SAT], previous self-test completed without error
Aug 14 11:59:58 yyyy rsyncd[7788]: connect from irrelevant (192.0.43.11)
Aug 14 11:59:58 yyyy rsyncd[7788]: rsync on xxx/ from irrelevant (192.0.43.11)
Aug 14 11:59:58 yyyy rsyncd[7788]: building file list
Aug 14 11:59:58 yyyy rsyncd[21919]: sent 2836906453 bytes received 6768 bytes total size 29221543998
Aug 14 11:59:58 yyyy rsyncd[23864]: rsync error: timeout in data send/receive (code 30) at io.c(137) [sender=3.0.9]
Aug 14 11:59:58 yyyy spamd[19119]: spamd: result: Y 11 - AWL,BAYES_50,DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,HTML_MESSAGE,RCVD_IN_BRBL_LASTEXT,RCVD_IN_PSBL,RCVD_IN_RP_RNBL,RDNS_NONE,URIBL_BLACK,URIBL_DBL_SPAM scantime=1.2,size=6910,user=sa-milt,uid=499,required_score=5.0,rhost=localhost,raddr=127.0.0.1,rport=57429,mid=<0.0.9881290652.3772024cf8879cycvau18081.0@example.com>,bayes=0.536244,autolearn=no
Aug 14 11:59:58 yyyy rsyncd[5534]: connect from irrelevant (192.0.43.11)
Aug 14 11:59:58 yyyy rsyncd[5534]: rsync on xxx/ from irrelevant (192.0.43.11)
Aug 14 11:59:58 yyyy rsyncd[5534]: building file list
Aug 14 11:59:58 yyyy rsyncd[7788]: rsync error: Received SIGINT
Aug 14 11:59:58 yyyy rsyncd[5534]: sent 294382 bytes received 781 bytes total size 29221543998
Aug 14 11:59:59 yyyy rsyncd[9874]: rsync error: timeout in data send/receive (code 30) at io.c(137) [sender=3.0.9]

View File

@ -1,15 +1,15 @@
Sep 21 22:03:07 [sshd] Invalid user toto from 212.41.96.185
1124012400 [sshd] Invalid user fuck from 212.41.96.185
1124012400 [sshd] Invalid user duck from 212.41.96.185
Sep 21 21:03:38 [sshd] Invalid user toto from 212.41.96.185
1124012500 [sshd] Invalid user fuck from 212.41.96.185
1124012500 [sshd] Invalid user duck from 212.41.96.185
Sep 21 21:03:46 [sshd] Invalid user toto from 212.41.96.185
Aug 14 11:58:48 [sshd] Invalid user fuck from 212.41.96.185
Aug 14 11:58:48 [sshd] Invalid user duck from 212.41.96.185
Aug 14 11:59:58 [sshd] Invalid user toto from 212.41.96.185
Sep 21 21:04:03 [sshd] Invalid user fuck from 212.41.96.185
Sep 21 21:04:03 [sshd] Invalid user duck from 212.41.96.185
- Last output repeated twice -
2005/08/14 11:57:00 [sshd] Invalid user toto from 212.41.96.186
2005/08/14 11:58:00 [sshd] Invalid user fuck from 212.41.96.186
2005/08/14 11:58:00 [sshd] Invalid user duck from 212.41.96.186
2005/08/14 11:59:00 [sshd] Invalid user toto from 212.41.96.186
2005/08/14 12:00:00 [sshd] Invalid user fuck from 212.41.96.186
2005/08/14 12:00:00 [sshd] Invalid user duck from 212.41.96.186
- Last output repeated twice -
Sep 21 21:09:01 [sshd] Invalid user toto from 212.41.96.185

View File

@ -28,11 +28,13 @@ import sys
import time
import tempfile
from server.jail import Jail
from server.filterpoll import FilterPoll
from server.filter import FileFilter, DNSUtils
from server.failmanager import FailManager
from server.failmanager import FailManagerEmpty
from fail2ban.server.jail import Jail
from fail2ban.server.filterpoll import FilterPoll
from fail2ban.server.filter import FileFilter, DNSUtils
from fail2ban.server.failmanager import FailManager
from fail2ban.server.failmanager import FailManagerEmpty
TEST_FILES_DIR = os.path.join(os.path.dirname(__file__), "files")
#
# Useful helpers
@ -179,7 +181,7 @@ class IgnoreIP(unittest.TestCase):
class LogFile(unittest.TestCase):
FILENAME = "testcases/files/testcase01.log"
FILENAME = os.path.join(TEST_FILES_DIR, "testcase01.log")
def setUp(self):
"""Call before every test case."""
@ -519,11 +521,12 @@ def get_monitor_failures_testcase(Filter_):
class GetFailures(unittest.TestCase):
FILENAME_01 = "testcases/files/testcase01.log"
FILENAME_02 = "testcases/files/testcase02.log"
FILENAME_03 = "testcases/files/testcase03.log"
FILENAME_04 = "testcases/files/testcase04.log"
FILENAME_USEDNS = "testcases/files/testcase-usedns.log"
FILENAME_01 = os.path.join(TEST_FILES_DIR, "testcase01.log")
FILENAME_02 = os.path.join(TEST_FILES_DIR, "testcase02.log")
FILENAME_03 = os.path.join(TEST_FILES_DIR, "testcase03.log")
FILENAME_04 = os.path.join(TEST_FILES_DIR, "testcase04.log")
FILENAME_USEDNS = os.path.join(TEST_FILES_DIR, "testcase-usedns.log")
FILENAME_MULTILINE = os.path.join(TEST_FILES_DIR, "testcase-multiline.log")
# so that they could be reused by other tests
FAILURES_01 = ('193.168.0.128', 3, 1124013599.0,
@ -629,6 +632,53 @@ class GetFailures(unittest.TestCase):
self.assertRaises(FailManagerEmpty, self.filter.failManager.toBan)
def testGetFailuresMultiLine(self):
output = [("192.0.43.10", 2, 1124013599.0),
("192.0.43.11", 1, 1124013598.0)]
self.filter.addLogPath(GetFailures.FILENAME_MULTILINE)
self.filter.addFailRegex("^.*rsyncd\[(?P<pid>\d+)\]: connect from .+ \(<HOST>\)$<SKIPLINES>^.+ rsyncd\[(?P=pid)\]: rsync error: .*$")
self.filter.setMaxLines(100)
self.filter.setMaxRetry(1)
self.filter.getFailures(GetFailures.FILENAME_MULTILINE)
_assert_correct_last_attempt(self, self.filter, output.pop())
_assert_correct_last_attempt(self, self.filter, output.pop())
self.assertRaises(FailManagerEmpty, self.filter.failManager.toBan)
def testGetFailuresMultiLineIgnoreRegex(self):
output = [("192.0.43.10", 2, 1124013599.0)]
self.filter.addLogPath(GetFailures.FILENAME_MULTILINE)
self.filter.addFailRegex("^.*rsyncd\[(?P<pid>\d+)\]: connect from .+ \(<HOST>\)$<SKIPLINES>^.+ rsyncd\[(?P=pid)\]: rsync error: .*$")
self.filter.addIgnoreRegex("rsync error: Received SIGINT")
self.filter.setMaxLines(100)
self.filter.setMaxRetry(1)
self.filter.getFailures(GetFailures.FILENAME_MULTILINE)
_assert_correct_last_attempt(self, self.filter, output.pop())
self.assertRaises(FailManagerEmpty, self.filter.failManager.toBan)
def testGetFailuresMultiLineMultiRegex(self):
output = [("192.0.43.10", 2, 1124013599.0),
("192.0.43.11", 1, 1124013598.0),
("192.0.43.15", 1, 1124013598.0)]
self.filter.addLogPath(GetFailures.FILENAME_MULTILINE)
self.filter.addFailRegex("^.*rsyncd\[(?P<pid>\d+)\]: connect from .+ \(<HOST>\)$<SKIPLINES>^.+ rsyncd\[(?P=pid)\]: rsync error: .*$")
self.filter.addFailRegex("^.* sendmail\[.*, msgid=<(?P<msgid>[^>]+).*relay=\[<HOST>\].*$<SKIPLINES>^.+ spamd: result: Y \d+ .*,mid=<(?P=msgid)>(,bayes=[.\d]+)?(,autolearn=\S+)?\s*$")
self.filter.setMaxLines(100)
self.filter.setMaxRetry(1)
self.filter.getFailures(GetFailures.FILENAME_MULTILINE)
_assert_correct_last_attempt(self, self.filter, output.pop())
_assert_correct_last_attempt(self, self.filter, output.pop())
_assert_correct_last_attempt(self, self.filter, output.pop())
self.assertRaises(FailManagerEmpty, self.filter.failManager.toBan)
class DNSUtilsTests(unittest.TestCase):
def testUseDns(self):

View File

@ -28,8 +28,11 @@ __copyright__ = "Copyright (c) 2004 Cyril Jaquier"
__license__ = "GPL"
import unittest, socket, time, tempfile, os, locale
from server.server import Server
from common.exceptions import UnknownJailException
from fail2ban.server.server import Server
from fail2ban.exceptions import UnknownJailException
TEST_FILES_DIR = os.path.join(os.path.dirname(__file__), "files")
class StartStop(unittest.TestCase):
@ -279,14 +282,14 @@ class Transmitter(TransmitterBase):
self.jailAddDelTest(
"logpath",
[
"testcases/files/testcase01.log",
"testcases/files/testcase02.log",
"testcases/files/testcase03.log",
os.path.join(TEST_FILES_DIR, "testcase01.log"),
os.path.join(TEST_FILES_DIR, "testcase02.log"),
os.path.join(TEST_FILES_DIR, "testcase03.log"),
],
self.jailName
)
# Try duplicates
value = "testcases/files/testcase04.log"
value = os.path.join(TEST_FILES_DIR, "testcase04.log")
self.assertEqual(
self.transm.proceed(["set", self.jailName, "addlogpath", value]),
(0, [value]))

View File

@ -28,8 +28,9 @@ __copyright__ = "Copyright (c) 2013 Steven Hiscocks"
__license__ = "GPL"
import unittest, time, tempfile, os, threading
from server.asyncserver import AsyncServer, AsyncServerException
from client.csocket import CSocket
from fail2ban.server.asyncserver import AsyncServer, AsyncServerException
from fail2ban.client.csocket import CSocket
class Socket(unittest.TestCase):

View File

@ -22,7 +22,7 @@
# $Revision$
__author__ = "Cyril Jaquier, Yaroslav Halchenko"
__copyright__ = "Copyright (c) 2004 Cyril Jaquier, 2011-2012 Yaroslav Halchenko"
__copyright__ = "Copyright (c) 2004 Cyril Jaquier, 2011-2013 Yaroslav Halchenko"
__license__ = "GPL"
version = "0.8.8"
version = "0.9.0a0"

104
files/nagios/README Normal file
View File

@ -0,0 +1,104 @@
Description
-----------
This plugin checks if the fail2ban server is running and how many IPs are currently banned.
You can use this plugin to monitor all the jails or just a specific jail.
How to use
----------
Just have to run the following command:
$ ./check_fail2ban --help
If you need to use this script with NRPE you just have to do the
following steps:
1 allow your user to run the script with the sudo rights. Just add
something like that in your /etc/sudoers (use visudo) :
nagios ALL=(ALL) NOPASSWD: /<path-to>/check_fail2ban
2 then just add this kind of line in your NRPE config file :
command[check_fail2ban]=/usr/bin/sudo /<path-to>/check_fail2ban
3 don't forget to restart your NRPE daemon
/!\ be careful to let no one able to update the check_fail2ban ;)
------------------------------------------------------------------------------
Notes (from f2ban.txt)
-----
It seems that Fail2ban is currently not working, please login and check
HELP:
1.) stop the Service
/etc/init.d/fail2ban stop
2.) delete the socket if available
rm /tmp/fail2ban.sock
3.) start the Service
/etc/init.d/fail2ban start
4.) check if fail2ban is working
fail2ban-client ping
Answer should be "pong"
5.) if the answer is not "pong" run away or CRY FOR HELP ;-)
Help
----
Usage: /<path-to>/check_fail2ban [-p] [-D "CHECK FAIL2BAN ACTIVITY"] [-v] [-c 2] [-w 1] [-s /<path-to>/socket] [-P /usr/bin/fail2ban-client]
Options:
-h, --help
Print detailed help screen
-V, --version
Print version information
-D, --display=STRING
To modify the output display
default is "CHECK FAIL2BAN ACTIVITY"
-P, --path-fail2ban_client=STRING
Specify the path to the tw_cli binary
default value is /usr/bin/fail2ban-client
-c, --critical=INT
Specify a critical threshold
default is 2
-w, --warning=INT
Specify a warning threshold
default is 1
-s, --socket=STRING
Specify a socket path
default is unset
-p, --perfdata
If you want to activate the perfdata output
-v, --verbose
Show details for command-line debugging (Nagios may truncate the output)
Example
-------
# for a specific jail
$ ./check_fail2ban --verbose -p -j ssh -w 1 -c 5 -P /usr/bin/fail2ban-client
DEBUG : fail2ban_client_path: /usr/bin/fail2ban-client
DEBUG : /usr/bin/fail2ban-client exists and is executable
DEBUG : final fail2ban command: /usr/bin/fail2ban-client
DEBUG : warning threshold : 1, critical threshold : 5
DEBUG : it seems the connection with the fail2ban server is ok
CHECK FAIL2BAN ACTIVITY - OK - 0 current banned IP(s) for the specific jail ssh | currentBannedIP=0
# for all the current jails
$ ./check_fail2ban --verbose -p -w 1 -c 5 -P /usr/bin/fail2ban-client
DEBUG : fail2ban_client_path: /usr/bin/fail2ban-client
DEBUG : /usr/bin/fail2ban-client exists and is executable
DEBUG : final fail2ban command: /usr/bin/fail2ban-client
DEBUG : warning threshold : 1, critical threshold : 5
DEBUG : it seems the connection with the fail2ban server is ok
DEBUG : jails list: apache, ssh-ddos, ssh
DEBUG : the jail apache has currently 0 banned IPs
DEBUG : the jail ssh-ddos has currently 0 banned IPs
DEBUG : the jail ssh has currently 0 banned IPs
CHECK FAIL2BAN ACTIVITY - OK - 3 detected jails with 0 current banned IP(s) | currentBannedIP=0

View File

@ -1,105 +1,346 @@
#!/bin/bash
#!/usr/bin/perl
# -------------------------------------------------------
# -=- <check_fail2ban> -=-
# -------------------------------------------------------
#
# Usage: ./check_fail2ban
###############################################################################################
# Description:
# This plugin will check the status of Fail2ban.
# Description : This plugin checks if the fail2ban server is running
# and how many IPs are currently banned.
#
#
# Created: 2008-10-25 (Sebastian Mueller)
# inspired by the work of Sebastian Mueller - http://www.elchtest.eu
#
#
# Changes: 2008-10-26 fixed some issues (Sebastian Mueller)
# Changes: 2009-01-25 add the second check, when server is not replying and the
# process is hang-up (Sebastian Mueller)
# Version : 0.1
# -------------------------------------------------------
# In :
# - see the How to use section
#
# please visit my website http://www.elchtest.eu or my personal WIKI http://wiki.elchtest.eu
# Out :
# - only print on the standard output
#
################################################################################################
# if you have any questions, send a mail to linux@krabbe-offline.de
# Features :
# - perfdata output
# - works with only a specific jail
#
# this script is for my personal use. read the script before running/using it!!!
# Fix Me/Todo :
# - too many things ;) but let me know what do you think about it
#
# ####################################################################
# ####################################################################
# GPL v2
# This program 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.
#
# YOU HAVE BEEN WARNED. THIS MAY DESTROY YOUR MACHINE. I ACCEPT NO RESPONSIBILITY.
###############################################################################################
# This program 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 this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
# ####################################################################
# ####################################################################
# How to use :
# ------------
#
# Just have to run the following command:
# $ ./check_fail2ban --help
#
# If you need to use this script with NRPE you just have to do the
# following steps:
#
# 1 allow your user to run the script with the sudo rights. Just add
# something like that in your /etc/sudoers (use visudo) :
# nagios ALL=(ALL) NOPASSWD: /<path-to>/check_fail2ban
#
# 2 then just add this kind of line in your NRPE config file :
# command[check_fail2ban]=/usr/bin/sudo /<path-to>/check_fail2ban
#
# 3 don't forget to restart your NRPE daemon
#
#
# /!\ be careful to let no one able to update the check_fail2ban ;)
# ------------------------------------------------------------------------------
#
# ####################################################################
# ####################################################################
# Changelog :
# -----------
#
# --------------------------------------------------------------------
# Date:12/03/2013 Version:0.1 Author:Erwan Ben Souiden
# >> creation
# ####################################################################
# ####################################################################
# Don't touch anything under this line!
# You shall not pass - Gandalf is watching you
# ####################################################################
use strict;
use warnings;
use Getopt::Long qw(:config no_ignore_case);
# Generic variables
# -----------------
my $version = '0.1';
my $author = 'Erwan Labynocle Ben Souiden';
my $a_mail = 'erwan@aleikoum.net';
my $script_name = 'check_fail2ban';
my $verbose_value = 0;
my $version_value = 0;
my $more_value = 0;
my $help_value = 0;
my $perfdata_value = 0;
my %ERRORS=('OK'=>0,'WARNING'=>1,'CRITICAL'=>2,'UNKNOWN'=>3,'DEPENDENT'=>4);
# Plugin default variables
# ------------------------
my $display = 'CHECK FAIL2BAN ACTIVITY';
my ($critical,$warning) = (2,1);
my $fail2ban_client_path = '/usr/bin/fail2ban-client';
my $fail2ban_socket = '';
my $jail_specific = '';
GetOptions (
'P=s' => \ $fail2ban_client_path,
'path-fail2ban_client=s' => \ $fail2ban_client_path,
'j=s' => \ $jail_specific,
'jail=s' => \ $jail_specific,
'w=i' => \ $warning,
'warning=i' => \ $warning,
'socket=s' => \ $fail2ban_socket,
'S=s' => \ $fail2ban_socket,
'c=i' => \ $critical,
'critical=i' => \ $critical,
'V' => \ $version_value,
'version' => \ $version_value,
'h' => \ $help_value,
'H' => \ $help_value,
'help' => \ $help_value,
'display=s' => \ $display,
'D=s' => \ $display,
'perfdata' => \ $perfdata_value,
'p' => \ $perfdata_value,
'v' => \ $verbose_value,
'verbose' => \ $verbose_value
);
print_usage() if ($help_value);
print_version() if ($version_value);
SECOND_CHECK=0
STATE_OK=0
STATE_CRITICAL=2
######################################################################
# Read the Status from fail2ban-client
######################################################################
check_processes_fail2ban()
{
F2B=`sudo -u root fail2ban-client ping | awk -F " " '{print $3}'`
exit_fail2ban=0
if [[ $F2B = "pong" ]]; then
exit_fail2ban=$STATE_OK
else
exit_fail2ban=$STATE_CRITICAL
fi
# Syntax check of your specified options
# --------------------------------------
print "DEBUG : fail2ban_client_path: $fail2ban_client_path\n" if ($verbose_value);
if (($fail2ban_client_path eq "")) {
print $display.'- one or more following arguments are missing: fail2ban_client_path'."\n";
exit $ERRORS{"UNKNOWN"};
}
######################################################################
# first check in the Background, PID will be killed when no response
# after 10 seconds, might be possible, otherwise the script will be
# present in your memory all the time
######################################################################
check_processes_fail2ban &
pid=$!
if(! -x $fail2ban_client_path) {
print $display.' - '.$fail2ban_client_path.' is not executable by you'."\n";
exit $ERRORS{"UNKNOWN"};
}
print "DEBUG : $fail2ban_client_path exists and is executable\n" if ($verbose_value);
typeset -i i=0
while ps $pid >/dev/null
do
sleep 1
i=$i+1
if [ $i -ge 10 ]
then
kill $pid
SECOND_CHECK=1
exit_fail2ban=$STATE_CRITICAL
break
fi
done
my $fail2ban_cmd = $fail2ban_client_path;
$fail2ban_cmd .= " -s $fail2ban_socket" if ($fail2ban_socket);
######################################################################
# when the Server response (does not mean the FAIL2BAN is working)
# in the first step, then it will run again and test the Service
# and provide the real status
######################################################################
print "DEBUG : final fail2ban command: $fail2ban_cmd\n" if ($verbose_value);
print "DEBUG : warning threshold : $warning, critical threshold : $critical\n" if ($verbose_value);
if (($critical < 0) or ($warning < 0) or ($critical < $warning)) {
print $display.' - the thresholds must be integers and the critical threshold higher or equal than the warning threshold'."\n";
exit $ERRORS{"UNKNOWN"};
}
# Core script
# -----------
my ($how_many_jail,$how_many_banned,$return_print,$plugstate) = (0,0,"","OK");
if [ $SECOND_CHECK -eq 0 ]; then
check_processes_fail2ban
elif [ $SECOND_CHECK -eq 1 ]; then
exit_fail2ban=$STATE_CRITICAL
fi
### Test the connection to the fail2ban server
my @command_output = `$fail2ban_cmd ping`;
my $return_code = $?;
if ($return_code) {
print $display.'CRITICAL - non-zero exit code during testing fail2ban-client ping, check if the server is running and if you have the good permissions';
exit $ERRORS{"CRITICAL"};
}
else {
print "DEBUG : it seems the connection with the fail2ban server is ok\n" if ($verbose_value);
}
### Only if you specify one jail
if ($jail_specific) {
my $current_ban_number = currently_ban("$fail2ban_cmd","$jail_specific");
if ($current_ban_number == -1) {
print $display.' - CRITICAL - impossible to retrieve info about the jail '.$jail_specific;
exit $ERRORS{"CRITICAL"};
}
else {
$how_many_banned = int($current_ban_number);
$return_print = $how_many_banned.' current banned IP(s) for the specific jail '.$jail_specific;
}
}
### To analyze all the jail
else {
# Retrieve the jails list
my @jail_list = obtain_jail_list("$fail2ban_cmd");
if ($jail_list[0] eq "-1") {
print $display.' - CRITICAL - impossible to retrieve the jail list'."\n";
exit $ERRORS{"CRITICAL"};
}
######################################################################
# Main Menu
######################################################################
foreach (@jail_list) {
$how_many_jail ++;
my $jail_name = $_;
$jail_name =~ tr/ //ds;
my $current_ban_number = currently_ban("$fail2ban_cmd","$jail_name");
if ($current_ban_number == -1) {
print "DEBUG : problem to parse the current banned IPs for jail $jail_name\n" if ($verbose_value);
}
else {
print "DEBUG : the jail $jail_name has currently $current_ban_number banned IPs\n" if ($verbose_value);
$how_many_banned += int($current_ban_number);
}
}
$return_print = $how_many_jail.' detected jails with '.$how_many_banned.' current banned IP(s)';
}
### Final
$plugstate = "CRITICAL" if ($how_many_banned >= $critical);
$plugstate = "WARNING" if (($how_many_banned >= $warning) && ($how_many_banned < $critical));
$return_print = $display." - ".$plugstate." - ".$return_print;
$return_print .= " | currentBannedIP=$how_many_banned" if ($perfdata_value);
print $return_print;
exit $ERRORS{"$plugstate"};
final_exit=$exit_fail2ban
if [ $final_exit -eq 0 ]; then
echo "SYSTEM OK - Fail2ban is working normally"
exitstatus=$STATE_OK
elif [ $final_exit -ne "0" ]; then
echo "SYSTEM WARNING - Fail2Ban is not working"
######################################################################
# If don't have a Nagios Server for monitoring, remove the comment and
# add your Mail Address. You can check it with a Cron Job once an hour.
# put a txt file on your server and describe how to fix the issue, this
# could be attached to the mail.
######################################################################
# mutt -s "FAIL2BAN NOT WORKING" your@example.com < /home/f2ban.txt
# ####################################################################
# function 1 : display the help
# -----------------------------
sub print_usage {
print <<EOT;
$script_name version $version by $author
exitstatus=$STATE_CRITICAL
fi
exit $exitstatus
This plugin checks if the fail2ban server is running and how many IPs are currently banned.
You can use this plugin to monitor all the jails or just a specific jail.
Usage: /<path-to>/$script_name [-p] [-D "$display"] [-v] [-c 2] [-w 1] [-s /<path-to>/socket] [-P /usr/bin/fail2ban-client]
Options:
-h, --help
Print detailed help screen
-V, --version
Print version information
-D, --display=STRING
To modify the output display
default is "CHECK FAIL2BAN ACTIVITY"
-P, --path-fail2ban_client=STRING
Specify the path to the tw_cli binary
default value is /usr/bin/fail2ban-client
-c, --critical=INT
Specify a critical threshold
default is 2
-w, --warning=INT
Specify a warning threshold
default is 1
-s, --socket=STRING
Specify a socket path
default is unset
-p, --perfdata
If you want to activate the perfdata output
-v, --verbose
Show details for command-line debugging (Nagios may truncate the output)
Send email to $a_mail if you have questions
regarding use of this software. To submit patches or suggest improvements,
send email to $a_mail
This plugin has been created by $author
Hope you will enjoy it ;)
Remember :
This program 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.
This program 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 this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
EOT
exit $ERRORS{"UNKNOWN"};
}
# function 2 : display version information
# ----------------------------------------
sub print_version {
print <<EOT;
$script_name version $version
EOT
exit $ERRORS{"UNKNOWN"};
}
# function 3 : return the jail list
# ---------------------------------
sub obtain_jail_list {
my ($fail2ban_client_path) = @_;
my @command_output = `$fail2ban_client_path status`;
my $return_code = $?;
if ($return_code) {
return -1;
}
my @jail_list;
foreach (@command_output) {
if ($_=~/^.*Jail list:\t+(.*)/) {
print "DEBUG : jails list: $1\n" if ($verbose_value);
@jail_list = split(/,/, $1);
}
}
return @jail_list;
}
# function 4 : return how many IP are currently ban for a given jail
# ------------------------------------------------------------------
sub currently_ban {
my ($fail2ban_client_path,$jail_name) = @_;
my @command_output = `$fail2ban_client_path status $jail_name`;
my $return_code = $?;
if ($return_code) {
return -1;
}
foreach (@command_output) {
if ($_=~/^.*Currently banned:\t+(.*)/) {
my $current_count = $1;
$current_count =~ tr/ //ds;
return $current_count;
}
}
return -1;
}

View File

@ -1,18 +0,0 @@
It seems that Fail2ban is currently not working, please login and check
HELP:
1.) stop the Service
/etc/init.d/fail2ban stop
2.) delete the socket if available
rm /tmp/fail2ban.sock
3.) start the Service
/etc/init.d/fail2ban start
4.) check if fail2ban is working
fail2ban-client ping
Answer should be "pong"
5.) if the answer is not "pong" run away or CRY FOR HELP ;-)

View File

@ -1,6 +1,3 @@
[install]
install-purelib=/usr/share/fail2ban
[sdist]
formats=bztar

View File

@ -32,11 +32,12 @@ except ImportError:
# python 2.x
from distutils.command.build_py import build_py
from distutils.command.build_scripts import build_scripts
from common.version import version
from os.path import isfile, join, isdir
import sys
from glob import glob
from fail2ban.version import version
longdesc = '''
Fail2Ban scans log files like /var/log/pwdfail or
/var/log/apache/error_log and bans IP that makes
@ -47,7 +48,7 @@ commands.'''
setup(
name = "fail2ban",
version = version,
description = "Ban IPs that make too many password failure",
description = "Ban IPs that make too many password failures",
long_description = longdesc,
author = "Cyril Jaquier",
author_email = "cyril.jaquier@fail2ban.org",
@ -56,15 +57,21 @@ setup(
platforms = "Posix",
cmdclass = {'build_py': build_py, 'build_scripts': build_scripts},
scripts = [
'fail2ban-client',
'fail2ban-server',
'fail2ban-regex'
'bin/fail2ban-client',
'bin/fail2ban-server',
'bin/fail2ban-regex',
'bin/fail2ban-testcases',
],
packages = [
'common',
'client',
'server'
'fail2ban',
'fail2ban.client',
'fail2ban.server',
'fail2ban.tests',
],
package_data = {
'fail2ban.tests':
['files/*.log', 'files/filter.d/*.conf'],
},
data_files = [
('/etc/fail2ban',
glob("config/*.conf")