Compare commits

...
134 Commits
Author SHA1 Message Date
Cyril Jaquier 3ba3346dec - Update for release (0.6.2)
git-svn-id: https://fail2ban.svn.sourceforge.net/svnroot/fail2ban/branches/FAIL2BAN-0_6@486 a942ae1a-1317-0410-a47c-b1dcaea8d605
2006-12-11 21:43:57 +00:00
Cyril Jaquier ed0f57dbad - Added pydev project file
git-svn-id: https://fail2ban.svn.sourceforge.net/svnroot/fail2ban/branches/FAIL2BAN-0_6@485 a942ae1a-1317-0410-a47c-b1dcaea8d605
2006-12-11 21:14:58 +00:00
Cyril Jaquier 0a8f24c5f4 - Added named group "host" for "failregex"
- Fixed vulnerability CVE-2006-6302

git-svn-id: https://fail2ban.svn.sourceforge.net/svnroot/fail2ban/branches/FAIL2BAN-0_6@484 a942ae1a-1317-0410-a47c-b1dcaea8d605
2006-12-10 21:16:26 +00:00
Cyril Jaquier 8a253db9b5 - Propagated patches from Yaroslav Halchenko
git-svn-id: https://fail2ban.svn.sourceforge.net/svnroot/fail2ban/branches/FAIL2BAN-0_6@449 a942ae1a-1317-0410-a47c-b1dcaea8d605
2006-11-06 22:43:42 +00:00
Cyril Jaquier adf7827efd - Added Eclipse project
git-svn-id: https://fail2ban.svn.sourceforge.net/svnroot/fail2ban/branches/FAIL2BAN-0_6@448 a942ae1a-1317-0410-a47c-b1dcaea8d605
2006-11-06 22:35:06 +00:00
Cyril Jaquier bfbf8a70d2 - Updated
git-svn-id: https://fail2ban.svn.sourceforge.net/svnroot/fail2ban/branches/FAIL2BAN-0_6@248 a942ae1a-1317-0410-a47c-b1dcaea8d605
2006-03-19 18:35:21 +00:00
Cyril Jaquier 089770d1c0 - Fixed UTF-8 log file reading
git-svn-id: https://fail2ban.svn.sourceforge.net/svnroot/fail2ban/branches/FAIL2BAN-0_6@247 a942ae1a-1317-0410-a47c-b1dcaea8d605
2006-03-19 18:30:33 +00:00
Cyril Jaquier 2304f07a38 - Fixed logfile path
git-svn-id: https://fail2ban.svn.sourceforge.net/svnroot/fail2ban/branches/FAIL2BAN-0_6@245 a942ae1a-1317-0410-a47c-b1dcaea8d605
2006-03-17 16:28:46 +00:00
Cyril Jaquier 22995edd97 This commit was manufactured by cvs2svn to create branch 'FAIL2BAN-0_6'.
git-svn-id: https://fail2ban.svn.sourceforge.net/svnroot/fail2ban/branches/FAIL2BAN-0_6@244 a942ae1a-1317-0410-a47c-b1dcaea8d605
2006-03-15 23:07:12 +00:00
Cyril Jaquier 97aa913e24 - Updated for 0.6.1
git-svn-id: https://fail2ban.svn.sourceforge.net/svnroot/fail2ban/trunk@243 a942ae1a-1317-0410-a47c-b1dcaea8d605
2006-03-15 23:07:12 +00:00
Cyril Jaquier cbc18112bf - Updated
git-svn-id: https://fail2ban.svn.sourceforge.net/svnroot/fail2ban/trunk@242 a942ae1a-1317-0410-a47c-b1dcaea8d605
2006-02-21 12:46:58 +00:00
Cyril Jaquier b659cb2c2a - Updated
git-svn-id: https://fail2ban.svn.sourceforge.net/svnroot/fail2ban/trunk@241 a942ae1a-1317-0410-a47c-b1dcaea8d605
2006-02-13 21:37:44 +00:00
Cyril Jaquier 293f077d7b - Updated
git-svn-id: https://fail2ban.svn.sourceforge.net/svnroot/fail2ban/trunk@240 a942ae1a-1317-0410-a47c-b1dcaea8d605
2006-02-12 18:15:44 +00:00
Cyril Jaquier 83ea17fd24 - Updated
git-svn-id: https://fail2ban.svn.sourceforge.net/svnroot/fail2ban/trunk@239 a942ae1a-1317-0410-a47c-b1dcaea8d605
2006-02-12 12:30:39 +00:00
Cyril Jaquier dfb6f63753 - Updated
git-svn-id: https://fail2ban.svn.sourceforge.net/svnroot/fail2ban/trunk@238 a942ae1a-1317-0410-a47c-b1dcaea8d605
2006-02-11 15:30:04 +00:00
Cyril Jaquier 7e24b948bf - Added vsftpd support. Thanks to zugeschmiert
git-svn-id: https://fail2ban.svn.sourceforge.net/svnroot/fail2ban/trunk@237 a942ae1a-1317-0410-a47c-b1dcaea8d605
2006-02-11 15:29:32 +00:00
Cyril Jaquier 054d18dd28 - Updated with ideas for 0.7
git-svn-id: https://fail2ban.svn.sourceforge.net/svnroot/fail2ban/trunk@236 a942ae1a-1317-0410-a47c-b1dcaea8d605
2006-02-10 10:26:16 +00:00
Cyril Jaquier d29648d4de - Added a more robust firewall initialization loop. Thanks to Yaroslav Halchenko
git-svn-id: https://fail2ban.svn.sourceforge.net/svnroot/fail2ban/trunk@235 a942ae1a-1317-0410-a47c-b1dcaea8d605
2006-01-22 11:10:29 +00:00
Cyril Jaquier ad4280d506 - Updated
git-svn-id: https://fail2ban.svn.sourceforge.net/svnroot/fail2ban/trunk@234 a942ae1a-1317-0410-a47c-b1dcaea8d605
2006-01-22 11:08:42 +00:00
Cyril Jaquier de7acd4d6c - Added support for shorewall and hosts.deny
- Renamed fail2ban.conf.default to fail2ban.conf.iptables


git-svn-id: https://fail2ban.svn.sourceforge.net/svnroot/fail2ban/trunk@233 a942ae1a-1317-0410-a47c-b1dcaea8d605
2006-01-22 11:07:22 +00:00
Cyril Jaquier 3e86a8204b - Removed 192.168.0.0/16 from ignoreip
git-svn-id: https://fail2ban.svn.sourceforge.net/svnroot/fail2ban/trunk@232 a942ae1a-1317-0410-a47c-b1dcaea8d605
2006-01-12 16:20:00 +00:00
Cyril Jaquier 1044b82e12 - Removed debug option
- Added SMTP authentification support
- Changed syslog output to a more standard format


git-svn-id: https://fail2ban.svn.sourceforge.net/svnroot/fail2ban/trunk@231 a942ae1a-1317-0410-a47c-b1dcaea8d605
2006-01-03 15:16:22 +00:00
Cyril Jaquier 79318b3549 - Updated
git-svn-id: https://fail2ban.svn.sourceforge.net/svnroot/fail2ban/trunk@230 a942ae1a-1317-0410-a47c-b1dcaea8d605
2006-01-03 15:14:27 +00:00
Cyril Jaquier 6386c9e580 - Added SMTP authentification support
git-svn-id: https://fail2ban.svn.sourceforge.net/svnroot/fail2ban/trunk@229 a942ae1a-1317-0410-a47c-b1dcaea8d605
2006-01-03 15:13:41 +00:00
Cyril Jaquier 85f1d74d85 - Removed debug option
git-svn-id: https://fail2ban.svn.sourceforge.net/svnroot/fail2ban/trunk@228 a942ae1a-1317-0410-a47c-b1dcaea8d605
2006-01-03 15:13:24 +00:00
Cyril Jaquier fb07353aeb - Added TAI64N support
git-svn-id: https://fail2ban.svn.sourceforge.net/svnroot/fail2ban/trunk@227 a942ae1a-1317-0410-a47c-b1dcaea8d605
2006-01-03 15:13:04 +00:00
Cyril Jaquier be26cd5b75 - Removed debug option
- Added SMTP authentification support
- Added TAI64N support


git-svn-id: https://fail2ban.svn.sourceforge.net/svnroot/fail2ban/trunk@226 a942ae1a-1317-0410-a47c-b1dcaea8d605
2006-01-03 15:11:57 +00:00
Yaroslav Halchenko 3eb0ca0ee5 propagated fix for the path bug. Thanks to Nick Craig-Wood
git-svn-id: https://fail2ban.svn.sourceforge.net/svnroot/fail2ban/trunk@225 a942ae1a-1317-0410-a47c-b1dcaea8d605
2005-12-27 15:09:50 +00:00
Cyril Jaquier 7494fe283b - Updated
git-svn-id: https://fail2ban.svn.sourceforge.net/svnroot/fail2ban/trunk@224 a942ae1a-1317-0410-a47c-b1dcaea8d605
2005-12-16 23:51:59 +00:00
Cyril Jaquier 9cd787c50e - Fixed crash when time format does not match data
git-svn-id: https://fail2ban.svn.sourceforge.net/svnroot/fail2ban/trunk@223 a942ae1a-1317-0410-a47c-b1dcaea8d605
2005-12-16 23:50:59 +00:00
Cyril Jaquier 15806fc3da - Added permanent banning feature
git-svn-id: https://fail2ban.svn.sourceforge.net/svnroot/fail2ban/trunk@222 a942ae1a-1317-0410-a47c-b1dcaea8d605
2005-12-16 23:48:52 +00:00
Cyril Jaquier 716e0840fc - Removed unneeded semicolon
git-svn-id: https://fail2ban.svn.sourceforge.net/svnroot/fail2ban/trunk@221 a942ae1a-1317-0410-a47c-b1dcaea8d605
2005-12-16 23:47:03 +00:00
Cyril Jaquier cd38dddd00 - Fixed locale bug. Thanks to Fernando Jos�
git-svn-id: https://fail2ban.svn.sourceforge.net/svnroot/fail2ban/trunk@220 a942ae1a-1317-0410-a47c-b1dcaea8d605
2005-12-16 23:44:34 +00:00
Cyril Jaquier 52e7a26756 - Updated to CVS version
git-svn-id: https://fail2ban.svn.sourceforge.net/svnroot/fail2ban/trunk@219 a942ae1a-1317-0410-a47c-b1dcaea8d605
2005-12-16 23:44:06 +00:00
Cyril Jaquier af827330b2 - Updated
git-svn-id: https://fail2ban.svn.sourceforge.net/svnroot/fail2ban/trunk@218 a942ae1a-1317-0410-a47c-b1dcaea8d605
2005-12-16 23:43:46 +00:00
Cyril Jaquier 840f6cd052 - Merged FAIL2BAN-0_5 with HEAD
git-svn-id: https://fail2ban.svn.sourceforge.net/svnroot/fail2ban/trunk@216 a942ae1a-1317-0410-a47c-b1dcaea8d605
2005-11-20 17:07:47 +00:00
Cyril Jaquier 07d127bebd - Added an initd script for RedHat/Fedora. Thanks to Andrey G. Grozin
git-svn-id: https://fail2ban.svn.sourceforge.net/svnroot/fail2ban/trunk@113 a942ae1a-1317-0410-a47c-b1dcaea8d605
2005-07-01 09:30:52 +00:00
Cyril Jaquier 73ff1540e8 - Prepared for 0.4.1
git-svn-id: https://fail2ban.svn.sourceforge.net/svnroot/fail2ban/trunk@111 a942ae1a-1317-0410-a47c-b1dcaea8d605
2005-06-30 09:30:59 +00:00
Cyril Jaquier be43f2eaeb - Changed PID lock file location from /tmp to /var/run
git-svn-id: https://fail2ban.svn.sourceforge.net/svnroot/fail2ban/trunk@110 a942ae1a-1317-0410-a47c-b1dcaea8d605
2005-06-30 09:26:38 +00:00
Cyril Jaquier 7b118f42d3 - Initd script for Gentoo
git-svn-id: https://fail2ban.svn.sourceforge.net/svnroot/fail2ban/trunk@109 a942ae1a-1317-0410-a47c-b1dcaea8d605
2005-06-30 09:25:28 +00:00
Cyril Jaquier 9317581b18 - Modified for readability. Thanks to Iain Lea
git-svn-id: https://fail2ban.svn.sourceforge.net/svnroot/fail2ban/trunk@108 a942ae1a-1317-0410-a47c-b1dcaea8d605
2005-06-29 06:17:28 +00:00
Cyril Jaquier 51f1dcee55 - Fixed textToDNS method which generated wrong matches for "rhost=12-xyz...". Thanks to Tom Pike
git-svn-id: https://fail2ban.svn.sourceforge.net/svnroot/fail2ban/trunk@107 a942ae1a-1317-0410-a47c-b1dcaea8d605
2005-05-28 19:46:18 +00:00
Cyril Jaquier a051e05cb4 - Prepared for 0.4.0 release
git-svn-id: https://fail2ban.svn.sourceforge.net/svnroot/fail2ban/trunk@105 a942ae1a-1317-0410-a47c-b1dcaea8d605
2005-04-24 11:04:29 +00:00
Cyril Jaquier b0cae2c43f - Changed all sections to disabled by default
- Add "Invalid user" to SSH failregex


git-svn-id: https://fail2ban.svn.sourceforge.net/svnroot/fail2ban/trunk@104 a942ae1a-1317-0410-a47c-b1dcaea8d605
2005-04-24 11:03:44 +00:00
Cyril Jaquier 468f70dc15 - Changed to CVS version
git-svn-id: https://fail2ban.svn.sourceforge.net/svnroot/fail2ban/trunk@103 a942ae1a-1317-0410-a47c-b1dcaea8d605
2005-04-03 12:13:11 +00:00
Cyril Jaquier 0c9c50397a - Fixed bug in utils/dns.py
git-svn-id: https://fail2ban.svn.sourceforge.net/svnroot/fail2ban/trunk@102 a942ae1a-1317-0410-a47c-b1dcaea8d605
2005-04-03 12:12:52 +00:00
Cyril Jaquier a4ff90cd0a - Fixed textToDNS method which did not recognize "12-344-54-33.adsl.xyz.ab". Thanks to K�vin Drapel
git-svn-id: https://fail2ban.svn.sourceforge.net/svnroot/fail2ban/trunk@101 a942ae1a-1317-0410-a47c-b1dcaea8d605
2005-04-03 12:08:57 +00:00
Cyril Jaquier 77dc3e4261 - Fixed exception if trying to kill Fail2Ban with a fail2ban.pid file present. Thanks to K�vin Drapel
git-svn-id: https://fail2ban.svn.sourceforge.net/svnroot/fail2ban/trunk@99 a942ae1a-1317-0410-a47c-b1dcaea8d605
2005-03-31 16:04:52 +00:00
Cyril Jaquier 04ae381215 - Prepared for 0.3.1 release
git-svn-id: https://fail2ban.svn.sourceforge.net/svnroot/fail2ban/trunk@98 a942ae1a-1317-0410-a47c-b1dcaea8d605
2005-03-31 15:52:02 +00:00
Cyril Jaquier 35e12b9ef3 - Cleanups
git-svn-id: https://fail2ban.svn.sourceforge.net/svnroot/fail2ban/trunk@97 a942ae1a-1317-0410-a47c-b1dcaea8d605
2005-03-31 15:46:57 +00:00
Cyril Jaquier 6f6742266c - Improved debug messages
git-svn-id: https://fail2ban.svn.sourceforge.net/svnroot/fail2ban/trunk@96 a942ae1a-1317-0410-a47c-b1dcaea8d605
2005-03-31 15:45:24 +00:00
Cyril Jaquier 62feec3227 - Improved verbose mode
git-svn-id: https://fail2ban.svn.sourceforge.net/svnroot/fail2ban/trunk@95 a942ae1a-1317-0410-a47c-b1dcaea8d605
2005-03-30 22:48:38 +00:00
Cyril Jaquier 4d9615f68a - Updated main loop (needed by logreader optimization)
git-svn-id: https://fail2ban.svn.sourceforge.net/svnroot/fail2ban/trunk@94 a942ae1a-1317-0410-a47c-b1dcaea8d605
2005-03-29 14:41:34 +00:00
Cyril Jaquier 3368f7dd14 - Updated TODO list
git-svn-id: https://fail2ban.svn.sourceforge.net/svnroot/fail2ban/trunk@93 a942ae1a-1317-0410-a47c-b1dcaea8d605
2005-03-29 14:38:56 +00:00
Cyril Jaquier 7f62f9df89 - The optimization in log reading should work
git-svn-id: https://fail2ban.svn.sourceforge.net/svnroot/fail2ban/trunk@92 a942ae1a-1317-0410-a47c-b1dcaea8d605
2005-03-29 14:37:46 +00:00
Cyril Jaquier c442955e30 - Bug fix: check for DNS only if no IP address found
git-svn-id: https://fail2ban.svn.sourceforge.net/svnroot/fail2ban/trunk@91 a942ae1a-1317-0410-a47c-b1dcaea8d605
2005-03-11 15:33:36 +00:00
Cyril Jaquier 949eb89c76 - Removed the "host" command dependency
git-svn-id: https://fail2ban.svn.sourceforge.net/svnroot/fail2ban/trunk@90 a942ae1a-1317-0410-a47c-b1dcaea8d605
2005-03-08 21:11:46 +00:00
Cyril Jaquier 0a80b69db5 - Removed the "host" command dependency. Used Python socket module instead. Thanks to K�vin Drapel
git-svn-id: https://fail2ban.svn.sourceforge.net/svnroot/fail2ban/trunk@89 a942ae1a-1317-0410-a47c-b1dcaea8d605
2005-03-08 21:11:07 +00:00
Cyril Jaquier 10d0070d42 - Log parsing improvements were totally wrong. Removed
git-svn-id: https://fail2ban.svn.sourceforge.net/svnroot/fail2ban/trunk@88 a942ae1a-1317-0410-a47c-b1dcaea8d605
2005-03-08 21:08:16 +00:00
Cyril Jaquier 36571c2ba9 - Bug fix: return [] instead of 'None'
git-svn-id: https://fail2ban.svn.sourceforge.net/svnroot/fail2ban/trunk@87 a942ae1a-1317-0410-a47c-b1dcaea8d605
2005-03-07 17:08:38 +00:00
Cyril Jaquier 064ef28dc4 - Bug fix: check for log rotation using the file size. Not the best solution...
git-svn-id: https://fail2ban.svn.sourceforge.net/svnroot/fail2ban/trunk@86 a942ae1a-1317-0410-a47c-b1dcaea8d605
2005-03-07 14:46:33 +00:00
Cyril Jaquier dabc1e9681 - Added "utils" to packages
git-svn-id: https://fail2ban.svn.sourceforge.net/svnroot/fail2ban/trunk@85 a942ae1a-1317-0410-a47c-b1dcaea8d605
2005-03-06 18:28:19 +00:00
Cyril Jaquier d6c1eb1543 - Return value of createDaemon() changed to True
git-svn-id: https://fail2ban.svn.sourceforge.net/svnroot/fail2ban/trunk@84 a942ae1a-1317-0410-a47c-b1dcaea8d605
2005-03-06 18:27:42 +00:00
Cyril Jaquier 54f2fc0ae5 - Added utils/__init__.py and utils/dns.py
git-svn-id: https://fail2ban.svn.sourceforge.net/svnroot/fail2ban/trunk@83 a942ae1a-1317-0410-a47c-b1dcaea8d605
2005-03-06 17:52:53 +00:00
Cyril Jaquier 7af62c05fa - Initial import
git-svn-id: https://fail2ban.svn.sourceforge.net/svnroot/fail2ban/trunk@82 a942ae1a-1317-0410-a47c-b1dcaea8d605
2005-03-06 17:51:24 +00:00
Cyril Jaquier 6fb00dc582 - Improved log parsing speed. We remember the last position and restart from there when the file is modified
- Added DNS lookup support
- Removed unused functions


git-svn-id: https://fail2ban.svn.sourceforge.net/svnroot/fail2ban/trunk@81 a942ae1a-1317-0410-a47c-b1dcaea8d605
2005-03-06 17:49:41 +00:00
Cyril Jaquier fa39e3b57d - Added "self" in method parameters
git-svn-id: https://fail2ban.svn.sourceforge.net/svnroot/fail2ban/trunk@80 a942ae1a-1317-0410-a47c-b1dcaea8d605
2005-03-06 17:47:51 +00:00
Cyril Jaquier f6b9749650 - Corrected log level
- Dict iteration improved


git-svn-id: https://fail2ban.svn.sourceforge.net/svnroot/fail2ban/trunk@79 a942ae1a-1317-0410-a47c-b1dcaea8d605
2005-03-06 17:46:56 +00:00
Cyril Jaquier ad93288bd8 - Corrected log level
- Removed unused import


git-svn-id: https://fail2ban.svn.sourceforge.net/svnroot/fail2ban/trunk@78 a942ae1a-1317-0410-a47c-b1dcaea8d605
2005-03-06 17:45:55 +00:00
Cyril Jaquier 1a876366a7 - Added a killApp() function
- Dict iteration improved


git-svn-id: https://fail2ban.svn.sourceforge.net/svnroot/fail2ban/trunk@77 a942ae1a-1317-0410-a47c-b1dcaea8d605
2005-03-06 17:44:48 +00:00
Cyril Jaquier bc4524c165 - Updated
git-svn-id: https://fail2ban.svn.sourceforge.net/svnroot/fail2ban/trunk@76 a942ae1a-1317-0410-a47c-b1dcaea8d605
2005-03-06 17:42:59 +00:00
Cyril Jaquier d1ec7fb830 - Change to CVS version
git-svn-id: https://fail2ban.svn.sourceforge.net/svnroot/fail2ban/trunk@75 a942ae1a-1317-0410-a47c-b1dcaea8d605
2005-03-06 17:42:04 +00:00
Cyril Jaquier 7fb2508960 - Version 0.3.0. Named it 0.3 because there is a lot of changes in this release
git-svn-id: https://fail2ban.svn.sourceforge.net/svnroot/fail2ban/trunk@73 a942ae1a-1317-0410-a47c-b1dcaea8d605
2005-02-24 13:59:34 +00:00
Cyril Jaquier f0625224c7 - Added a default value for each option
git-svn-id: https://fail2ban.svn.sourceforge.net/svnroot/fail2ban/trunk@72 a942ae1a-1317-0410-a47c-b1dcaea8d605
2005-02-23 17:47:30 +00:00
Cyril Jaquier 3d9318ad3e - Splitted "checkForPID" into "createPID" and "checkForPID". Fixed the bug which created a PID lock file when calling Fail2Ban with the kill option
git-svn-id: https://fail2ban.svn.sourceforge.net/svnroot/fail2ban/trunk@71 a942ae1a-1317-0410-a47c-b1dcaea8d605
2005-02-23 17:31:46 +00:00
Cyril Jaquier c429a69845 - Added the "-k" option. Kills a currently running Fail2Ban
git-svn-id: https://fail2ban.svn.sourceforge.net/svnroot/fail2ban/trunk@70 a942ae1a-1317-0410-a47c-b1dcaea8d605
2005-02-23 16:56:29 +00:00
Cyril Jaquier 45dd8ea43e - Increment "crtRuleNbr" after the creation of the rule
git-svn-id: https://fail2ban.svn.sourceforge.net/svnroot/fail2ban/trunk@69 a942ae1a-1317-0410-a47c-b1dcaea8d605
2005-02-23 16:53:03 +00:00
Cyril Jaquier 42937a5522 - Added "ipfw-start-rule" option (thanks to Robert Edeker)
- Added "enabled" option


git-svn-id: https://fail2ban.svn.sourceforge.net/svnroot/fail2ban/trunk@68 a942ae1a-1317-0410-a47c-b1dcaea8d605
2005-02-22 21:14:04 +00:00
Cyril Jaquier 9a74701807 - Added "ipfw-start-rule" option (thanks to Robert Edeker)
git-svn-id: https://fail2ban.svn.sourceforge.net/svnroot/fail2ban/trunk@67 a942ae1a-1317-0410-a47c-b1dcaea8d605
2005-02-22 21:11:46 +00:00
Cyril Jaquier acbbb11578 - A rule is added with a specified number now
git-svn-id: https://fail2ban.svn.sourceforge.net/svnroot/fail2ban/trunk@66 a942ae1a-1317-0410-a47c-b1dcaea8d605
2005-02-22 21:11:17 +00:00
Cyril Jaquier 7b13c386f9 - The options have a specified type now
git-svn-id: https://fail2ban.svn.sourceforge.net/svnroot/fail2ban/trunk@65 a942ae1a-1317-0410-a47c-b1dcaea8d605
2005-02-22 21:10:08 +00:00
Cyril Jaquier 78b32ef3b2 - Added "ipfw-start-rule" option (thanks to Robert Edeker)
- Added "enabled" option


git-svn-id: https://fail2ban.svn.sourceforge.net/svnroot/fail2ban/trunk@64 a942ae1a-1317-0410-a47c-b1dcaea8d605
2005-02-22 21:08:36 +00:00
Cyril Jaquier 3122f5eeae - Added PID lock file option
- Added more comments


git-svn-id: https://fail2ban.svn.sourceforge.net/svnroot/fail2ban/trunk@63 a942ae1a-1317-0410-a47c-b1dcaea8d605
2005-02-20 13:38:10 +00:00
Cyril Jaquier 4961847529 - Added PID lock file support
- Improved some parts of the code


git-svn-id: https://fail2ban.svn.sourceforge.net/svnroot/fail2ban/trunk@62 a942ae1a-1317-0410-a47c-b1dcaea8d605
2005-02-20 13:34:43 +00:00
Cyril Jaquier 2131d080c2 - Added PID lock file option
git-svn-id: https://fail2ban.svn.sourceforge.net/svnroot/fail2ban/trunk@61 a942ae1a-1317-0410-a47c-b1dcaea8d605
2005-02-20 13:33:55 +00:00
Cyril Jaquier 1711a87dff - Added PID lock file support
- Added log reader name support
- Improve some algorithms
- Changed some info messages to warn


git-svn-id: https://fail2ban.svn.sourceforge.net/svnroot/fail2ban/trunk@60 a942ae1a-1317-0410-a47c-b1dcaea8d605
2005-02-20 13:33:17 +00:00
Cyril Jaquier deffa8f5aa - Added log reader name
git-svn-id: https://fail2ban.svn.sourceforge.net/svnroot/fail2ban/trunk@59 a942ae1a-1317-0410-a47c-b1dcaea8d605
2005-02-20 11:16:56 +00:00
Cyril Jaquier 16dbc44607 - Added TODO file
git-svn-id: https://fail2ban.svn.sourceforge.net/svnroot/fail2ban/trunk@58 a942ae1a-1317-0410-a47c-b1dcaea8d605
2005-02-20 11:15:06 +00:00
Cyril Jaquier c7947c68e9 - Bantime was not used in the log reader
git-svn-id: https://fail2ban.svn.sourceforge.net/svnroot/fail2ban/trunk@57 a942ae1a-1317-0410-a47c-b1dcaea8d605
2005-02-18 22:14:02 +00:00
Cyril Jaquier 2b5812ef9b - parser.py no more needed
git-svn-id: https://fail2ban.svn.sourceforge.net/svnroot/fail2ban/trunk@56 a942ae1a-1317-0410-a47c-b1dcaea8d605
2005-02-18 21:53:16 +00:00
Cyril Jaquier ff088ec333 - Added more comments
git-svn-id: https://fail2ban.svn.sourceforge.net/svnroot/fail2ban/trunk@55 a942ae1a-1317-0410-a47c-b1dcaea8d605
2005-02-18 21:51:32 +00:00
Cyril Jaquier e339a48751 - Fixed bug when flushing ban list
git-svn-id: https://fail2ban.svn.sourceforge.net/svnroot/fail2ban/trunk@54 a942ae1a-1317-0410-a47c-b1dcaea8d605
2005-02-18 21:49:51 +00:00
Cyril Jaquier f4b083d79b - Added more comments
- Catch exception when option not present in section


git-svn-id: https://fail2ban.svn.sourceforge.net/svnroot/fail2ban/trunk@53 a942ae1a-1317-0410-a47c-b1dcaea8d605
2005-02-18 21:48:34 +00:00
Cyril Jaquier b5eb68d884 - Only scan log files which were modified
git-svn-id: https://fail2ban.svn.sourceforge.net/svnroot/fail2ban/trunk@52 a942ae1a-1317-0410-a47c-b1dcaea8d605
2005-02-18 21:46:56 +00:00
Cyril Jaquier 78dab1db70 - Updated information
git-svn-id: https://fail2ban.svn.sourceforge.net/svnroot/fail2ban/trunk@51 a942ae1a-1317-0410-a47c-b1dcaea8d605
2005-02-18 21:45:34 +00:00
Cyril Jaquier 2e5bfe5bb6 - Changed Fail2Ban in order to handle several log files
git-svn-id: https://fail2ban.svn.sourceforge.net/svnroot/fail2ban/trunk@50 a942ae1a-1317-0410-a47c-b1dcaea8d605
2005-02-18 13:30:54 +00:00
Cyril Jaquier 2c778a9b76 - Version 0.1.2. Second beta version
git-svn-id: https://fail2ban.svn.sourceforge.net/svnroot/fail2ban/trunk@49 a942ae1a-1317-0410-a47c-b1dcaea8d605
2004-11-21 09:29:11 +00:00
Cyril Jaquier a562542523 - Remove posix from import
- Update help message
- Add support for multiple firewall class. It is now really simple to add new ones
- Add support for interface selection


git-svn-id: https://fail2ban.svn.sourceforge.net/svnroot/fail2ban/trunk@48 a942ae1a-1317-0410-a47c-b1dcaea8d605
2004-11-06 14:08:04 +00:00
Cyril Jaquier 11330ff944 - Fail2ban now support ipfw and ipfwadm
- New options


git-svn-id: https://fail2ban.svn.sourceforge.net/svnroot/fail2ban/trunk@47 a942ae1a-1317-0410-a47c-b1dcaea8d605
2004-11-06 14:06:06 +00:00
Cyril Jaquier f1770f937b - Update current changes
git-svn-id: https://fail2ban.svn.sourceforge.net/svnroot/fail2ban/trunk@46 a942ae1a-1317-0410-a47c-b1dcaea8d605
2004-11-06 14:05:09 +00:00
Cyril Jaquier 88313ea611 - Add firewall/ipfw.py and firewall/ipfwadm.py
git-svn-id: https://fail2ban.svn.sourceforge.net/svnroot/fail2ban/trunk@45 a942ae1a-1317-0410-a47c-b1dcaea8d605
2004-11-06 14:04:34 +00:00
Cyril Jaquier 8598ff2315 - Change to CVS version
git-svn-id: https://fail2ban.svn.sourceforge.net/svnroot/fail2ban/trunk@44 a942ae1a-1317-0410-a47c-b1dcaea8d605
2004-11-06 14:03:43 +00:00
Cyril Jaquier fabe6e59b4 - Add firewall and interface options
git-svn-id: https://fail2ban.svn.sourceforge.net/svnroot/fail2ban/trunk@43 a942ae1a-1317-0410-a47c-b1dcaea8d605
2004-11-06 14:03:17 +00:00
Cyril Jaquier 4d098fbd7a - Initial import
git-svn-id: https://fail2ban.svn.sourceforge.net/svnroot/fail2ban/trunk@42 a942ae1a-1317-0410-a47c-b1dcaea8d605
2004-11-06 14:02:27 +00:00
Cyril Jaquier 01a53b045b - Add interface parameter
git-svn-id: https://fail2ban.svn.sourceforge.net/svnroot/fail2ban/trunk@41 a942ae1a-1317-0410-a47c-b1dcaea8d605
2004-11-06 14:02:07 +00:00
Cyril Jaquier 6930f5c0c3 - Version 0.1.1. This is the first beta release
git-svn-id: https://fail2ban.svn.sourceforge.net/svnroot/fail2ban/trunk@39 a942ae1a-1317-0410-a47c-b1dcaea8d605
2004-10-23 08:42:53 +00:00
Cyril Jaquier f3dd99da0c - Add SIGTERM handler
git-svn-id: https://fail2ban.svn.sourceforge.net/svnroot/fail2ban/trunk@38 a942ae1a-1317-0410-a47c-b1dcaea8d605
2004-10-18 20:54:29 +00:00
Cyril Jaquier c7513aba77 - Fix retryAllowed. It is now conf["maxretry"]
- Add SIGTERM handler in order to exit properly when in daemon mode


git-svn-id: https://fail2ban.svn.sourceforge.net/svnroot/fail2ban/trunk@37 a942ae1a-1317-0410-a47c-b1dcaea8d605
2004-10-18 20:50:56 +00:00
Cyril Jaquier b9349fd45e - Configuration using /etc/fail2ban.conf
git-svn-id: https://fail2ban.svn.sourceforge.net/svnroot/fail2ban/trunk@36 a942ae1a-1317-0410-a47c-b1dcaea8d605
2004-10-16 22:18:25 +00:00
Cyril Jaquier 3b7f952cd2 - Update installation + configuration instructions
git-svn-id: https://fail2ban.svn.sourceforge.net/svnroot/fail2ban/trunk@35 a942ae1a-1317-0410-a47c-b1dcaea8d605
2004-10-16 22:17:58 +00:00
Cyril Jaquier f1d7157cae - Add config/fail2ban.conf.default
git-svn-id: https://fail2ban.svn.sourceforge.net/svnroot/fail2ban/trunk@34 a942ae1a-1317-0410-a47c-b1dcaea8d605
2004-10-16 22:17:35 +00:00
Cyril Jaquier aee13b03ee - Default config file
git-svn-id: https://fail2ban.svn.sourceforge.net/svnroot/fail2ban/trunk@33 a942ae1a-1317-0410-a47c-b1dcaea8d605
2004-10-16 22:16:14 +00:00
Cyril Jaquier d50f1cd0f7 - Remove this file has it is no more necessary. Fail2Ban seems to be more services dependant than syslog daemons
git-svn-id: https://fail2ban.svn.sourceforge.net/svnroot/fail2ban/trunk@32 a942ae1a-1317-0410-a47c-b1dcaea8d605
2004-10-14 10:39:43 +00:00
Cyril Jaquier 052f35eccb - Initial import
git-svn-id: https://fail2ban.svn.sourceforge.net/svnroot/fail2ban/trunk@31 a942ae1a-1317-0410-a47c-b1dcaea8d605
2004-10-14 10:38:22 +00:00
Cyril Jaquier ded1b1492b - Remove metalog class. Use now the "service" classes (Sshd for the moment)
- Code comments


git-svn-id: https://fail2ban.svn.sourceforge.net/svnroot/fail2ban/trunk@30 a942ae1a-1317-0410-a47c-b1dcaea8d605
2004-10-14 10:34:25 +00:00
Cyril Jaquier 1070273151 - Code comments
git-svn-id: https://fail2ban.svn.sourceforge.net/svnroot/fail2ban/trunk@29 a942ae1a-1317-0410-a47c-b1dcaea8d605
2004-10-14 10:31:53 +00:00
Cyril Jaquier 3331c9dccb - Change executeCmd to private
- Code comments


git-svn-id: https://fail2ban.svn.sourceforge.net/svnroot/fail2ban/trunk@28 a942ae1a-1317-0410-a47c-b1dcaea8d605
2004-10-14 10:31:32 +00:00
Cyril Jaquier 18029d4426 - Add log4py import exception handling
- Remove metalog class. Now use LogReader
- Add -r option: you can specifie the maximum number of login failure before ban
- Code comments


git-svn-id: https://fail2ban.svn.sourceforge.net/svnroot/fail2ban/trunk@27 a942ae1a-1317-0410-a47c-b1dcaea8d605
2004-10-14 10:30:25 +00:00
Cyril Jaquier 3fa88d60a6 - Some small update about current work
git-svn-id: https://fail2ban.svn.sourceforge.net/svnroot/fail2ban/trunk@26 a942ae1a-1317-0410-a47c-b1dcaea8d605
2004-10-14 10:28:04 +00:00
Cyril Jaquier 1786004c3d - Add logreader/parser.py and logreader/sshd.py
- Remove logreader/metalog.py


git-svn-id: https://fail2ban.svn.sourceforge.net/svnroot/fail2ban/trunk@25 a942ae1a-1317-0410-a47c-b1dcaea8d605
2004-10-14 10:27:27 +00:00
Cyril Jaquier 28c1d658a4 - Change to CVS version
git-svn-id: https://fail2ban.svn.sourceforge.net/svnroot/fail2ban/trunk@24 a942ae1a-1317-0410-a47c-b1dcaea8d605
2004-10-14 10:26:17 +00:00
Cyril Jaquier 03d73b78f8 - Setup and dist files
git-svn-id: https://fail2ban.svn.sourceforge.net/svnroot/fail2ban/trunk@22 a942ae1a-1317-0410-a47c-b1dcaea8d605
2004-10-12 21:45:41 +00:00
Cyril Jaquier 4eeb61c0e1 - Update help message
- Add -i option: ignore ip list. Space separated ip list
- Add -t option: ban time in seconds. 600 to ban ip for 10 minutes
- Add a info message saying that fail2ban is running


git-svn-id: https://fail2ban.svn.sourceforge.net/svnroot/fail2ban/trunk@21 a942ae1a-1317-0410-a47c-b1dcaea8d605
2004-10-12 21:44:09 +00:00
Cyril Jaquier bb896fb391 - Add a debug message when adding ip to ignore list
git-svn-id: https://fail2ban.svn.sourceforge.net/svnroot/fail2ban/trunk@20 a942ae1a-1317-0410-a47c-b1dcaea8d605
2004-10-12 21:40:50 +00:00
Cyril Jaquier 8eb470019c - Add log4py support
- Remove old verbose mode
- Add debug feature
- Add option -f <pwdfail file>. This is the log file to read from
- Add option -l <log file>. This is the file to log fail2ban messages
- Add option -d. Allow fail2ban to run without root permissions. Do not execute OS command


git-svn-id: https://fail2ban.svn.sourceforge.net/svnroot/fail2ban/trunk@19 a942ae1a-1317-0410-a47c-b1dcaea8d605
2004-10-11 10:26:39 +00:00
Cyril Jaquier a2ea1164b3 - Add log4py support
- Remove old verbose mode


git-svn-id: https://fail2ban.svn.sourceforge.net/svnroot/fail2ban/trunk@18 a942ae1a-1317-0410-a47c-b1dcaea8d605
2004-10-11 10:23:53 +00:00
Cyril Jaquier c286d56855 - Add log4py support
- Remove old verbose mode
- Add debug feature


git-svn-id: https://fail2ban.svn.sourceforge.net/svnroot/fail2ban/trunk@17 a942ae1a-1317-0410-a47c-b1dcaea8d605
2004-10-11 10:22:41 +00:00
Cyril Jaquier be1755cac1 - Change quoting style
git-svn-id: https://fail2ban.svn.sourceforge.net/svnroot/fail2ban/trunk@16 a942ae1a-1317-0410-a47c-b1dcaea8d605
2004-10-11 10:21:56 +00:00
Cyril Jaquier e561e39583 - Add verbose option
git-svn-id: https://fail2ban.svn.sourceforge.net/svnroot/fail2ban/trunk@15 a942ae1a-1317-0410-a47c-b1dcaea8d605
2004-10-10 23:46:58 +00:00
Cyril Jaquier 4602bb1bfc - Add this file with .py extension in order to by recognize as Python source file with pydev (Eclipse plugin)
- Add command line options: -v (verbose mode), -h (help), -b (background)
- Add daemon function found on aspn.activestate.com


git-svn-id: https://fail2ban.svn.sourceforge.net/svnroot/fail2ban/trunk@14 a942ae1a-1317-0410-a47c-b1dcaea8d605
2004-10-10 23:44:24 +00:00
Cyril Jaquier 5fc0a65163 - removing this file. Replaced by fail2ban.py
git-svn-id: https://fail2ban.svn.sourceforge.net/svnroot/fail2ban/trunk@11 a942ae1a-1317-0410-a47c-b1dcaea8d605
2004-10-10 23:41:07 +00:00
Cyril Jaquier 012301b644 - Complete rewrite to use the log-reader and firewall classes
git-svn-id: https://fail2ban.svn.sourceforge.net/svnroot/fail2ban/trunk@10 a942ae1a-1317-0410-a47c-b1dcaea8d605
2004-10-10 13:35:52 +00:00
Cyril Jaquier 68ab4b0b26 - a few changes and corrections
git-svn-id: https://fail2ban.svn.sourceforge.net/svnroot/fail2ban/trunk@9 a942ae1a-1317-0410-a47c-b1dcaea8d605
2004-10-10 13:35:11 +00:00
Cyril Jaquier 0de46864a1 - update some dates
git-svn-id: https://fail2ban.svn.sourceforge.net/svnroot/fail2ban/trunk@8 a942ae1a-1317-0410-a47c-b1dcaea8d605
2004-10-10 13:34:02 +00:00
34 changed files with 3611 additions and 262 deletions
+17
View File
@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>fail2ban-stable</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.python.pydev.PyDevBuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.python.pydev.pythonNature</nature>
</natures>
</projectDescription>
+12
View File
@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<?eclipse-pydev version="1.0"?>
<pydev_project>
<pydev_property name="org.python.pydev.PYTHON_PROJECT_VERSION">python 2.4</pydev_property>
<pydev_pathproperty name="org.python.pydev.PROJECT_SOURCE_PATH">
<path>/fail2ban-stable/confreader</path>
<path>/fail2ban-stable/firewall</path>
<path>/fail2ban-stable/logreader</path>
<path>/fail2ban-stable/utils</path>
</pydev_pathproperty>
</pydev_project>
+201
View File
@@ -0,0 +1,201 @@
__ _ _ ___ _
/ _|__ _(_) |_ ) |__ __ _ _ _
| _/ _` | | |/ /| '_ \/ _` | ' \
|_| \__,_|_|_/___|_.__/\__,_|_||_|
=============================================================
Fail2Ban (version 0.6.2) 2006/12/11
=============================================================
ver. 0.6.2 (2006/12/11) - stable
----------
- Fixed UTF-8 log file parsing
- Propagated patches introduced by Debian maintainer
(Yaroslav Halchenko):
* Made locale configurable
* Fixed warning if ignoreip is empty
- Added named group "host" for "failregex". Fixed security
vulnerability CVE-2006-6302
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
+29
View File
@@ -0,0 +1,29 @@
README
CHANGELOG
TODO
setup.cfg
setup.py
version.py
fail2ban
fail2ban.py
firewall/__init__.py
firewall/firewall.py
logreader/__init__.py
logreader/logreader.py
confreader/__init__.py
confreader/configreader.py
utils/__init__.py
utils/dns.py
utils/process.py
utils/mail.py
utils/strings.py
utils/pidlock.py
config/fail2ban.conf.iptables
config/fail2ban.conf.shorewall
config/fail2ban.conf.hostsdeny
config/gentoo-initd
config/gentoo-confd
config/redhat-initd
config/debian-initd
man/fail2ban.8
man/fail2ban.conf.5
+162
View File
@@ -0,0 +1,162 @@
__ _ _ ___ _
/ _|__ _(_) |_ ) |__ __ _ _ _
| _/ _` | | |/ /| '_ \/ _` | ' \
|_| \__,_|_|_/___|_.__/\__,_|_||_|
=============================================================
Fail2Ban (version 0.6.2) 2006/12/11
=============================================================
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.6.2.tar.bz2
> cd fail2ban-0.6.2
> python setup.py install
This will install Fail2Ban into /usr/lib/fail2ban. The
fail2ban executable is 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 -h
to see if everything is alright. You can configure fail2ban
with a config file. Different kind of configuration files are
available:
iptables: copy config/fail2ban.conf.iptables to
/etc/fail2ban.conf
hosts.deny: copy config/fail2ban.conf.hostsdeny to
/etc/fail2ban.conf
shorewall: copy config/fail2ban.conf.shorewall to
/etc/fail2ban.conf
Do not forget to edit fail2ban.conf to meet your needs.
You can use the initd script available in config/. Copy
<dist>-initd to /etc/init.d/fail2ban. Gentoo users must copy
gentoo-confd to /etc/conf.d/fail2ban. You can start fail2ban:
> /etc/init.d/fail2ban start
Gentoo users can add it to the default runlevel:
> rc-update add fail2ban default
Configuration:
--------------
You can configure fail2ban using the file /etc/fail2ban.conf
or using command line options. Command line options override
the value stored in fail2ban.conf. Here are the command line
options:
-b start in background
-c <FILE> read configuration file FILE
-p <FILE> create PID lock in FILE
-h display this help message
-i <IP(s)> IP(s) to ignore
-k kill a currently running instance
-r <VALUE> allow a max of VALUE password failure [maxfailures]
-t <TIME> ban IP for TIME seconds [bantime]
-f <TIME> lifetime in seconds of failed entry [findtime]
-v verbose. Use twice for greater effect
-V print software version
Please note that a vulnerability (CVE-2006-6302) affects
version < 0.6.2. Since 0.6.2, a named group "host" was added
to "failregex". This group must match the host address. Old
configuration files will still work but will generate a
warning. In this case, please update your configuration file.
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
+95
View File
@@ -0,0 +1,95 @@
__ _ _ ___ _
/ _|__ _(_) |_ ) |__ __ _ _ _
| _/ _` | | |/ /| '_ \/ _` | ' \
|_| \__,_|_|_/___|_.__/\__,_|_||_|
=============================================================
ToDo $Revision$
=============================================================
See Feature Request Tracking System at SourceForge.net
- 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.
+73
View File
@@ -0,0 +1,73 @@
#! /bin/sh
#
# Fail2Ban init.d file - to be launched on boot
#
# Written by Miquel van Smoorenburg <miquels@cistron.nl>.
# Modified for Debian
# by Ian Murdock <imurdock@gnu.ai.mit.edu>.
# Adjusted for Fail2Ban
# by Yaroslav Halchenko <debian@onerussian.com>.
#
# Version: $Id$
#
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
DAEMON=/usr/bin/fail2ban
NAME=fail2ban
DESC=fail2ban
PIDFILE=/var/run/$NAME.pid
test -x $DAEMON || exit 0
# Include fail2ban defaults if available
if [ -f /etc/default/fail2ban ] ; then
. /etc/default/fail2ban
fi
DAEMON_OPTS=$FAIL2BAN_OPTS
set -e
case "$1" in
start)
echo -n "Starting $DESC: "
[ -f $PIDFILE ] && [ ! -d /proc/`cat $PIDFILE` ] && rm -f $PIDFILE
start-stop-daemon --start --quiet --pidfile $PIDFILE \
-b --exec $DAEMON -- $DAEMON_OPTS
echo "$NAME."
;;
stop)
echo -n "Stopping $DESC: "
start-stop-daemon --stop --quiet --pidfile $PIDFILE
echo "$NAME."
;;
restart|force-reload)
echo -n "Restarting $DESC: "
( $0 stop )
sleep 1
$0 start
;;
status)
echo -n "Status of $DESC: "
if [ ! -e "$PIDFILE" ]; then
echo "$NAME is not running."
exit 3
fi
if [ ! -r "$PIDFILE" ]; then
echo "$PIDFILE not readable, status of $NAME unknown."
exit 4
fi
if [ -d /proc/`cat "$PIDFILE"` ]; then
echo "$NAME is running."
exit 0
else
echo "$NAME is not running but $PIDFILE exists."
exit 1
fi
;;
*)
N=/etc/init.d/$NAME
echo "Usage: $N {start|stop|restart|force-reload|status}" >&2
exit 1
;;
esac
exit 0
+336
View File
@@ -0,0 +1,336 @@
# Fail2Ban configuration file
#
# $Revision$
#
# 2005.06.21 modified for readability Iain Lea iain@bricbrac.de
[DEFAULT]
# Option: background
# Notes.: start fail2ban as a daemon. Output is redirect to logfile.
# Values: [true | false] Default: false
#
background = false
# Option: locale
# Notes.: global (cannot be redefined per section) locale to use for
# timestamp pattern matching by changing LC_TIME for
# fail2ban process. Empty entry sets locale to default one
# (usually specified by LC_ALL environment variable).
# Values: LOCALE Default:
#
locale =
# Option: logtargets
# Notes.: log targets. Space separated list of logging targets.
# Values: STDERR SYSLOG file Default: /var/log/fail2ban.log
#
logtargets = /var/log/fail2ban.log
# Option: syslog-target
# Notes.: where to find syslog facility if logtarget SYSLOG.
# Values: SOCKET HOST HOST:PORT Default: /dev/log
#
syslog-target = /dev/log
# Option: syslog-facility
# Notes.: which syslog facility to use if logtarget SYSLOG.
# Values: NUM Default: 1
#
syslog-facility = 1
# Option: pidlock
# Notes.: path of the PID lock file (must be able to write to file).
# Values: FILE Default: /var/run/fail2ban.pid
#
pidlock = /var/run/fail2ban.pid
# Option: maxfailures
# Notes.: number of failures before IP gets banned.
# Values: NUM Default: 5
#
maxfailures = 5
# Option: bantime
# Notes.: number of seconds an IP will be banned. If set to a negative
# value, IP will never be unbanned (permanent banning).
# Values: NUM Default: 600
#
bantime = 600
# Option: findtime
# Notes.: lifetime in seconds of a "failed" log entry.
# Values: NUM Default: 600
#
findtime = 600
# Option: ignoreip
# 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:
#
ignoreip =
# Option: cmdstart
# Notes.: command executed once at the start of Fail2Ban
# Values: CMD Default:
#
cmdstart =
# Option: cmdend
# Notes.: command executed once at the end of Fail2Ban.
# Values: CMD Default:
#
cmdend =
# Option: polltime
# Notes.: number of seconds fail2ban sleeps between iterations.
# Values: NUM Default: 1
#
polltime = 1
# Option: reinittime
# Notes.: minimal number of seconds between the re-initialization of
# firewalls due to external changes in their rules (see fwcheck)
# Values: NUM Default: 100
#
reinittime = 10
# Option: maxreinits
# Notes.: maximal number of re-initialization of firewalls due to external
# changes. -1 stays for infinite, so only reinittime is of importance
# Values: NUM Default: -1
#
maxreinits = -1
# NOTE: Interpolations
#
# fwstart, as well as fwend, fwcheck, fwban, fwunban, use interpolations
# so %(__name__)s will be substituted by a name of each section
# (unless the option is overriden in a section).
# If you are going to use interpolations in your setup, please make
# sure that you specified options port and protocol (which also has
# an option in DEFAULT).
#
# Option: hostsdeny
# Notes.: hosts.deny file path.
# Values: STR Default: /etc/hosts.deny
#
hostsdeny = /etc/hosts.deny
# 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
#
fwban = IP=<ip> && echo "ALL: $IP" >> %(hostsdeny)s
# 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
#
fwunban = IP=<ip> && sed -i.old s/ALL:\ $IP// %(hostsdeny)s
[MAIL]
# Option: enabled
# Notes.: enable mail notification when banning an IP address.
# Values: [true | false] Default: false
#
enabled = false
# Option: host
# Notes.: host running the mail server.
# Values: STR Default: localhost
#
host = localhost
# Option: port
# Notes.: port of the mail server.
# Values: INT Default: 25
#
port = 25
# Option: user
# Notes.: the username for smtp-server if authentification is required.
# if user is empty, no authentification is done.
# Values: STR Default:
#
user =
# Option: password
# Notes.: the smtp-user's password if authentification is required.
# Values: STR Default:
#
password =
# Option: from
# Notes.: e-mail address of the sender.
# Values: MAIL Default: fail2ban
#
from = fail2ban
# Option: to
# Notes.: e-mail addresses of the receiver. Addresses are space
# separated.
# Values: MAIL Default: root
#
to = root
# Option: localtime
# Notes.: report local time (including timezone) or GMT
# Values: [true | false] Default: false
#
localtime = true
# Option: subject
# Notes.: subject of the e-mail.
# Tags: <section> active section (eg ssh, apache, etc)
# <ip> IP address
# <failures> number of failures
# <failtime> unix timestamp of the last failure
# Values: TEXT Default: [Fail2Ban] <section>: Banned <ip>
#
subject = [Fail2Ban] <section>: Banned <ip>
# Option: message
# Notes.: message of the e-mail.
# Tags: <section> active section (eg ssh, apache, etc)
# <ip> IP address
# <failures> number of failures
# <failtime> unix timestamp of the last failure
# <br> new line
# Values: TEXT Default:
#
message = Hi,<br>
The IP <ip> has just been banned by Fail2Ban after
<failures> attempts against <section>.<br>
Regards,<br>
Fail2Ban
# You can define a new section for each log file to check for
# password failure. Each section has to define the following
# options: logfile, fwban, fwunban, timeregex, timepattern,
# failregex.
[Apache]
# Option: enabled
# Notes.: enable monitoring for this section.
# Values: [true | false] Default: false
#
enabled = false
# 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 = [[]client (?P<host>\S*)[]] user .*(?:: authentication failure|not found)
[VSFTPD]
# Option: enabled
# Notes.: enable monitoring for this section.
# Values: [true | false] Default: false
#
enabled = false
# Option: logfile
# Notes.: logfile to monitor.
# Values: FILE Default: /var/log/secure
#
logfile = /var/log/vsftpd.log
# Option: port
# Notes.: specifies port to monitor
# Values: [ NUM | STRING ] Default:
#
port = ftp
# 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 = vsftpd: \(pam_unix\) authentication failure; .* rhost=(?P<host>\S+)
[SSH]
# Option: enabled
# Notes.: enable monitoring for this section.
# Values: [true | false] Default: true
#
enabled = true
# Option: logfile
# Notes.: logfile to monitor.
# Values: FILE Default: /var/log/secure
#
logfile = /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*)
+370
View File
@@ -0,0 +1,370 @@
# Fail2Ban configuration file
#
# $Revision$
#
# 2005.06.21 modified for readability Iain Lea iain@bricbrac.de
[DEFAULT]
# Option: background
# Notes.: start fail2ban as a daemon. Output is redirect to logfile.
# Values: [true | false] Default: false
#
background = false
# Option: locale
# Notes.: global (cannot be redefined per section) locale to use for
# timestamp pattern matching by changing LC_TIME for
# fail2ban process. Empty entry sets locale to default one
# (usually specified by LC_ALL environment variable).
# Values: LOCALE Default:
#
locale =
# Option: logtargets
# Notes.: log targets. Space separated list of logging targets.
# Values: STDERR SYSLOG file Default: /var/log/fail2ban.log
#
logtargets = /var/log/fail2ban.log
# Option: syslog-target
# Notes.: where to find syslog facility if logtarget SYSLOG.
# Values: SOCKET HOST HOST:PORT Default: /dev/log
#
syslog-target = /dev/log
# Option: syslog-facility
# Notes.: which syslog facility to use if logtarget SYSLOG.
# Values: NUM Default: 1
#
syslog-facility = 1
# Option: pidlock
# Notes.: path of the PID lock file (must be able to write to file).
# Values: FILE Default: /var/run/fail2ban.pid
#
pidlock = /var/run/fail2ban.pid
# Option: maxfailures
# Notes.: number of failures before IP gets banned.
# Values: NUM Default: 5
#
maxfailures = 5
# Option: bantime
# Notes.: number of seconds an IP will be banned. If set to a negative
# value, IP will never be unbanned (permanent banning).
# Values: NUM Default: 600
#
bantime = 600
# Option: findtime
# Notes.: lifetime in seconds of a "failed" log entry.
# Values: NUM Default: 600
#
findtime = 600
# Option: ignoreip
# 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:
#
ignoreip =
# Option: cmdstart
# Notes.: command executed once at the start of Fail2Ban
# Values: CMD Default:
#
cmdstart =
# Option: cmdend
# Notes.: command executed once at the end of Fail2Ban.
# Values: CMD Default:
#
cmdend =
# Option: polltime
# Notes.: number of seconds fail2ban sleeps between iterations.
# Values: NUM Default: 1
#
polltime = 1
# Option: reinittime
# Notes.: minimal number of seconds between the re-initialization of
# firewalls due to external changes in their rules (see fwcheck)
# Values: NUM Default: 100
#
reinittime = 10
# Option: maxreinits
# Notes.: maximal number of re-initialization of firewalls due to external
# changes. -1 stays for infinite, so only reinittime is of importance
# Values: NUM Default: -1
#
maxreinits = -1
# NOTE: Interpolations
#
# fwstart, as well as fwend, fwcheck, fwban, fwunban, use interpolations
# so %(__name__)s will be substituted by a name of each section
# (unless the option is overriden in a section).
# If you are going to use interpolations in your setup, please make
# sure that you specified options port and protocol (which also has
# an option in DEFAULT).
#
# Option: protocol
# Notes.: internally used by config reader for interpolations.
# Values: [ tcp | udp | icmp | all ] Default: tcp
#
protocol = tcp
# Option: fwstart
# Notes.: command executed once at the start of Fail2Ban.
# Values: CMD Default:
#
fwstart = iptables -N fail2ban-%(__name__)s
iptables -A fail2ban-%(__name__)s -j RETURN
iptables -I INPUT -p %(protocol)s --dport %(port)s -j fail2ban-%(__name__)s
# Option: fwend
# Notes.: command executed once at the end of Fail2Ban
# Values: CMD Default:
#
fwend = iptables -D INPUT -p %(protocol)s --dport %(port)s -j fail2ban-%(__name__)s
iptables -F fail2ban-%(__name__)s
iptables -X fail2ban-%(__name__)s
# Option: fwcheck
# Notes.: command executed once before each fwban command
# Values: CMD Default:
#
fwcheck = iptables -L INPUT | grep -q fail2ban-%(__name__)s
# 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
#
fwban = iptables -I fail2ban-%(__name__)s 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
#
fwunban = iptables -D fail2ban-%(__name__)s -s <ip> -j DROP
[MAIL]
# Option: enabled
# Notes.: enable mail notification when banning an IP address.
# Values: [true | false] Default: false
#
enabled = false
# Option: host
# Notes.: host running the mail server.
# Values: STR Default: localhost
#
host = localhost
# Option: port
# Notes.: port of the mail server.
# Values: INT Default: 25
#
port = 25
# Option: user
# Notes.: the username for smtp-server if authentification is required.
# if user is empty, no authentification is done.
# Values: STR Default:
#
user =
# Option: password
# Notes.: the smtp-user's password if authentification is required.
# Values: STR Default:
#
password =
# Option: from
# Notes.: e-mail address of the sender.
# Values: MAIL Default: fail2ban
#
from = fail2ban
# Option: to
# Notes.: e-mail addresses of the receiver. Addresses are space
# separated.
# Values: MAIL Default: root
#
to = root
# Option: localtime
# Notes.: report local time (including timezone) or GMT
# Values: [true | false] Default: false
#
localtime = true
# Option: subject
# Notes.: subject of the e-mail.
# Tags: <section> active section (eg ssh, apache, etc)
# <ip> IP address
# <failures> number of failures
# <failtime> unix timestamp of the last failure
# Values: TEXT Default: [Fail2Ban] <section>: Banned <ip>
#
subject = [Fail2Ban] <section>: Banned <ip>
# Option: message
# Notes.: message of the e-mail.
# Tags: <section> active section (eg ssh, apache, etc)
# <ip> IP address
# <failures> number of failures
# <failtime> unix timestamp of the last failure
# <br> new line
# Values: TEXT Default:
#
message = Hi,<br>
The IP <ip> has just been banned by Fail2Ban after
<failures> attempts against <section>.<br>
Regards,<br>
Fail2Ban
# You can define a new section for each log file to check for
# password failure. Each section has to define the following
# options: logfile, fwban, fwunban, timeregex, timepattern,
# failregex.
[Apache]
# Option: enabled
# Notes.: enable monitoring for this section.
# Values: [true | false] Default: false
#
enabled = false
# Option: logfile
# Notes.: logfile to monitor.
# Values: FILE Default: /var/log/httpd/access_log
#
logfile = /var/log/httpd/access_log
# Option: port
# Notes.: specifies port to monitor
# Values: [ NUM | STRING ] Default:
#
port = http
# 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 = [[]client (?P<host>\S*)[]] user .*(?:: authentication failure|not found)
[VSFTPD]
# Option: enabled
# Notes.: enable monitoring for this section.
# Values: [true | false] Default: false
#
enabled = false
# Option: logfile
# Notes.: logfile to monitor.
# Values: FILE Default: /var/log/secure
#
logfile = /var/log/vsftpd.log
# Option: port
# Notes.: specifies port to monitor
# Values: [ NUM | STRING ] Default:
#
port = ftp
# 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 = vsftpd: \(pam_unix\) authentication failure; .* rhost=(?P<host>\S+)
[SSH]
# Option: enabled
# Notes.: enable monitoring for this section.
# Values: [true | false] Default: true
#
enabled = true
# Option: logfile
# Notes.: logfile to monitor.
# Values: FILE Default: /var/log/secure
#
logfile = /var/log/secure
# Option: port
# Notes.: specifies port to monitor
# Values: [ NUM | STRING ] Default:
#
port = ssh
# 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*)
+324
View File
@@ -0,0 +1,324 @@
# Fail2Ban configuration file
#
# $Revision$
#
# 2005.06.21 modified for readability Iain Lea iain@bricbrac.de
[DEFAULT]
# Option: background
# Notes.: start fail2ban as a daemon. Output is redirect to logfile.
# Values: [true | false] Default: false
#
background = false
# Option: locale
# Notes.: global (cannot be redefined per section) locale to use for
# timestamp pattern matching by changing LC_TIME for
# fail2ban process. Empty entry sets locale to default one
# (usually specified by LC_ALL environment variable).
# Values: LOCALE Default:
#
locale =
# Option: logtargets
# Notes.: log targets. Space separated list of logging targets.
# Values: STDERR SYSLOG file Default: /var/log/fail2ban.log
#
logtargets = /var/log/fail2ban.log
# Option: syslog-target
# Notes.: where to find syslog facility if logtarget SYSLOG.
# Values: SOCKET HOST HOST:PORT Default: /dev/log
#
syslog-target = /dev/log
# Option: syslog-facility
# Notes.: which syslog facility to use if logtarget SYSLOG.
# Values: NUM Default: 1
#
syslog-facility = 1
# Option: pidlock
# Notes.: path of the PID lock file (must be able to write to file).
# Values: FILE Default: /var/run/fail2ban.pid
#
pidlock = /var/run/fail2ban.pid
# Option: maxfailures
# Notes.: number of failures before IP gets banned.
# Values: NUM Default: 5
#
maxfailures = 5
# Option: bantime
# Notes.: number of seconds an IP will be banned. If set to a negative
# value, IP will never be unbanned (permanent banning).
# Values: NUM Default: 600
#
bantime = 600
# Option: findtime
# Notes.: lifetime in seconds of a "failed" log entry.
# Values: NUM Default: 600
#
findtime = 600
# Option: ignoreip
# 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:
#
ignoreip =
# Option: cmdstart
# Notes.: command executed once at the start of Fail2Ban
# Values: CMD Default:
#
cmdstart =
# Option: cmdend
# Notes.: command executed once at the end of Fail2Ban.
# Values: CMD Default:
#
cmdend =
# Option: polltime
# Notes.: number of seconds fail2ban sleeps between iterations.
# Values: NUM Default: 1
#
polltime = 1
# Option: reinittime
# Notes.: minimal number of seconds between the re-initialization of
# firewalls due to external changes in their rules (see fwcheck)
# Values: NUM Default: 100
#
reinittime = 10
# Option: maxreinits
# Notes.: maximal number of re-initialization of firewalls due to external
# changes. -1 stays for infinite, so only reinittime is of importance
# Values: NUM Default: -1
#
maxreinits = -1
# NOTE: Interpolations
#
# fwstart, as well as fwend, fwcheck, fwban, fwunban, use interpolations
# so %(__name__)s will be substituted by a name of each section
# (unless the option is overriden in a section).
# If you are going to use interpolations in your setup, please make
# sure that you specified options port and protocol (which also has
# an option in DEFAULT).
#
# 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
#
fwban = shorewall drop <ip>
# 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
#
fwunban = shorewall allow <ip>
[MAIL]
# Option: enabled
# Notes.: enable mail notification when banning an IP address.
# Values: [true | false] Default: false
#
enabled = false
# Option: host
# Notes.: host running the mail server.
# Values: STR Default: localhost
#
host = localhost
# Option: port
# Notes.: port of the mail server.
# Values: INT Default: 25
#
port = 25
# Option: user
# Notes.: the username for smtp-server if authentification is required.
# if user is empty, no authentification is done.
# Values: STR Default:
#
user =
# Option: password
# Notes.: the smtp-user's password if authentification is required.
# Values: STR Default:
#
password =
# Option: from
# Notes.: e-mail address of the sender.
# Values: MAIL Default: fail2ban
#
from = fail2ban
# Option: to
# Notes.: e-mail addresses of the receiver. Addresses are space
# separated.
# Values: MAIL Default: root
#
to = root
# Option: localtime
# Notes.: report local time (including timezone) or GMT
# Values: [true | false] Default: false
#
localtime = true
# Option: subject
# Notes.: subject of the e-mail.
# Tags: <section> active section (eg ssh, apache, etc)
# <ip> IP address
# <failures> number of failures
# <failtime> unix timestamp of the last failure
# Values: TEXT Default: [Fail2Ban] <section>: Banned <ip>
#
subject = [Fail2Ban] <section>: Banned <ip>
# Option: message
# Notes.: message of the e-mail.
# Tags: <section> active section (eg ssh, apache, etc)
# <ip> IP address
# <failures> number of failures
# <failtime> unix timestamp of the last failure
# <br> new line
# Values: TEXT Default:
#
message = Hi,<br>
The IP <ip> has just been banned by Fail2Ban after
<failures> attempts against <section>.<br>
Regards,<br>
Fail2Ban
# You can define a new section for each log file to check for
# password failure. Each section has to define the following
# options: logfile, fwban, fwunban, timeregex, timepattern,
# failregex.
[Apache]
# Option: enabled
# Notes.: enable monitoring for this section.
# Values: [true | false] Default: false
#
enabled = false
# 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 = [[]client (?P<host>\S*)[]] user .*(?:: authentication failure|not found)
[VSFTPD]
# Option: enabled
# Notes.: enable monitoring for this section.
# Values: [true | false] Default: false
#
enabled = false
# Option: logfile
# Notes.: logfile to monitor.
# Values: FILE Default: /var/log/secure
#
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 = vsftpd: \(pam_unix\) authentication failure; .* rhost=(?P<host>\S+)
[SSH]
# Option: enabled
# Notes.: enable monitoring for this section.
# Values: [true | false] Default: true
#
enabled = true
# Option: logfile
# Notes.: logfile to monitor.
# Values: FILE Default: /var/log/secure
#
logfile = /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*)
+23
View File
@@ -0,0 +1,23 @@
# 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$
# Command line options for Fail2Ban. Refer to "fail2ban -h" for
# valid options.
FAIL2BAN_OPTS="-v"
+50
View File
@@ -0,0 +1,50 @@
#!/sbin/runscript
# 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: Sireyessire, Cyril Jaquier
#
# $Revision$
opts="start stop restart showlog"
FAIL2BAN="/usr/bin/fail2ban"
depend() {
need net
need logger
after iptables
}
start() {
ebegin "Starting fail2ban"
${FAIL2BAN} -b ${FAIL2BAN_OPTS} > /dev/null
eend $? "Failed to start fail2ban"
}
stop() {
ebegin "Stopping fail2ban"
${FAIL2BAN} -k > /dev/null
eend $? "Failed to stop fail2ban"
}
zap() {
rm /var/run/fail2ban.pid
}
showlog(){
less /var/log/fail2ban.log
}
+78
View File
@@ -0,0 +1,78 @@
#!/bin/bash
#
# fail2ban
#
# chkconfig: 345 91 9
# description: if many unsuccessfull login attempts from some ip address \
# during a short period happen, this address is banned \
# by the firewall
#
# Author: Andrey G. Grozin
#
# $Revision$
# Source function library.
. /etc/init.d/functions
# Get config.
. /etc/sysconfig/network
# Check that networking is up.
[ "${NETWORKING}" = "no" ] && exit 0
[ -f /etc/fail2ban.conf ] || exit 0
FAIL2BAN="/usr/bin/fail2ban"
PIDFILE="/var/run/fail2ban.pid"
RETVAL=0
start() {
echo -n $"Starting fail2ban: "
"${FAIL2BAN}" -b > /dev/null
RETVAL=$?
echo
}
stop() {
if [ -f "${PIDFILE}" ]; then
echo -n $"Stopping fail2ban: "
"${FAIL2BAN}" -k > /dev/null
echo
fi
}
restart() {
stop
start
}
# See how we were called.
case "$1" in
start)
start
;;
stop)
stop
;;
status)
status fail2ban
RETVAL=$?
;;
reload)
restart
;;
restart)
restart
;;
condrestart)
if [ -f "${PIDFILE}" ]; then
restart
fi
;;
*)
echo $"Usage: $0 {start|stop|status|restart|condrestart}"
exit 1
;;
esac
exit $RETVAL
+25
View File
@@ -0,0 +1,25 @@
# 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"
+85
View File
@@ -0,0 +1,85 @@
# 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")
class ConfigReader:
""" This class allow the handling of the configuration options.
The DEFAULT section contains the global information about
Fail2Ban. Each other section is for a different log file.
"""
def __init__(self, confPath):
self.confPath = confPath
self.configParser = SafeConfigParser()
def openConf(self):
""" Opens the configuration file.
"""
self.configParser.read(self.confPath)
def getSections(self):
""" Returns all the sections present in the configuration
file except the DEFAULT and MAIL sections.
"""
sections = self.configParser.sections()
sections.remove("MAIL")
logSys.debug("Found sections: " + `sections`)
return sections
# 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 getLogOptions(self, sec, options):
""" Gets all the options of a given section. The options
are defined in the optionValues list.
"""
values = dict()
for option in options:
try:
if option[0] == "bool":
v = self.configParser.getboolean(sec, option[1])
elif option[0] == "int":
v = self.configParser.getint(sec, option[1])
else:
v = self.configParser.get(sec, option[1])
values[option[1]] = v
except NoOptionError:
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
+35 -138
View File
@@ -26,146 +26,43 @@ __date__ = "$Date$"
__copyright__ = "Copyright (c) 2004 Cyril Jaquier"
__license__ = "GPL"
import posix,sys,os
import string,re,time
import sys, traceback, logging
from firewall.iptables import Iptables
# Inserts our own modules path first in the list
# fix for bug #343821
sys.path.insert(1, "/usr/lib/fail2ban")
def checkForRoot():
""" Check for root user.
"""
uid = `posix.getuid()`
if uid == '0':
return True
else:
return False
# Now we can import our modules.
import fail2ban
from utils.pidlock import PIDLock
# start: To be removed
def executeCmd(cmd):
return #os.system(cmd)
# Get the instance of the logger.
logSys = logging.getLogger("fail2ban")
def unBanIP(ip):
iptables = 'iptables -D INPUT -i eth0 -s '+ip+' -j DROP'
executeCmd(iptables)
print iptables
# Get PID lock file instance
pidLock = PIDLock()
def banIP(ip):
iptables = 'iptables -I INPUT 1 -i eth0 -s '+ip+' -j DROP'
executeCmd(iptables)
print iptables
# end:
def checkForUnBan(banList, currentTime, banTime):
""" Check for user to remove from ban list.
"""
iterBanList = banList.iteritems()
for i in range(len(banList)):
element = iterBanList.next()
ip = element[0]
btime = element[1]
if btime < currentTime-banTime:
del banList[ip]
unBanIP(ip)
print '`->', currentTime
return banList
def checkForBan(retryList, banList, currentTime):
iterRetry = retryList.iteritems()
for i in range(len(retryList)):
element = iterRetry.next()
retry = element[1][0]
ip = element[0]
if element[1][0] > 2 and not banList.has_key(ip):
banList[ip] = currentTime
banIP(ip)
print '`->', currentTime
return banList
def flushBanList(banList):
iterBanList = banList.iteritems()
for i in range(len(banList)):
element = iterBanList.next()
ip = element[0]
unBanIP(ip)
def parseLogLine(line):
""" Match sshd failed password log
"""
if re.search("Failed password", line):
matchIP = re.search("(?:\d{1,3}\.){3}\d{1,3}", line)
return matchIP
if __name__ == "__main__":
# start: For object oriented testing
f = Iptables()
f.banIP('11', 1231)
f.banIP('13', 1232)
f.banIP('13', 1233)
f.unBanIP('11')
f.viewBanList()
f.flushBanList()
# end:
if not checkForRoot():
print "You must be root."
#sys.exit(-1)
logPath = './log-test/test'
banTime = 60
ignoreIPs = '127.0.0.1'
lastModTime = 0
banList = dict()
while True:
try:
currentTime = time.time()
banList = checkForUnBan(banList, currentTime, banTime)
try:
pwdFailStats = os.stat(logPath)
except OSError:
print "Unable to get stat on", logPath
sys.exit(-1)
if lastModTime == pwdFailStats.st_mtime:
time.sleep(1)
continue
print logPath, 'has been modified'
lastModTime = pwdFailStats.st_mtime
try:
pwdfail = open(logPath)
except OSError:
print "Unable to open", logPath
sys.exit(-1)
retryList = dict()
for line in pwdfail.readlines():
match = parseLogLine(line)
if match:
ip = match.group()
date = list(time.strptime(line[0:15], "%b %d %H:%M:%S"))
date[0] = time.gmtime()[0]
unixTime = time.mktime(date)
if unixTime < currentTime-banTime:
continue
if re.search(ip, ignoreIPs):
print 'Ignore ', ip
continue
print 'Found', ip, 'at', unixTime
if retryList.has_key(`ip`):
retryList[`ip`] = (retryList[`ip`][0]+1,unixTime)
else:
retryList[`ip`] = (1,unixTime)
pwdfail.close()
banList = checkForBan(retryList, banList, currentTime)
except KeyboardInterrupt:
print 'Restoring iptables...'
flushBanList(banList)
print 'Exiting...'
sys.exit(0)
# Handle all the unhandled exceptions
try:
# Start the application
fail2ban.main()
except SystemExit:
# We called sys.exit(). Nothing wrong so just pass
pass
except Exception, e:
# Print the exception data
(type, value, tb) = sys.exc_info()
tbStack = traceback.extract_tb(tb)
logSys.error("Fail2Ban got an unhandled exception and died.")
logSys.error("Type: " + `type.__name__` + "\n" +
"Value: " + `e.args` + "\n" +
"TB: " + `tbStack`)
# Try to clean up after ourselves
# just for extreme caution - wrapping with try
try:
fail2ban.restoreFwRules()
except Exception:
pass
# Remove the PID lock file. Should close #1239562
pidLock.remove()
logging.shutdown()
Executable
+554
View File
@@ -0,0 +1,554 @@
# 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
# Modified by: Yaroslav Halchenko (SYSLOG, findtime)
#
# $Revision$
__author__ = "Cyril Jaquier"
__version__ = "$Revision$"
__date__ = "$Date$"
__copyright__ = "Copyright (c) 2004 Cyril Jaquier"
__license__ = "GPL"
import time, sys, getopt, os, string, signal, logging, logging.handlers, \
copy, locale
from ConfigParser import *
from version import version
from firewall.firewall import Firewall
from logreader.logreader import LogReader
from confreader.configreader import ConfigReader
from utils.mail import Mail
from utils.pidlock import PIDLock
from utils.dns import *
from utils.process import *
# Get the instance of the logger.
logSys = logging.getLogger("fail2ban")
# Get PID lock file instance
pidLock = PIDLock()
# Global variables
logFwList = list()
conf = dict()
def dispUsage():
""" Prints Fail2Ban command line options and exits
"""
print "Usage: "+sys.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 " -c <FILE> read configuration file FILE"
print " -p <FILE> create PID lock in FILE"
print " -h display this help message"
print " -i <IP(s)> IP(s) to ignore"
print " -k kill a currently running instance"
print " -r <VALUE> allow a max of VALUE password failure [maxfailures]"
print " -t <TIME> ban IP for TIME seconds [bantime]"
print " -f <TIME> lifetime in seconds of failed entry [findtime]"
print " -v verbose. Use twice for greater effect"
print " -V print software version"
print
print "Report bugs to <lostcontrol@users.sourceforge.net>"
sys.exit(0)
def dispVersion():
""" Prints Fail2Ban version and exits
"""
print sys.argv[0]+" "+version
sys.exit(0)
def checkForRoot():
""" Check for root user.
"""
uid = `os.getuid()`
if uid == '0':
return True
else:
return False
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`)
killApp()
def setFwMustCheck(value):
""" Set the mustCheck value of the firewalls (True/False)
"""
for element in logFwList:
element[2].setMustCheck(value)
def initializeFwRules():
""" Initializes firewalls by running cmdstart and then
fwstart for each section
"""
# Execute global start command
executeCmd(conf["cmdstart"], conf["debug"])
# Execute start command of each section
for element in logFwList:
element[2].initialize(conf["debug"])
def reBan():
""" For each section asks the Firewall to reban known IPs
"""
for element in logFwList:
element[2].reBan(conf["debug"])
def restoreFwRules():
""" Flush the ban list
"""
logSys.warn("Restoring firewall rules...")
try:
for element in logFwList:
# Execute end command of each section
element[2].restore(conf["debug"])
# Execute global end command
executeCmd(conf["cmdend"], conf["debug"])
except ExternalError:
# nothing bad really - we can survive :-)
pass
def killApp():
""" Flush the ban list, remove the PID lock file and exit
nicely.
"""
# Restore Fw rules
restoreFwRules()
# Remove the PID lock
pidLock.remove()
logSys.info("Exiting...")
logging.shutdown()
sys.exit(0)
def getCmdLineOptions(optList):
""" Gets the command line options
"""
for opt in optList:
if opt[0] == "-v":
conf["verbose"] = conf["verbose"] + 1
if opt[0] == "-b":
conf["background"] = True
if opt[0] == "-d":
conf["debug"] = True
if opt[0] == "-t":
try:
conf["bantime"] = int(opt[1])
except ValueError:
logSys.warn("banTime must be an integer")
logSys.warn("Using default value")
if opt[0] == "-f":
try:
conf["findtime"] = int(opt[1])
except ValueError:
logSys.warn("findTime must be an integer")
logSys.warn("Using default value")
if opt[0] == "-i":
conf["ignoreip"] = opt[1]
if opt[0] == "-r":
conf["maxfailures"] = int(opt[1])
if opt[0] == "-p":
conf["pidlock"] = opt[1]
if opt[0] == "-k":
conf["kill"] = True
def main():
""" Fail2Ban main function
"""
# Add the default logging handler
stdout = logging.StreamHandler(sys.stdout)
logSys.addHandler(stdout)
# Default formatter
formatterstring='%(levelname)s: %(message)s'
formatter = logging.Formatter('%(asctime)s ' + formatterstring)
stdout.setFormatter(formatter)
conf["kill"] = False
conf["debug"] = False
conf["verbose"] = 0
conf["conffile"] = "/etc/fail2ban.conf"
# Reads the command line options.
try:
cmdOpts = 'hvVbdkc:t:i:r:p:'
cmdLongOpts = ['help', 'version']
optList, args = getopt.getopt(sys.argv[1:], cmdOpts, cmdLongOpts)
except getopt.GetoptError:
dispUsage()
# 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()
# Reads the config file and create a LogReader instance for
# each log file to check.
confReader = ConfigReader(conf["conffile"])
confReader.openConf()
# Options
optionValues = (["bool", "background", False],
["str", "logtargets", "/var/log/fail2ban.log"],
["str", "syslog-target", "/dev/log"],
["int", "syslog-facility", 1],
["str", "pidlock", "/var/run/fail2ban.pid"],
["str", "locale", ""],
["int", "maxfailures", 5],
["int", "bantime", 600],
["int", "findtime", 600],
["str", "ignoreip", ""],
["int", "polltime", 1],
["str", "cmdstart", ""],
["str", "cmdend", ""],
["int", "reinittime", 100],
["int", "maxreinits", 100])
# Gets global configuration options
conf.update(confReader.getLogOptions("DEFAULT", optionValues))
# Gets command line options
getCmdLineOptions(optList)
# PID lock
pidLock.setPath(conf["pidlock"])
# Set the LC_TIME with the user's default setting
try:
logSys.info("Setting LC_TIME locale option to '%s'"%conf["locale"])
locale.setlocale(locale.LC_TIME, conf["locale"])
except Exception:
logSys.error("Unable to set locale to '%s'"%conf["locale"])
sys.exit(-1)
# Now we can kill properly a running instance if needed
if conf["kill"]:
pid = pidLock.exists()
if pid:
killPID(int(pid))
logSys.warn("Killed Fail2Ban with PID "+pid)
sys.exit(0)
else:
logSys.error("No running Fail2Ban found")
sys.exit(-1)
# Start Fail2Ban in daemon mode
if conf["background"]:
retCode = createDaemon()
signal.signal(signal.SIGTERM, sigTERMhandler)
if not retCode:
logSys.error("Unable to start daemon")
sys.exit(-1)
# Process some options
# First setup Log targets
# Bug fix for #1234699
os.umask(0077)
for target in conf["logtargets"].split():
# target formatter
# By default global formatter is taken. Is different for SYSLOG
tformatter = formatter
if target == "STDERR":
hdlr = logging.StreamHandler(sys.stderr)
elif target == "SYSLOG":
# SYSLOG target can be either
# a socket (file, so it starts with /)
# or hostname
# or hostname:port
syslogtargets = re.findall("(/[\w/]*)|([^/ ][^: ]*)(:(\d+)){,1}",
conf["syslog-target"])
# we are waiting for a single match
syslogtargets = syslogtargets[0]
# assign facility if it was defined
if conf["syslog-facility"] < 0:
facility = handlers.SysLogHandler.LOG_USER
else:
facility = conf["syslog-facility"]
if len(syslogtargets) == 0: # everything default
hdlr = logging.handlers.SysLogHandler()
else:
if not (syslogtargets[0] == ""): # got socket
syslogtarget = syslogtargets[0]
else: # got hostname and maybe a port
if syslogtargets[3] == "": # no port specified
port = 514
else:
port = int(syslogtargets[3])
syslogtarget = (syslogtargets[1], port)
hdlr = logging.handlers.SysLogHandler(syslogtarget, facility)
tformatter = logging.Formatter("%(asctime)s %(name)s " +
formatterstring, "%b %e %T");
else:
# Target should be a file
try:
open(target, "a")
hdlr = logging.FileHandler(target)
except IOError:
logSys.error("Unable to log to " + target)
continue
# Set formatter and add handler to logger
hdlr.setFormatter(tformatter)
logSys.addHandler(hdlr)
# Verbose level
if conf["verbose"]:
logSys.warn("Verbose level is "+`conf["verbose"]`)
if conf["verbose"] == 1:
logSys.setLevel(logging.INFO)
elif conf["verbose"] > 1:
logSys.setLevel(logging.DEBUG)
if conf["verbose"] > 2:
formatterstring = ('%(levelname)s: [%(filename)s (%(lineno)d)] ' +
'%(message)s')
formatter = logging.Formatter("%(asctime)s " + formatterstring)
stdout.setFormatter(formatter)
# Debug mode. Should only be used by developers
if conf["debug"]:
logSys.warn("DEBUG MODE: FIREWALL COMMANDS ARE _NOT_ EXECUTED BUT " +
"ONLY DISPLAYED IN THE LOG MESSAGES")
# Ignores IP list
# and filter out empty entries. Otherwise
# WARNING: is not a valid IP address
ignoreIPList = filter(None, conf["ignoreip"].split(' '))
# Checks for root user. This is necessary because log files
# are owned by root and firewall needs root access.
if not checkForRoot():
logSys.error("You must be root")
if not conf["debug"]:
sys.exit(-1)
# Checks that no instance of Fail2Ban is currently running.
pid = pidLock.exists()
if pid:
logSys.error("Fail2Ban already running with PID "+pid)
sys.exit(-1)
else:
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("MaxFailure is " + `conf["maxfailures"]`)
# Options
optionValues = (["bool", "enabled", False],
["str", "host", "localhost"],
["int", "port", "25"],
["str", "from", "root"],
["str", "to", "root"],
["str", "user", ''],
["str", "password", ''],
["bool", "localtime", False],
["str", "subject", "[Fail2Ban] Banned <ip>"],
["str", "message", "Fail2Ban notification"])
# Gets global configuration options
mailConf = confReader.getLogOptions("MAIL", optionValues)
# Create mailer if enabled
if mailConf["enabled"]:
logSys.debug("Mail enabled")
mail = Mail(mailConf["host"], mailConf["port"])
mail.setFromAddr(mailConf["from"])
mail.setUser(mailConf["user"])
mail.setPassword(mailConf["password"])
mail.setToAddr(mailConf["to"])
mail.setLocalTimeFlag(mailConf["localtime"])
logSys.debug("to: " + mailConf["to"] + " from: " + mailConf["from"])
# Options
optionValues = (["bool", "enabled", False],
["str", "logfile", "/dev/null"],
["int", "maxfailures", conf["maxfailures"]],
["int", "bantime", conf["bantime"]],
["int", "findtime", conf["findtime"]],
["str", "timeregex", ""],
["str", "timepattern", ""],
["str", "failregex", ""],
["str", "fwstart", ""],
["str", "fwend", ""],
["str", "fwban", ""],
["str", "fwunban", ""],
["str", "fwcheck", ""])
logSys.info("Fail2Ban v" + version + " is running")
# Gets the options of each sections
for t in confReader.getSections():
l = confReader.getLogOptions(t, optionValues)
if l["enabled"]:
# Creates a logreader object
lObj = LogReader(l["logfile"], l["timeregex"], l["timepattern"],
l["failregex"], l["maxfailures"], l["findtime"])
# Creates a firewall object
fObj = Firewall(l["fwstart"], l["fwend"], l["fwban"], l["fwunban"],
l["fwcheck"], l["bantime"])
# "Name" the firewall
fObj.setSection(t)
# Links them into a list. I'm not really happy
# with this :/
logFwList.append([t, lObj, fObj, dict(), l])
# We add 127.0.0.1 to the ignore list has we do not want
# to be ban ourself.
for element in logFwList:
element[1].addIgnoreIP("127.0.0.1")
while len(ignoreIPList) > 0:
ip = ignoreIPList.pop()
# Bug fix for #1239557
if isValidIP(ip):
for element in logFwList:
element[1].addIgnoreIP(ip)
else:
logSys.warn(ip + " is not a valid IP address")
# Startup loop -- necessary to avoid crash if it takes time for iptables
# to startup. To avoid introduction of new config options, reusing
# maxreinits and polltime.
reinits = 0
while True:
try:
initializeFwRules()
break
except ExternalError, e:
reinits += 1
logSys.warn(e)
if conf["maxreinits"] < 0 or (reinits < conf["maxreinits"]):
logSys.warn("#%d attempt to initialize the firewalls" % reinits)
else:
logSys.error("Exiting: Too many attempts to initialize the " +
"firewall")
killApp()
time.sleep(conf["polltime"])
# try to reinit once if it fails immediately
lastReinitTime = time.time() - conf["reinittime"] - 1
reinits = 0
# Main loop
while True:
try:
sys.stdout.flush()
sys.stderr.flush()
# Checks if some IP have to be remove from ban
# list.
for element in logFwList:
element[2].checkForUnBan(conf["debug"])
# If the log file has not been modified since the
# last time, we sleep for 1 second. This is active
# polling so not very effective.
modList = list()
for element in logFwList:
if element[1].isModified():
modList.append(element)
if len(modList) == 0:
time.sleep(conf["polltime"])
continue
# Gets the failure list from the log file. For a given IP,
# takes only the service which has the most password failures.
for element in modList:
e = element[1].getFailures()
for key in e.iterkeys():
if element[3].has_key(key):
element[3][key] = (element[3][key][0] + e[key][0],
e[key][1])
else:
element[3][key] = (e[key][0], e[key][1])
# Remove the oldest failure attempts from the global list.
# We iterate the failure list and ban IP that make
# *retryAllowed* login failures.
unixTime = time.time()
for element in logFwList:
fails = element[3].copy()
findTime = element[1].getFindTime()
for attempt in fails:
failTime = fails[attempt][1]
if failTime < unixTime - findTime:
del element[3][attempt]
elif fails[attempt][0] >= element[1].getMaxRetry():
aInfo = {"section": element[0],
"ip": attempt,
"failures": element[3][attempt][0],
"failtime": failTime}
logSys.info(element[0] + ": " + aInfo["ip"] +
" has " + `aInfo["failures"]` +
" login failure(s). Banned.")
element[2].addBanIP(aInfo, conf["debug"])
# Send a mail notification
if 'mail' in locals():
mail.sendmail(mailConf["subject"],
mailConf["message"], aInfo)
del element[3][attempt]
except ExternalError, e:
# Something wrong while dealing with Iptables.
# May be chain got removed?
reinits += 1
logSys.error(e)
if ((unixTime - lastReinitTime > conf["reinittime"]) and
((conf["maxreinits"] < 0) or (reinits < conf["maxreinits"]))):
logSys.warn("#%d reinitialization of firewalls"%reinits)
lastReinitTime = unixTime
else:
logSys.error("Exiting: reinits follow too often, or too many " +
"reinit attempts")
killApp()
# We already failed runCheck so disable it until
# restoring a safe state
setFwMustCheck(False)
# save firewalls to keep a list of IPs for rebanning
logFwListCopy = copy.deepcopy(logFwList)
try:
# restore as much as possible
restoreFwRules()
# reinitialize all the chains
initializeFwRules()
# restore the lists of baned IPs
logFwList.__init__(logFwListCopy)
# reBan known IPs
reBan()
# Now we can enable the runCheck test again
setFwMustCheck(True)
except ExternalError:
raise ExternalError("Big Oops happened: situation is out of " +
"control. Something is wrong with your " +
"setup. Please check your settings")
except KeyboardInterrupt:
# When the user press <ctrl>+<c> we exit nicely.
killApp()
+161 -21
View File
@@ -24,29 +24,169 @@ __date__ = "$Date$"
__copyright__ = "Copyright (c) 2004 Cyril Jaquier"
__license__ = "GPL"
import time, os, logging, re
from utils.process import executeCmd
from utils.strings import replaceTag
# unfortunately but I have to bring ExternalError in especially for
# flushBanList: if one of IPs got flushed manually outside or something, we
# might endup with not "full" flush unless we handle exception within the loop
from utils.process import ExternalError
# Gets the instance of the logger.
logSys = logging.getLogger("fail2ban")
class Firewall:
""" Manages the ban list and executes the command that ban
the IP.
"""
banList = dict()
def addBanIP(self, ip, time):
self.banList[ip] = time
def delBanIP(self, ip):
del self.banList[ip]
def flushBanList(self):
iterBanList = self.banList.iteritems()
for i in range(len(self.banList)):
element = iterBanList.next()
ip = element[0]
self.unBanIP(ip)
def executeCmd(self, cmd):
return #os.system(cmd)
def __init__(self, startRule, endRule, banRule, unBanRule, checkRule,
banTime):
self.banRule = banRule
self.unBanRule = unBanRule
self.checkRule = checkRule
self.startRule = startRule
self.endRule = endRule
self.banTime = banTime
self.banList = dict()
self.section = ""
self.mustCheck = True
def setSection(self, section):
""" Set optional section name for clarify of logging
"""
self.section = section
def getMustCheck(self):
""" Return true if the runCheck test is executed
"""
return self.mustCheck
def setMustCheck(self, value):
""" Enable or disable the execution of runCheck test
"""
self.mustCheck = value
def initialize(self, debug):
logSys.debug("%s: Initialize firewall rules"%self.section)
executeCmd(self.startRule, debug)
def restore(self, debug):
logSys.debug("%s: Restore firewall rules"%self.section)
try:
self.flushBanList(debug)
executeCmd(self.endRule, debug)
except ExternalError:
pass
def addBanIP(self, aInfo, debug):
""" Bans an IP.
"""
ip = aInfo["ip"]
if not self.inBanList(ip):
crtTime = time.time()
if self.banTime < 0:
banMsg = "Ban (permanent)"
else:
banMsg = "Ban (%d s)"%self.banTime
logSys.warn("%s: %s "%(self.section, banMsg) + ip)
self.banList[ip] = crtTime
aInfo["bantime"] = crtTime
self.runCheck(debug)
cmd = self.banIP(aInfo)
if executeCmd(cmd, debug):
raise ExternalError("Firewall: execution of fwban command " +
"'%s' failed"%cmd)
else:
self.runCheck(debug)
logSys.error("%s: "%self.section+ip+" already in ban list")
def delBanIP(self, aInfo, debug):
""" Unban an IP.
"""
ip = aInfo["ip"]
if self.inBanList(ip):
logSys.warn("%s: Unban "%self.section + ip)
del self.banList[ip]
self.runCheck(debug)
executeCmd(self.unBanIP(aInfo), debug)
else:
logSys.error("%s: "%self.section+ip+" not in ban list")
def reBan(self, debug):
""" Re-Bans known IPs.
TODO: implement "failures" and "failtime"
"""
for ip in self.banList:
aInfo = {"ip": ip,
"bantime":self.banList[ip]}
logSys.warn("%s: ReBan "%self.section + ip)
# next piece is similar to the on in addBanIp
# so might be one more function will not hurt
self.runCheck(debug)
executeCmd(self.banIP(aInfo), debug)
def inBanList(self, ip):
""" Checks if IP is in ban list.
"""
return self.banList.has_key(ip)
def runCheck(self, debug):
""" Runs fwcheck command and throws an exception if it returns non-0
result
"""
if self.mustCheck:
executeCmd(self.checkRule, debug)
else:
return None
def checkForUnBan(self, debug):
""" Check for IP to remove from ban list. If banTime is smaller than
zero, IP will be never removed.
"""
if self.banTime < 0:
# Permanent banning
return
banListTemp = self.banList.copy()
for element in banListTemp.iteritems():
btime = element[1]
if btime < time.time()-self.banTime:
aInfo = {"ip": element[0],
"bantime": btime,
"unbantime": time.time()}
self.delBanIP(aInfo, debug)
def flushBanList(self, debug):
""" Flushes the ban list and of course the firewall rules.
Called when fail2ban exits.
"""
banListTemp = self.banList.copy()
for element in banListTemp.iteritems():
aInfo = {"ip": element[0],
"bantime": element[1],
"unbantime": time.time()}
try:
self.delBanIP(aInfo, debug)
except ExternalError:
# we must let it fail here in the loop, or we don't
# flush properly
pass
def banIP(self, aInfo):
""" Returns query to ban IP.
"""
query = replaceTag(self.banRule, aInfo)
return query
def unBanIP(self, aInfo):
""" Returns query to unban IP.
"""
query = replaceTag(self.unBanRule, aInfo)
return query
def viewBanList(self):
iterBanList = self.banList.iteritems()
for i in range(len(self.banList)):
element = iterBanList.next()
""" Prints the ban list on screen. Usefull for debugging.
"""
for element in self.banList.iteritems():
print element
+108
View File
@@ -0,0 +1,108 @@
[Wed Mar 31 15:11:28 2005] [error] [client www.google.ch] user cyril: authentication failure for "/phpinfo": Password Mismatch
[Mon Jan 03 05:02:15 2005] [error] [client 81.83.248.17] File does not exist: /var/www/jaquier.dyndns.org/htdocs/msadc
[Mon Jan 03 05:02:20 2005] [error] [client 81.83.248.17] File does not exist: /var/www/jaquier.dyndns.org/htdocs/msadc
[Mon Jan 03 05:02:20 2005] [error] [client 81.83.248.17] File does not exist: /var/www/jaquier.dyndns.org/htdocs/msadc
[Mon Jan 03 05:02:21 2005] [error] [client 81.83.248.17] File does not exist: /var/www/jaquier.dyndns.org/htdocs/msadc
[Mon Jan 03 05:02:22 2005] [error] [client 81.83.248.17] File does not exist: /var/www/jaquier.dyndns.org/htdocs/msadc
[Mon Jan 03 05:02:22 2005] [error] [client 81.83.248.17] File does not exist: /var/www/jaquier.dyndns.org/htdocs/msadc
[Mon Jan 03 05:02:22 2005] [error] [client 81.83.248.17] File does not exist: /var/www/jaquier.dyndns.org/htdocs/msadc
[Mon Jan 03 05:02:22 2005] [error] [client 81.83.248.17] File does not exist: /var/www/jaquier.dyndns.org/htdocs/\xe0
[Mon Jan 03 05:02:23 2005] [error] [client 81.83.248.17] File does not exist: /var/www/jaquier.dyndns.org/htdocs/msdac
[Mon Jan 03 05:02:23 2005] [error] [client 81.83.248.17] File does not exist: /var/www/jaquier.dyndns.org/htdocs/msdac
[Mon Jan 03 05:02:24 2005] [error] [client 81.83.248.17] File does not exist: /var/www/jaquier.dyndns.org/htdocs/PBServer
[Mon Jan 03 05:02:24 2005] [error] [client 81.83.248.17] File does not exist: /var/www/jaquier.dyndns.org/htdocs/PBServer
[Mon Jan 03 05:02:27 2005] [error] [client 81.83.248.17] File does not exist: /var/www/jaquier.dyndns.org/htdocs/Rpc
[Mon Jan 03 05:02:27 2005] [error] [client 81.83.248.17] File does not exist: /var/www/jaquier.dyndns.org/htdocs/Rpc
[Mon Jan 03 05:02:27 2005] [error] [client 81.83.248.17] File does not exist: /var/www/jaquier.dyndns.org/htdocs/samples
[Mon Jan 03 05:02:27 2005] [error] [client 81.83.248.17] File does not exist: /var/www/jaquier.dyndns.org/htdocs/samples
[Mon Jan 03 05:02:28 2005] [error] [client 81.83.248.17] File does not exist: /var/www/jaquier.dyndns.org/htdocs/scripts..\xc1\x9c..
[Mon Jan 03 05:02:28 2005] [error] [client 81.83.248.17] File does not exist: /var/www/jaquier.dyndns.org/htdocs/scripts
[Mon Jan 03 05:02:28 2005] [error] [client 81.83.248.17] File does not exist: /var/www/jaquier.dyndns.org/htdocs/scripts
[Mon Jan 03 05:02:28 2005] [error] [client 81.83.248.17] File does not exist: /var/www/jaquier.dyndns.org/htdocs/scripts
[Mon Jan 03 05:02:32 2005] [error] [client 81.83.248.17] File does not exist: /var/www/jaquier.dyndns.org/htdocs/scripts
[Mon Jan 03 05:02:32 2005] [error] [client 81.83.248.17] File does not exist: /var/www/jaquier.dyndns.org/htdocs/scripts
[Mon Jan 03 05:02:33 2005] [error] [client 81.83.248.17] File does not exist: /var/www/jaquier.dyndns.org/htdocs/scripts
[Mon Jan 03 05:02:33 2005] [error] [client 81.83.248.17] File does not exist: /var/www/jaquier.dyndns.org/htdocs/scripts
[Mon Jan 03 05:02:33 2005] [error] [client 81.83.248.17] File does not exist: /var/www/jaquier.dyndns.org/htdocs/scripts
[Mon Jan 03 05:02:34 2005] [error] [client 81.83.248.17] File does not exist: /var/www/jaquier.dyndns.org/htdocs/scripts
[Mon Jan 03 05:02:34 2005] [error] [client 81.83.248.17] File does not exist: /var/www/jaquier.dyndns.org/htdocs/scripts
[Mon Jan 03 05:02:38 2005] [error] [client 81.83.248.17] File does not exist: /var/www/jaquier.dyndns.org/htdocs/scripts
[Mon Jan 03 05:02:38 2005] [error] [client 81.83.248.17] File does not exist: /var/www/jaquier.dyndns.org/htdocs/scripts
[Mon Jan 03 05:02:38 2005] [error] [client 81.83.248.17] File does not exist: /var/www/jaquier.dyndns.org/htdocs/scripts
[Mon Jan 03 05:02:38 2005] [error] [client 81.83.248.17] File does not exist: /var/www/jaquier.dyndns.org/htdocs/scripts
[Mon Jan 03 05:02:39 2005] [error] [client 81.83.248.17] File does not exist: /var/www/jaquier.dyndns.org/htdocs/scripts
[Mon Jan 03 05:02:39 2005] [error] [client 81.83.248.17] File does not exist: /var/www/jaquier.dyndns.org/htdocs/scripts
[Mon Jan 03 11:08:29 2005] [error] [client 128.178.150.127] File does not exist: /var/www/jaquier.dyndns.org/htdocs/favicon.ico
[Mon Jan 03 20:08:52 2005] [error] [client 83.76.202.195] File does not exist: /var/www/jaquier.dyndns.org/htdocs/favicon.ico
[Tue Jan 04 15:19:50 2005] [error] [client 213.221.138.70] File does not exist: /var/www/jaquier.dyndns.org/htdocs/favicon.ico
[Tue Jan 04 15:19:55 2005] [error] [client 213.221.138.70] File does not exist: /var/www/jaquier.dyndns.org/htdocs/favicon.ico
[Tue Jan 04 15:20:01 2005] [error] [client 213.221.138.70] File does not exist: /var/www/jaquier.dyndns.org/htdocs/favicon.ico
[Tue Jan 04 15:20:05 2005] [error] [client 213.221.138.70] File does not exist: /var/www/jaquier.dyndns.org/htdocs/favicon.ico
[Tue Jan 04 15:20:08 2005] [error] [client 213.221.138.70] File does not exist: /var/www/jaquier.dyndns.org/htdocs/favicon.ico
[Tue Jan 04 15:20:12 2005] [error] [client 213.221.138.70] File does not exist: /var/www/jaquier.dyndns.org/htdocs/favicon.ico
[Tue Jan 04 15:20:16 2005] [error] [client 213.221.138.70] File does not exist: /var/www/jaquier.dyndns.org/htdocs/favicon.ico
[Tue Jan 04 15:20:22 2005] [error] [client 213.221.138.70] File does not exist: /var/www/jaquier.dyndns.org/htdocs/favicon.ico
[Tue Jan 04 15:20:26 2005] [error] [client 213.221.138.70] File does not exist: /var/www/jaquier.dyndns.org/htdocs/favicon.ico
[Tue Jan 04 15:20:28 2005] [error] [client 213.221.138.70] File does not exist: /var/www/jaquier.dyndns.org/htdocs/favicon.ico
[Tue Jan 04 15:20:38 2005] [error] [client 213.221.138.70] File does not exist: /var/www/jaquier.dyndns.org/htdocs/favicon.ico
[Tue Jan 04 20:54:59 2005] [error] [client 192.168.0.129] File does not exist: /var/www/jaquier.dyndns.org/htdocs/favicon.ico
[Tue Jan 04 20:55:04 2005] [error] [client 192.168.0.129] File does not exist: /var/www/jaquier.dyndns.org/htdocs/favicon.ico
[Tue Jan 04 20:55:29 2005] [error] [client 192.168.0.129] File does not exist: /var/www/jaquier.dyndns.org/htdocs/favicon.ico
[Tue Jan 04 21:34:29 2005] [error] [client 81.63.51.202] File does not exist: /var/www/jaquier.dyndns.org/htdocs/favicon.ico
[Tue Jan 04 21:34:32 2005] [error] [client 81.63.51.202] File does not exist: /var/www/jaquier.dyndns.org/htdocs/favicon.ico
[Wed Jan 05 00:17:41 2005] [error] [client 217.251.126.37] File does not exist: /var/www/jaquier.dyndns.org/htdocs/favicon.ico
[Wed Jan 05 00:18:03 2005] [error] [client 217.251.126.37] File does not exist: /var/www/jaquier.dyndns.org/htdocs/favicon.ico
[Wed Jan 05 00:18:12 2005] [error] [client 217.251.126.37] File does not exist: /var/www/jaquier.dyndns.org/htdocs/favicon.ico
[Wed Jan 05 01:24:38 2005] [error] [client 81.63.51.202] File does not exist: /var/www/jaquier.dyndns.org/htdocs/favicon.ico
[Wed Jan 05 01:24:40 2005] [error] [client 81.63.51.202] File does not exist: /var/www/jaquier.dyndns.org/htdocs/favicon.ico
[Wed Jan 05 01:24:46 2005] [error] [client 81.63.51.202] File does not exist: /var/www/jaquier.dyndns.org/htdocs/favicon.ico
[Wed Jan 05 01:24:48 2005] [error] [client 81.63.51.202] File does not exist: /var/www/jaquier.dyndns.org/htdocs/favicon.ico
[Wed Jan 05 01:25:58 2005] [error] [client 81.63.51.202] File does not exist: /var/www/jaquier.dyndns.org/htdocs/favicon.ico
[Wed Jan 05 01:26:34 2005] [error] [client 81.63.51.202] File does not exist: /var/www/jaquier.dyndns.org/htdocs/favicon.ico
[Wed Jan 05 01:26:37 2005] [error] [client 81.63.51.202] File does not exist: /var/www/jaquier.dyndns.org/htdocs/favicon.ico
[Wed Jan 05 10:13:02 2005] [error] [client 192.168.0.129] File does not exist: /var/www/jaquier.dyndns.org/htdocs/favicon.ico
[Wed Jan 05 10:13:07 2005] [error] [client 192.168.0.129] File does not exist: /var/www/jaquier.dyndns.org/htdocs/favicon.ico
[Wed Jan 05 10:13:10 2005] [error] [client 192.168.0.129] File does not exist: /var/www/jaquier.dyndns.org/htdocs/favicon.ico
[Wed Jan 05 10:17:07 2005] [error] [client 192.168.0.129] File does not exist: /var/www/jaquier.dyndns.org/htdocs/favicon.ico
[Wed Jan 05 14:41:40 2005] [error] [client 192.168.0.129] File does not exist: /var/www/jaquier.dyndns.org/htdocs/favicon.ico
[Wed Jan 05 14:41:45 2005] [error] [client 192.168.0.129] File does not exist: /var/www/jaquier.dyndns.org/htdocs/favicon.ico
[Wed Jan 05 14:41:47 2005] [error] [client 192.168.0.129] File does not exist: /var/www/jaquier.dyndns.org/htdocs/favicon.ico
[Wed Jan 05 14:41:51 2005] [error] [client 192.168.0.129] File does not exist: /var/www/jaquier.dyndns.org/htdocs/favicon.ico
[Wed Jan 05 14:55:30 2005] [error] [client 212.101.4.200] File does not exist: /var/www/jaquier.dyndns.org/htdocs/favicon.ico
[Wed Jan 05 15:03:44 2005] [error] [client 192.168.0.129] File does not exist: /var/www/jaquier.dyndns.org/htdocs/favicon.ico
[Wed Jan 05 15:03:48 2005] [error] [client 192.168.0.129] File does not exist: /var/www/jaquier.dyndns.org/htdocs/favicon.ico
[Wed Jan 05 15:03:52 2005] [error] [client 192.168.0.129] File does not exist: /var/www/jaquier.dyndns.org/htdocs/favicon.ico
[Wed Jan 05 15:03:57 2005] [error] [client 192.168.0.129] File does not exist: /var/www/jaquier.dyndns.org/htdocs/favicon.ico
[Wed Jan 05 15:06:45 2005] [error] [client 212.101.4.200] File does not exist: /var/www/jaquier.dyndns.org/htdocs/favicon.ico
[Wed Mar 05 15:07:28 2005] [error] [client 192.168.0.128] user cyril: authentication failure for "/phpinfo": Password Mismatch
[Wed Jan 05 15:08:01 2005] [error] [client 192.168.0.128] user not found: /phpinfo
[Wed Jan 05 15:10:45 2005] [crit] [client 192.168.0.128] (13)Permission denied: /var/www/jaquier.dyndns.org/htdocs/css/.htaccess pcfg_openfile: unable to check htaccess file, ensure it is readable, referer: http://earth/phpinfo
[Wed Jan 05 15:10:45 2005] [crit] [client 192.168.0.128] (13)Permission denied: /var/www/jaquier.dyndns.org/htdocs/images/.htaccess pcfg_openfile: unable to check htaccess file, ensure it is readable, referer: http://earth/phpinfo
[Wed Jan 05 15:10:45 2005] [error] [client 192.168.0.128] File does not exist: /var/www/jaquier.dyndns.org/htdocs/favicon.ico
[Wed Jan 05 15:11:09 2005] [error] [client 192.168.0.128] user test not found: /phpinfo
[Wed Jan 05 15:11:10 2005] [error] [client 192.168.0.128] user test not found: /phpinfo
[Wed Jan 06 15:11:11 2005] [error] [client 192.168.0.128] user test not found: /phpinfo
[Wed Jan 06 15:11:13 2005] [error] [client 192.168.0.128] user test not found: /phpinfo
[Wed Jan 06 15:11:14 2005] [error] [client 192.168.0.128] user test not found: /phpinfo
[Wed Jan 05 15:11:15 2005] [crit] [client 192.168.0.128] (13)Permission denied: /var/www/jaquier.dyndns.org/htdocs/css/.htaccess pcfg_openfile: unable to check htaccess file, ensure it is readable, referer: http://earth/phpinfo
[Wed Jan 05 15:11:15 2005] [crit] [client 192.168.0.128] (13)Permission denied: /var/www/jaquier.dyndns.org/htdocs/images/.htaccess pcfg_openfile: unable to check htaccess file, ensure it is readable, referer: http://earth/phpinfo
[Wed Jan 05 15:11:15 2005] [error] [client 192.168.0.128] File does not exist: /var/www/jaquier.dyndns.org/htdocs/favicon.ico
[Wed Jan 05 15:12:32 2005] [error] [client 212.101.4.200] File does not exist: /var/www/jaquier.dyndns.org/htdocs/favicon.ico
[Wed Jan 05 15:13:48 2005] [error] [client 192.168.0.129] File does not exist: /var/www/jaquier.dyndns.org/htdocs/favicon.ico
[Wed Jan 05 15:13:51 2005] [error] [client 192.168.0.129] File does not exist: /var/www/jaquier.dyndns.org/htdocs/favicon.ico
[Wed Jan 05 15:13:52 2005] [error] [client 192.168.0.129] File does not exist: /var/www/jaquier.dyndns.org/htdocs/favicon.ico
[Wed Jan 05 15:13:52 2005] [error] [client 192.168.0.129] File does not exist: /var/www/jaquier.dyndns.org/htdocs/favicon.ico
[Wed Jan 05 15:13:54 2005] [error] [client 192.168.0.129] File does not exist: /var/www/jaquier.dyndns.org/htdocs/favicon.ico
[Wed Jan 05 15:13:56 2005] [error] [client 192.168.0.129] File does not exist: /var/www/jaquier.dyndns.org/htdocs/favicon.ico
[Wed Jan 05 15:13:59 2005] [error] [client 192.168.0.129] File does not exist: /var/www/jaquier.dyndns.org/htdocs/favicon.ico
[Wed Jan 05 15:14:20 2005] [error] [client 192.168.0.129] File does not exist: /var/www/jaquier.dyndns.org/htdocs/favicon.ico
[Wed Jan 05 15:14:24 2005] [error] [client 192.168.0.129] File does not exist: /var/www/jaquier.dyndns.org/htdocs/favicon.ico
[Wed Jan 05 15:14:29 2005] [error] [client 192.168.0.129] File does not exist: /var/www/jaquier.dyndns.org/htdocs/favicon.ico
[Wed Jan 05 15:14:34 2005] [error] [client 192.168.0.129] File does not exist: /var/www/jaquier.dyndns.org/htdocs/favicon.ico
[Wed Mar 10 15:08:28 2005] [error] [client www.google.ch] user cyril: authentication failure for "/phpinfo": Password Mismatch
[Wed Mar 10 15:09:28 2005] [error] [client www.google.ch] user cyril: authentication failure for "/phpinfo": Password Mismatch
[Wed Mar 10 15:11:28 2005] [error] [client www.google.ch] user cyril: authentication failure for "/phpinfo": Password Mismatch
[Wed Mar 30 15:11:28 2005] [error] [client www.google.ch] user cyril: authentication failure for "/phpinfo": Password Mismatch
[Wed Mar 30 15:11:28 2005] [error] [client www.google.ch] user cyril: authentication failure for "/phpinfo": Password Mismatch
[Wed Mar 30 15:11:28 2005] [error] [client www.google.ch] user cyril: authentication failure for "/phpinfo": Password Mismatch
[Wed Mar 30 15:11:28 2005] [error] [client www.google.ch] user cyril: authentication failure for "/phpinfo": Password Mismatch
+11 -4
View File
@@ -1,4 +1,11 @@
- Last output repeated 2 times -
Oct 7 11:47:08 [sshd] Failed password for illegal user test from 69.182.27.122 port 34015 ssh2
Oct 7 11:47:09 [sshd] Failed password for illegal user guest from 69.182.27.122 port 34068 ssh2
Oct 7 11:47:11 [sshd] Failed password for illegal user admin from 69.182.27.122 port 34127 ssh2
Jan 7 17:53:15 [sshd] (pam_unix) 2 more authentication failures; logname= uid=0 euid=0 tty=ssh ruser= rhost=62.220.137.36 user=kevin
Jan 7 17:53:26 [sshd] (pam_unix) authentication failure; logname= uid=0 euid=0 tty=ssh ruser= rhost=62.220.137.36 user=kevin
Mar 7 17:53:28 [sshd] error: PAM: Authentication failure for kevin from 62.220.137.36
Mar 7 17:55:28 [sshd] error: PAM: Authentication failure for kevin from 62.220.137.36
Mar 7 17:57:28 [sshd] error: PAM: Authentication failure for kevin from 62.220.137.36
Mar 7 17:57:28 [sshd] error: PAM: Authentication failure for kevin from 192.168.0.128
Mar 7 17:57:28 [sshd] error: PAM: Authentication failure for kevin from 192.168.0.128
Mar 7 17:57:28 [sshd] error: PAM: Authentication failure for kevin from 192.168.0.128
Mar 7 17:57:28 [sshd] error: PAM: Authentication failure for kevin from 192.168.0.128
Mar 7 17:57:28 [sshd] error: PAM: Authentication failure for kevin from www.google.ch
Mar 7 17:57:28 [sshd] error: PAM: Authentication failure for kevin from www.google.ch
+5 -4
View File
@@ -425,7 +425,8 @@ Oct 7 01:03:12 [sshd] Failed password for illegal user tata from 128.178.164.52
- Last output repeated 2 times -
Oct 7 01:03:20 [sshd] Failed password for illegal user tata from 128.178.164.52 port 37187 ssh2
- Last output repeated 2 times -
Oct 8 11:47:08 [sshd] Failed password for illegal user test from 69.182.27.122 port 34015 ssh2
Oct 8 11:47:09 [sshd] Failed password for illegal user guest from 69.182.27.122 port 34068 ssh2
Oct 8 11:47:11 [sshd] Failed password for illegal user admin from 69.182.27.122 port 34127 ssh2
Oct 9 21:54:11 yellow sshd[16069]: Failed password for cyril from 212.41.79.210 port 29404 ssh2
Nov 14 11:47:08 [sshd] Failed password for illegal user test from 69.182.27.122 port 34015 ssh2
Nov 14 11:47:09 [sshd] Failed password for illegal user guest from 69.182.27.122 port 34068 ssh2
Nov 14 11:47:11 [sshd] Failed password for illegal user admin from 69.182.27.122 port 34127 ssh2
Nov 15 11:12:11 yellow sshd[16069]: Failed password for cyril from 212.41.79.210 port 29404 ssh2
Nov 15 21:54:11 yellow sshd[16069]: Illegal user for cyril from 212.41.79.210 port 29404 ssh2
+188 -16
View File
@@ -24,44 +24,216 @@ __date__ = "$Date$"
__copyright__ = "Copyright (c) 2004 Cyril Jaquier"
__license__ = "GPL"
import os, sys
import os, sys, time, re, logging
from utils.dns import *
# Gets the instance of the logger.
logSys = logging.getLogger("fail2ban")
class LogReader:
""" Reads a log file and reports information about IP that make password
failure, bad user or anything else that is considered as doubtful login
attempt.
"""
def __init__(self, logPath, findTime = 3600):
def __init__(self, logPath, timeregex, timepattern, failregex,
maxRetry, findTime):
self.logPath = logPath
self.maxRetry = maxRetry
self.timeregex = timeregex
self.timepattern = timepattern
self.failregex = failregex
self.findTime = findTime
self.ignoreIpList = []
self.lastModTime = 0
self.lastPos = 0
self.lastDate = 0
self.logStats = None
def getMaxRetry(self):
""" Gets the maximum number of failures
"""
return self.maxRetry
def getFindTime(self):
""" Gets the find time.
"""
return self.findTime
def addIgnoreIP(self, ip):
""" Adds an IP to the ignore list.
"""
logSys.debug("Add "+ip+" to ignore list")
self.ignoreIpList.append(ip)
def inIgnoreIPList(self, ip):
return ip in self.ignoreIpList
""" Checks if IP is in the ignore list.
"""
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])
a = cidr(s[0], s[1])
b = cidr(ip, s[1])
if a == b:
return True
return False
def openLogFile(self):
""" Opens the log file specified on init.
"""
try:
fileHandler = open(self.logPath)
except OSError:
print "Unable to open", self.logPath
sys.exit(-1)
logSys.error("Unable to open "+self.logPath)
return fileHandler
def isModified(self):
""" Checks if the log file has been modified using os.stat().
"""
try:
logStats = os.stat(self.logPath)
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:
print "Unable to get stat on", logPath
sys.exit(-1)
if self.lastModTime == logStats.st_mtime:
logSys.error("Unable to get stat on "+self.logPath)
return False
else:
print self.logPath, 'has been modified'
self.lastModTime = logStats.st_mtime
return True
def getPwdFailure(self):
failList = self.getFailInfo(self.findTime)
def setFilePos(self, file):
""" 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.
"""
line = file.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)
file.seek(self.lastPos)
def getFailures(self):
""" Gets all the failure in the log file which are
newer than time.time()-self.findTime.
Returns a dict with the IP, the number of failure
and the latest failure time.
"""
ipList = dict()
logSys.debug(self.logPath)
logFile = self.openLogFile()
self.setFilePos(logFile)
lastLine = None
for line in logFile:
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)
if ipList.has_key(ip):
ipList[ip] = (ipList[ip][0]+1, unixTime)
else:
ipList[ip] = (1, unixTime)
self.lastPos = logFile.tell()
if lastLine:
self.lastDate = self.getTime(lastLine)
logFile.close()
return ipList
def findFailure(self, line):
""" Finds the failure in line. Uses the failregex pattern
to find it and timeregex in order to find the logging
time.
Returns a dict with IP and timestamp.
"""
failList = list()
match = re.search(self.failregex, line)
if match:
timeMatch = re.search(self.timeregex, match.string)
if timeMatch:
date = self.getUnixTime(timeMatch.group())
try:
# Fix for CVE-2006-6302
matchString = match.group("host")
except IndexError:
# However does not break the current configuration
logSys.warn("No 'host' group defined. This is a security " +
"issue. Please fix your configuration file " +
"and look at CVE-2006-6302")
matchString = match.string
ipMatch = textToIp(matchString)
if ipMatch:
for ip in ipMatch:
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.
"""
date = 0
timeMatch = re.search(self.timeregex, line)
if timeMatch:
date = self.getUnixTime(timeMatch.group())
return date
def getUnixTime(self, value):
""" Returns the Unix timestamp of the given value.
Pattern should describe the date construction of
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
-65
View File
@@ -1,65 +0,0 @@
# This file is part of Fail2Ban.
#
# Fail2Ban is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# Fail2Ban is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Fail2Ban; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
# Author: Cyril Jaquier
#
# $Revision$
__author__ = "Cyril Jaquier"
__version__ = "$Revision$"
__date__ = "$Date$"
__copyright__ = "Copyright (c) 2004 Cyril Jaquier"
__license__ = "GPL"
import re, time
from logreader import LogReader
class Metalog(LogReader):
def getFailInfo(self, findTime):
ipList = dict()
logFile = self.openLogFile()
for line in logFile.readlines():
match = self.parseLogLine(line)
if match:
ip = match[0]
unixTime = match[1]
if unixTime < time.time()-self.findTime:
continue
if self.inIgnoreIPList(ip):
print 'Ignore', ip
continue
print 'Found', ip, 'at', unixTime
if ipList.has_key(ip):
ipList[ip] = (ipList[ip][0]+1, unixTime)
else:
ipList[ip] = (1, unixTime)
logFile.close()
return ipList
def parseLogLine(self, line):
""" Match sshd failed password log
"""
if re.search("Failed password", line):
matchIP = re.search("(?:\d{1,3}\.){3}\d{1,3}", line)
if matchIP:
date = list(time.strptime(line[0:15], "%b %d %H:%M:%S"))
date[0] = time.gmtime()[0]
unixTime = time.mktime(date)
return [matchIP.group(), unixTime]
else:
return False
+58
View File
@@ -0,0 +1,58 @@
.\"
.TH "FAIL2BAN" "8" "July 2005" "Cyril Jaquier" "System administration tools"
.SH "NAME"
fail2ban \- bans IP that makes too many password failures
.SH "SYNOPSIS"
.B fail2ban
[\fIOPTIONS\fR]
.SH "DESCRIPTION"
\fBFail2Ban\fR reads log file that contains password failure report
and bans the corresponding IP addresses using firewall rules. It updates
firewall rules to reject the IP address.
.SH "OPTIONS"
.TP
\fB\-b\fR
start in background
.TP
\fB\-c\fR \fIFILE\fR
read configuration file \fIFILE\fR
.TP
\fB\-p\fR \fIFILE\fR
create PID lock in \fIFILE\fR
.TP
\fB\-h, \-\-help\fR
display this help message
.TP
\fB\-i\fR \fIIP\fR
\fIIP\fR(s) to ignore
.TP
\fB\-k\fR
kill a currently running Fail2Ban instance
.TP
\fB\-r\fR \fIVALUE\fR
allow a max of \fIVALUE\fR password failure [maxfailures]
.TP
\fB\-t\fR \fITIME\fR
ban IP for \fITIME\fR seconds [bantime]
.TP
\fB\-f\fR \fITIME\fR
lifetime in seconds of failed entry [findtime]
.TP
\fB\-v\fR
verbose. Use twice for greater effect
.TP
\fB\-V, \-\-version\fR
print software version
.SH "FILES"
.I /etc/fail2ban.conf
.RS
The configuration file. See \fBfail2ban.conf\fR(5) for further details.
.SH "REPORTING BUGS"
Please report bugs at http://sourceforge.net/projects/fail2ban/
via bug tracker
.SH "AUTHOR"
Cyril Jaquier <lostcontrol@users.sourceforge.net>
.SH "SEE ALSO"
.TP
See
.BR "http://fail2ban.sourceforge.net/".
+20
View File
@@ -0,0 +1,20 @@
.\"
.TH "FAIL2BAN.CONF" "5" "July 2005" "Cyril Jaquier" "System administration tools"
.SH "NAME"
fail2ban.conf \- configuration data for fail2ban
.SH "DESCRIPTION"
\fB/etc/fail2ban.conf\fR contains data about the general configuration of fail2ban, the mail notification and services to monitor.
.SH "VARIABLES"
Please look at the file itself
.SH "FILES"
.I /etc/fail2ban.conf
.SH "REPORTING BUGS"
Please report bugs at http://sourceforge.net/projects/fail2ban/
via bug tracker
.SH "AUTHOR"
Cyril Jaquier <lostcontrol@users.sourceforge.net>
.SH "SEE ALSO"
.BR fail2ban (8)
.TP
See
.BR "http://fail2ban.sourceforge.net/".
+5
View File
@@ -0,0 +1,5 @@
[install]
install-purelib=/usr/lib/fail2ban
[sdist]
formats=bztar
Executable
+82
View File
@@ -0,0 +1,82 @@
#!/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'],
py_modules = ['fail2ban', 'version'],
packages = ['firewall', 'logreader', 'confreader', 'utils']
)
# Do some checks after installation
# Search for obsolete files.
obsoleteFiles = []
elements = {"/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 file."
print "Use config/fail2ban.conf.* as example."
print
+25
View File
@@ -0,0 +1,25 @@
# 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"
+102
View File
@@ -0,0 +1,102 @@
# 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 os, re, socket, struct
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()
def textToDns(text):
""" Search for possible DNS in an arbitrary text.
Thanks to Tom Pike.
"""
match = re.findall("(?:(?:\w|-)+\.){2,}\w+", text)
if match:
return match
else:
return []
def searchIP(text):
""" Search if an IP address if directly available and return
it.
"""
match = re.findall("(?:\d{1,3}\.){3}\d{1,3}", text)
if match:
return match
else:
return []
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
def textToIp(text):
""" Return the IP of DNS found in a given text.
"""
ipList = list()
# Search for plain IP
plainIP = searchIP(text)
for element in plainIP:
if isValidIP(element):
ipList.append(element)
if not ipList:
# Try to get IP from possible DNS
dnsList = textToDns(text)
for element in dnsList:
dns = dnsToIp(element)
for e in dns:
ipList.append(e)
return ipList
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 & addr2bin(i)
def addr2bin(str):
""" Convert a string IPv4 address into an unsigned integer.
"""
return struct.unpack("!L", socket.inet_aton(str))[0]
def bin2addr(addr):
""" Convert a numeric IPv4 address into string n.n.n.n form.
"""
return socket.inet_ntoa(struct.pack("!L", addr))
+91
View File
@@ -0,0 +1,91 @@
# 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, smtplib, email.Utils
from utils.strings import replaceTag
# Gets the instance of the logger.
logSys = logging.getLogger("fail2ban")
class Mail:
""" Mailer class
"""
def __init__(self, host, port = 25):
self.host = host
self.port = port
self.localTimeFlag = False
def setFromAddr(self, fromAddr):
""" Set from: address
"""
self.fromAddr = fromAddr
def setUser(self, user):
""" Set smtpuser
"""
self.user = user
def setPassword(self, password):
""" Set smtppassword
"""
self.password = password
def setToAddr(self, toAddr):
""" Set to: address
"""
self.toAddr = toAddr.split()
def setLocalTimeFlag(self, localTimeFlag):
""" Set to: address
"""
self.localTimeFlag = localTimeFlag
def sendmail(self, subject, message, aInfo):
""" Send an email using smtplib
"""
subj = replaceTag(subject, aInfo)
msg = replaceTag(message, aInfo)
mail = ("From: %s\r\nTo: %s\r\nDate: %s\r\nSubject: %s\r\n\r\n" %
(self.fromAddr, ", ".join(self.toAddr),
email.Utils.formatdate(localtime = self.localTimeFlag),
subj)) + msg
try:
server = smtplib.SMTP(self.host, self.port)
#server.set_debuglevel(1)
if not self.user == '':
server.login(self.user, self.password)
server.sendmail(self.fromAddr, self.toAddr, mail)
logSys.debug("Email sent to " + `self.toAddr`)
server.quit()
except Exception, e:
logSys.error("Unable to send mail to " + self.host + ":" +
`self.port` + " from " + self.fromAddr + " to " +
`self.toAddr` + ": " + `e` + ": " + `e.args`)
+109
View File
@@ -0,0 +1,109 @@
# 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 os, logging
# Gets the instance of the logger.
logSys = logging.getLogger("fail2ban")
class PIDLock:
""" Manages the PID lock file.
The following class shows how to implement the singleton pattern[1] in
Python. A singleton is a class that makes sure only one instance of it
is ever created. Typically such classes are used to manage resources
that by their very nature can only exist once.
http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/52558
"""
class __impl:
""" Implementation of the singleton interface """
def setPath(self, path):
""" Set PID lock file path.
"""
self.path = path
def create(self):
""" Create PID lock.
"""
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.
"""
try:
os.remove(self.path)
logSys.debug("Removed PID lock " + self.path)
except OSError:
logSys.error("Unable to remove PID lock " + self.path)
except AttributeError:
# AttributeError if self.path wasn't specified yet
logSys.debug("PID lock not removed because not defined yet")
def exists(self):
""" Returns the current PID if Fail2Ban is running or False
if no instance found.
"""
try:
fileHandler = open(self.path)
pid = fileHandler.readline()
fileHandler.close()
return pid
except IOError:
return False
# storage for the instance reference
__instance = None
def __init__(self):
""" Create singleton instance """
# Check whether we already have an instance
if PIDLock.__instance is None:
# Create and remember instance
PIDLock.__instance = PIDLock.__impl()
# Store instance reference as the only member in the handle
self.__dict__['_PIDLock__instance'] = PIDLock.__instance
def __getattr__(self, attr):
""" Delegate access to implementation """
return getattr(self.__instance, attr)
def __setattr__(self, attr, value):
""" Delegate access to implementation """
return setattr(self.__instance, attr, value)
+137
View File
@@ -0,0 +1,137 @@
# 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 os, logging, signal
# Gets the instance of the logger.
logSys = logging.getLogger("fail2ban")
class ExternalError(UserWarning):
""" Exception to warn about failed fwcheck or fwban command
"""
pass
def createDaemon():
""" Detach a process from the controlling terminal and run it in the
background as a daemon.
http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/278731
"""
try:
# Fork a child process so the parent can exit. This will return control
# to the command line or shell. This is required so that the new process
# is guaranteed not to be a process group leader. We have this guarantee
# because the process GID of the parent is inherited by the child, but
# the child gets a new PID, making it impossible for its PID to equal its
# PGID.
pid = os.fork()
except OSError, e:
return((e.errno, e.strerror)) # ERROR (return a tuple)
if (pid == 0): # The first child.
# Next we call os.setsid() to become the session leader of this new
# session. The process also becomes the process group leader of the
# new process group. Since a controlling terminal is associated with a
# session, and this new session has not yet acquired a controlling
# terminal our process now has no controlling terminal. This shouldn't
# fail, since we're guaranteed that the child is not a process group
# leader.
os.setsid()
# When the first child terminates, all processes in the second child
# are sent a SIGHUP, so it's ignored.
signal.signal(signal.SIGHUP, signal.SIG_IGN)
try:
# Fork a second child to prevent zombies. Since the first child is
# a session leader without a controlling terminal, it's possible for
# it to acquire one by opening a terminal in the future. This second
# fork guarantees that the child is no longer a session leader, thus
# preventing the daemon from ever acquiring a controlling terminal.
pid = os.fork() # Fork a second child.
except OSError, e:
return((e.errno, e.strerror)) # ERROR (return a tuple)
if (pid == 0): # The second child.
# Ensure that the daemon doesn't keep any directory in use. Failure
# to do this could make a filesystem unmountable.
os.chdir("/")
else:
os._exit(0) # Exit parent (the first child) of the second child.
else:
os._exit(0) # Exit parent of the first child.
# Close all open files. Try the system configuration variable, SC_OPEN_MAX,
# for the maximum number of open files to close. If it doesn't exist, use
# the default value (configurable).
try:
maxfd = os.sysconf("SC_OPEN_MAX")
except (AttributeError, ValueError):
maxfd = 256 # default maximum
for fd in range(0, maxfd):
try:
os.close(fd)
except OSError: # ERROR (ignore)
pass
# Redirect the standard file descriptors to /dev/null.
os.open("/dev/null", os.O_RDONLY) # standard input (0)
os.open("/dev/null", os.O_RDWR) # standard output (1)
os.open("/dev/null", os.O_RDWR) # standard error (2)
return True
def killPID(pid):
""" Kills the process with the given PID using the
INT signal (same effect as <ctrl>+<c>).
"""
try:
return os.kill(pid, 2)
except OSError:
logSys.error("Can not kill process " + `pid` + ". Please check that " +
"Fail2Ban is not running and remove the file " +
"'/tmp/fail2ban.pid'")
return False
def executeCmd(cmd, debug):
""" Executes an OS command.
"""
if cmd == "":
logSys.debug("Nothing to do")
return None
logSys.debug(cmd)
if not debug:
retval = os.system(cmd)
if not retval == 0:
logSys.error("'" + cmd + "' returned " + `retval`)
raise ExternalError("Execution of command '%s' failed" % cmd)
return retval
else:
return None
+13 -14
View File
@@ -24,18 +24,17 @@ __date__ = "$Date$"
__copyright__ = "Copyright (c) 2004 Cyril Jaquier"
__license__ = "GPL"
from firewall import Firewall
import logging
class Iptables(Firewall):
def banIP(self, ip, time):
query = 'iptables -I INPUT 1 -i eth0 -s '+str(ip)+' -j DROP'
self.addBanIP(ip, time)
self.executeCmd(query)
print query
def unBanIP(self, ip):
query = 'iptables -D INPUT -i eth0 -s '+str(ip)+' -j DROP'
self.delBanIP(ip)
self.executeCmd(query)
print query
# Gets the instance of the logger.
logSys = logging.getLogger("fail2ban")
def replaceTag(query, aInfo):
""" Replace tags in query
"""
string = query
for tag in aInfo:
string = string.replace('<'+tag+'>', `aInfo[tag]`)
# New line
string = string.replace('<br>', '\n')
return string
+27
View File
@@ -0,0 +1,27 @@
# 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"
version = "0.6.2"