Compare commits

..
21 Commits
Author SHA1 Message Date
Yaroslav Halchenko de27944089 pristine-tar data for fail2ban_0.8.8.orig.tar.gz 2012-12-06 09:25:25 -05:00
Yaroslav Halchenko 00d022f9cf pristine-tar data for fail2ban_0.8.7.orig.tar.gz 2012-07-31 18:01:46 -04:00
Yaroslav Halchenko f07a494f9c pristine-tar data for fail2ban_0.8.6.orig.tar.gz 2012-01-01 01:02:38 -05:00
Yaroslav Halchenko d1b0f6bc68 pristine-tar data for fail2ban_0.8.5.orig.tar.gz 2011-09-28 12:32:01 -04:00
Yaroslav Halchenko 055d59a026 pristine-tar data for fail2ban_0.8.4+svn20110323.orig.tar.gz 2011-09-28 12:32:00 -04:00
Yaroslav Halchenko adc17f5062 pristine-tar data for fail2ban_0.8.4.orig.tar.gz 2011-09-28 12:32:00 -04:00
Yaroslav Halchenko 12a3e23a0d pristine-tar data for fail2ban_0.8.3.orig.tar.gz 2011-09-28 12:32:00 -04:00
Yaroslav Halchenko e39084902b pristine-tar data for fail2ban_0.8.2.orig.tar.gz 2011-09-28 12:31:59 -04:00
Yaroslav Halchenko 93d9a34d8b pristine-tar data for fail2ban_0.8.1.orig.tar.gz 2011-09-28 12:31:59 -04:00
Yaroslav Halchenko a8b53fc05f pristine-tar data for fail2ban_0.8.0.orig.tar.gz 2011-09-28 12:31:58 -04:00
Yaroslav Halchenko a2a1bd170d pristine-tar data for fail2ban_0.7.9.orig.tar.gz 2011-09-28 12:31:58 -04:00
Yaroslav Halchenko a2a5cdb329 pristine-tar data for fail2ban_0.7.8.orig.tar.gz 2011-09-28 12:31:58 -04:00
Yaroslav Halchenko 624f357cf5 pristine-tar data for fail2ban_0.7.7.orig.tar.gz 2011-09-28 12:31:57 -04:00
Yaroslav Halchenko c12f6be991 pristine-tar data for fail2ban_0.7.6.orig.tar.gz 2011-09-28 12:31:57 -04:00
Yaroslav Halchenko ce1ef568b1 pristine-tar data for fail2ban_0.7.5.orig.tar.gz 2011-09-28 12:31:56 -04:00
Yaroslav Halchenko 553d9dfc79 pristine-tar data for fail2ban_0.7.4.orig.tar.gz 2011-09-28 12:31:56 -04:00
Yaroslav Halchenko 4153272dfd pristine-tar data for fail2ban_0.6.1.orig.tar.gz 2011-09-28 12:31:55 -04:00
Yaroslav Halchenko 3878e9de84 pristine-tar data for fail2ban_0.6.0.orig.tar.gz 2011-09-28 12:31:55 -04:00
Yaroslav Halchenko 4dd4e76568 pristine-tar data for fail2ban_0.5.4.orig.tar.gz 2011-09-28 12:31:55 -04:00
Yaroslav Halchenko 6e27a9d4dd pristine-tar data for fail2ban_0.5.3.orig.tar.gz 2011-09-28 12:31:54 -04:00
Yaroslav Halchenko 9f5bbd82cb pristine-tar data for fail2ban_0.5.2.orig.tar.gz 2011-09-28 12:31:54 -04:00
150 changed files with 21 additions and 12685 deletions
-205
View File
@@ -1,205 +0,0 @@
__ _ _ ___ _
/ _|__ _(_) |_ ) |__ __ _ _ _
| _/ _` | | |/ /| '_ \/ _` | ' \
|_| \__,_|_|_/___|_.__/\__,_|_||_|
=============================================================
Fail2Ban (version 0.7.0) 2006/08/23
=============================================================
ver. 0.7.0 (2006/08/23) - alpha
----------
- Almost a complete rewrite :) Fail2ban design is really
better (IMHO). There is a lot of new features
- Client/Server architecture
- Multithreading. Each jail has its own threads: one for the
log reading and another for the actions
- Execute several actions
- Split configuration files. They are more readable and easy
to use
- failregex uses group (<host>) now. This feature was already
present in the Debian package
- lots of things...
ver. 0.6.1 (2006/03/16) - stable
----------
- Added permanent banning. Set banTime to a negative value to
enable this feature (-1 is perfect). Thanks to Mannone
- Fixed locale bug. Thanks to Fernando José
- Fixed crash when time format does not match data
- Propagated patch from Debian to fix fail2ban search path
addition to the path search list: now it is added first.
Thanks to Nick Craig-Wood
- Added SMTP authentification for mail notification. Thanks
to Markus Hoffmann
- Removed debug mode as it is confusing for people
- Added parsing of timestamp in TAI64N format (#1275325).
Thanks to Mark Edgington
- Added patch #1382936 (Default formatted syslog logging).
Thanks to Patrick Börjesson
- Removed 192.168.0.0/16 from ignoreip. Attacks could also
come from the local network.
- Robust startup: if iptables module does not get fully
initialized after startup of fail2ban, fail2ban will do
"maxreinit" attempts to initialize its own firewall. It
will sleep between attempts for "polltime" number of
seconds (closes Debian: #334272). Thanks to Yaroslav
Halchenko
- Added "interpolations" in fail2ban.conf. This is provided
by the ConfigParser module. Old configuration files still
work. Thanks to Yaroslav Halchenko
- Added initial support for hosts.deny and shorewall. Need
more testing. Please test. Thanks to kojiro from Gentoo
forum for hosts.deny support
- Added support for vsftpd. Thanks to zugeschmiert
ver. 0.6.0 (2005/11/20) - stable
----------
- Propagated patches introduced by Debian maintainer
(Yaroslav Halchenko):
* Added an option to report local time (including timezone)
or GMT in mail notification.
ver. 0.5.5 (2005/10/26) - beta
----------
- Propagated patches introduced by Debian maintainer
(Yaroslav Halchenko):
* Introduced fwcheck option to verify consistency of the
chains. Implemented automatic restart of fail2ban main
function in case check of fwban or fwunban command failed
(closes: #329163, #331695). (Introduced patch was further
adjusted by upstream author).
* Added -f command line parameter for [findtime].
* Added a cleanup of firewall rules on emergency shutdown
when unknown exception is catched.
* Fail2ban should not crash now if a wrong file name is
specified in config.
* reordered code a bit so that log targets are setup right
after background and then only loglevel (verbose, debug)
is processed, so the warning could be seen in the logs
* Added a keyword <section> in parsing of the subject and
the body of an email sent out by fail2ban (closes:
#330311)
ver. 0.5.4 (2005/09/13) - beta
----------
- Fixed bug #1286222.
- Propagated patches introduced by Debian maintainer
(Yaroslav Halchenko):
* Fixed handling of SYSLOG logging target. Now it can log
to any SYSLOG target and facility as directed by the
config
* Format of SYSLOG entries fixed to look closer to standard
* Fixed errata in config/gentoo-confd
* Introduced findtime configuration variable to control the
lifetime of caught "failed" log entries
ver. 0.5.3 (2005/09/08) - beta
----------
- Fixed a bug when overriding "maxfailures" or "bantime".
Thanks to Yaroslav Halchenko
- Added more debug output if an error occurs when sending
mail. Thanks to Stephen Gildea
- Renamed "maxretry" to "maxfailures" and changed default
value to 5. Thanks to Stephen Gildea
- Hopefully fixed bug #1256075
- Fixed bug #1262345
- Fixed exception handling in PIDLock
- Removed warning when using "-V" or "-h" with no config
file. Thanks to Yaroslav Halchenko
- Removed "-i eth0" from config file. Thanks to Yaroslav
Halchenko
ver. 0.5.2 (2005/08/06) - beta
----------
- Better PID lock file handling. Should close #1239562
- Added man pages
- Removed log4py dependency. Use logging module instead
- "maxretry" and "bantime" can be overridden in each section
- Fixed bug #1246278 (excessive memory usage)
- Fixed crash on wrong option value in configuration file
- Changed custom chains to lowercase
ver. 0.5.1 (2005/07/23) - beta
----------
- Fixed bugs #1241756, #1239557
- Added log targets in configuration file. Removed -l option
- Changed iptables rules in order to create a separated chain
for each section
- Fixed static banList in firewall.py
- Added an initd script for Debian. Thanks to Yaroslav
Halchenko
- Check for obsolete files after install
ver. 0.5.0 (2005/07/12) - beta
----------
- Added support for CIDR mask in ignoreip
- Added mail notification support
- Fixed bug #1234699
- Added tags replacement in rules definition. Should allow a
clean solution for Feature Request #1229479
- Removed "interface" and "firewall" options
- Added start and end commands in the configuration file.
Thanks to Yaroslav Halchenko
- Added firewall rules definition in the configuration file
- Cleaned fail2ban.py
- Added an initd script for RedHat/Fedora. Thanks to Andrey
G. Grozin
ver. 0.4.1 (2005/06/30) - stable
----------
- Fixed textToDNS method which generated wrong matches for
"rhost=12-xyz...". Thanks to Tom Pike
- fail2ban.conf modified for readability. Thanks to Iain Lea
- Added an initd script for Gentoo
- Changed default PID lock file location from /tmp to
/var/run
ver. 0.4.0 (2005/04/24) - stable
----------
- Fixed textToDNS which did not recognize strings like
"12-345-67-890.abcd.mnopqr.xyz"
ver. 0.3.1 (2005/03/31) - beta
----------
- Corrected level of messages
- Added DNS lookup support
- Improved parsing speed. Only parse the new log messages
- Added a second verbose level (-vv)
ver. 0.3.0 (2005/02/24) - beta
----------
- Re-writting of parts of the code in order to handle several
log files with different rules
- Removed sshd.py because it is no more needed
- Fixed a bug when exiting with IP in the ban list
- Added PID lock file
- Improved some parts of the code
- Added ipfw-start-rule option (thanks to Robert Edeker)
- Added -k option which kills a currently running Fail2Ban
ver. 0.1.2 (2004/11/21) - beta
----------
- Add ipfw and ipfwadm support. The rules are taken from
BlockIt. Thanks to Robert Edeker
- Add -e option which allows to set the interface. Thanks to
Robert Edeker who reminded me this
- Small code cleaning
ver. 0.1.1 (2004/10/23) - beta
----------
- Add SIGTERM handler in order to exit nicely when in daemon
mode
- Add -r option which allows to set the maximum number of
login failures
- Remove the Metalog class as the log file are not so syslog
daemon specific
- Rewrite log reader to be service centered. Sshd support
added. Match "Failed password" and "Illegal user"
- Add /etc/fail2ban.conf configuration support
- Code documentation
ver. 0.1.0 (2004/10/12) - alpha
----------
- Initial release
-50
View File
@@ -1,50 +0,0 @@
README
CHANGELOG
TODO
fail2ban-client
fail2ban-server
fail2ban-testcases
client/configreader.py
client/jailreader.py
client/fail2banreader.py
client/jailsreader.py
client/filterreader.py
client/actionreader.py
client/__init__.py
client/configurator.py
client/csocket.py
server/ssocket.py
server/banticket.py
server/filter.py
server/server.py
server/failticket.py
server/actions.py
server/faildata.py
server/failmanager.py
server/jailthread.py
server/transmitter.py
server/action.py
server/ticket.py
server/jail.py
server/__init__.py
server/banmanager.py
setup.py
testcases/banmanagertestcase.py
testcases/failmanagertestcase.py
testcases/clientreadertestcase.py
testcases/filtertestcase.py
testcases/__init__.py
testcases/servertestcase.py
testcases/files/testcase01.log
testcases/files/testcase02.log
version.py
config/jail.conf
config/filter.d/vsftpd.conf
config/filter.d/apache-auth.conf
config/filter.d/sshd.conf
config/action.d/iptables.conf
config/action.d/mail-whois.conf
config/action.d/dummy.conf
config/action.d/mail.conf
config/action.d/hostsdeny.conf
config/fail2ban.conf
-151
View File
@@ -1,151 +0,0 @@
__ _ _ ___ _
/ _|__ _(_) |_ ) |__ __ _ _ _
| _/ _` | | |/ /| '_ \/ _` | ' \
|_| \__,_|_|_/___|_.__/\__,_|_||_|
=============================================================
Fail2Ban (version 0.7.0) 2006/08/23
=============================================================
Fail2Ban scans log files like /var/log/pwdfail and bans IP
that makes too many password failures. It updates firewall
rules to reject the IP address. These rules can be defined by
the user. Fail2Ban can read multiple log files such as sshd
or Apache web server ones.
This is my first Python program. Moreover, English is not my
mother tongue...
More details:
-------------
Fail2Ban is rather simple. I have a home server connected to
the Internet which runs apache, samba, sshd, ... I see in my
logs that people are trying to log into my box using "manual"
brute force or scripts. They try 10, 20 and sometimes more
user/password (without success anyway). In order to
discourage these script kiddies, I wanted that sshd refuse
login from a specific ip after 3 password failures. After
some Google searches, I found that sshd was not able of that.
So I search for a script or program that do it. I found
nothing :-( So I decide to write mine and to learn Python :-)
For each sections defined in the configuration file, Fail2Ban
tries to find lines which match the failregex. Then it
retrieves the message time using timeregex and timepattern.
It finally gets the ip and if it has already done 3 or more
password failures in the last banTime, the ip is banned for
banTime using a firewall rule. This rule is set by the user
in the configuration file. Thus, Fail2Ban can be adapted for
lots of firewall. After banTime, the rule is deleted. Notice
that if no "plain" ip is available, Fail2Ban try to do DNS
lookup in order to found one or several ip's to ban.
Sections can be freely added so it is possible to monitor
several daemons at the same time.
Runs on my server and does its job rather well :-) The idea
is to make fail2ban usable with daemons and services that
require a login (sshd, telnetd, ...) and with different
firewalls.
Installation:
-------------
Require: python-2.4 (http://www.python.org)
To install, just do:
> tar xvfj fail2ban-0.7.0.tar.bz2
> cd fail2ban-0.7.0
> python setup.py install
This will install Fail2Ban into /usr/lib/fail2ban. The
executable scripts are placed into /usr/bin.
Gentoo: ebuilds are available on the website.
Debian: Fail2Ban is in Debian unstable.
RedHat: packages are available on the website.
Fail2Ban should now be correctly installed. Just type:
> fail2ban-client -h
to see if everything is alright.
Configuration:
--------------
You can configure fail2ban using the files in /etc/fail2ban
or using command line. Here are the available command line
options (not complete yet):
<COMMAND>
start start the server and the jails
reload reload the configuration
stop stop all jails and terminate the
server
status get the current status
set loglevel <LEVEL> set loglevel to <LEVEL>
get loglevel get loglevel
set logtarget <TARGET> set log target to <TARGET>
get logtarget get log target
add <JAIL> create <JAIL>
set <JAIL> <CMD> set the <CMD> value for <JAIL>
get <JAIL> <CMD> get the <CMD> value for <JAIL>
start <JAIL> start <JAIL>
stop <JAIL> stop <JAIL>. The jail is removed
status <JAIL> get the current status of <JAIL>
[OPTIONS]
-c <DIR> configuration directory
-d dump configuration. For debugging
-v increase verbosity
-q decrease verbosity
-x force execution of the server
-h display this help message
Contact:
--------
You need some new features, you found bugs or you just
appreciate this program, you can contact me at :
Website: http://fail2ban.sourceforge.net
Cyril Jaquier: <lostcontrol@users.sourceforge.net>
Thanks:
-------
Kévin Drapel, Marvin Rouge, Sireyessire, Robert Edeker,
Tom Pike, Iain Lea, Andrey G. Grozin, Yaroslav Halchenko,
Jonathan Kamens, Stephen Gildea, Markus Hoffmann, Mark
Edgington, Patrick Börjesson, kojiro, zugeschmiert
License:
--------
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
-115
View File
@@ -1,115 +0,0 @@
__ _ _ ___ _
/ _|__ _(_) |_ ) |__ __ _ _ _
| _/ _` | | |/ /| '_ \/ _` | ' \
|_| \__,_|_|_/___|_.__/\__,_|_||_|
=============================================================
ToDo $Revision$
=============================================================
Legend:
- not yet done
? maybe
# partially done
* done
- correct handling of threads (join???)
- signal handling (ctrl-c, etc)
- add a reload option to fail2ban-client
- see Feature Request Tracking System at SourceForge.net
* findall in dns.py should be no more needed
* remove utils/ directory
- improve installation process (better prefix support)
# improve documentation and website for user
* use Doxygen
- use PyLint to check the code
* better configuration files
- add a check to see if the time of the log messages is
correctly detected (valid regexp)
? use Gentoo Portage style for scripts.
- banning engines script in /etc/fail2ban/scripts.d
Example: /etc/fail2ban/scripts.d/iptables
Will be mostly bash scripting which is more "user
friendly".
- split configuration files in /etc/fail2ban/services.d
for log files
Example: /etc/fail2ban/services.d/apache
Mainly regular expressions.
- template for common regex in /etc/fail2ban/templates.d
Example: /etc/fail2ban/templates.d/date
Mainly regular expressions.
* remove debug mode (root check)
# better return values in function
? use more email.Utils in mail.py
? add gettext support. Is this really needed for a server
utility?
* send an email when fail2ban is running
* add multithreading. Python threading is not really
efficient. However, fail2ban could benefit of it. We could
use threads like this:
- one thread which check for host to unban.
- one thread per file to watch. This will allow things like
different polling time for each file.
<srv> is read-only (we only read log files) thus no locks
are required. However, <meth> is read-write and must take
care of concurrency in case of multithreading.
- add FAM/Gamin support. Should be quite efficient with
threading. Take care that handle_one_event() release the
Python lock.
# add a test framework. We could use unittest which is in
Python since 2.1. It should be possible to run all tests
automatically.
* add client/server using socket. Something similar to
gdesklets. DBUS seems to be designed for desktop use.
- fail2ban start -> start the daemon.
- fail2ban stop -> stop the daemon.
- fail2ban add <srv> <meth> -> add <srv> monitoring with
<meth> ban method (iptables, hosts.deny, etc).
- fail2ban del <srv> -> remove <srv> monitoring.
- fail2ban status <srv> -> query current fail2ban status.
Should return infos like a ban counter. Could be graph
with rrdtool.
- fail2ban pause <srv> -> suspend monitoring.
- fail2ban resume <srv> -> resume monitoring.
- fail2ban list -> list available services.
- fail2ban flush <srv> -> flush the <srv> ban list.
* remove PID file.
* remove most of the command lines options if possible.
- add the possibility to specify wildcard in log files.
Example: logfile = /var/log/apache2/access-*.log
Should we start one thread per file or just one thread per
serivce?
- autodetect date format in log file. Match the most popular
format and sort them using the hit ratio. Should avoid
user problem with regex and not have a big impact on perfs.
- restart automatically the daemon if an exception occurs.
- do not close socket after a send
- refactoring in server.py, actions.py, filter.py
-25
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$
__author__ = "Cyril Jaquier"
__version__ = "$Revision$"
__date__ = "$Date$"
__copyright__ = "Copyright (c) 2004 Cyril Jaquier"
__license__ = "GPL"
-90
View File
@@ -1,90 +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 configreader import ConfigReader
# Gets the instance of the logger.
logSys = logging.getLogger("fail2ban.client.config")
class ActionReader(ConfigReader):
def __init__(self, action, name):
ConfigReader.__init__(self)
self.file = action[0]
self.cInfo = action[1]
self.name = name
def setFile(self, file):
self.file = file
def getFile(self):
return self.file
def setName(self, name):
self.name = name
def getName(self):
return self.name
def read(self):
ConfigReader.read(self, "action.d/" + self.file)
def getOptions(self, pOpts):
opts = [["string", "actionstart", ""],
["string", "actionstop", ""],
["string", "actioncheck", ""],
["string", "actionban", ""],
["string", "actionunban", ""]]
self.opts = ConfigReader.getOptions(self, "Definition", opts, pOpts)
if self.has_section("Init"):
for opt in self.options("Init"):
if not self.cInfo.has_key(opt):
self.cInfo[opt] = self.get("Init", opt)
def convert(self):
head = ["set", self.name]
stream = list()
stream.append(head + ["addaction", self.file])
for opt in self.opts:
if opt == "actionstart":
stream.append(head + ["actionstart", self.file, self.opts[opt]])
elif opt == "actionstop":
stream.append(head + ["actionstop", self.file, self.opts[opt]])
elif opt == "actioncheck":
stream.append(head + ["actioncheck", self.file, self.opts[opt]])
elif opt == "actionban":
stream.append(head + ["actionban", self.file, self.opts[opt]])
elif opt == "actionunban":
stream.append(head + ["actionunban", self.file, self.opts[opt]])
# cInfo
if self.cInfo:
for p in self.cInfo:
stream.append(head + ["setcinfo", self.file, p, self.cInfo[p]])
return stream
-91
View File
@@ -1,91 +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 ConfigParser import *
# Gets the instance of the logger.
logSys = logging.getLogger("fail2ban.client.config")
class ConfigReader(SafeConfigParser):
basedir = "/etc/fail2ban/"
def __init__(self):
SafeConfigParser.__init__(self)
self.opts = None
@staticmethod
def setBaseDir(dir):
global basedir
path = dir.rstrip('/')
basedir = path + '/'
@staticmethod
def getBaseDir():
global basedir
return basedir
def read(self, filename):
global basedir
basename = basedir + filename
logSys.debug("Reading " + basename)
SafeConfigParser.read(self, [basename + ".conf", basename + ".local"])
##
# Read the options.
#
# Read the given option in the configuration file. Default values
# are used...
# Each optionValues entry is composed of an array with:
# 0 -> the type of the option
# 1 -> the name of the option
# 2 -> the default value for the option
def getOptions(self, sec, options, pOptions = None):
values = dict()
for option in options:
try:
if option[0] == "bool":
v = self.getboolean(sec, option[1])
elif option[0] == "int":
v = self.getint(sec, option[1])
else:
v = self.get(sec, option[1])
if not pOptions == None and option[1] in pOptions:
continue
values[option[1]] = v
except NoSectionError, e:
# No "Definition" section or wrong basedir
logSys.error(e)
except NoOptionError:
if not option[2] == None:
logSys.warn("No '" + option[1] + "' defined in '" + sec + "'")
values[option[1]] = option[2]
except ValueError:
logSys.warn("Wrong value for '" + option[1] + "' in '" + sec +
"'. Using default one: '" + `option[2]` + "'")
values[option[1]] = option[2]
return values
-68
View File
@@ -1,68 +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 configreader import ConfigReader
from fail2banreader import Fail2banReader
from jailsreader import JailsReader
# Gets the instance of the logger.
logSys = logging.getLogger("fail2ban.client.config")
class Configurator:
def __init__(self):
self.settings = dict()
self.streams = dict()
self.fail2ban = Fail2banReader()
self.jails = JailsReader()
def setBaseDir(self, dir):
ConfigReader.setBaseDir(dir)
def getBaseDir(self):
return ConfigReader.getBaseDir()
def readAll(self):
self.fail2ban.read()
self.jails.read()
def getAllOptions(self):
self.settings["general"] = self.fail2ban.getOptions()
self.settings["jails"] = self.jails.getOptions()
def convertToProtocol(self):
self.streams["general"] = self.fail2ban.convert()
self.streams["jails"] = self.jails.convert()
def getConfigStream(self):
cmds = list()
for opt in self.streams["general"]:
cmds.append(opt)
for opt in self.streams["jails"]:
cmds.append(opt)
return cmds
-54
View File
@@ -1,54 +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 socket, pickle
class CSocket:
def __init__(self):
self.socketFile = "/tmp/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)
#self.csock.connect(("localhost", 2222))
self.csock.connect(self.socketFile)
def send(self, msg):
# Convert every list member to string
obj = pickle.dumps(map(str, msg))
self.csock.send(obj + "<F2B_END_COMMAND>")
ret = self.receive(self.csock)
self.csock.close()
return ret
def receive(self, socket):
msg = ''
while msg.rfind("<F2B_END_COMMAND>") == -1:
chunk = socket.recv(6)
if chunk == '':
raise RuntimeError, "socket connection broken"
msg = msg + chunk
return pickle.loads(msg)
-54
View File
@@ -1,54 +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 configreader import ConfigReader
# Gets the instance of the logger.
logSys = logging.getLogger("fail2ban.client.config")
class Fail2banReader(ConfigReader):
def __init__(self):
ConfigReader.__init__(self)
def read(self):
ConfigReader.read(self, "fail2ban")
def getOptions(self):
opts = [["int", "loglevel", 1],
["string", "logtarget", "STDERR"]]
self.opts = ConfigReader.getOptions(self, "Definition", opts)
def convert(self):
stream = list()
for opt in self.opts:
if opt == "loglevel":
stream.append(["set", "loglevel", self.opts[opt]])
elif opt == "logtarget":
stream.append(["set", "logtarget", self.opts[opt]])
return stream
-80
View File
@@ -1,80 +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 configreader import ConfigReader
# Gets the instance of the logger.
logSys = logging.getLogger("fail2ban.client.config")
class FilterReader(ConfigReader):
def __init__(self, file, name):
ConfigReader.__init__(self)
self.file = file
self.name = name
def setFile(self, file):
self.file = file
def getFile(self):
return self.file
def setName(self, name):
self.name = name
def getName(self):
return self.name
def read(self):
ConfigReader.read(self, "filter.d/" + self.file)
def getOptions(self, pOpts):
opts = [["string", "logpath", "/var/log/sshd.log"],
["string", "timeregex", ""],
["string", "timepattern", ""],
["string", "failregex", ""],
["int", "maxtime", 600],
["int", "maxretry", 3]]
self.opts = ConfigReader.getOptions(self, "Definition", opts, pOpts)
def convert(self):
stream = list()
for opt in self.opts:
if opt == "logpath":
stream.append(["set", self.name, "logpath", self.opts[opt]])
elif opt == "timeregex":
stream.append(["set", self.name, "timeregex", self.opts[opt]])
elif opt == "timepattern":
stream.append(["set", self.name, "timepattern", self.opts[opt]])
elif opt == "failregex":
stream.append(["set", self.name, "failregex", self.opts[opt]])
elif opt == "maxtime":
stream.append(["set", self.name, "maxtime", self.opts[opt]])
elif opt == "maxretry":
stream.append(["set", self.name, "maxretry", self.opts[opt]])
return stream
-103
View File
@@ -1,103 +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, re
from configreader import ConfigReader
from filterreader import FilterReader
from actionreader import ActionReader
# Gets the instance of the logger.
logSys = logging.getLogger("fail2ban.client.config")
class JailReader(ConfigReader):
actionCRE = re.compile("^((?:\w|-|_|\.)+)(?:\[(.*)\])?$")
def __init__(self, name):
ConfigReader.__init__(self)
self.name = name
self.filter = None
self.actions = list()
def setName(self, value):
self.name = value
def getName(self):
return self.name
def read(self):
ConfigReader.read(self, "jail")
def isEnabled(self):
return self.opts["enabled"]
def getOptions(self):
opts = [["bool", "enabled", "false"],
["int", "maxretry", None],
["int", "bantime", 600],
["string", "filter", ""],
["string", "action", ""]]
self.opts = ConfigReader.getOptions(self, self.name, opts)
if self.isEnabled():
# Read filter
self.filter = FilterReader(self.opts["filter"], self.name)
self.filter.read()
self.filter.getOptions(self.opts)
# Read action
for act in self.opts["action"].split('\n'):
try:
splitAct = JailReader.splitAction(act)
action = ActionReader(splitAct, self.name)
action.read()
action.getOptions(self.opts)
self.actions.append(action)
except AttributeError, e:
logSys.error("Error in action definition " + act)
logSys.debug(e)
def convert(self):
stream = [["add", self.name]]
for opt in self.opts:
if opt == "maxretry":
stream.append(["set", self.name, "maxretry", self.opts[opt]])
elif opt == "bantime":
stream.append(["set", self.name, "bantime", self.opts[opt]])
stream.extend(self.filter.convert())
for action in self.actions:
stream.extend(action.convert())
return stream
@staticmethod
def splitAction(action):
m = JailReader.actionCRE.match(action)
d = dict()
if m.group(2) <> None:
for param in m.group(2).split(','):
p = param.split('=')
d[p[0].strip()] = p[1].strip()
return [m.group(1), d]
-73
View File
@@ -1,73 +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 configreader import ConfigReader
from jailreader import JailReader
# Gets the instance of the logger.
logSys = logging.getLogger("fail2ban.client.config")
class JailsReader(ConfigReader):
def __init__(self):
ConfigReader.__init__(self)
self.jails = list()
def read(self):
ConfigReader.read(self, "jail")
def getOptions(self):
opts = []
self.opts = ConfigReader.getOptions(self, "Definition", opts)
for sec in self.sections():
jail = JailReader(sec)
jail.read()
jail.getOptions()
if jail.isEnabled():
# We only add enabled jails
self.jails.append(jail)
def getFilterOptions(self, file):
filter = FilterReader(file)
filter.read()
return filter.getOptions()
def convert(self):
stream = list()
for opt in self.opts:
if opt == "":
stream.append([])
# Convert jails
for jail in self.jails:
stream.extend(jail.convert())
# Start jails
for jail in self.jails:
stream.append(["start", jail.getName()])
return stream
-54
View File
@@ -1,54 +0,0 @@
# Fail2Ban configuration file
#
# Author: Cyril Jaquier
#
# $Revision$
#
[Definition]
# Option: fwstart
# Notes.: command executed once at the start of Fail2Ban.
# Values: CMD Default:
#
actionstart = touch /tmp/fail2ban.dummy
echo "<init>" >> /tmp/fail2ban.dummy
# Option: fwend
# Notes.: command executed once at the end of Fail2Ban
# Values: CMD Default:
#
actionstop = rm /tmp/fail2ban.dummy
# Option: fwcheck
# Notes.: command executed once before each fwban command
# Values: CMD Default:
#
actioncheck =
# Option: fwban
# 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
# <failtime> unix timestamp of the last failure
# <bantime> unix timestamp of the ban time
# Values: CMD
# Default: iptables -I INPUT 1 -s <ip> -j DROP
#
actionban = echo "+<ip>" >> /tmp/fail2ban.dummy
# Option: fwunban
# Notes.: command executed when unbanning an IP. Take care that the
# command is executed with Fail2Ban user rights.
# Tags: <ip> IP address
# <bantime> unix timestamp of the ban time
# <unbantime> unix timestamp of the unban time
# Values: CMD
# Default: iptables -D INPUT -s <ip> -j DROP
#
actionunban = echo "-<ip>" >> /tmp/fail2ban.dummy
[Init]
init = 123
-66
View File
@@ -1,66 +0,0 @@
# Fail2Ban configuration file
#
# Author: Cyril Jaquier
#
# $Revision$
#
[Definition]
# Option: fwstart
# Notes.: command executed once at the start of Fail2Ban.
# Values: CMD Default:
#
actionstart = touch <tmpfile>
# Option: fwend
# Notes.: command executed once at the end of Fail2Ban
# Values: CMD Default:
#
actionstop = rm -f <tmpfile>
# Option: fwcheck
# Notes.: command executed once before each fwban command
# Values: CMD Default:
#
actioncheck =
# Option: fwban
# 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
# <failtime> unix timestamp of the last failure
# <bantime> unix timestamp of the ban time
# Values: CMD
# Default: iptables -I INPUT 1 -s <ip> -j DROP
#
actionban = IP=<ip> &&
echo "ALL: $IP" >> <file>
# Option: fwunban
# Notes.: command executed when unbanning an IP. Take care that the
# command is executed with Fail2Ban user rights.
# Tags: <ip> IP address
# <bantime> unix timestamp of the ban time
# <unbantime> unix timestamp of the unban time
# Values: CMD
# Default: iptables -D INPUT -s <ip> -j DROP
#
actionunban = IP=<ip> &&
grep -v "ALL: $IP" <file> > <tmpfile> &&
mv <tmpfile> <file>
[Init]
# Option: file
# Notes.: hosts.deny file path.
# Values: STR Default: /etc/hosts.deny
#
file = /etc/hosts.deny
# Option: file
# Notes.: hosts.deny temporary file path.
# Values: STR Default: /etc/hostsdeny.failban
#
tmpfile = /tmp/hosts.deny.tmp
-71
View File
@@ -1,71 +0,0 @@
# Fail2Ban configuration file
#
# Author: Cyril Jaquier
#
# $Revision$
#
[Definition]
# Option: fwstart
# Notes.: command executed once at the start of Fail2Ban.
# Values: CMD Default:
#
actionstart = iptables -N fail2ban-<name>
iptables -A fail2ban-<name> -j RETURN
iptables -I INPUT -p <protocol> --dport <port> -j fail2ban-<name>
# Option: fwend
# Notes.: command executed once at the end of Fail2Ban
# Values: CMD Default:
#
actionstop = iptables -D INPUT -p <protocol> --dport <port> -j fail2ban-<name>
iptables -F fail2ban-<name>
iptables -X fail2ban-<name>
# Option: fwcheck
# Notes.: command executed once before each fwban command
# Values: CMD Default:
#
actioncheck = iptables -L INPUT | grep -q fail2ban-<name>
# Option: fwban
# 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
# <failtime> unix timestamp of the last failure
# <bantime> unix timestamp of the ban time
# Values: CMD
# Default: iptables -I INPUT 1 -s <ip> -j DROP
#
actionban = iptables -I fail2ban-<name> 1 -s <ip> -j DROP
# Option: fwunban
# Notes.: command executed when unbanning an IP. Take care that the
# command is executed with Fail2Ban user rights.
# Tags: <ip> IP address
# <bantime> unix timestamp of the ban time
# <unbantime> unix timestamp of the unban time
# Values: CMD
# Default: iptables -D INPUT -s <ip> -j DROP
#
actionunban = iptables -D fail2ban-<name> -s <ip> -j DROP
[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
-71
View File
@@ -1,71 +0,0 @@
# Fail2Ban configuration file
#
# Author: Cyril Jaquier
#
# $Revision: 254 $
#
[Definition]
# Option: fwstart
# Notes.: command executed once at the start of Fail2Ban.
# Values: CMD Default:
#
actionstart = echo -en "Hi,\n
The jail <name> has been started successfuly.\n
Regards,\n
Fail2Ban"|mail -s "[Fail2Ban] <name>: started" <dest>
# Option: fwend
# Notes.: command executed once at the end of Fail2Ban
# Values: CMD Default:
#
actionstop = echo -en "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
# Values: CMD Default:
#
actioncheck =
# Option: fwban
# 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
# <failtime> unix timestamp of the last failure
# <bantime> unix timestamp of the ban time
# Values: CMD
# Default: iptables -I INPUT 1 -s <ip> -j DROP
#
actionban = echo -en "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
`whois <ip>`\n
Regards,\n
Fail2Ban"|mail -s "[Fail2Ban] <name>: banned <ip>" <dest>
# Option: fwunban
# Notes.: command executed when unbanning an IP. Take care that the
# command is executed with Fail2Ban user rights.
# Tags: <ip> IP address
# <bantime> unix timestamp of the ban time
# <unbantime> unix timestamp of the unban time
# Values: CMD
# Default: iptables -D INPUT -s <ip> -j DROP
#
actionunban =
[Init]
# Defaut name of the chain
#
name = default
# Destinataire of the mail
#
dest = root
-69
View File
@@ -1,69 +0,0 @@
# Fail2Ban configuration file
#
# Author: Cyril Jaquier
#
# $Revision: 254 $
#
[Definition]
# Option: fwstart
# Notes.: command executed once at the start of Fail2Ban.
# Values: CMD Default:
#
actionstart = echo -en "Hi,\n
The jail <name> has been started successfuly.\n
Regards,\n
Fail2Ban"|mail -s "[Fail2Ban] <name>: started" <dest>
# Option: fwend
# Notes.: command executed once at the end of Fail2Ban
# Values: CMD Default:
#
actionstop = echo -en "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
# Values: CMD Default:
#
actioncheck =
# Option: fwban
# 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
# <failtime> unix timestamp of the last failure
# <bantime> unix timestamp of the ban time
# Values: CMD
# Default: iptables -I INPUT 1 -s <ip> -j DROP
#
actionban = echo -en "Hi,\n
The IP <ip> has just been banned by Fail2Ban after
<failures> attempts against <name>.\n
Regards,\n
Fail2Ban"|mail -s "[Fail2Ban] <name>: banned <ip>" <dest>
# Option: fwunban
# Notes.: command executed when unbanning an IP. Take care that the
# command is executed with Fail2Ban user rights.
# Tags: <ip> IP address
# <bantime> unix timestamp of the ban time
# <unbantime> unix timestamp of the unban time
# Values: CMD
# Default: iptables -D INPUT -s <ip> -j DROP
#
actionunban =
[Init]
# Defaut name of the chain
#
name = default
# Destinataire of the mail
#
dest = root
-24
View File
@@ -1,24 +0,0 @@
# Fail2Ban configuration file
#
# Author: Cyril Jaquier
#
# $Revision$
#
[Definition]
# Option: loglevel
# Notes.: Set the log level output.
# 1 = ERROR
# 2 = WARN
# 3 = INFO
# 4 = DEBUG
# Values: NUM Default: 3
#
loglevel = 3
# Option: logtarget
# Notes.: Set the log target. This could be a file, SYSLOG, STDERR.
# Values: STDERR SYSLOG file Default: /var/log/fail2ban.log
#
logtarget = /var/log/fail2ban.log
-42
View File
@@ -1,42 +0,0 @@
# Fail2Ban configuration file
#
# Author: Cyril Jaquier
#
# $Revision$
#
[Definition]
# Option: maxretry
# Notes.: number of failures before IP gets banned.
# Values: NUM Default: 5
#
maxretry = 5
# Option: logfile
# Notes.: logfile to monitor.
# Values: FILE Default: /var/log/httpd/access_log
#
logfile = /var/log/httpd/access_log
# Option: timeregex
# Notes.: regex to match timestamp in Apache logfile. For TAI64N format,
# use timeregex = @[0-9a-f]{24}
# Values: [Wed Jan 05 15:08:01 2005]
# Default: \S{3} \S{3} \d{2} \d{2}:\d{2}:\d{2} \d{4}
#
timeregex = \S{3} \S{3} \d{2} \d{2}:\d{2}:\d{2} \d{4}
# Option: timepattern
# Notes.: format used in "timeregex" fields definition. Note that '%' must be
# escaped with '%' (see http://rgruet.free.fr/PQR2.3.html#timeModule).
# For TAI64N format, use timepattern = tai64n
# Values: TEXT Default: %%a %%b %%d %%H:%%M:%%S %%Y
#
timepattern = %%a %%b %%d %%H:%%M:%%S %%Y
# Option: failregex
# Notes.: regex to match the password failure messages in the logfile.
# Values: TEXT Default: authentication failure|user .* not found
#
failregex = authentication failure|user .* not found
-43
View File
@@ -1,43 +0,0 @@
# Fail2Ban configuration file
#
# Author: Cyril Jaquier
#
# $Revision$
#
[Definition]
# Option: maxretry
# Notes.: number of failures before IP gets banned.
# Values: NUM Default: 5
#
maxretry = 5
# Option: logpath
# Notes.: logfile to monitor.
# Values: FILE Default: /var/log/secure
#
logpath = /var/log/secure
# Option: timeregex
# Notes.: regex to match timestamp in SSH logfile. For TAI64N format,
# use timeregex = @[0-9a-f]{24}
# Values: [Mar 7 17:53:28]
# Default: \S{3}\s{1,2}\d{1,2} \d{2}:\d{2}:\d{2}
#
timeregex = \S{3}\s{1,2}\d{1,2} \d{2}:\d{2}:\d{2}
# Option: timepattern
# Notes.: format used in "timeregex" fields definition. Note that '%' must be
# escaped with '%' (see http://rgruet.free.fr/PQR2.3.html#timeModule).
# For TAI64N format, use timepattern = tai64n
# Values: TEXT Default: %%b %%d %%H:%%M:%%S
#
timepattern = %%b %%d %%H:%%M:%%S
# Option: failregex
# Notes.: regex to match the password failures messages in the logfile.
# Values: TEXT Default: Authentication failure|Failed password|Invalid user
#
failregex = (?:(?:Authentication failure|Failed [-/\w+]+) for(?: [iI](?:llegal|nvalid) user)?|[Ii](?:llegal|nvalid) user|ROOT LOGIN REFUSED) .*(?: from|FROM) (?:::f{4,6}:)?(?P<host>\S*)
-40
View File
@@ -1,40 +0,0 @@
# Fail2Ban configuration file
#
# Author: Cyril Jaquier
#
# $Revision$
#
[Definition]
# Option: maxretry
# Notes.: number of failures before IP gets banned.
# Values: NUM Default: 5
#
maxretry = 5
# Option: logfile
# Notes.: logfile to monitor.
# Values: FILE Default: /var/log/vsftpd.log
#
logfile = /var/log/vsftpd.log
# Option: timeregex
# Notes.: regex to match timestamp in VSFTPD logfile.
# Values: [Mar 7 17:53:28]
# Default: \S{3}\s{1,2}\d{1,2} \d{2}:\d{2}:\d{2}
#
timeregex = \S{3}\s{1,2}\d{1,2} \d{2}:\d{2}:\d{2}
# Option: timepattern
# Notes.: format used in "timeregex" fields definition. Note that '%' must be
# escaped with '%' (see http://rgruet.free.fr/PQR2.3.html#timeModule)
# Values: TEXT Default: %%b %%d %%H:%%M:%%S
#
timepattern = %%b %%d %%H:%%M:%%S
# Option: failregex
# Notes.: regex to match the password failures messages in the logfile.
# Values: TEXT Default: Authentication failure|Failed password|Invalid user
#
failregex = FAIL LOGIN
-15
View File
@@ -1,15 +0,0 @@
# Fail2Ban configuration file
#
# Author: Cyril Jaquier
#
# $Revision$
#
[dummy]
enabled = false
filter = sshd
action = hostsdeny[file=/tmp/hosts.deny]
mail[name=SSH, dest=cyril.jaquier@bluewin.ch]
maxretry = 2
bantime = 10
-1237
View File
File diff suppressed because it is too large Load Diff
-269
View File
@@ -1,269 +0,0 @@
#!/usr/bin/env python
# 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 sys, string, os, pickle, re, logging, getopt, time
# Inserts our own modules path first in the list
# fix for bug #343821
sys.path.insert(1, "/usr/lib/fail2ban")
# Now we can import our modules
from version import version
from client.csocket import CSocket
from client.configurator import Configurator
# Gets the instance of the logger.
logSys = logging.getLogger("fail2ban.client")
##
#
# @todo This class needs cleanup.
class Fail2banClient:
def __init__(self):
self.argv = None
self.stream = None
self.conf = dict()
self.conf["conf"] = "/etc/fail2ban"
self.conf["dump"] = False
self.conf["force"] = False
self.conf["verbose"] = 2
def dispUsage(self):
""" Prints Fail2Ban command line options and exits
"""
print "Usage: "+self.argv[0]+" [OPTIONS] <COMMAND>"
print
print "Fail2Ban v" + version + " reads log file that contains password failure report"
print "and bans the corresponding IP addresses using firewall rules."
print
print " <COMMAND>"
print
print " start start the server and the jails"
print " reload reload the configuration"
print " stop stop all jails and terminate the server"
print " status get the current status"
print
print " set loglevel <LEVEL> set loglevel to <LEVEL>"
print " get loglevel get loglevel"
print " set logtarget <TARGET> set log target to <TARGET>"
print " get logtarget get log target"
print
print " add <JAIL> create <JAIL>"
print " set <JAIL> <CMD> set the <CMD> value for <JAIL>"
print " get <JAIL> <CMD> get the <CMD> value for <JAIL>"
print " start <JAIL> start <JAIL>"
print " stop <JAIL> stop <JAIL>. The jail is removed"
print " status <JAIL> get the current status of <JAIL>"
print
print " [OPTIONS]"
print
print " -c <DIR> configuration directory"
print " -d dump configuration. For debugging"
print " -v increase verbosity"
print " -q decrease verbosity"
print " -x force execution of the server"
print " -h display this help message"
print
print "Report bugs to <lostcontrol@users.sourceforge.net>"
def getCmdLineOptions(self, optList):
""" Gets the command line options
"""
for opt in optList:
if opt[0] == "-c":
self.conf["conf"] = opt[1]
elif opt[0] == "-d":
self.conf["dump"] = True
elif opt[0] == "-v":
self.conf["verbose"] = self.conf["verbose"] + 1
elif opt[0] == "-q":
self.conf["verbose"] = self.conf["verbose"] - 1
elif opt[0] == "-x":
self.conf["force"] = True
elif opt[0] in ["-h", "--help"]:
self.dispUsage()
sys.exit(0)
def ping(self):
return self.processCmd([["ping"]], False)
@staticmethod
def processCmd(cmd, showRet = True):
for c in cmd:
try:
client = CSocket()
except Exception, e:
if showRet:
logSys.error(e)
logSys.error("Arrggh... Start the server first")
return False
ret = client.send(c)
if ret[0] == 0:
logSys.debug("OK : " + `ret[1]`)
if showRet:
print `ret[1]`
else:
logSys.error("NOK: " + `ret[1].args`)
return False
return True
##
# Process a command line.
#
# Process one command line and exit.
# @param cmd the command line
def processCommand(self, cmd):
if self.conf["dump"]:
self.readConfig()
self.dumpConfig(self.stream)
return True
if len(sys.argv) < 2:
self.dispUsage()
return False
if len(cmd) == 1 and cmd[0] == "start":
if self.ping():
logSys.info("Server already running")
return False
else:
self.startServerAsync(self.conf["force"])
# Read the config while the server is starting
self.readConfig()
try:
# Wait for the server to start
self.waitOnServer()
# Configure the server
self.processCmd(self.stream, False)
return True
except ServerExecutionException:
logSys.error("Could not start server. Try -x option")
return False
elif len(cmd) == 1 and cmd[0] == "reload":
if self.ping():
self.readConfig()
self.processCmd(['stop', 'all'], False)
# Configure the server
return self.processCmd(self.stream, False)
else:
logSys.error("Could not find server")
return False
else:
return self.processCmd([cmd])
##
# Start Fail2Ban server.
#
# Start the Fail2ban server in daemon mode.
def startServerAsync(self, force = False):
args = list()
args.append("fail2ban-server")
args.append("-b")
if force:
args.append("-x")
pid = os.fork()
if pid == 0:
os.execv("fail2ban-server", args)
def waitOnServer(self):
# Wait for the server to start
cnt = 0
while not self.ping():
if cnt > 10:
raise ServerExecutionException("Failed to start server")
time.sleep(0.1)
cnt = cnt + 1
def start(self, argv):
# Command line options
self.argv = argv
# Reads the command line options.
try:
cmdOpts = 'hc:xdvq'
cmdLongOpts = ['help']
optList, args = getopt.getopt(self.argv[1:], cmdOpts, cmdLongOpts)
except getopt.GetoptError:
self.dispUsage()
self.getCmdLineOptions(optList)
verbose = self.conf["verbose"]
if verbose <= 0:
logSys.setLevel(logging.ERROR)
elif verbose == 1:
logSys.setLevel(logging.WARN)
elif verbose == 2:
logSys.setLevel(logging.INFO)
else:
logSys.setLevel(logging.DEBUG)
# Add the default logging handler
stdout = logging.StreamHandler(sys.stdout)
# set a format which is simpler for console use
formatter = logging.Formatter('%(levelname)-6s %(message)s')
# tell the handler to use this format
stdout.setFormatter(formatter)
logSys.addHandler(stdout)
return self.processCommand(args)
def readConfig(self):
# Read the configuration
cfg = Configurator()
cfg.setBaseDir(self.conf["conf"])
cfg.readAll()
cfg.getAllOptions()
cfg.convertToProtocol()
self.stream = cfg.getConfigStream()
@staticmethod
def dumpConfig(cmd):
for c in cmd:
print c
return True
class ServerExecutionException(Exception):
pass
if __name__ == "__main__":
client = Fail2banClient()
# Exit with correct return value
if client.start(sys.argv):
sys.exit(0)
else:
sys.exit(-1)
-121
View File
@@ -1,121 +0,0 @@
#!/usr/bin/env python
# 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 locale, getopt, sys
# Inserts our own modules path first in the list
# fix for bug #343821
sys.path.insert(1, "/usr/lib/fail2ban")
from version import version
from server.server import Server
from utils.process import *
##
# \mainpage Fail2Ban
#
# \section Introduction
#
# Fail2ban is designed to protect your server against brute force attacks.
# Its first goal was to protect a SSH server.
class Fail2banServer:
def __init__(self):
self.server = None
self.argv = None
self.conf = dict()
self.conf["background"] = True
self.conf["force"] = False
def dispUsage(self):
""" Prints Fail2Ban command line options and exits
"""
print "Usage: "+self.argv[0]+" [OPTIONS]"
print
print "Fail2Ban v" + version + " reads log file that contains password failure report"
print "and bans the corresponding IP addresses using firewall rules."
print
print " -b start in background"
print " -f start in foreground"
print " -x force execution of the server"
print " -h display this help message"
print
print "Report bugs to <lostcontrol@users.sourceforge.net>"
sys.exit(0)
def getCmdLineOptions(self, optList):
""" Gets the command line options
"""
for opt in optList:
if opt[0] == "-b":
self.conf["background"] = True
if opt[0] == "-f":
self.conf["background"] = False
if opt[0] == "-x":
self.conf["force"] = True
if opt[0] in ["-h", "--help"]:
self.dispUsage()
#def sigTERMhandler(signum, frame):
# """ Handles the TERM signal when in daemon mode in order to
# exit properly.
# """
# logSys.debug("Signal handler called with sig "+`signum`)
# server.quit()
def start(self, argv):
# Command line options
self.argv = argv
# Reads the command line options.
try:
cmdOpts = 'bfxh'
cmdLongOpts = ['help']
optList, args = getopt.getopt(self.argv[1:], cmdOpts, cmdLongOpts)
except getopt.GetoptError:
self.dispUsage()
self.getCmdLineOptions(optList)
if self.conf["background"]:
retCode = createDaemon()
#signal.signal(signal.SIGTERM, sigTERMhandler)
if not retCode:
print "Unable to start daemon"
sys.exit(-1)
try:
self.server = Server()
self.server.start(self.conf["force"])
except Exception, e:
print e
self.server.quit()
if __name__ == "__main__":
server = Fail2banServer()
server.start(sys.argv)
-69
View File
@@ -1,69 +0,0 @@
#!/usr/bin/env python
# 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 unittest, logging, sys
# Inserts our own modules path first in the list
# fix for bug #343821
sys.path.insert(1, "/usr/lib/fail2ban")
from version import version
from testcases import banmanagertestcase
from testcases import clientreadertestcase
from testcases import failmanagertestcase
from testcases import filtertestcase
from testcases import servertestcase
# Gets the instance of the logger.
logSys = logging.getLogger("fail2ban")
# Add the default logging handler
stdout = logging.StreamHandler(sys.stdout)
logSys.addHandler(stdout)
logSys.setLevel(logging.FATAL)
print "Fail2ban " + version + " test suite. Please wait..."
tests = unittest.TestSuite()
# Filter
tests.addTest(unittest.makeSuite(filtertestcase.IgnoreIP))
tests.addTest(unittest.makeSuite(filtertestcase.LogFile))
#tests.addTest(unittest.makeSuite(filtertestcase.GetFailures))
# Server
#tests.addTest(unittest.makeSuite(servertestcase.StartStop))
#tests.addTest(unittest.makeSuite(servertestcase.Transmitter))
# FailManager
tests.addTest(unittest.makeSuite(failmanagertestcase.AddFailure))
# BanManager
tests.addTest(unittest.makeSuite(banmanagertestcase.AddFailure))
# ClientReader
tests.addTest(unittest.makeSuite(clientreadertestcase.JailReaderTest))
# Tests runner
testRunner = unittest.TextTestRunner()
testRunner.run(tests)
Binary file not shown.
+1
View File
@@ -0,0 +1 @@
432096e69a64df45cd8aa49b66e5f473cb8de972
Binary file not shown.
+1
View File
@@ -0,0 +1 @@
9018dec2acaf9038b973d2874ef4848fdcfcfc2e
Binary file not shown.
+1
View File
@@ -0,0 +1 @@
881b05f931fee22ff04637209b4a6d774149fb56
Binary file not shown.
+1
View File
@@ -0,0 +1 @@
7bd8c4dda6b2978e8eaaaad8f428727ac3a36d49
Binary file not shown.
+1
View File
@@ -0,0 +1 @@
151df27656b75c6f83a42857c28b99c9793998f0
Binary file not shown.
+1
View File
@@ -0,0 +1 @@
6e5843a7cebd7b3d92274eb3da391e3e6c166284
Binary file not shown.
+1
View File
@@ -0,0 +1 @@
4d1f6ac73abc134098cce4b80ef682d9c44c2dde
Binary file not shown.
+1
View File
@@ -0,0 +1 @@
c84e58c2b2e51c836804b9c3b6aa85a08ede3136
Binary file not shown.
+1
View File
@@ -0,0 +1 @@
2fbc8d5a7b02c8ab5627119670d41e7dafe22389
Binary file not shown.
+1
View File
@@ -0,0 +1 @@
86b7a61244f6c27ed4e94f18081643988cd1d91f
Binary file not shown.
+1
View File
@@ -0,0 +1 @@
691bb92d39ae67f576588f2f2d40db6ed7ee7135
Binary file not shown.
+1
View File
@@ -0,0 +1 @@
2021bb12e4e71229259325345d5b72bf6e586f19
Binary file not shown.
+1
View File
@@ -0,0 +1 @@
e6efcd92753868d0d2c72bab092e9d56cad108bb
Binary file not shown.
+1
View File
@@ -0,0 +1 @@
539467a8d37d0f36eaab69f319dbded1c9cec9fe
Binary file not shown.
+1
View File
@@ -0,0 +1 @@
164460619940fff77273095d46ae8b040854ec84
Binary file not shown.
@@ -0,0 +1 @@
c0e3a3e494ac5a187e42a6b92b85301e3a386ab2
Binary file not shown.
+1
View File
@@ -0,0 +1 @@
12548aff657cd32fac53e4dae5745c180a87f753
Binary file not shown.
+1
View File
@@ -0,0 +1 @@
4f733aa21111e27cb707cc9e05e820c27e54694b
Binary file not shown.
+1
View File
@@ -0,0 +1 @@
a20d1f8c337d2b90c99f8d708e586e5a1dcedaba
Binary file not shown.
+1
View File
@@ -0,0 +1 @@
caed3e0be38f2896fdce863ee1d81e0f7b949117
Binary file not shown.
+1
View File
@@ -0,0 +1 @@
bd48aba82f2d7e9265e076b37b628b7985da91de
-2
View File
@@ -1,2 +0,0 @@
#!/bin/bash
kill `ps ax|grep fail2ban|grep -v grep|awk '{print $1}'`
-25
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$
__author__ = "Cyril Jaquier"
__version__ = "$Revision$"
__date__ = "$Date$"
__copyright__ = "Copyright (c) 2004 Cyril Jaquier"
__license__ = "GPL"
-223
View File
@@ -1,223 +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, logging, os
# Gets the instance of the logger.
logSys = logging.getLogger("fail2ban.actions.action")
##
# Execute commands.
#
# This class reads the failures from the Jail queue and decide if an
# action has to be taken. A BanManager take care of the banned IP
# addresses.
class Action:
def __init__(self, name):
self.name = name
self.cInfo = dict()
## Command executed in order to initialize the system.
self.actionStart = ''
## Command executed when an IP address gets banned.
self.actionBan = ''
## Command executed when an IP address gets removed.
self.actionUnban = ''
## Command executed in order to check requirements.
self.actionCheck = ''
## Command executed in order to stop the system.
self.actionStop = ''
logSys.debug("Created Action")
def setName(self, name):
self.name = name
def getName(self):
return self.name
def setCInfo(self, key, value):
self.cInfo[key] = value
def getCInfo(self, key):
return self.cInfo[key]
def delCInfo(self, key):
del self.cInfo[key]
##
# Set the "start" command.
#
# @param value the command
def setActionStart(self, value):
self.actionStart = value
logSys.info("Set actionStart = %s" % value)
##
# Get the "start" command.
#
# @return the command
def getActionStart(self):
return self.actionStart
def execActionStart(self):
startCmd = Action.replaceTag(self.actionStart, self.cInfo)
return Action.executeCmd(startCmd)
##
# Set the "ban" command.
#
# @param value the command
def setActionBan(self, value):
self.actionBan = value
logSys.info("Set actionBan = %s" % value)
##
# Get the "ban" command.
#
# @return the command
def getActionBan(self):
return self.actionBan
def execActionBan(self, aInfo):
return self.processCmd(self.actionBan, aInfo);
##
# Set the "unban" command.
#
# @param value the command
def setActionUnban(self, value):
self.actionUnban = value
logSys.info("Set actionUnban = %s" % value)
##
# Get the "unban" command.
#
# @return the command
def getActionUnban(self):
return self.actionUnban
def execActionUnban(self, aInfo):
return self.processCmd(self.actionUnban, aInfo);
##
# Set the "check" command.
#
# @param value the command
def setActionCheck(self, value):
self.actionCheck = value
logSys.info("Set actionCheck = %s" % value)
##
# Get the "check" command.
#
# @return the command
def getActionCheck(self):
return self.actionCheck
##
# Set the "stop" command.
#
# @param value the command
def setActionStop(self, value):
self.actionStop = value
logSys.info("Set actionStop = %s" % value)
##
# Get the "stop" command.
#
# @return the command
def getActionStop(self):
return self.actionStop
def execActionStop(self):
stopCmd = Action.replaceTag(self.actionStop, self.cInfo)
return Action.executeCmd(stopCmd)
@staticmethod
def replaceTag(query, aInfo):
""" Replace tags in query
"""
string = query
for tag in aInfo:
string = string.replace('<' + tag + '>', str(aInfo[tag]))
# New line
string = string.replace("<br>", '\n')
return string
def processCmd(self, cmd, aInfo = None):
""" Executes an OS command.
"""
if cmd == "":
logSys.debug("Nothing to do")
return True
checkCmd = Action.replaceTag(self.actionCheck, self.cInfo)
if not Action.executeCmd(checkCmd):
logSys.error("Invariant check failed. Trying to restore a sane" +
" environment")
stopCmd = Action.replaceTag(self.actionStop, self.cInfo)
Action.executeCmd(stopCmd)
startCmd = Action.replaceTag(self.actionStart, self.cInfo)
Action.executeCmd(startCmd)
if not Action.executeCmd(checkCmd):
logSys.fatal("Unable to restore environment")
return False
# Replace tags
if not aInfo == None:
realCmd = Action.replaceTag(cmd, aInfo)
else:
realCmd = cmd
# Replace static fields
realCmd = Action.replaceTag(realCmd, self.cInfo)
return Action.executeCmd(realCmd)
@staticmethod
def executeCmd(realCmd):
logSys.debug(realCmd)
retval = os.system(realCmd)
#if not retval == 0:
# logSys.error("'" + cmd + "' returned " + `retval`)
# raise Exception("Execution of command '%s' failed" % cmd)
if retval == 0:
return True
else:
logSys.error("%s returned %x" % (realCmd, retval))
return False
-184
View File
@@ -1,184 +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"
from banmanager import BanManager
from failmanager import FailManager, FailManagerEmpty
from jailthread import JailThread
from action import Action
import time, logging, os
# Gets the instance of the logger.
logSys = logging.getLogger("fail2ban.actions")
##
# Execute commands.
#
# This class reads the failures from the Jail queue and decide if an
# action has to be taken. A BanManager take care of the banned IP
# addresses.
class Actions(JailThread):
##
# Constructor.
#
# Initialize the filter object with default values.
# @param jail the jail object
def __init__(self, jail):
JailThread.__init__(self, jail)
## The jail which contains this action.
self.jail = jail
self.actions = list()
## The ban manager.
self.banManager = BanManager()
def addAction(self, name):
action = Action(name)
self.actions.append(action)
def delAction(self, name):
for action in self.actions:
if action.getName() == name:
self.actions.remove(action)
break
def getAction(self, name):
for action in self.actions:
if action.getName() == name:
return action
raise KeyError
def getLastAction(self):
action = self.actions.pop()
self.actions.append(action)
return action
##
# Set the ban time.
#
# @param value the time
def setBanTime(self, value):
self.banManager.setBanTime(value)
logSys.info("Set banTime = %s" % value)
##
# Get the ban time.
#
# @return the time
def getBanTime(self):
return self.banManager.getBanTime()
##
# Main loop.
#
# This function is the main loop of the thread. It checks the Jail
# queue and executes commands when an IP address is banned.
# @return True when the thread exits nicely
def run(self):
for action in self.actions:
action.execActionStart()
self.setActive(True)
while self.isActive():
if not self.isIdle:
#logSys.debug(self.jail.getName() + ": action")
ret = self.checkBan()
if not ret:
self.checkUnBan()
time.sleep(self.sleepTime)
else:
time.sleep(self.sleepTime)
self.flushBan()
for action in self.actions:
action.execActionStop()
logSys.debug(self.jail.getName() + ": action terminated")
return True
##
# Check for IP address to ban.
#
# Look in the Jail queue for FailTicket. If a ticket is available,
# it executes the "ban" command and add a ticket to the BanManager.
# @return True if an IP address get banned
def checkBan(self):
logSys.debug("Check for IP address to ban")
ticket = self.jail.getFailTicket()
if ticket != False:
aInfo = dict()
bTicket = BanManager.createBanTicket(ticket)
aInfo["ip"] = bTicket.getIP()
aInfo["failures"] = bTicket.getAttempt()
logSys.info("Ban %s" % aInfo["ip"])
for action in self.actions:
action.execActionBan(aInfo)
self.banManager.addBanTicket(bTicket)
return True
return False
##
# Check for IP address to unban.
#
# Unban IP address which are outdated.
def checkUnBan(self):
logSys.debug("Check for IP address to unban")
for ticket in self.banManager.unBanList(time.time()):
aInfo = dict()
aInfo["ip"] = ticket.getIP()
logSys.info("Unban %s" % aInfo["ip"])
for action in self.actions:
action.execActionUnban(aInfo)
##
# Flush the ban list.
#
# Unban all IP address which are still in the banning list.
def flushBan(self):
logSys.debug("Flush ban list")
for ticket in self.banManager.flushBanList():
aInfo = dict()
aInfo["ip"] = ticket.getIP()
logSys.info("Unban %s" % aInfo["ip"])
for action in self.actions:
action.execActionUnban(aInfo)
##
# Get the status of the filter.
#
# Get some informations about the filter state such as the total
# number of failures.
# @return a list with tuple
def status(self):
ret = [("Currently banned", self.banManager.size()),
("Total banned", self.banManager.getBanTotal())]
return ret
-186
View File
@@ -1,186 +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"
from banticket import BanTicket
from threading import Lock
import time, logging
# Gets the instance of the logger.
logSys = logging.getLogger("fail2ban.action")
##
# Banning Manager.
#
# Manage the banned IP addresses. Convert FailTicket to BanTicket.
# This class is mainly used by the Action class.
class BanManager:
##
# Constructor.
#
# Initialize members with default values.
def __init__(self):
## Mutex used to protect the ban list.
self.lock = Lock()
## The ban list.
self.banList = list()
## The amount of time an IP address gets banned.
self.banTime = 600
## Total number of banned IP address
self.banTotal = 0
##
# Set the ban time.
#
# Set the amount of time an IP address get banned.
# @param value the time
def setBanTime(self, value):
self.banTime = int(value)
##
# Get the ban time.
#
# Get the amount of time an IP address get banned.
# @return the time
def getBanTime(self):
return self.banTime
##
# Set the total number of banned address.
#
# @param value total number
def setBanTotal(self, value):
self.banTotal = value
##
# Get the total number of banned address.
#
# @return the total number
def getBanTotal(self):
return self.banTotal
##
# Create a ban ticket.
#
# Create a BanTicket from a FailTicket. The timestamp of the BanTicket
# is the current time. This is a static method.
# @param ticket the FailTicket
# @return a BanTicket
@staticmethod
def createBanTicket(ticket):
ip = ticket.getIP()
#lastTime = ticket.getTime()
lastTime = time.time()
banTicket = BanTicket(ip, lastTime)
banTicket.setAttempt(ticket.getAttempt())
return banTicket
##
# Add a ban ticket.
#
# Add a BanTicket instance into the ban list.
# @param ticket the ticket
# @return True if the IP address is not in the ban list
def addBanTicket(self, ticket):
self.lock.acquire()
if not self.inBanList(ticket):
self.banList.append(ticket)
self.banTotal += 1
self.lock.release()
return True
self.lock.release()
return False
##
# Delete a ban ticket.
#
# Remove a BanTicket from the ban list.
# @param ticket the ticket
def delBanTicket(self, ticket):
self.banList.remove(ticket)
##
# Get the size of the ban list.
#
# @return the size
def size(self):
return len(self.banList)
##
# Check if a ticket is in the list.
#
# Check if a BanTicket with a given IP address is already in the
# ban list.
# @param ticket the ticket
# @return True if a ticket already exists
def inBanList(self, ticket):
for i in self.banList:
if ticket.getIP() == i.getIP():
return True
return False
##
# Get the list of IP address to unban.
#
# Return a list of BanTicket which need to be unbanned.
# @param time the time
# @return the list of ticket to unban
# @todo Check the delete operation
def unBanList(self, time):
uBList = list()
self.lock.acquire()
for ticket in self.banList:
if ticket.getTime() < time - self.banTime:
uBList.append(ticket)
self.delBanTicket(ticket)
self.lock.release()
return uBList
##
# Flush the ban list.
#
# Get the ban list and initialize it with an empty one.
# @return the complete ban list
def flushBanList(self):
self.lock.acquire()
uBList = self.banList
self.banList = list()
self.lock.release()
return uBList
-50
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 time, 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)
-53
View File
@@ -1,53 +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, logging
# Gets the instance of the logger.
logSys = logging.getLogger("fail2ban")
class FailData:
def __init__(self):
self.retry = 0
self.lastTime = 0
def setRetry(self, value):
self.retry = value
def getRetry(self):
return self.retry
def inc(self):
self.retry += 1
def setLastTime(self, value):
if value > self.lastTime:
self.lastTime = value
def getLastTime(self):
return self.lastTime
-109
View File
@@ -1,109 +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"
from faildata import FailData
from failticket import FailTicket
from threading import Lock
import time, logging
# Gets the instance of the logger.
logSys = logging.getLogger("fail2ban.filter")
class FailManager:
def __init__(self):
self.lock = Lock()
self.failList = dict()
self.maxRetry = 3
self.maxTime = 600
self.failTotal = 0
def setFailTotal(self, value):
self.failTotal = value
def getFailTotal(self):
return self.failTotal
def setMaxRetry(self, value):
self.maxRetry = value
def getMaxRetry(self):
return self.maxRetry
def setMaxTime(self, value):
self.maxTime = value
def getMaxTime(self):
return self.maxTime
def addFailure(self, ticket):
self.lock.acquire()
ip = ticket.getIP()
unixTime = ticket.getTime()
if self.failList.has_key(ip):
fData = self.failList[ip]
fData.inc()
fData.setLastTime(unixTime)
else:
fData = FailData()
fData.inc()
fData.setLastTime(unixTime)
self.failList[ip] = fData
self.failTotal += 1
self.lock.release()
def size(self):
return len(self.failList)
def cleanup(self, time):
self.lock.acquire()
tmp = self.failList.copy()
for item in tmp:
if tmp[item].getLastTime() < time - self.maxTime:
self.delFailure(item)
self.lock.release()
def delFailure(self, ip):
if self.failList.has_key(ip):
del self.failList[ip]
def toBan(self):
self.lock.acquire()
for ip in self.failList:
data = self.failList[ip]
if data.getRetry() >= self.maxRetry:
self.delFailure(ip)
self.lock.release()
# Create a FailTicket from BanData
failTicket = FailTicket(ip, data.getLastTime())
failTicket.setAttempt(data.getRetry())
return failTicket
self.lock.release()
raise FailManagerEmpty
class FailManagerEmpty(Exception):
pass
-37
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 time, 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)
-556
View File
@@ -1,556 +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"
from failmanager import FailManager
from failmanager import FailManagerEmpty
from failticket import FailTicket
from jailthread import JailThread
import time, logging, os, re, sys, socket
# Gets the instance of the logger.
logSys = logging.getLogger("fail2ban.filter")
##
# Log reader class.
#
# This class reads a log file and detects login failures or anything else
# that matches a given regular expression. This class is instanciated by
# a Jail object.
class Filter(JailThread):
##
# Constructor.
#
# Initialize the filter object with default values.
# @param jail the jail object
def __init__(self, jail):
JailThread.__init__(self, jail)
## The jail which contains this filter.
self.jail = jail
## The failures manager.
self.failManager = FailManager()
## The log file handler.
self.fileHandler = None
## The log file path.
self.logPath = ''
## The regular expression matching the date.
self.timeRegex = ''
self.timeRegexObj = None
## The pattern matching the date.
self.timePattern = ''
## The regular expression matching the failure.
self.failRegex = ''
self.failRegexObj = None
## The amount of time to look back.
self.findTime = 6000
## The ignore IP list.
self.ignoreIpList = []
## The time of the last modification of the file.
self.lastModTime = 0
## The last position of the file.
self.lastPos = 0
## The last date in tht log file.
self.lastDate = 0
## The file statistics.
self.logStats = None
logSys.info("Created Filter")
##
# Set the log file path
#
# @param value log file path
def setLogPath(self, value):
self.logPath = value
logSys.info("Set logfile = %s" % value)
##
# Get the log file path
#
# @return log file path
def getLogPath(self):
return self.logPath
##
# Set the regular expression which matches the time.
#
# @param value the regular expression
def setTimeRegex(self, value):
self.timeRegex = value
self.timeRegexObj = re.compile(value)
logSys.info("Set timeregex = %s" % value)
##
# Get the regular expression which matches the time.
#
# @return the regular expression
def getTimeRegex(self):
return self.timeRegex
##
# Set the time pattern.
#
# @param value the time pattern
def setTimePattern(self, value):
self.timePattern = value
logSys.info("Set timepattern = %s" % value)
##
# Get the time pattern.
#
# @return the time pattern
def getTimePattern(self):
return self.timePattern
##
# Set the regular expression which matches the failure.
#
# The regular expression can also match any other pattern than failures
# and thus can be used for many purporse.
# @param value the regular expression
def setFailRegex(self, value):
self.failRegex = value
self.failRegexObj = re.compile(value)
logSys.info("Set failregex = %s" % value)
##
# Get the regular expression which matches the failure.
#
# @return the regular expression
def getFailRegex(self):
return self.failRegex
##
# Set the time needed to find a failure.
#
# This value tells the filter how long it has to take failures into
# account.
# @param value the time
def setFindTime(self, value):
self.findTime = value
logSys.info("Set findtime = %s" % value)
##
# Get the time needed to find a failure.
#
# @return the time
def getFindTime(self):
return self.findTime
##
# Set the maximum retry value.
#
# @param value the retry value
def setMaxRetry(self, value):
self.failManager.setMaxRetry(value)
logSys.info("Set maxRetry = %s" % value)
##
# Get the maximum retry value.
#
# @return the retry value
def getMaxRetry(self):
return self.failManager.getMaxRetry()
##
# Set the maximum time a failure stays in the list.
#
# @param value the maximum time
def setMaxTime(self, value):
self.failManager.setMaxTime(value)
logSys.info("Set maxTime = %s" % value)
##
# Get the maximum time a failure stays in the list.
#
# @return the time value
def getMaxTime(self):
return self.failManager.getMaxTime()
##
# Main loop.
#
# This function is the main loop of the thread. It checks if the
# file has been modified and looks for failures.
# @return True when the thread exits nicely
def run(self):
self.setActive(True)
while self.isActive():
if not self.isIdle:
if self.isModified():
self.getFailures()
try:
ticket = self.failManager.toBan()
self.jail.putFailTicket(ticket)
except FailManagerEmpty:
self.failManager.cleanup(time.time())
time.sleep(self.sleepTime)
else:
time.sleep(self.sleepTime)
logSys.debug(self.jail.getName() + ": filter terminated")
return True
##
# Add an IP to the ignore list.
#
# IP addresses in the ignore list are not taken into account
# when finding failures. CIDR mask are also accepted.
# @param ip IP address to ignore
def addIgnoreIP(self, ip):
logSys.debug("Add " + ip + " to ignore list")
self.ignoreIpList.append(ip)
##
# Check if IP address is in the ignore list.
#
# Check if the given IP address matches an IP address or a CIDR
# mask in the ignore list.
# @param ip IP address
# @return True if IP address is in ignore list
def inIgnoreIPList(self, ip):
for i in self.ignoreIpList:
s = i.split('/', 1)
# IP address without CIDR mask
if len(s) == 1:
s.insert(1, '32')
s[1] = long(s[1])
try:
a = DNSUtils.cidr(s[0], s[1])
b = DNSUtils.cidr(ip, s[1])
except Exception:
return False
if a == b:
return True
return False
##
# Open the log file.
def openLogFile(self):
""" Opens the log file specified on init.
"""
try:
self.fileHandler = open(self.logPath)
except OSError:
logSys.error("Unable to open "+self.logPath)
##
# Close the log file.
def closeLogFile(self):
self.fileHandler.close()
##
# Checks if the log file has been modified.
#
# Checks if the log file has been modified using os.stat().
# @return True if log file has been modified
def isModified(self):
try:
self.logStats = os.stat(self.logPath)
if self.lastModTime == self.logStats.st_mtime:
return False
else:
logSys.debug(self.logPath + " has been modified")
self.lastModTime = self.logStats.st_mtime
return True
except OSError:
logSys.error("Unable to get stat on " + self.logPath)
return False
##
# 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.fileHandler.readline()
if self.lastDate < self.getTime(line):
logSys.debug("Date " + `self.lastDate` + " is " + "smaller than " +
`self.getTime(line)`)
logSys.debug("Log rotation detected for " + self.logPath)
self.lastPos = 0
logSys.debug("Setting file position to " + `self.lastPos` + " for " +
self.logPath)
self.fileHandler.seek(self.lastPos)
##
# Get the file position.
def getFilePos(self):
return self.fileHandler.tell()
##
# Gets all the failure in the log file.
#
# Gets all the failure in the log file which are newer than
# time.time()-self.findTime. When a failure is detected, a FailTicket
# is created and is added to the FailManager.
def getFailures(self):
ipList = dict()
logSys.debug(self.logPath)
self.openLogFile()
self.setFilePos()
lastLine = None
for line in self.fileHandler:
try:
# Try to convert UTF-8 string to Latin-1
line = line.decode('utf-8').encode('latin-1')
except UnicodeDecodeError:
pass
if not self.hasTime(line):
# There is no valid time in this line
continue
lastLine = line
for element in self.findFailure(line):
ip = element[0]
unixTime = element[1]
if unixTime < time.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 = self.getFilePos()
if lastLine:
self.lastDate = self.getTime(lastLine)
self.closeLogFile()
##
# Finds the failure in a line.
#
# 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):
failList = list()
match = self.failRegexObj.search(line)
if match:
timeMatch = self.timeRegexObj.search(match.string)
if timeMatch:
date = self.getUnixTime(timeMatch.group())
try:
ipMatch = DNSUtils.textToIp(match.group("host"))
if ipMatch:
for ip in ipMatch:
failList.append([ip, date])
except IndexError:
logSys.error("There is no 'host' group in the rule. " +
"Please correct your configuration.")
return failList
##
# Check is a line contains a valid date.
#
# @param line the line
# @return True if the line contains a valid date
def hasTime(self, line):
timeMatch = re.search(self.timeRegex, line)
if timeMatch:
return True
else:
return False
##
# Get the time of a log line.
#
# @param line the line
# @return the timestamp of the log line
def getTime(self, line):
date = 0
timeMatch = re.search(self.timeRegex, line)
if timeMatch:
date = self.getUnixTime(timeMatch.group())
return date
##
# Get the Unix timestamp.
#
# Get the Unix timestamp of a given date. Pattern should describe the
# date construction of value.
# @param value the date
# @return the Unix timestamp
def getUnixTime(self, value):
try:
# Check if the parsed value is in TAI64N format
if not self.timePattern.lower() == "tai64n":
date = list(time.strptime(value, self.timePattern))
else:
# extract part of format which represents seconds since epoch
seconds_since_epoch = value[2:17]
date = list(time.gmtime(int(seconds_since_epoch, 16)))
except ValueError, e:
logSys.error(e)
logSys.error("Please check the format and your locale settings.")
return None
if date[0] < 2000:
# There is probably no year field in the logs
date[0] = time.gmtime()[0]
# Bug fix for #1241756
# If the date is greater than the current time, we suppose
# that the log is not from this year but from the year before
if time.mktime(date) > time.time():
date[0] -= 1
unixTime = time.mktime(date)
return unixTime
##
# Get the status of the filter.
#
# Get some informations about the filter state such as the total
# number of failures.
# @return a list with tuple
def status(self):
ret = [("Currently failed", self.failManager.size()),
("Total failed", self.failManager.getFailTotal())]
return ret
##
# Utils class for DNS and IP handling.
#
# This class contains only static methods used to handle DNS and IP
# addresses.
import socket, struct
class DNSUtils:
dnsCRE = re.compile("(?:(?:\w|-)+\.){2,}\w+")
ipCRE = re.compile("(?:\d{1,3}\.){3}\d{1,3}")
@staticmethod
def dnsToIp(dns):
""" Convert a DNS into an IP address using the Python socket module.
Thanks to Kevin Drapel.
"""
try:
return socket.gethostbyname_ex(dns)[2]
except socket.gaierror:
return list()
@staticmethod
def textToDns(text):
""" Search for possible DNS in an arbitrary text.
Thanks to Tom Pike.
"""
match = DNSUtils.dnsCRE.match(text)
if match:
return match
else:
return None
@staticmethod
def searchIP(text):
""" Search if an IP address if directly available and return
it.
"""
match = DNSUtils.ipCRE.match(text)
if match:
return match
else:
return None
@staticmethod
def isValidIP(str):
""" Return true if str is a valid IP
"""
s = str.split('/', 1)
try:
socket.inet_aton(s[0])
return True
except socket.error:
return False
@staticmethod
def textToIp(text):
""" Return the IP of DNS found in a given text.
"""
ipList = list()
# Search for plain IP
plainIP = DNSUtils.searchIP(text)
if not plainIP == None:
plainIPStr = plainIP.group(0)
if DNSUtils.isValidIP(plainIPStr):
ipList.append(plainIPStr)
if not ipList:
# Try to get IP from possible DNS
dns = DNSUtils.textToDns(text)
if not dns == None:
ip = DNSUtils.dnsToIp(dns.group(0))
for e in ip:
ipList.append(e)
return ipList
@staticmethod
def cidr(i, n):
""" Convert an IP address string with a CIDR mask into a 32-bit
integer.
"""
# 32-bit IPv4 address mask
MASK = 0xFFFFFFFFL
return ~(MASK >> n) & MASK & DNSUtils.addr2bin(i)
@staticmethod
def addr2bin(str):
""" Convert a string IPv4 address into an unsigned integer.
"""
return struct.unpack("!L", socket.inet_aton(str))[0]
@staticmethod
def bin2addr(addr):
""" Convert a numeric IPv4 address into string n.n.n.n form.
"""
return socket.inet_ntoa(struct.pack("!L", addr))
-95
View File
@@ -1,95 +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"
from actions import Actions
from filter import Filter
import Queue
class Jail:
def __init__(self, name, filter = None, action = None):
self.name = name
self.queue = Queue.Queue()
self.filter = Filter(self)
self.action = Actions(self)
def setName(self, name):
self.name = name
def getName(self):
return self.name
def setFilter(self, filter):
self.filter = filter
def getFilter(self):
return self.filter
def setAction(self, action):
self.action = action
def getAction(self):
return self.action
def putFailTicket(self, ticket):
self.queue.put(ticket)
def getFailTicket(self):
try:
return self.queue.get(False)
except Queue.Empty:
return False
def start(self):
self.filter.start()
self.action.start()
def stop(self):
self.filter.stop()
self.action.stop()
self.filter.join()
self.action.join()
def isActive(self):
isActive0 = self.filter.isActive()
isActive1 = self.action.isActive()
return isActive0 or isActive1
def setIdle(self, value):
self.filter.setIdle(value)
self.action.setIdle(value)
def getIdle(self):
return self.filter.getIdle() or self.action.getIdle()
def getStatus(self):
fStatus = self.filter.status()
aStatus = self.action.status()
ret = [("filter", fStatus),
("action", aStatus)]
return ret
-114
View File
@@ -1,114 +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"
from threading import Thread
class JailThread(Thread):
##
# Constructor.
#
# Initialize the filter object with default values.
# @param jail the jail object
def __init__(self, jail):
Thread.__init__(self)
## Control the state of the thread.
self.isRunning = False
## Control the idle state of the thread.
self.isIdle = False
## The time the thread sleeps in the loop.
self.sleepTime = 1
##
# Set the time that the thread sleeps.
#
# This value could also be called "polling time". A value of 1 is a
# good one. This unit is "second"
# @param value the polling time (second)
def setSleepTime(self, value):
self.sleepTime = value
logSys.info("Set sleeptime = " + value)
##
# Get the time that the thread sleeps.
#
# @return the polling time
def getSleepTime(self):
return self.sleeptime
##
# Set the idle flag.
#
# This flag stops the check of the log file.
# @param value boolean value
def setIdle(self, value):
self.isIdle = value
##
# Get the idle state.
#
# @return the idle state
def getIdle(self):
return self.isIdle
##
# Stop the thread.
#
# Stop the exection of the thread and quit.
def stop(self):
self.isRunning = False
##
# Set the isRunning flag.
#
# @param value True if the thread is running
def setActive(self, value):
self.isRunning = value
##
# Check if the thread is active.
#
# Check if the filter thread is running.
# @return True if the thread is running
def isActive(self):
return self.isRunning
##
# Get the status of the thread
#
# Get some informations about the thread. This is an abstract method.
# @return a list with tuple
def status(self):
pass
-359
View File
@@ -1,359 +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"
from jail import Jail
from transmitter import Transmitter
import locale, logging, sys
# Gets the instance of the logger.
logSys = logging.getLogger("fail2ban.server")
class Server:
def __init__(self):
self.jails = dict()
self.transm = Transmitter(self)
self.logLevel = 3
self.logTarget = "STDERR"
# Set logging level
self.setLogLevel(self.logLevel)
self.setLogTarget(self.logTarget)
def start(self, force):
# Start the communication
self.transm.start(force)
def quit(self):
self.stopAllJail()
self.transm.stop()
def addJail(self, name):
self.jails[name] = Jail(name)
def delJail(self, name):
if self.jails.has_key(name):
del self.jails[name]
else:
raise ServerUnknownJail(name)
def startJail(self, name):
if self.jails.has_key(name):
self.jails[name].start()
else:
raise ServerUnknownJail(name)
def stopJail(self, name):
if self.jails.has_key(name):
if self.isActive(name):
self.jails[name].stop()
self.delJail(name)
else:
raise ServerUnknownJail(name)
def stopAllJail(self):
for jail in self.jails.copy():
self.stopJail(jail)
def isActive(self, name):
if self.jails.has_key(name):
return self.jails[name].isActive()
else:
raise ServerUnknownJail(name)
def setIdleJail(self, name, value):
if self.jails.has_key(name):
self.jails[name].setIdle(value)
return True
else:
raise ServerUnknownJail(name)
def getIdleJail(self, name):
if self.jails.has_key(name):
return self.jails[name].getIdle()
else:
raise ServerUnknownJail(name)
# Filter
def setLogPath(self, name, file):
if self.jails.has_key(name):
self.jails[name].getFilter().setLogPath(file)
def getLogPath(self, name):
if self.jails.has_key(name):
return self.jails[name].getFilter().getLogPath()
else:
raise ServerUnknownJail(name)
def setTimeRegex(self, name, value):
if self.jails.has_key(name):
self.jails[name].getFilter().setTimeRegex(value)
else:
raise ServerUnknownJail(name)
def getTimeRegex(self, name):
if self.jails.has_key(name):
return self.jails[name].getFilter().getTimeRegex()
else:
raise ServerUnknownJail(name)
def setTimePattern(self, name, value):
if self.jails.has_key(name):
self.jails[name].getFilter().setTimePattern(value)
else:
raise ServerUnknownJail(name)
def getTimePattern(self, name):
if self.jails.has_key(name):
return self.jails[name].getFilter().getTimePattern()
else:
raise ServerUnknownJail(name)
def setFailRegex(self, name, value):
if self.jails.has_key(name):
self.jails[name].getFilter().setFailRegex(value)
else:
raise ServerUnknownJail(name)
def getFailRegex(self, name):
if self.jails.has_key(name):
return self.jails[name].getFilter().getFailRegex()
else:
raise ServerUnknownJail(name)
def setMaxRetry(self, name, value):
if self.jails.has_key(name):
self.jails[name].getFilter().setMaxRetry(value)
else:
raise ServerUnknownJail(name)
def getMaxRetry(self, name):
if self.jails.has_key(name):
return self.jails[name].getFilter().getMaxRetry()
else:
raise ServerUnknownJail(name)
def setMaxTime(self, name, value):
if self.jails.has_key(name):
self.jails[name].getFilter().setMaxTime(value)
else:
raise ServerUnknownJail(name)
def getMaxTime(self, name):
if self.jails.has_key(name):
return self.jails[name].getFilter().getMaxTime()
else:
raise ServerUnknownJail(name)
# Action
def addAction(self, name, value):
if self.jails.has_key(name):
self.jails[name].getAction().addAction(value)
else:
raise ServerUnknownJail(name)
def getLastAction(self, name):
if self.jails.has_key(name):
return self.jails[name].getAction().getLastAction()
else:
raise ServerUnknownJail(name)
def delAction(self, name, value):
if self.jails.has_key(name):
self.jails[name].getAction().delAction(value)
else:
raise ServerUnknownJail(name)
def setCInfo(self, name, action, key, value):
if self.jails.has_key(name):
self.jails[name].getAction().getAction(action).setCInfo(key, value)
else:
raise ServerUnknownJail(name)
def getCInfo(self, name, action, key):
if self.jails.has_key(name):
return self.jails[name].getAction().getAction(action).getCInfo(key)
else:
raise ServerUnknownJail(name)
def delCInfo(self, name, action, key):
if self.jails.has_key(name):
self.jails[name].getAction().getAction(action).delCInfo(key)
else:
raise ServerUnknownJail(name)
def setBanTime(self, name, value):
if self.jails.has_key(name):
self.jails[name].getAction().setBanTime(value)
else:
raise ServerUnknownJail(name)
def getBanTime(self, name):
if self.jails.has_key(name):
return self.jails[name].getAction().getBanTime()
else:
raise ServerUnknownJail(name)
def setActionStart(self, name, action, value):
if self.jails.has_key(name):
self.jails[name].getAction().getAction(action).setActionStart(value)
else:
raise ServerUnknownJail(name)
def getActionStart(self, name, action):
if self.jails.has_key(name):
return self.jails[name].getAction().getAction(action).getActionStart()
else:
raise ServerUnknownJail(name)
def setActionStop(self, name, action, value):
if self.jails.has_key(name):
self.jails[name].getAction().getAction(action).setActionStop(value)
else:
raise ServerUnknownJail(name)
def getActionStop(self, name, action):
if self.jails.has_key(name):
return self.jails[name].getAction().getAction(action).getActionStop()
else:
raise ServerUnknownJail(name)
def setActionCheck(self, name, action, value):
if self.jails.has_key(name):
self.jails[name].getAction().getAction(action).setActionCheck(value)
else:
raise ServerUnknownJail(name)
def getActionCheck(self, name, action):
if self.jails.has_key(name):
return self.jails[name].getAction().getAction(action).getActionCheck()
else:
raise ServerUnknownJail(name)
def setActionBan(self, name, action, value):
if self.jails.has_key(name):
self.jails[name].getAction().getAction(action).setActionBan(value)
else:
raise ServerUnknownJail(name)
def getActionBan(self, name, action):
if self.jails.has_key(name):
return self.jails[name].getAction().getAction(action).getActionBan()
else:
raise ServerUnknownJail(name)
def setActionUnban(self, name, action, value):
if self.jails.has_key(name):
self.jails[name].getAction().getAction(action).setActionUnban(value)
else:
raise ServerUnknownJail(name)
def getActionUnban(self, name, action):
if self.jails.has_key(name):
return self.jails[name].getAction().getAction(action).getActionUnban()
else:
raise ServerUnknownJail(name)
# Status
def status(self):
jailList = ''
for jail in self.jails:
jailList += jail + ', '
length = len(jailList)
if not length == 0:
jailList = jailList[:length-2]
ret = [("Number of jail", len(self.jails)),
("Jail list", jailList)]
return ret
def statusJail(self, name):
if self.jails.has_key(name):
return self.jails[name].getStatus()
raise ServerUnknownJail(name)
# Logging
##
# Set the logging level.
#
# Incrementing the value gives more messages.
# 0 = FATAL
# 1 = ERROR
# 2 = WARNING
# 3 = INFO
# 4 = DEBUG
# @param value the level
def setLogLevel(self, value):
self.logLevel = value
logLevel = logging.DEBUG
if value == 0:
logLevel = logging.FATAL
elif value == 1:
logLevel = logging.ERROR
elif value == 2:
logLevel = logging.WARNING
elif value == 3:
logLevel = logging.INFO
logging.getLogger("fail2ban").setLevel(logLevel)
##
# Get the logging level.
#
# @see setLogLevel
# @return the log level
def getLogLevel(self):
return self.logLevel
def setLogTarget(self, target):
# Remove previous handler
logging.getLogger("fail2ban").handlers = []
self.logTarget = target
if target == "SYSLOG":
logSys.error("Not yet implemented")
return False
elif target == "STDERR":
hdlr = logging.StreamHandler(sys.stderr)
else:
# Target should be a file
try:
open(target, "a")
hdlr = logging.FileHandler(target)
except IOError:
logSys.error("Unable to log to " + target)
return False
# set a format which is simpler for console use
formatter = logging.Formatter('%(name)-16s: %(levelname)-6s %(message)s')
# tell the handler to use this format
hdlr.setFormatter(formatter)
logging.getLogger("fail2ban").addHandler(hdlr)
return True
def getLogTarget(self):
return self.logTarget
class ServerUnknownJail(Exception):
pass
-112
View File
@@ -1,112 +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"
from threading import Thread
import socket, time, logging, pickle, os, os.path
# Gets the instance of the logger.
logSys = logging.getLogger("fail2ban.comm")
class SSocket(Thread):
def __init__(self, transmitter):
Thread.__init__(self)
self.socketFile = "/tmp/fail2ban.sock"
self.transmit = transmitter
self.isRunning = False
logSys.debug("Created SSocket")
def initialize(self, force = False):
# Remove socket
if os.path.exists(self.socketFile):
logSys.error("Fail2ban seems to be already running")
if force:
logSys.warn("Forcing execution of the server")
os.remove(self.socketFile)
else:
raise SSocketErrorException("Server already running")
# Create an INET, STREAMing socket
#self.ssock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.ssock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
#self.ssock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
self.ssock.setblocking(False)
# Bind the socket to a public host and a well-known port
#self.ssock.bind(("localhost", 2222))
self.ssock.bind(self.socketFile)
# Become a server socket
self.ssock.listen(1)
def run(self):
self.isRunning = True
stime = 1.0
while self.isRunning:
try:
# Accept connections from outside
(csock, address) = self.ssock.accept()
stime /= 10
logSys.debug("Connection accepted")
msg = self.receive(csock)
msg = self.transmit.proceed(msg)
self.send(csock, msg)
csock.close()
except Exception:
time.sleep(stime)
stime += 0.05
if stime > 1.0:
stime = 1.0
self.ssock.close()
# Remove socket
if os.path.exists(self.socketFile):
logSys.debug("Removed socket file " + self.socketFile)
os.remove(self.socketFile)
logSys.debug("Socket shutdown")
return True
##
# Stop the thread.
#
# Set the isRunning flag to False.
# @bug It seems to be some concurrency problem with this flag
def stop(self):
self.isRunning = False
def send(self, socket, msg):
obj = pickle.dumps(msg)
socket.send(obj + "<F2B_END_COMMAND>")
def receive(self, socket):
msg = ''
while msg.rfind("<F2B_END_COMMAND>") == -1:
chunk = socket.recv(6)
if chunk == '':
raise RuntimeError, "socket connection broken"
msg = msg + chunk
return pickle.loads(msg)
class SSocketErrorException(Exception):
pass
-56
View File
@@ -1,56 +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, logging
# Gets the instance of the logger.
logSys = logging.getLogger("fail2ban")
class Ticket:
def __init__(self, ip, time):
self.ip = ip
self.time = time
self.attempt = 0
def setIP(self, value):
self.ip = value
def getIP(self):
return self.ip
def setTime(self, value):
self.time = value
def getTime(self):
return self.time
def setAttempt(self, value):
self.attempt = value
def getAttempt(self):
return self.attempt
-217
View File
@@ -1,217 +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"
from ssocket import SSocket
from ssocket import SSocketErrorException
import re, pickle, logging
# Gets the instance of the logger.
logSys = logging.getLogger("fail2ban.comm")
class Transmitter:
def __init__(self, server):
self.server = server
self.socket = SSocket(self)
def start(self, force):
try:
self.socket.initialize(force)
self.socket.start()
except SSocketErrorException:
logSys.error("Could not start server")
##
# Stop the transmitter.
#
# @bug Fix the issue with join(). When using servertestcase.py, errors
# happen which disappear when using join() in this function.
def stop(self):
self.socket.stop()
#self.socket.join()
def proceed(self, action):
# Deserialize object
logSys.debug("Action: " + `action`)
try:
ret = self.actionHandler(action)
ack = 0, ret
except Exception, e:
logSys.warn("Invalid command")
ack = 1, e
return ack
##
# Handle an action.
#
#
def actionHandler(self, action):
if action[0] == "ping":
return "pong"
elif action[0] == "add":
name = action[1]
if name == "all":
raise Exception("Reserved name")
self.server.addJail(name)
return name
elif action[0] == "start":
name = action[1]
self.server.startJail(name)
return None
elif action[0] == "stop":
if len(action) == 1:
self.server.quit()
elif action[1] == "all":
self.server.stopAllJail()
else:
name = action[1]
self.server.stopJail(name)
return None
elif action[0] == "sleep":
value = action[1]
time.sleep(int(value))
return None
elif action[0] == "set":
return self.actionSet(action[1:])
elif action[0] == "get":
return self.actionGet(action[1:])
elif action[0] == "status":
return self.status(action[1:])
raise Exception("Invalid command")
def actionSet(self, action):
name = action[0]
# Logging
if name == "loglevel":
value = int(action[1])
self.server.setLogLevel(value)
return self.server.getLogLevel()
elif name == "logtarget":
value = action[1]
self.server.setLogTarget(value)
return self.server.getLogTarget()
# Jail
elif action[1] == "idle":
if action[2] == "on":
self.server.setIdleJail(name, True)
elif action[2] == "off":
self.server.setIdleJail(name, False)
return self.server.getIdleJail(name)
# Filter
elif action[1] == "logpath":
value = action[2]
self.server.setLogPath(name, value)
return self.server.getLogPath(name)
elif action[1] == "timeregex":
value = action[2]
self.server.setTimeRegex(name, value)
return self.server.getTimeRegex(name)
elif action[1] == "timepattern":
value = action[2]
self.server.setTimePattern(name, value)
return self.server.getTimePattern(name)
elif action[1] == "failregex":
value = action[2]
self.server.setFailRegex(name, value)
return self.server.getFailRegex(name)
elif action[1] == "maxtime":
value = action[2]
self.server.setMaxTime(name, int(value))
return self.server.getMaxTime(name)
elif action[1] == "maxretry":
value = action[2]
self.server.setMaxRetry(name, int(value))
return self.server.getMaxRetry(name)
# Action
elif action[1] == "bantime":
value = action[2]
self.server.setBanTime(name, int(value))
return self.server.getBanTime(name)
elif action[1] == "addaction":
value = action[2]
self.server.addAction(name, value)
return self.server.getLastAction(name).getName()
elif action[1] == "delaction":
self.server.delAction(name, value)
return None
elif action[1] == "setcinfo":
act = action[2]
key = action[3]
value = action[4]
self.server.setCInfo(name, act, key, value)
return self.server.getCInfo(name, act, key)
elif action[1] == "delcinfo":
act = action[2]
key = action[3]
self.server.delCInfo(name, act, key)
return None
elif action[1] == "actionstart":
act = action[2]
value = action[3]
self.server.setActionStart(name, act, value)
return self.server.getActionStart(name, act)
elif action[1] == "actionstop":
act = action[2]
value = action[3]
self.server.setActionStop(name, act, value)
return self.server.getActionStop(name, act)
elif action[1] == "actioncheck":
act = action[2]
value = action[3]
self.server.setActionCheck(name, act, value)
return self.server.getActionCheck(name, act)
elif action[1] == "actionban":
act = action[2]
value = action[3]
self.server.setActionBan(name, act, value)
return self.server.getActionBan(name, act)
elif action[1] == "actionunban":
act = action[2]
value = action[3]
self.server.setActionUnban(name, act, value)
return self.server.getActionUnban(name, act)
raise Exception("Invalid command (no set action)")
def actionGet(self, action):
name = action[0]
# Logging
if name == "loglevel":
return self.server.getLogLevel()
# Filter
if action[1] == "logpath":
return self.server.getLogPath(name)
raise Exception("Invalid command (no get action)")
def status(self, action):
if len(action) == 0:
return self.server.status()
else:
name = action[0]
return self.server.statusJail(name)
raise Exception("Invalid command (no status)")
-5
View File
@@ -1,5 +0,0 @@
[install]
install-purelib=/usr/lib/fail2ban
[sdist]
formats=bztar
-126
View File
@@ -1,126 +0,0 @@
#!/usr/bin/env python
# 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 distutils.core import setup
from version import version
from os.path import isfile, join
from sys import exit, argv
longdesc = '''
Fail2Ban scans log files like /var/log/pwdfail or
/var/log/apache/error_log and bans IP that makes
too many password failures. It updates firewall rules
to reject the IP address or executes user defined
commands.'''
setup(
name = "fail2ban",
version = version,
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",
license = "GPL",
platforms = "Posix",
scripts = [
'fail2ban-client',
'fail2ban-server'
],
py_modules = ['version'],
packages = [
'client',
'server'
],
data_files = [
('/etc/fail2ban',
[
'config/fail2ban.conf',
'config/jail.conf'
]
),
('/etc/fail2ban/filter.d',
[
'config/filter.d/vsftpd.conf',
'config/filter.d/apache-auth.conf',
'config/filter.d/sshd.conf'
]
),
('/etc/fail2ban/action.d',
[
'config/action.d/iptables.conf',
'config/action.d/mail-whois.conf',
'config/action.d/dummy.conf',
'config/action.d/mail.conf',
'config/action.d/hostsdeny.conf'
]
)
]
)
# Do some checks after installation
# Search for obsolete files.
obsoleteFiles = []
elements = {
"/etc/":
[
"fail2ban.conf"
],
"/usr/bin/":
[
"fail2ban.py"
],
"/usr/lib/fail2ban/firewall/":
[
"iptables.py",
"ipfwadm.py",
"ipfw.py"
]
}
for dir in elements:
for f in elements[dir]:
path = join(dir, f)
if isfile(path):
obsoleteFiles.append(path)
if obsoleteFiles:
print
print "Obsolete files from previous Fail2Ban versions were found on " \
"your system."
print "Please delete them:"
print
for f in obsoleteFiles:
print "\t" + f
print
# Update config file
if argv[1] == "install":
print
print "Please do not forget to update your configuration files."
print "They are in /etc/fail2ban/."
print
-25
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$
__author__ = "Cyril Jaquier"
__version__ = "$Revision$"
__date__ = "$Date$"
__copyright__ = "Copyright (c) 2004 Cyril Jaquier"
__license__ = "GPL"
-56
View File
@@ -1,56 +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 unittest, socket, time, pickle
from server.banmanager import BanManager
from server.banticket import BanTicket
class AddFailure(unittest.TestCase):
def setUp(self):
"""Call before every test case."""
self.ticket = BanTicket('193.168.0.128', 1167605999.0)
self.banManager = BanManager()
self.assertTrue(self.banManager.addBanTicket(self.ticket))
def tearDown(self):
"""Call after every test case."""
def testAdd(self):
self.assertEqual(self.banManager.size(), 1)
def testAddDuplicate(self):
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.assertTrue(self.banManager.inBanList(ticket))
def testInListNOK(self):
ticket = BanTicket('111.111.1.111', 1167605999.0)
self.assertFalse(self.banManager.inBanList(ticket))
-43
View File
@@ -1,43 +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: 253 $
__author__ = "Cyril Jaquier"
__version__ = "$Revision: 253 $"
__date__ = "$Date: 2006-07-17 00:21:58 +0200 (Mon, 17 Jul 2006) $"
__copyright__ = "Copyright (c) 2004 Cyril Jaquier"
__license__ = "GPL"
import unittest
from client.jailreader import JailReader
class JailReaderTest(unittest.TestCase):
def setUp(self):
"""Call before every test case."""
def tearDown(self):
"""Call after every test case."""
def testSplitAction(self):
action = "mail-whois[name=SSH]"
expected = ['mail-whois', {'name': 'SSH'}]
result = JailReader.splitAction(action)
self.assertEquals(expected, result)
-79
View File
@@ -1,79 +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 unittest, socket, time, pickle
from server.failmanager import FailManager
from server.failmanager import FailManagerEmpty
from server.failticket import FailTicket
class AddFailure(unittest.TestCase):
def setUp(self):
"""Call before every test case."""
self.items = [['193.168.0.128', 1167605999.0],
['193.168.0.128', 1167605999.0],
['193.168.0.128', 1167605999.0],
['193.168.0.128', 1167605999.0],
['193.168.0.128', 1167605999.0],
['87.142.124.10', 1167605999.0],
['87.142.124.10', 1167605999.0],
['87.142.124.10', 1167605999.0]]
self.failManager = FailManager()
for i in self.items:
self.failManager.addFailure(FailTicket(i[0], i[1]))
def tearDown(self):
"""Call after every test case."""
def testAdd(self):
self.assertEqual(self.failManager.size(), 2)
def testDel(self):
self.failManager.delFailure('193.168.0.128')
self.failManager.delFailure('111.111.1.111')
self.assertEqual(self.failManager.size(), 1)
def testCleanupOK(self):
timestamp = 1167606999.0
self.failManager.cleanup(timestamp)
self.assertEqual(self.failManager.size(), 0)
def testCleanupNOK(self):
timestamp = 1167605990.0
self.failManager.cleanup(timestamp)
self.assertEqual(self.failManager.size(), 2)
def testbanOK(self):
self.failManager.setMaxRetry(5)
#ticket = FailTicket('193.168.0.128', None)
ticket = self.failManager.toBan()
self.assertEqual(ticket.getIP(), "193.168.0.128")
def testbanNOK(self):
self.failManager.setMaxRetry(10)
self.assertRaises(FailManagerEmpty, self.failManager.toBan)
-18
View File
@@ -1,18 +0,0 @@
Déc 31 23:59:59 [sshd] error: PAM: Authentication failure for kevin from 193.168.0.128
Déc 31 23:59:59 [sshd] error: PAM: Authentication failure for kevin from 193.168.0.128
Déc 31 23:59:59 [sshd] error: PAM: Authentication failure for kevin from 193.168.0.128
Dec 31 23:59:59 [sshd] error: PAM: Authentication failure for kevin from failed.dns.ch
Dec 31 23:59:59 [sshd] error: PAM: Authentication failure for kevin from failed.dns.ch
Dec 31 23:59:59 [sshd] error: PAM: Authentication failure for kevin from failed.dns.ch
Dez 31 23:59:59 [sshd] error: PAM: Authentication failure for kevin from 193.168.0.128
Dez 31 23:59:59 [sshd] error: PAM: Authentication failure for kevin from 193.168.0.128
Dez 31 23:59:59 [sshd] error: PAM: Authentication failure for kevin from 193.168.0.128
De 31 23:59:59 [sshd] error: PAM: Authentication failure for kevin from 193.168.0.128
De 31 23:59:59 [sshd] error: PAM: Authentication failure for kevin from 193.168.0.128
De 31 23:59:59 [sshd] error: PAM: Authentication failure for kevin from 193.168.0.128
Dec 31 23:59:59 [sshd] error: PAM: Authentication failure for kevin from 193.168.0.128
Dec 31 23:59:59 [sshd] error: PAM: Authentication failure for kevin from 193.168.0.128
Dec 31 23:59:59 [sshd] error: PAM: Authentication failure for kevin from 193.168.0.128
Dec 31 23:59:59 [sshd] error: PAM: Authentication failure for kevin from 87.142.124.10
Dec 31 23:59:59 [sshd] error: PAM: Authentication failure for kevin from 87.142.124.10
Dec 31 23:59:59 [sshd] error: PAM: Authentication failure for kevin from 87.142.124.10
-10
View File
@@ -1,10 +0,0 @@
Mar 16 04:57:00 i60p295 sshd[11437]: input_userauth_request: illegal user test123
Mar 16 04:57:00 i60p295 sshd[11437]: Failed password for illegal user test123 from ::ffff:66.38.192.238 port 51381 ssh2
Mar 16 04:57:00 i60p295 sshd[11437]: Connection closed by ::ffff:66.38.192.238
Mar 16 10:33:59 i60p295 sshd[12365]: Failed publickey for roehl from ::ffff:141.3.81.106 port 51332 ssh2
Mar 16 10:33:59 i60p295 sshd[12365]: Failed publickey for roehl from ::ffff:141.3.81.106 port 51332 ssh2
Mar 16 10:33:59 i60p295 sshd[12365]: Postponed keyboard-interactive for roehl from ::ffff:141.3.81.106 port 51332 ssh2
Mar 16 10:34:01 i60p295 sshd[12365]: Postponed keyboard-interactive/pam for roehl from ::ffff:141.3.81.106 port 51332 ssh2
Mar 16 10:34:01 i60p295 sshd[12365]: Accepted keyboard-interactive/pam for roehl from ::ffff:141.3.81.106 port 51332 ssh2
Mär 16 10:33:59 i60p295 sshd[12365]: Failed publickey for roehl from ::ffff:141.3.81.106 port 51332 ssh2
Mär 16 10:33:59 i60p295 sshd[12365]: Failed publickey for roehl from ::ffff:141.3.81.106 port 51332 ssh2
-98
View File
@@ -1,98 +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 unittest, socket
from server.filter import Filter
from server.failmanager import FailManager
class IgnoreIP(unittest.TestCase):
def setUp(self):
"""Call before every test case."""
self.filter = Filter(None)
def tearDown(self):
"""Call after every test case."""
def testIgnoreIPOK(self):
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.assertTrue(self.filter.inIgnoreIPList(ip))
def testIgnoreIPNOK(self):
ipList = "", "999.999.999.999", "abcdef", "192.168.0"
for ip in ipList:
self.filter.addIgnoreIP(ip)
self.assertFalse(self.filter.inIgnoreIPList(ip))
class LogFile(unittest.TestCase):
def setUp(self):
"""Call before every test case."""
self.filter = Filter(None)
self.filter.setLogPath("testcases/files/testcase01.log")
def tearDown(self):
"""Call after every test case."""
def testOpen(self):
self.filter.openLogFile()
def testIsModified(self):
self.filter.openLogFile()
self.assertTrue(self.filter.isModified())
class GetFailures(unittest.TestCase):
def setUp(self):
"""Call before every test case."""
self.filter = Filter(None)
self.filter.setLogPath("testcases/files/testcase01.log")
self.filter.setTimeRegex("\S{3}\s{1,2}\d{1,2} \d{2}:\d{2}:\d{2}")
self.filter.setTimePattern("%b %d %H:%M:%S")
self.filter.setFailRegex("(?:(?:Authentication failure|Failed [-/\w+]+) for(?: [iI](?:llegal|nvalid) user)?|[Ii](?:llegal|nvalid) user|ROOT LOGIN REFUSED) .*(?: from|FROM) (?:::f{4,6}:)?(?P<host>\S*)")
def tearDown(self):
"""Call after every test case."""
def testGetFailures(self):
output = [('87.142.124.10', 3, 1167605999.0),
('193.168.0.128', 3, 1167605999.0)]
self.filter.openLogFile()
self.filter.getFailures()
found = []
for ip in self.filter.failManager.failList:
fData = self.filter.failManager.failList[ip]
retry = fData.getRetry()
lTime = fData.getLastTime()
found.append((ip, retry, lTime))
self.assertEqual(found, output)
-127
View File
@@ -1,127 +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 unittest, socket, time
from server.server import Server
class StartStop(unittest.TestCase):
def setUp(self):
"""Call before every test case."""
self.server = Server()
self.server.setLogLevel(0)
self.server.start(False)
def tearDown(self):
"""Call after every test case."""
self.server.quit()
def testStartStopJail(self):
name = "TestCase"
self.server.addJail(name)
self.server.startJail(name)
time.sleep(1)
self.server.stopJail(name)
class Transmitter(unittest.TestCase):
def setUp(self):
"""Call before every test case."""
self.server = Server()
self.server.setLogLevel(0)
self.server.start(False)
def tearDown(self):
"""Call after every test case."""
self.server.quit()
def testSetActionOK(self):
name = "TestCase"
cmdList = [["add", name],
["set", name, "actionstart", "Action Start"],
["set", name, "actionstop", "Action Stop"],
["set", name, "actioncheck", "Action Check"],
["set", name, "actionban", "Action Ban"],
["set", name, "actionunban", "Action Unban"],
["quit"]]
outList = [(0, name),
(0, 'Action Start'),
(0, 'Action Stop'),
(0, 'Action Check'),
(0, 'Action Ban'),
(0, 'Action Unban'),
(0, None)]
cnt = 0
for cmd in cmdList:
self.assertEqual(self.server.transm.proceed(cmd), outList[cnt])
cnt += 1
def testSetActionNOK(self):
name = "TestCase"
cmdList = [["addd", name],
["set", name, "test"],
["prout prout", "Stop"],
["fail2ban", "sucks"],
["set"],
["_/&%", "@*+%&"],
[" quit"]]
outList = [1,
1,
1,
1,
1,
1,
1]
cnt = 0
for cmd in cmdList:
msg = self.server.transm.proceed(cmd)
self.assertEqual(msg[0], outList[cnt])
cnt += 1
def testJail(self):
name = "TestCase"
cmdList = [["add", name],
["set", name, "logpath", "testcases/files/testcase01.log"],
["set", name, "timeregex", "\S{3}\s{1,2}\d{1,2} \d{2}:\d{2}:\d{2}"],
["set", name, "timepattern", "%b %d %H:%M:%S"],
["set", name, "failregex", "Authentication failure"],
["start", name],
["stop", name],
["quit"]]
for cmd in cmdList:
self.server.transm.proceed(cmd)
if cmd == ["start", name]:
time.sleep(2)
jail = self.server.jails[name]
self.assertEqual(jail.getFilter().failManager.size(), 0)
self.assertEqual(jail.getAction().banManager.size(), 2)
-205
View File
@@ -1,205 +0,0 @@
__ _ _ ___ _
/ _|__ _(_) |_ ) |__ __ _ _ _
| _/ _` | | |/ /| '_ \/ _` | ' \
|_| \__,_|_|_/___|_.__/\__,_|_||_|
=============================================================
Fail2Ban (version 0.7.0) 2006/08/23
=============================================================
ver. 0.7.0 (2006/08/23) - alpha
----------
- Almost a complete rewrite :) Fail2ban design is really
better (IMHO). There is a lot of new features
- Client/Server architecture
- Multithreading. Each jail has its own threads: one for the
log reading and another for the actions
- Execute several actions
- Split configuration files. They are more readable and easy
to use
- failregex uses group (<host>) now. This feature was already
present in the Debian package
- lots of things...
ver. 0.6.1 (2006/03/16) - stable
----------
- Added permanent banning. Set banTime to a negative value to
enable this feature (-1 is perfect). Thanks to Mannone
- Fixed locale bug. Thanks to Fernando José
- Fixed crash when time format does not match data
- Propagated patch from Debian to fix fail2ban search path
addition to the path search list: now it is added first.
Thanks to Nick Craig-Wood
- Added SMTP authentification for mail notification. Thanks
to Markus Hoffmann
- Removed debug mode as it is confusing for people
- Added parsing of timestamp in TAI64N format (#1275325).
Thanks to Mark Edgington
- Added patch #1382936 (Default formatted syslog logging).
Thanks to Patrick Börjesson
- Removed 192.168.0.0/16 from ignoreip. Attacks could also
come from the local network.
- Robust startup: if iptables module does not get fully
initialized after startup of fail2ban, fail2ban will do
"maxreinit" attempts to initialize its own firewall. It
will sleep between attempts for "polltime" number of
seconds (closes Debian: #334272). Thanks to Yaroslav
Halchenko
- Added "interpolations" in fail2ban.conf. This is provided
by the ConfigParser module. Old configuration files still
work. Thanks to Yaroslav Halchenko
- Added initial support for hosts.deny and shorewall. Need
more testing. Please test. Thanks to kojiro from Gentoo
forum for hosts.deny support
- Added support for vsftpd. Thanks to zugeschmiert
ver. 0.6.0 (2005/11/20) - stable
----------
- Propagated patches introduced by Debian maintainer
(Yaroslav Halchenko):
* Added an option to report local time (including timezone)
or GMT in mail notification.
ver. 0.5.5 (2005/10/26) - beta
----------
- Propagated patches introduced by Debian maintainer
(Yaroslav Halchenko):
* Introduced fwcheck option to verify consistency of the
chains. Implemented automatic restart of fail2ban main
function in case check of fwban or fwunban command failed
(closes: #329163, #331695). (Introduced patch was further
adjusted by upstream author).
* Added -f command line parameter for [findtime].
* Added a cleanup of firewall rules on emergency shutdown
when unknown exception is catched.
* Fail2ban should not crash now if a wrong file name is
specified in config.
* reordered code a bit so that log targets are setup right
after background and then only loglevel (verbose, debug)
is processed, so the warning could be seen in the logs
* Added a keyword <section> in parsing of the subject and
the body of an email sent out by fail2ban (closes:
#330311)
ver. 0.5.4 (2005/09/13) - beta
----------
- Fixed bug #1286222.
- Propagated patches introduced by Debian maintainer
(Yaroslav Halchenko):
* Fixed handling of SYSLOG logging target. Now it can log
to any SYSLOG target and facility as directed by the
config
* Format of SYSLOG entries fixed to look closer to standard
* Fixed errata in config/gentoo-confd
* Introduced findtime configuration variable to control the
lifetime of caught "failed" log entries
ver. 0.5.3 (2005/09/08) - beta
----------
- Fixed a bug when overriding "maxfailures" or "bantime".
Thanks to Yaroslav Halchenko
- Added more debug output if an error occurs when sending
mail. Thanks to Stephen Gildea
- Renamed "maxretry" to "maxfailures" and changed default
value to 5. Thanks to Stephen Gildea
- Hopefully fixed bug #1256075
- Fixed bug #1262345
- Fixed exception handling in PIDLock
- Removed warning when using "-V" or "-h" with no config
file. Thanks to Yaroslav Halchenko
- Removed "-i eth0" from config file. Thanks to Yaroslav
Halchenko
ver. 0.5.2 (2005/08/06) - beta
----------
- Better PID lock file handling. Should close #1239562
- Added man pages
- Removed log4py dependency. Use logging module instead
- "maxretry" and "bantime" can be overridden in each section
- Fixed bug #1246278 (excessive memory usage)
- Fixed crash on wrong option value in configuration file
- Changed custom chains to lowercase
ver. 0.5.1 (2005/07/23) - beta
----------
- Fixed bugs #1241756, #1239557
- Added log targets in configuration file. Removed -l option
- Changed iptables rules in order to create a separated chain
for each section
- Fixed static banList in firewall.py
- Added an initd script for Debian. Thanks to Yaroslav
Halchenko
- Check for obsolete files after install
ver. 0.5.0 (2005/07/12) - beta
----------
- Added support for CIDR mask in ignoreip
- Added mail notification support
- Fixed bug #1234699
- Added tags replacement in rules definition. Should allow a
clean solution for Feature Request #1229479
- Removed "interface" and "firewall" options
- Added start and end commands in the configuration file.
Thanks to Yaroslav Halchenko
- Added firewall rules definition in the configuration file
- Cleaned fail2ban.py
- Added an initd script for RedHat/Fedora. Thanks to Andrey
G. Grozin
ver. 0.4.1 (2005/06/30) - stable
----------
- Fixed textToDNS method which generated wrong matches for
"rhost=12-xyz...". Thanks to Tom Pike
- fail2ban.conf modified for readability. Thanks to Iain Lea
- Added an initd script for Gentoo
- Changed default PID lock file location from /tmp to
/var/run
ver. 0.4.0 (2005/04/24) - stable
----------
- Fixed textToDNS which did not recognize strings like
"12-345-67-890.abcd.mnopqr.xyz"
ver. 0.3.1 (2005/03/31) - beta
----------
- Corrected level of messages
- Added DNS lookup support
- Improved parsing speed. Only parse the new log messages
- Added a second verbose level (-vv)
ver. 0.3.0 (2005/02/24) - beta
----------
- Re-writting of parts of the code in order to handle several
log files with different rules
- Removed sshd.py because it is no more needed
- Fixed a bug when exiting with IP in the ban list
- Added PID lock file
- Improved some parts of the code
- Added ipfw-start-rule option (thanks to Robert Edeker)
- Added -k option which kills a currently running Fail2Ban
ver. 0.1.2 (2004/11/21) - beta
----------
- Add ipfw and ipfwadm support. The rules are taken from
BlockIt. Thanks to Robert Edeker
- Add -e option which allows to set the interface. Thanks to
Robert Edeker who reminded me this
- Small code cleaning
ver. 0.1.1 (2004/10/23) - beta
----------
- Add SIGTERM handler in order to exit nicely when in daemon
mode
- Add -r option which allows to set the maximum number of
login failures
- Remove the Metalog class as the log file are not so syslog
daemon specific
- Rewrite log reader to be service centered. Sshd support
added. Match "Failed password" and "Illegal user"
- Add /etc/fail2ban.conf configuration support
- Code documentation
ver. 0.1.0 (2004/10/12) - alpha
----------
- Initial release
-51
View File
@@ -1,51 +0,0 @@
README
CHANGELOG
TODO
fail2ban-client
fail2ban-server
fail2ban-testcases
client/configreader.py
client/jailreader.py
client/fail2banreader.py
client/jailsreader.py
client/filterreader.py
client/actionreader.py
client/__init__.py
client/configurator.py
client/csocket.py
server/ssocket.py
server/banticket.py
server/filter.py
server/server.py
server/failticket.py
server/actions.py
server/faildata.py
server/failmanager.py
server/jailthread.py
server/transmitter.py
server/action.py
server/ticket.py
server/jail.py
server/__init__.py
server/banmanager.py
setup.py
setup.cfg
testcases/banmanagertestcase.py
testcases/failmanagertestcase.py
testcases/clientreadertestcase.py
testcases/filtertestcase.py
testcases/__init__.py
testcases/servertestcase.py
testcases/files/testcase01.log
testcases/files/testcase02.log
version.py
config/jail.conf
config/filter.d/vsftpd.conf
config/filter.d/apache-auth.conf
config/filter.d/sshd.conf
config/action.d/iptables.conf
config/action.d/mail-whois.conf
config/action.d/dummy.conf
config/action.d/mail.conf
config/action.d/hostsdeny.conf
config/fail2ban.conf
-151
View File
@@ -1,151 +0,0 @@
__ _ _ ___ _
/ _|__ _(_) |_ ) |__ __ _ _ _
| _/ _` | | |/ /| '_ \/ _` | ' \
|_| \__,_|_|_/___|_.__/\__,_|_||_|
=============================================================
Fail2Ban (version 0.7.0) 2006/08/23
=============================================================
Fail2Ban scans log files like /var/log/pwdfail and bans IP
that makes too many password failures. It updates firewall
rules to reject the IP address. These rules can be defined by
the user. Fail2Ban can read multiple log files such as sshd
or Apache web server ones.
This is my first Python program. Moreover, English is not my
mother tongue...
More details:
-------------
Fail2Ban is rather simple. I have a home server connected to
the Internet which runs apache, samba, sshd, ... I see in my
logs that people are trying to log into my box using "manual"
brute force or scripts. They try 10, 20 and sometimes more
user/password (without success anyway). In order to
discourage these script kiddies, I wanted that sshd refuse
login from a specific ip after 3 password failures. After
some Google searches, I found that sshd was not able of that.
So I search for a script or program that do it. I found
nothing :-( So I decide to write mine and to learn Python :-)
For each sections defined in the configuration file, Fail2Ban
tries to find lines which match the failregex. Then it
retrieves the message time using timeregex and timepattern.
It finally gets the ip and if it has already done 3 or more
password failures in the last banTime, the ip is banned for
banTime using a firewall rule. This rule is set by the user
in the configuration file. Thus, Fail2Ban can be adapted for
lots of firewall. After banTime, the rule is deleted. Notice
that if no "plain" ip is available, Fail2Ban try to do DNS
lookup in order to found one or several ip's to ban.
Sections can be freely added so it is possible to monitor
several daemons at the same time.
Runs on my server and does its job rather well :-) The idea
is to make fail2ban usable with daemons and services that
require a login (sshd, telnetd, ...) and with different
firewalls.
Installation:
-------------
Require: python-2.4 (http://www.python.org)
To install, just do:
> tar xvfj fail2ban-0.7.0.tar.bz2
> cd fail2ban-0.7.0
> python setup.py install
This will install Fail2Ban into /usr/lib/fail2ban. The
executable scripts are placed into /usr/bin.
Gentoo: ebuilds are available on the website.
Debian: Fail2Ban is in Debian unstable.
RedHat: packages are available on the website.
Fail2Ban should now be correctly installed. Just type:
> fail2ban-client -h
to see if everything is alright.
Configuration:
--------------
You can configure fail2ban using the files in /etc/fail2ban
or using command line. Here are the available command line
options (not complete yet):
<COMMAND>
start start the server and the jails
reload reload the configuration
stop stop all jails and terminate the
server
status get the current status
set loglevel <LEVEL> set loglevel to <LEVEL>
get loglevel get loglevel
set logtarget <TARGET> set log target to <TARGET>
get logtarget get log target
add <JAIL> create <JAIL>
set <JAIL> <CMD> set the <CMD> value for <JAIL>
get <JAIL> <CMD> get the <CMD> value for <JAIL>
start <JAIL> start <JAIL>
stop <JAIL> stop <JAIL>. The jail is removed
status <JAIL> get the current status of <JAIL>
[OPTIONS]
-c <DIR> configuration directory
-d dump configuration. For debugging
-v increase verbosity
-q decrease verbosity
-x force execution of the server
-h display this help message
Contact:
--------
You need some new features, you found bugs or you just
appreciate this program, you can contact me at :
Website: http://fail2ban.sourceforge.net
Cyril Jaquier: <lostcontrol@users.sourceforge.net>
Thanks:
-------
Kévin Drapel, Marvin Rouge, Sireyessire, Robert Edeker,
Tom Pike, Iain Lea, Andrey G. Grozin, Yaroslav Halchenko,
Jonathan Kamens, Stephen Gildea, Markus Hoffmann, Mark
Edgington, Patrick Börjesson, kojiro, zugeschmiert
License:
--------
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
-115
View File
@@ -1,115 +0,0 @@
__ _ _ ___ _
/ _|__ _(_) |_ ) |__ __ _ _ _
| _/ _` | | |/ /| '_ \/ _` | ' \
|_| \__,_|_|_/___|_.__/\__,_|_||_|
=============================================================
ToDo $Revision$
=============================================================
Legend:
- not yet done
? maybe
# partially done
* done
- correct handling of threads (join???)
- signal handling (ctrl-c, etc)
- add a reload option to fail2ban-client
- see Feature Request Tracking System at SourceForge.net
* findall in dns.py should be no more needed
* remove utils/ directory
- improve installation process (better prefix support)
# improve documentation and website for user
* use Doxygen
- use PyLint to check the code
* better configuration files
- add a check to see if the time of the log messages is
correctly detected (valid regexp)
? use Gentoo Portage style for scripts.
- banning engines script in /etc/fail2ban/scripts.d
Example: /etc/fail2ban/scripts.d/iptables
Will be mostly bash scripting which is more "user
friendly".
- split configuration files in /etc/fail2ban/services.d
for log files
Example: /etc/fail2ban/services.d/apache
Mainly regular expressions.
- template for common regex in /etc/fail2ban/templates.d
Example: /etc/fail2ban/templates.d/date
Mainly regular expressions.
* remove debug mode (root check)
# better return values in function
? use more email.Utils in mail.py
? add gettext support. Is this really needed for a server
utility?
* send an email when fail2ban is running
* add multithreading. Python threading is not really
efficient. However, fail2ban could benefit of it. We could
use threads like this:
- one thread which check for host to unban.
- one thread per file to watch. This will allow things like
different polling time for each file.
<srv> is read-only (we only read log files) thus no locks
are required. However, <meth> is read-write and must take
care of concurrency in case of multithreading.
- add FAM/Gamin support. Should be quite efficient with
threading. Take care that handle_one_event() release the
Python lock.
# add a test framework. We could use unittest which is in
Python since 2.1. It should be possible to run all tests
automatically.
* add client/server using socket. Something similar to
gdesklets. DBUS seems to be designed for desktop use.
- fail2ban start -> start the daemon.
- fail2ban stop -> stop the daemon.
- fail2ban add <srv> <meth> -> add <srv> monitoring with
<meth> ban method (iptables, hosts.deny, etc).
- fail2ban del <srv> -> remove <srv> monitoring.
- fail2ban status <srv> -> query current fail2ban status.
Should return infos like a ban counter. Could be graph
with rrdtool.
- fail2ban pause <srv> -> suspend monitoring.
- fail2ban resume <srv> -> resume monitoring.
- fail2ban list -> list available services.
- fail2ban flush <srv> -> flush the <srv> ban list.
* remove PID file.
* remove most of the command lines options if possible.
- add the possibility to specify wildcard in log files.
Example: logfile = /var/log/apache2/access-*.log
Should we start one thread per file or just one thread per
serivce?
- autodetect date format in log file. Match the most popular
format and sort them using the hit ratio. Should avoid
user problem with regex and not have a big impact on perfs.
- restart automatically the daemon if an exception occurs.
- do not close socket after a send
- refactoring in server.py, actions.py, filter.py
-25
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$
__author__ = "Cyril Jaquier"
__version__ = "$Revision$"
__date__ = "$Date$"
__copyright__ = "Copyright (c) 2004 Cyril Jaquier"
__license__ = "GPL"

Some files were not shown because too many files have changed in this diff Show More