diff --git a/CHANGELOG b/CHANGELOG index 7c477030..de0736a0 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -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 ---------- - Better PID lock file handling. Should close #1239562 diff --git a/PKG-INFO b/PKG-INFO index 35bfe63d..d08ff836 100644 --- a/PKG-INFO +++ b/PKG-INFO @@ -1,6 +1,6 @@ Metadata-Version: 1.0 Name: fail2ban -Version: 0.5.2 +Version: 0.5.3 Summary: Ban IPs that make too many password failure Home-page: http://fail2ban.sourceforge.net Author: Cyril Jaquier @@ -11,5 +11,5 @@ Description: /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. It needs log4py. + commands. Platform: Posix diff --git a/README b/README index 4997742a..ba03b945 100644 --- a/README +++ b/README @@ -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 @@ -58,15 +58,16 @@ Require: python-2.3 (http://www.python.org) To install, just do: -> tar xvfj fail2ban-0.5.2.tar.bz2 -> cd fail2ban-0.5.2 +> tar xvfj fail2ban-0.5.3.tar.bz2 +> cd fail2ban-0.5.3 > python setup.py install This will install Fail2Ban into /usr/lib/fail2ban. The fail2ban executable is placed into /usr/bin. -Gentoo: an ebuild is available on the website. -Debian: a package is available on the website. +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: @@ -121,7 +122,8 @@ Thanks: ------- 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: -------- diff --git a/TODO b/TODO index 5b383282..bfdb1a90 100644 --- a/TODO +++ b/TODO @@ -10,3 +10,5 @@ ToDo See Feature Request Tracking System at SourceForge.net - improve installation process (better prefix support) +- install Fail2ban into /usr/share +- better configuration files diff --git a/config/fail2ban.conf.default b/config/fail2ban.conf.default index fa25a57b..29fc7b31 100644 --- a/config/fail2ban.conf.default +++ b/config/fail2ban.conf.default @@ -1,6 +1,6 @@ # Fail2Ban configuration file # -# $Revision: 1.8.2.9 $ +# $Revision: 1.8.2.11 $ # # 2005.06.21 modified for readability Iain Lea iain@bricbrac.de @@ -39,11 +39,11 @@ syslog-facility = 1 # pidlock = /var/run/fail2ban.pid -# Option: maxretry -# Notes.: number of retrys before IP gets banned. -# Values: NUM Default: 3 +# Option: maxfailures +# Notes.: number of failures before IP gets banned. +# Values: NUM Default: 5 # -maxretry = 5 +maxfailures = 5 # Option: bantime # 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. # You can use CIDR mask in order to specify a range. # Example: ignoreip = 192.168.0.1/24 123.45.235.65 -# Values: IP Default: empty -# Examples -# ignoreip = 192.168.0.0/24 +# Values: IP Default: 192.168.0.0/16 # ignoreip = 192.168.0.0/16 @@ -133,7 +131,7 @@ subject = [Fail2Ban] Banned # number of failures # unix timestamp of the last failure #
new line -# Values: TEXT Default: +# Values: TEXT Default: # message = Hi,
The IP has just been banned by Fail2Ban after @@ -200,7 +198,7 @@ fwunban = iptables -D fail2ban-http -s -j DROP # Option: timeregex # 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} # 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 -j DROP # Option: timeregex # 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} # timeregex = \S{3}\s{1,2}\d{1,2} \d{2}:\d{2}:\d{2} diff --git a/debian/changelog b/debian/changelog index f8ce2224..7c261914 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,9 @@ +fail2ban (0.5.3-1) UNRELEASED; urgency=low + + * (NOT RELEASED YET) New upstream release + + -- Yaroslav Halchenko Fri, 9 Sep 2005 16:55:00 -0400 + fail2ban (0.5.2-5) unstable; urgency=low * Included a patch from Stephen Gildea to provide "status" report by diff --git a/debian/watch b/debian/watch index cb006dfe..d079a78e 100644 --- a/debian/watch +++ b/debian/watch @@ -3,4 +3,5 @@ # Site Directory Pattern Version Script 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 diff --git a/fail2ban.py b/fail2ban.py index 19f53029..8d6046ba 100755 --- a/fail2ban.py +++ b/fail2ban.py @@ -17,11 +17,11 @@ # Author: Cyril Jaquier # Modified by: Yaroslav Halchenko (SYSLOG, findtime) # -# $Revision: 1.20.2.13 $ +# $Revision: 1.20.2.16 $ __author__ = "Cyril Jaquier" -__version__ = "$Revision: 1.20.2.13 $" -__date__ = "$Date: 2005/08/06 18:44:06 $" +__version__ = "$Revision: 1.20.2.16 $" +__date__ = "$Date: 2005/09/05 21:12:08 $" __copyright__ = "Copyright (c) 2004 Cyril Jaquier" __license__ = "GPL" @@ -130,7 +130,7 @@ def getCmdLineOptions(optList): if opt[0] == "-i": conf["ignoreip"] = opt[1] if opt[0] == "-r": - conf["maxretry"] = int(opt[1]) + conf["maxfailures"] = int(opt[1]) if opt[0] == "-p": conf["pidlock"] = opt[1] if opt[0] == "-k": @@ -162,12 +162,12 @@ def main(): # Pre-parsing of command line options for the -c option for opt in optList: + if opt[0] == "-c": + conf["conffile"] = opt[1] if opt[0] in ["-h", "--help"]: dispUsage() if opt[0] in ["-V", "--version"]: dispVersion() - if opt[0] == "-c": - conf["conffile"] = opt[1] # Reads the config file and create a LogReader instance for # each log file to check. @@ -181,7 +181,7 @@ def main(): ["int", "syslog-facility", 1], ["bool", "debug", False], ["str", "pidlock", "/var/run/fail2ban.pid"], - ["int", "maxretry", 3], + ["int", "maxfailures", 5], ["int", "bantime", 600], ["int", "findtime", 600], ["str", "ignoreip", ""], @@ -293,16 +293,7 @@ def main(): # Ignores IP list 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 # are owned by root and firewall needs root access. if not checkForRoot(): @@ -316,12 +307,15 @@ def main(): logSys.error("Fail2Ban already running with PID "+pid) sys.exit(-1) 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("BanTime is " + `conf["bantime"]`) logSys.debug("FindTime is " + `conf["findtime"]`) - logSys.debug("retryAllowed is " + `conf["maxretry"]`) + logSys.debug("MaxFailure is " + `conf["maxfailures"]`) # Options optionValues = (["bool", "enabled", False], @@ -346,9 +340,9 @@ def main(): # Options optionValues = (["bool", "enabled", False], ["str", "logfile", "/dev/null"], - ["int", "maxretry", maxRetry], - ["int", "bantime", banTime], - ["int", "findtime", findTime], + ["int", "maxfailures", conf["maxfailures"]], + ["int", "bantime", conf["bantime"]], + ["int", "findtime", conf["findtime"]], ["str", "timeregex", ""], ["str", "timepattern", ""], ["str", "failregex", ""], @@ -364,7 +358,7 @@ def main(): # Creates a logreader object lObj = LogReader(l["logfile"], l["timeregex"], l["timepattern"], - l["failregex"], l["maxretry"], l["findtime"]) + l["failregex"], l["maxfailures"], l["findtime"]) # Creates a firewall object fObj = Firewall(l["fwban"], l["fwunban"], l["bantime"]) # Links them into a list. I'm not really happy @@ -381,6 +375,8 @@ def main(): if isValidIP(ip): for element in logFwList: element[1].addIgnoreIP(ip) + else: + logSys.warn(ip + " is not a valid IP address") logSys.info("Fail2Ban v" + version + " is running") # Execute global start command diff --git a/logreader/logreader.py b/logreader/logreader.py index 7a27ea29..1e6ec979 100644 --- a/logreader/logreader.py +++ b/logreader/logreader.py @@ -16,11 +16,11 @@ # Author: Cyril Jaquier # -# $Revision: 1.13.2.7 $ +# $Revision: 1.13.2.8 $ __author__ = "Cyril Jaquier" -__version__ = "$Revision: 1.13.2.7 $" -__date__ = "$Date: 2005/08/06 18:43:11 $" +__version__ = "$Revision: 1.13.2.8 $" +__date__ = "$Date: 2005/09/05 21:06:15 $" __copyright__ = "Copyright (c) 2004 Cyril Jaquier" __license__ = "GPL" @@ -134,11 +134,13 @@ class LogReader: logSys.debug(self.logPath) logFile = self.openLogFile() self.setFilePos(logFile) - lastLine = '' + lastLine = None for line in logFile: + if not self.hasTime(line): + # There is no valid time in this line + continue lastLine = line - failList = self.findFailure(line) - for element in failList: + for element in self.findFailure(line): ip = element[0] unixTime = element[1] if unixTime < time.time()-self.findTime: @@ -152,7 +154,8 @@ class LogReader: else: ipList[ip] = (1, unixTime) self.lastPos = logFile.tell() - self.lastDate = self.getTime(lastLine) + if lastLine: + self.lastDate = self.getTime(lastLine) logFile.close() return ipList @@ -175,6 +178,15 @@ class LogReader: failList.append([ip, date]) 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): """ Gets the time of a log message. """ diff --git a/setup.py b/setup.py index 891f9ea1..25b0e1e1 100755 --- a/setup.py +++ b/setup.py @@ -18,11 +18,11 @@ # Author: Cyril Jaquier # -# $Revision: 1.4.2.3 $ +# $Revision: 1.4.2.4 $ __author__ = "Cyril Jaquier" -__version__ = "$Revision: 1.4.2.3 $" -__date__ = "$Date: 2005/07/28 20:30:34 $" +__version__ = "$Revision: 1.4.2.4 $" +__date__ = "$Date: 2005/08/07 13:10:39 $" __copyright__ = "Copyright (c) 2004 Cyril Jaquier" __license__ = "GPL" diff --git a/utils/dns.py b/utils/dns.py index 45b091bc..814e2ed9 100644 --- a/utils/dns.py +++ b/utils/dns.py @@ -16,11 +16,11 @@ # Author: Cyril Jaquier # -# $Revision: 1.7.2.2 $ +# $Revision: 1.7.2.3 $ __author__ = "Cyril Jaquier" -__version__ = "$Revision: 1.7.2.2 $" -__date__ = "$Date: 2005/07/22 21:11:42 $" +__version__ = "$Revision: 1.7.2.3 $" +__date__ = "$Date: 2005/08/17 19:26:49 $" __copyright__ = "Copyright (c) 2004 Cyril Jaquier" __license__ = "GPL" @@ -58,8 +58,9 @@ def searchIP(text): def isValidIP(str): """ Return true if str is a valid IP """ + s = str.split('/', 1) try: - socket.inet_aton(str) + socket.inet_aton(s[0]) return True except socket.error: return False diff --git a/utils/mail.py b/utils/mail.py index 44b0954b..5ae2fc43 100644 --- a/utils/mail.py +++ b/utils/mail.py @@ -16,11 +16,11 @@ # Author: Cyril Jaquier # -# $Revision: 1.1.2.2 $ +# $Revision: 1.1.2.3 $ __author__ = "Cyril Jaquier" -__version__ = "$Revision: 1.1.2.2 $" -__date__ = "$Date: 2005/08/01 16:35:18 $" +__version__ = "$Revision: 1.1.2.3 $" +__date__ = "$Date: 2005/09/08 18:05:59 $" __copyright__ = "Copyright (c) 2004 Cyril Jaquier" __license__ = "GPL" @@ -64,8 +64,8 @@ class Mail: server.sendmail(self.fromAddr, self.toAddr, mail) logSys.debug("Email sent to " + `self.toAddr`) server.quit() - except Exception: + except Exception, e: logSys.error("Unable to send mail to " + self.host + ":" + `self.port` + " from " + self.fromAddr + " to " + - `self.toAddr`) + `self.toAddr` + ": " + `e` + ": " + `e.args`) \ No newline at end of file diff --git a/utils/pidlock.py b/utils/pidlock.py index 7df9945b..40ca5385 100644 --- a/utils/pidlock.py +++ b/utils/pidlock.py @@ -16,11 +16,11 @@ # Author: Cyril Jaquier # -# $Revision: 1.1.2.1 $ +# $Revision: 1.1.2.2 $ __author__ = "Cyril Jaquier" -__version__ = "$Revision: 1.1.2.1 $" -__date__ = "$Date: 2005/08/04 20:48:30 $" +__version__ = "$Revision: 1.1.2.2 $" +__date__ = "$Date: 2005/08/07 13:08:18 $" __copyright__ = "Copyright (c) 2004 Cyril Jaquier" __license__ = "GPL" @@ -51,17 +51,25 @@ class PIDLock: def create(self): """ Create PID lock. """ - fileHandler = open(self.path, mode='w') - pid = os.getpid() - fileHandler.write(`pid` + '\n') - fileHandler.close() - logSys.debug("Created PID lock (" + `pid` + ") in " + self.path) + try: + fileHandler = open(self.path, mode='w') + pid = os.getpid() + fileHandler.write(`pid` + '\n') + 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): """ Remove PID lock. """ - os.remove(self.path) - logSys.debug("Removed PID lock " + self.path) + try: + 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): """ Returns the current PID if Fail2Ban is running or False diff --git a/version.py b/version.py index 214d99fe..30da7d75 100644 --- a/version.py +++ b/version.py @@ -16,12 +16,12 @@ # Author: Cyril Jaquier # -# $Revision: 1.12.2.6 $ +# $Revision: 1.12.2.8 $ __author__ = "Cyril Jaquier" -__version__ = "$Revision: 1.12.2.6 $" -__date__ = "$Date: 2005/08/06 15:07:11 $" +__version__ = "$Revision: 1.12.2.8 $" +__date__ = "$Date: 2005/09/08 18:20:51 $" __copyright__ = "Copyright (c) 2004 Cyril Jaquier" __license__ = "GPL" -version = "0.5.2" +version = "0.5.3"