merged with upstream. Need to propagate 'Debian' patches into upstream as soon as possible because they lead to conflicts on upgrades

debian-releases/etch
Yaroslav Halchenko 2005-09-09 21:15:41 +00:00
parent e32a92e7c9
commit 66c8660494
14 changed files with 118 additions and 76 deletions

View File

@ -4,9 +4,25 @@
|_| \__,_|_|_/___|_.__/\__,_|_||_| |_| \__,_|_|_/___|_.__/\__,_|_||_|
============================================================= =============================================================
Fail2Ban (version 0.5.2) 2005/08/06 Fail2Ban (version 0.5.3) 2005/09/08
============================================================= =============================================================
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 ver. 0.5.2 (2005/08/06) - beta
---------- ----------
- Better PID lock file handling. Should close #1239562 - Better PID lock file handling. Should close #1239562

View File

@ -1,6 +1,6 @@
Metadata-Version: 1.0 Metadata-Version: 1.0
Name: fail2ban Name: fail2ban
Version: 0.5.2 Version: 0.5.3
Summary: Ban IPs that make too many password failure Summary: Ban IPs that make too many password failure
Home-page: http://fail2ban.sourceforge.net Home-page: http://fail2ban.sourceforge.net
Author: Cyril Jaquier Author: Cyril Jaquier
@ -11,5 +11,5 @@ Description:
/var/log/apache/error_log and bans IP that makes /var/log/apache/error_log and bans IP that makes
too many password failures. It updates firewall rules too many password failures. It updates firewall rules
to reject the IP address or executes user defined to reject the IP address or executes user defined
commands. It needs log4py. commands.
Platform: Posix Platform: Posix

14
README
View File

@ -4,7 +4,7 @@
|_| \__,_|_|_/___|_.__/\__,_|_||_| |_| \__,_|_|_/___|_.__/\__,_|_||_|
============================================================= =============================================================
Fail2Ban (version 0.5.2) 2005/08/06 Fail2Ban (version 0.5.3) 2005/09/08
============================================================= =============================================================
Fail2Ban scans log files like /var/log/pwdfail and bans IP Fail2Ban scans log files like /var/log/pwdfail and bans IP
@ -58,15 +58,16 @@ Require: python-2.3 (http://www.python.org)
To install, just do: To install, just do:
> tar xvfj fail2ban-0.5.2.tar.bz2 > tar xvfj fail2ban-0.5.3.tar.bz2
> cd fail2ban-0.5.2 > cd fail2ban-0.5.3
> python setup.py install > python setup.py install
This will install Fail2Ban into /usr/lib/fail2ban. The fail2ban This will install Fail2Ban into /usr/lib/fail2ban. The fail2ban
executable is placed into /usr/bin. executable is placed into /usr/bin.
Gentoo: an ebuild is available on the website. Gentoo: ebuilds are available on the website.
Debian: a package is 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 should now be correctly installed. Just type:
@ -121,7 +122,8 @@ Thanks:
------- -------
Kévin Drapel, Marvin Rouge, Sireyessire, Robert Edeker, Kévin Drapel, Marvin Rouge, Sireyessire, Robert Edeker,
Tom Pike, Iain Lea, Andrey G. Grozin, Yaroslav Halchenko Tom Pike, Iain Lea, Andrey G. Grozin, Yaroslav Halchenko,
Jonathan Kamens, Stephen Gildea
License: License:
-------- --------

2
TODO
View File

@ -10,3 +10,5 @@ ToDo
See Feature Request Tracking System at SourceForge.net See Feature Request Tracking System at SourceForge.net
- improve installation process (better prefix support) - improve installation process (better prefix support)
- install Fail2ban into /usr/share
- better configuration files

View File

@ -1,6 +1,6 @@
# Fail2Ban configuration file # Fail2Ban configuration file
# #
# $Revision: 1.8.2.9 $ # $Revision: 1.8.2.11 $
# #
# 2005.06.21 modified for readability Iain Lea iain@bricbrac.de # 2005.06.21 modified for readability Iain Lea iain@bricbrac.de
@ -39,11 +39,11 @@ syslog-facility = 1
# #
pidlock = /var/run/fail2ban.pid pidlock = /var/run/fail2ban.pid
# Option: maxretry # Option: maxfailures
# Notes.: number of retrys before IP gets banned. # Notes.: number of failures before IP gets banned.
# Values: NUM Default: 3 # Values: NUM Default: 5
# #
maxretry = 5 maxfailures = 5
# Option: bantime # Option: bantime
# Notes.: number of seconds an IP will be banned. # Notes.: number of seconds an IP will be banned.
@ -61,9 +61,7 @@ findtime = 600
# Notes.: space separated list of IP's to be ignored by fail2ban. # Notes.: space separated list of IP's to be ignored by fail2ban.
# You can use CIDR mask in order to specify a range. # You can use CIDR mask in order to specify a range.
# Example: ignoreip = 192.168.0.1/24 123.45.235.65 # Example: ignoreip = 192.168.0.1/24 123.45.235.65
# Values: IP Default: empty # Values: IP Default: 192.168.0.0/16
# Examples
# ignoreip = 192.168.0.0/24
# #
ignoreip = 192.168.0.0/16 ignoreip = 192.168.0.0/16
@ -133,7 +131,7 @@ subject = [Fail2Ban] Banned <ip>
# <failures> number of failures # <failures> number of failures
# <failtime> unix timestamp of the last failure # <failtime> unix timestamp of the last failure
# <br> new line # <br> new line
# Values: TEXT Default: # Values: TEXT Default:
# #
message = Hi,<br> message = Hi,<br>
The IP <ip> has just been banned by Fail2Ban after The IP <ip> has just been banned by Fail2Ban after
@ -200,7 +198,7 @@ fwunban = iptables -D fail2ban-http -s <ip> -j DROP
# Option: timeregex # Option: timeregex
# Notes.: regex to match timestamp in Apache logfile. # Notes.: regex to match timestamp in Apache logfile.
# Values: [Wed Jan 05 15:08:01 2005] # Values: [Wed Jan 05 15:08:01 2005]
# Default: \S{3} \S{3} \d{2} \d{2}:\d{2}:\d{2} \d{4} # 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} timeregex = \S{3} \S{3} \d{2} \d{2}:\d{2}:\d{2} \d{4}
@ -272,7 +270,7 @@ fwunban = iptables -D fail2ban-ssh -s <ip> -j DROP
# Option: timeregex # Option: timeregex
# Notes.: regex to match timestamp in SSH logfile. # Notes.: regex to match timestamp in SSH logfile.
# Values: [Mar 7 17:53:28] # Values: [Mar 7 17:53:28]
# Default: \S{3}\s{1,2}\d{1,2} \d{2}:\d{2}:\d{2} # 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} timeregex = \S{3}\s{1,2}\d{1,2} \d{2}:\d{2}:\d{2}

6
debian/changelog vendored
View File

@ -1,3 +1,9 @@
fail2ban (0.5.3-1) UNRELEASED; urgency=low
* (NOT RELEASED YET) New upstream release
-- Yaroslav Halchenko <debian@onerussian.com> Fri, 9 Sep 2005 16:55:00 -0400
fail2ban (0.5.2-5) unstable; urgency=low fail2ban (0.5.2-5) unstable; urgency=low
* Included a patch from Stephen Gildea to provide "status" report by * Included a patch from Stephen Gildea to provide "status" report by

3
debian/watch vendored
View File

@ -3,4 +3,5 @@
# Site Directory Pattern Version Script # Site Directory Pattern Version Script
version=3 version=3
http://prdownloads.sf.net/fail2ban/fail2ban-(.*)\.tar\.bz2 debian svn-upgrade http://heanet.dl.sourceforge.net/sourceforge/fail2ban/ \
fail2ban-(.*)\.tar\.bz2 debian svn-upgrade

View File

@ -17,11 +17,11 @@
# Author: Cyril Jaquier # Author: Cyril Jaquier
# Modified by: Yaroslav Halchenko (SYSLOG, findtime) # Modified by: Yaroslav Halchenko (SYSLOG, findtime)
# #
# $Revision: 1.20.2.13 $ # $Revision: 1.20.2.16 $
__author__ = "Cyril Jaquier" __author__ = "Cyril Jaquier"
__version__ = "$Revision: 1.20.2.13 $" __version__ = "$Revision: 1.20.2.16 $"
__date__ = "$Date: 2005/08/06 18:44:06 $" __date__ = "$Date: 2005/09/05 21:12:08 $"
__copyright__ = "Copyright (c) 2004 Cyril Jaquier" __copyright__ = "Copyright (c) 2004 Cyril Jaquier"
__license__ = "GPL" __license__ = "GPL"
@ -130,7 +130,7 @@ def getCmdLineOptions(optList):
if opt[0] == "-i": if opt[0] == "-i":
conf["ignoreip"] = opt[1] conf["ignoreip"] = opt[1]
if opt[0] == "-r": if opt[0] == "-r":
conf["maxretry"] = int(opt[1]) conf["maxfailures"] = int(opt[1])
if opt[0] == "-p": if opt[0] == "-p":
conf["pidlock"] = opt[1] conf["pidlock"] = opt[1]
if opt[0] == "-k": if opt[0] == "-k":
@ -162,12 +162,12 @@ def main():
# Pre-parsing of command line options for the -c option # Pre-parsing of command line options for the -c option
for opt in optList: for opt in optList:
if opt[0] == "-c":
conf["conffile"] = opt[1]
if opt[0] in ["-h", "--help"]: if opt[0] in ["-h", "--help"]:
dispUsage() dispUsage()
if opt[0] in ["-V", "--version"]: if opt[0] in ["-V", "--version"]:
dispVersion() dispVersion()
if opt[0] == "-c":
conf["conffile"] = opt[1]
# Reads the config file and create a LogReader instance for # Reads the config file and create a LogReader instance for
# each log file to check. # each log file to check.
@ -181,7 +181,7 @@ def main():
["int", "syslog-facility", 1], ["int", "syslog-facility", 1],
["bool", "debug", False], ["bool", "debug", False],
["str", "pidlock", "/var/run/fail2ban.pid"], ["str", "pidlock", "/var/run/fail2ban.pid"],
["int", "maxretry", 3], ["int", "maxfailures", 5],
["int", "bantime", 600], ["int", "bantime", 600],
["int", "findtime", 600], ["int", "findtime", 600],
["str", "ignoreip", ""], ["str", "ignoreip", ""],
@ -293,16 +293,7 @@ def main():
# Ignores IP list # Ignores IP list
ignoreIPList = conf["ignoreip"].split(' ') ignoreIPList = conf["ignoreip"].split(' ')
# maxretry option
maxRetry = conf["maxretry"]
# bantime option
banTime = conf["bantime"]
# findtime option
findTime = conf["findtime"]
# Checks for root user. This is necessary because log files # Checks for root user. This is necessary because log files
# are owned by root and firewall needs root access. # are owned by root and firewall needs root access.
if not checkForRoot(): if not checkForRoot():
@ -316,12 +307,15 @@ def main():
logSys.error("Fail2Ban already running with PID "+pid) logSys.error("Fail2Ban already running with PID "+pid)
sys.exit(-1) sys.exit(-1)
else: else:
pidLock.create() ret = pidLock.create()
if not ret:
# Unable to create PID lock. Exit
sys.exit(-1)
logSys.debug("ConfFile is " + conf["conffile"]) logSys.debug("ConfFile is " + conf["conffile"])
logSys.debug("BanTime is " + `conf["bantime"]`) logSys.debug("BanTime is " + `conf["bantime"]`)
logSys.debug("FindTime is " + `conf["findtime"]`) logSys.debug("FindTime is " + `conf["findtime"]`)
logSys.debug("retryAllowed is " + `conf["maxretry"]`) logSys.debug("MaxFailure is " + `conf["maxfailures"]`)
# Options # Options
optionValues = (["bool", "enabled", False], optionValues = (["bool", "enabled", False],
@ -346,9 +340,9 @@ def main():
# Options # Options
optionValues = (["bool", "enabled", False], optionValues = (["bool", "enabled", False],
["str", "logfile", "/dev/null"], ["str", "logfile", "/dev/null"],
["int", "maxretry", maxRetry], ["int", "maxfailures", conf["maxfailures"]],
["int", "bantime", banTime], ["int", "bantime", conf["bantime"]],
["int", "findtime", findTime], ["int", "findtime", conf["findtime"]],
["str", "timeregex", ""], ["str", "timeregex", ""],
["str", "timepattern", ""], ["str", "timepattern", ""],
["str", "failregex", ""], ["str", "failregex", ""],
@ -364,7 +358,7 @@ def main():
# Creates a logreader object # Creates a logreader object
lObj = LogReader(l["logfile"], l["timeregex"], l["timepattern"], lObj = LogReader(l["logfile"], l["timeregex"], l["timepattern"],
l["failregex"], l["maxretry"], l["findtime"]) l["failregex"], l["maxfailures"], l["findtime"])
# Creates a firewall object # Creates a firewall object
fObj = Firewall(l["fwban"], l["fwunban"], l["bantime"]) fObj = Firewall(l["fwban"], l["fwunban"], l["bantime"])
# Links them into a list. I'm not really happy # Links them into a list. I'm not really happy
@ -381,6 +375,8 @@ def main():
if isValidIP(ip): if isValidIP(ip):
for element in logFwList: for element in logFwList:
element[1].addIgnoreIP(ip) element[1].addIgnoreIP(ip)
else:
logSys.warn(ip + " is not a valid IP address")
logSys.info("Fail2Ban v" + version + " is running") logSys.info("Fail2Ban v" + version + " is running")
# Execute global start command # Execute global start command

View File

@ -16,11 +16,11 @@
# Author: Cyril Jaquier # Author: Cyril Jaquier
# #
# $Revision: 1.13.2.7 $ # $Revision: 1.13.2.8 $
__author__ = "Cyril Jaquier" __author__ = "Cyril Jaquier"
__version__ = "$Revision: 1.13.2.7 $" __version__ = "$Revision: 1.13.2.8 $"
__date__ = "$Date: 2005/08/06 18:43:11 $" __date__ = "$Date: 2005/09/05 21:06:15 $"
__copyright__ = "Copyright (c) 2004 Cyril Jaquier" __copyright__ = "Copyright (c) 2004 Cyril Jaquier"
__license__ = "GPL" __license__ = "GPL"
@ -134,11 +134,13 @@ class LogReader:
logSys.debug(self.logPath) logSys.debug(self.logPath)
logFile = self.openLogFile() logFile = self.openLogFile()
self.setFilePos(logFile) self.setFilePos(logFile)
lastLine = '' lastLine = None
for line in logFile: for line in logFile:
if not self.hasTime(line):
# There is no valid time in this line
continue
lastLine = line lastLine = line
failList = self.findFailure(line) for element in self.findFailure(line):
for element in failList:
ip = element[0] ip = element[0]
unixTime = element[1] unixTime = element[1]
if unixTime < time.time()-self.findTime: if unixTime < time.time()-self.findTime:
@ -152,7 +154,8 @@ class LogReader:
else: else:
ipList[ip] = (1, unixTime) ipList[ip] = (1, unixTime)
self.lastPos = logFile.tell() self.lastPos = logFile.tell()
self.lastDate = self.getTime(lastLine) if lastLine:
self.lastDate = self.getTime(lastLine)
logFile.close() logFile.close()
return ipList return ipList
@ -175,6 +178,15 @@ class LogReader:
failList.append([ip, date]) failList.append([ip, date])
return failList return failList
def hasTime(self, line):
""" Return true if the line contains a date
"""
timeMatch = re.search(self.timeregex, line)
if timeMatch:
return True
else:
return False
def getTime(self, line): def getTime(self, line):
""" Gets the time of a log message. """ Gets the time of a log message.
""" """

View File

@ -18,11 +18,11 @@
# Author: Cyril Jaquier # Author: Cyril Jaquier
# #
# $Revision: 1.4.2.3 $ # $Revision: 1.4.2.4 $
__author__ = "Cyril Jaquier" __author__ = "Cyril Jaquier"
__version__ = "$Revision: 1.4.2.3 $" __version__ = "$Revision: 1.4.2.4 $"
__date__ = "$Date: 2005/07/28 20:30:34 $" __date__ = "$Date: 2005/08/07 13:10:39 $"
__copyright__ = "Copyright (c) 2004 Cyril Jaquier" __copyright__ = "Copyright (c) 2004 Cyril Jaquier"
__license__ = "GPL" __license__ = "GPL"

View File

@ -16,11 +16,11 @@
# Author: Cyril Jaquier # Author: Cyril Jaquier
# #
# $Revision: 1.7.2.2 $ # $Revision: 1.7.2.3 $
__author__ = "Cyril Jaquier" __author__ = "Cyril Jaquier"
__version__ = "$Revision: 1.7.2.2 $" __version__ = "$Revision: 1.7.2.3 $"
__date__ = "$Date: 2005/07/22 21:11:42 $" __date__ = "$Date: 2005/08/17 19:26:49 $"
__copyright__ = "Copyright (c) 2004 Cyril Jaquier" __copyright__ = "Copyright (c) 2004 Cyril Jaquier"
__license__ = "GPL" __license__ = "GPL"
@ -58,8 +58,9 @@ def searchIP(text):
def isValidIP(str): def isValidIP(str):
""" Return true if str is a valid IP """ Return true if str is a valid IP
""" """
s = str.split('/', 1)
try: try:
socket.inet_aton(str) socket.inet_aton(s[0])
return True return True
except socket.error: except socket.error:
return False return False

View File

@ -16,11 +16,11 @@
# Author: Cyril Jaquier # Author: Cyril Jaquier
# #
# $Revision: 1.1.2.2 $ # $Revision: 1.1.2.3 $
__author__ = "Cyril Jaquier" __author__ = "Cyril Jaquier"
__version__ = "$Revision: 1.1.2.2 $" __version__ = "$Revision: 1.1.2.3 $"
__date__ = "$Date: 2005/08/01 16:35:18 $" __date__ = "$Date: 2005/09/08 18:05:59 $"
__copyright__ = "Copyright (c) 2004 Cyril Jaquier" __copyright__ = "Copyright (c) 2004 Cyril Jaquier"
__license__ = "GPL" __license__ = "GPL"
@ -64,8 +64,8 @@ class Mail:
server.sendmail(self.fromAddr, self.toAddr, mail) server.sendmail(self.fromAddr, self.toAddr, mail)
logSys.debug("Email sent to " + `self.toAddr`) logSys.debug("Email sent to " + `self.toAddr`)
server.quit() server.quit()
except Exception: except Exception, e:
logSys.error("Unable to send mail to " + self.host + ":" + logSys.error("Unable to send mail to " + self.host + ":" +
`self.port` + " from " + self.fromAddr + " to " + `self.port` + " from " + self.fromAddr + " to " +
`self.toAddr`) `self.toAddr` + ": " + `e` + ": " + `e.args`)

View File

@ -16,11 +16,11 @@
# Author: Cyril Jaquier # Author: Cyril Jaquier
# #
# $Revision: 1.1.2.1 $ # $Revision: 1.1.2.2 $
__author__ = "Cyril Jaquier" __author__ = "Cyril Jaquier"
__version__ = "$Revision: 1.1.2.1 $" __version__ = "$Revision: 1.1.2.2 $"
__date__ = "$Date: 2005/08/04 20:48:30 $" __date__ = "$Date: 2005/08/07 13:08:18 $"
__copyright__ = "Copyright (c) 2004 Cyril Jaquier" __copyright__ = "Copyright (c) 2004 Cyril Jaquier"
__license__ = "GPL" __license__ = "GPL"
@ -51,17 +51,25 @@ class PIDLock:
def create(self): def create(self):
""" Create PID lock. """ Create PID lock.
""" """
fileHandler = open(self.path, mode='w') try:
pid = os.getpid() fileHandler = open(self.path, mode='w')
fileHandler.write(`pid` + '\n') pid = os.getpid()
fileHandler.close() fileHandler.write(`pid` + '\n')
logSys.debug("Created PID lock (" + `pid` + ") in " + self.path) fileHandler.close()
logSys.debug("Created PID lock (" + `pid` + ") in " + self.path)
return True
except:
logSys.error("Unable to create PID lock " + self.path)
return False
def remove(self): def remove(self):
""" Remove PID lock. """ Remove PID lock.
""" """
os.remove(self.path) try:
logSys.debug("Removed PID lock " + self.path) os.remove(self.path)
logSys.debug("Removed PID lock " + self.path)
except OSError:
logSys.error("Unable to remove PID lock " + self.path)
def exists(self): def exists(self):
""" Returns the current PID if Fail2Ban is running or False """ Returns the current PID if Fail2Ban is running or False

View File

@ -16,12 +16,12 @@
# Author: Cyril Jaquier # Author: Cyril Jaquier
# #
# $Revision: 1.12.2.6 $ # $Revision: 1.12.2.8 $
__author__ = "Cyril Jaquier" __author__ = "Cyril Jaquier"
__version__ = "$Revision: 1.12.2.6 $" __version__ = "$Revision: 1.12.2.8 $"
__date__ = "$Date: 2005/08/06 15:07:11 $" __date__ = "$Date: 2005/09/08 18:20:51 $"
__copyright__ = "Copyright (c) 2004 Cyril Jaquier" __copyright__ = "Copyright (c) 2004 Cyril Jaquier"
__license__ = "GPL" __license__ = "GPL"
version = "0.5.2" version = "0.5.3"