Compare commits

..
Author SHA1 Message Date
Yaroslav Halchenko 408bed5464 preliminary patch for backports to wheezy etc (systemd support "disabled")
also removing obsolete patch for lucid -- will just not build for it any longer
2014-10-27 23:15:38 -04:00
Yaroslav Halchenko 4e543da4ba changelog + policy boost 2014-10-27 22:02:23 -04:00
Yaroslav Halchenko b1d7c3f3ff Merge tag '0.9.1' into debian
What aught to be a bugfix release delayed into a featured release 0.9.1

ver. 0.9.1 (2014/10/29) - better, faster, stronger
----------

- Refactoring (IMPORTANT -- Please review your setup and configuration):
   * iptables-common.conf replaced iptables-blocktype.conf
     (iptables-blocktype.local should still be read) and now also
     provides defaults for the chain, port, protocol and name tags

- Fixes:
   * start of file2ban aborted (on slow hosts, systemd considers the server has
     been timed out and kills him), see gh-824
   * UTF-8 fixes in pure-ftp thanks to Johannes Weberhofer. Closes gh-806.
   * systemd backend error on bad utf-8 in python3
   * badips.py action error when logging HTTP error raised with badips request
   * fail2ban-regex failed to work in python3 due to space/tab mix
   * recidive regex samples incorrect log level
   * journalmatch for recidive incorrect PRIORITY
   * loglevel couldn't be changed in fail2ban.conf
   * Handle case when no sqlite library is available for persistent database
   * Only reban once per IP from database on fail2ban restart
   * Nginx filter to support missing server_name. Closes gh-676
   * fail2ban-regex assertion error caused by miscount missed lines with
     multiline regex
   * Fix actions failing to execute for Python 3.4.0. Workaround for
     http://bugs.python.org/issue21207
   * Database now returns persistent bans on restart (bantime < 0)
   * Recursive action tags now fully processed. Fixes issue with bsd-ipfw
     action
   * Fixed TypeError with "ipfailures" and "ipjailfailures" action tags.
     Thanks Serg G. Brester
   * Correct times for non-timezone date times formats during DST
   * Pass a copy of, not original, aInfo into actions to avoid side-effects
   * Per-distribution paths to the exim's main log
   * Ignored IPs are no longer banned when being restored from persistent
     database
   * Manually unbanned IPs are now removed from persistent database, such they
     wont be banned again when Fail2Ban is restarted
   * Pass "bantime" parameter to the actions in default jail's action
     definition(s)
   * filters.d/sieve.conf - fixed typo in _daemon.  Thanks Jisoo Park
   * cyrus-imap -- also catch also failed logins via secured (imaps/pop3s).
     Regression was introduced while strengthening failregex in 0.8.11 (bd175f)
     Debian bug #755173
   * postfix-sasl - added journalmatch.  Thanks Luc Maisonobe
   * postfix* - match with a new daemon string (postfix/submission/smtpd).
     Closes gh-804 .  Thanks Paul Traina
   * apache - added filter for AH01630 client denied by server configuration.

- New features:
   - New filters:
     - monit  Thanks Jason H Martin
     - directadmin  Thanks niorg
     - apache-shellshock  Thanks Eugene Hopkinson (SlowRiot)
   - New actions:
     - symbiosis-blacklist-allports  for Bytemark symbiosis firewall
   - fail2ban-client can fetch the running server version
   - Added Cloudflare API action

- Enhancements
   * Start performance of fail2ban-client (and tests) increased, start time
     and cpu usage rapidly reduced. Introduced a shared storage logic, to
     bypass reading lots of config files (see gh-824).
     Thanks to Joost Molenaar for good catch (reported gh-820).
   * Fail2ban-regex - add print-all-matched option. Closes gh-652
   * Suppress fail2ban-client warnings for non-critical config options
   * Match non "Bye Bye" disconnect messages for sshd locked account regex
   * courier-smtp filter:
     - match lines with user names
     - match lines containing "535 Authentication failed" attempts
   * Add <chain> tag to iptables-ipsets
   * Realign fail2ban log output with white space to improve readability. Does
     not affect SYSLOG output
   * Log unhandled exceptions
   * cyrus-imap: catch "user not found" attempts
   * Add support for Portsentry

* tag '0.9.1': (36 commits)
  ENH: additional versioning changes
  Refreshed manpages
  ENH: fail early in generate-man + provide PYTHONPATH upstairs
  Changes for the 0.9.1 release versioning
  Populated MANIFEST with more entries which were preiously missed or duplicated. Sorted within each "section"
  Add portsentry to changelog
  ConfigReader.touch renamed into protected _create_unshared
  DOC: documentation about available vagrantfile setup
  Added myself into THANKS
  DOC: adjust docs in mytime to place docs into docstrings
  ENH: do use @staticmethod (we are well beyond support of 2.4 now)
  testExecuteTimeout fixed: give a test still 1 second, because system could be too busy
  coverage: no cover (for failed except)
  fix: fail2ban-regex with filter file failed (after merging #824, because test case missing); test case for 'readexplicit' added;
  ENH:  remove obsolete code for python < 2.6 (we support >= 2.6)
  DOC: very minor (tabs/spaces)
  We better check that installation doesn't cause any errors as well
  code review, change log entries added;
  reset share/cache storage (if we use 'reload' in client with interactive mode)
  normalize tabs/spaces in docstrings;
  ...
2014-10-27 21:52:39 -04:00
Yaroslav Halchenko a0115ee458 ENH: additional versioning changes 2014-10-27 21:49:40 -04:00
Yaroslav Halchenko d0a5fe620f Refreshed manpages 2014-10-27 21:47:48 -04:00
Yaroslav Halchenko 564eb3389b ENH: fail early in generate-man + provide PYTHONPATH upstairs 2014-10-27 21:47:07 -04:00
Yaroslav Halchenko 987356d6c0 Changes for the 0.9.1 release versioning 2014-10-27 21:43:17 -04:00
Yaroslav Halchenko 9e8e4dde69 Populated MANIFEST with more entries which were preiously missed or duplicated. Sorted within each "section" 2014-10-27 21:43:11 -04:00
Yaroslav Halchenko fc145eb795 Merge pull request #748 from pacop/master
ENH: Add dateTime format for PortSentry
2014-10-25 12:34:00 -04:00
Yaroslav Halchenko 8a453018a9 Merge pull request #830 from sebres/_tent/cache-config-read-fix1
fix: fail2ban-regex with filter file failed
2014-10-25 12:30:55 -04:00
pacop b60e2bf42f Add portsentry to changelog 2014-10-25 18:17:57 +02:00
pacop e3a037ee3f merge master 2014-10-25 18:15:34 +02:00
sebres 3dac765598 ConfigReader.touch renamed into protected _create_unshared 2014-10-25 17:20:01 +02:00
Yaroslav Halchenko 0b5413ec0b Merge branch 'master' of git://github.com/fail2ban/fail2ban
* 'master' of git://github.com/fail2ban/fail2ban:
2014-10-25 10:38:28 -04:00
Florian Pelgrim 3dabd5fc83 DOC: documentation about available vagrantfile setup
manually picked up from a commit within
https://github.com/fail2ban/fail2ban/pull/786
2014-10-25 10:38:18 -04:00
Florian Pelgrim 6293e44889 Added myself into THANKS 2014-10-25 10:37:28 -04:00
Yaroslav Halchenko b2b5d0b41c Merge pull request #829 from yarikoptic/minimal_python2.6
ENH:  remove obsolete code for python < 2.6 (we support >= 2.6)
2014-10-25 10:32:10 -04:00
Yaroslav Halchenko e1a5decc00 DOC: adjust docs in mytime to place docs into docstrings 2014-10-25 09:34:37 -04:00
Yaroslav Halchenko caa6006a31 ENH: do use @staticmethod (we are well beyond support of 2.4 now) 2014-10-25 09:25:18 -04:00
sebres 07d4badfd0 testExecuteTimeout fixed: give a test still 1 second, because system could be too busy 2014-10-24 05:42:58 +02:00
sebres bef0502e6b coverage: no cover (for failed except) 2014-10-24 05:28:35 +02:00
sebres 0b0ea41f87 fix: fail2ban-regex with filter file failed (after merging #824, because test case missing);
test case for 'readexplicit' added;
2014-10-24 04:59:44 +02:00
Yaroslav Halchenko d4015d6566 ENH: remove obsolete code for python < 2.6 (we support >= 2.6) 2014-10-23 14:51:51 -04:00
Yaroslav Halchenko e2f49b7334 DOC: very minor (tabs/spaces) 2014-10-23 14:44:10 -04:00
Yaroslav Halchenko 78e1a13fad Merge branch '_tent/cache-config-read' of https://github.com/sebres/fail2ban
* '_tent/cache-config-read' of https://github.com/sebres/fail2ban:
  code review, change log entries added;
  reset share/cache storage (if we use 'reload' in client with interactive mode)
  normalize tabs/spaces in docstrings;
  cache-config-read-v2 merged; logging normalized, set log level for loading (read or use shared) file(s) to INFO; prevent to read some files twice by read inside "_getIncludes" and by "read" self (occurred by only one file);
  code review; more stable config sharing, configurator always shares it config readers now;
  code review: use the same code (corresponding test cases - with sharing on and without it);
  rewritten caching resp. sharing of ConfigReader and SafeConfigParserWithIncludes (v.2, first and second level cache, without fingerprinting etc.);
  code review
  ConfigReader/ConfigWrapper renamed as suggested from @yarikoptic; + code clarifying (suggested also);
  Partially merge remote-tracking from 'sebres:cache-config-read-820': test cases extended, configurator.py adapted for test case.
  ENH: keep spitting out logging to the screen in LogCaptureTestCases if HEAVYDEBUG
  test case for check the read of config files will be cached;
  more precise by test
  ConfigWrapper class introduced: sharing of the same ConfigReader object between JailsReader and JailReader (don't read jail config each jail); sharing of the same DefinitionInitConfigReader (ActionReader, FilterReader) between all jails using that; cache of read a config files was optimized; test case extended for all types of config readers;
  config cache optimized - prevent to read the same config file inside different resources multiple times; test case: read jail file only once;
  test case for check the read of config files will be cached;
  caching of read config files, to make start of fail2ban faster, see issue #820
2014-10-23 14:28:33 -04:00
Yaroslav Halchenko 5ac496d030 We better check that installation doesn't cause any errors as well 2014-10-12 17:28:35 -04:00
Yaroslav Halchenko fbce121967 adjusted changelog revision, apparently I fell into a trap of unannotated tag for 0.9.0 release 2014-10-12 16:45:57 -04:00
Yaroslav Halchenko 6f4e542eff Merge commit '0.9.0-252-g47441d1' into debian-releases/experimental
* commit '0.9.0-252-g47441d1':
  BF: made tests util digest.py friendly to python3
2014-10-12 16:45:30 -04:00
Yaroslav Halchenko 47441d1383 Merge remote-tracking branch 'origin/master'
* origin/master:
  RF: moving logwatch setup/sample logs under files/logwatch
  ENH: print rebans stats even if no "Failures" are logged, and reduce indentation in output
  ENH: untabified and reindented entire script for sane formatting (no functional changes)
  BF: logwatch -- fixing up regex for 'already banned'
  Sample logfiles to test logwatch services script
  Adjusting fail2ban logwatch script to match lines from 0.9 as well
2014-10-12 16:44:24 -04:00
Yaroslav Halchenko 86a5f42f73 BF: made tests util digest.py friendly to python3 2014-10-12 16:40:29 -04:00
Yaroslav Halchenko a33207bf87 changelog 2014-10-12 10:31:48 -04:00
Yaroslav Halchenko eb6cc726ff Merge branch 'debian-release/experimental' of https://github.com/schaal/fail2ban into debian-releases/experimental
* 'debian-release/experimental' of https://github.com/schaal/fail2ban:
  Switch debian packaging to use python3
2014-10-12 10:26:48 -04:00
Yaroslav Halchenko cb662e2368 Merge commit '0.9.0a2-814-g98dc084' into debian-releases/experimental
* commit '0.9.0a2-814-g98dc084':
  tests: define CONFIG_DIR in utils.
  forgot to add test case to last commit
  adding test case, changelog and thanks entries for apache shellshock filter
  adding jail conf for shellshock filter
  adding filter to detect Shellshock attack attempts against bash scripts through apache.  See http://seclists.org/oss-sec/2014/q3/650
  Add apache filter for AH01630 client denied by server configuration
  RF: moving logwatch setup/sample logs under files/logwatch
  DOC: Changelog and THANKS for  previous changes
  RF: remove those two additional failregexes for the postfix
  ENH: add empty ignoreregex to avoid a warning (Close #805)
  Update test cases and also suport smtps per request.
  Add support for postfix/submission/smtpd matching.
  ENH: print rebans stats even if no "Failures" are logged, and reduce indentation in output
  ENH: untabified and reindented entire script for sane formatting (no functional changes)
  BF: logwatch -- fixing up regex for 'already banned'
  Sample logfiles to test logwatch services script
  Adjusting fail2ban logwatch script to match lines from 0.9 as well
2014-10-12 10:26:36 -04:00
Yaroslav Halchenko 98dc0844ce Merge pull request #782 from yarikoptic/bf/logwatch
logwatch file (original 1.5 version + fixes for change of logs in 0.9)
2014-10-10 22:15:57 -04:00
sebres 7d3e6e9935 code review, change log entries added; 2014-10-10 20:06:58 +02:00
sebres 73a06d55a8 reset share/cache storage (if we use 'reload' in client with interactive mode) 2014-10-10 18:50:24 +02:00
sebres 7f5d4aa7a6 normalize tabs/spaces in docstrings; 2014-10-10 16:59:40 +02:00
sebres 95bdcdecaa cache-config-read-v2 merged;
logging normalized, set log level for loading (read or use shared) file(s) to INFO;
prevent to read some files twice by read inside "_getIncludes" and by "read" self (occurred by only one file);
2014-10-10 16:49:08 +02:00
sebres 02a46d0901 code review;
more stable config sharing, configurator always shares it config readers now;
2014-10-10 12:05:49 +02:00
sebres e0eb4f2358 code review: use the same code (corresponding test cases - with sharing on and without it); 2014-10-10 02:47:42 +02:00
sebres c35b4b24d2 rewritten caching resp. sharing of ConfigReader and SafeConfigParserWithIncludes (v.2, first and second level cache, without fingerprinting etc.); 2014-10-10 02:10:13 +02:00
sebres 37952ab75f code review 2014-10-09 19:51:53 +02:00
sebres f67053c2ec ConfigReader/ConfigWrapper renamed as suggested from @yarikoptic;
+ code clarifying (suggested also);
2014-10-09 19:01:49 +02:00
sebres f6723a12ff Merge branch 'cache-config-read-820' into _tent/cache-config-read 2014-10-09 18:01:31 +02:00
sebres b62ce14ccd Partially merge remote-tracking from 'sebres:cache-config-read-820':
test cases extended, configurator.py adapted for test case.
2014-10-09 18:00:45 +02:00
Yaroslav Halchenko 0c5f11079c ENH: keep spitting out logging to the screen in LogCaptureTestCases if HEAVYDEBUG 2014-10-09 10:47:00 -04:00
sebres f31607ded1 test case for check the read of config files will be cached;
Conflicts:
	fail2ban/tests/clientreadertestcase.py -- removed not needed
        time in imports
2014-10-09 10:30:17 -04:00
sebres 51cae63bf0 more precise by test 2014-10-09 15:39:58 +02:00
sebres 4244c87802 ConfigWrapper class introduced: sharing of the same ConfigReader object between JailsReader and JailReader (don't read jail config each jail);
sharing of the same DefinitionInitConfigReader (ActionReader, FilterReader) between all jails using that;
cache of read a config files was optimized;
test case extended for all types of config readers;
2014-10-09 14:51:08 +02:00
sebres 2a54e61238 config cache optimized - prevent to read the same config file inside different resources multiple times;
test case: read jail file only once;
2014-10-08 15:44:32 +02:00
sebres af4b48e841 test case for check the read of config files will be cached; 2014-10-07 14:37:40 +02:00
pacop ce4f2d1c88 added filter for PortSentry with jail and samples 2014-10-04 15:08:12 +02:00
pacop 37acc6b832 ENH: Add dateTime format for PortSentry
Added dateTime format for PortSentry with EPOCH format
2014-10-04 14:55:22 +02:00
Daniel Schaal 97e01985a8 Merge remote-tracking branch 'origin/master' into debian-release/experimental 2014-10-03 17:56:12 +02:00
Daniel Schaal 3f9859a127 Switch debian packaging to use python3 2014-10-03 17:44:49 +02:00
sebres d00af327c5 caching of read config files, to make start of fail2ban faster, see issue #820 2014-10-03 02:11:55 +02:00
Yaroslav Halchenko 05fcb1f104 Merge pull request #813 from schaal/tests-configdir-env-variable
tests: Add function to utils to calculate CONFIG_DIR
2014-10-01 14:19:26 -04:00
Daniel Schaal 270ea363d3 tests: define CONFIG_DIR in utils. 2014-10-01 19:50:03 +02:00
Yaroslav Halchenko b912d61ccb Merge pull request #818 from slowriot/master
adding filter to detect Shellshock attack attempts with Apache
2014-09-29 09:32:21 -04:00
SlowRiot 5d526bbeb1 forgot to add test case to last commit 2014-09-29 00:49:22 +01:00
SlowRiot 7b5dc9f24f adding test case, changelog and thanks entries for apache shellshock filter 2014-09-26 18:48:56 +01:00
SlowRiot fc5f729f01 adding jail conf for shellshock filter 2014-09-26 16:37:50 +01:00
SlowRiot 4f636eb0e3 adding filter to detect Shellshock attack attempts against bash scripts through apache. See http://seclists.org/oss-sec/2014/q3/650 2014-09-26 16:25:07 +01:00
Yaroslav Halchenko bfaf33b6ba Merge pull request #812 from nickweeds/master
Issue #810: Update apache-auth.conf filter to match AH01630: client denied by server configuration
2014-09-14 21:01:50 -04:00
Nick Weeds 2c158fe168 Add apache filter for AH01630 client denied by server configuration 2014-09-14 21:54:05 +01:00
Yaroslav Halchenko caa851e5c8 RF: moving logwatch setup/sample logs under files/logwatch 2014-09-14 09:48:14 -04:00
Yaroslav Halchenko 8f521b8551 DOC: Changelog and THANKS for previous changes 2014-09-13 10:27:37 -04:00
Yaroslav Halchenko 0e1f8f7f39 RF: remove those two additional failregexes for the postfix
see comment
https://github.com/fail2ban/fail2ban/pull/804\#discussion_r17512426
2014-09-13 10:25:27 -04:00
Yaroslav Halchenko 96c20c8379 Merge pull request #804 from pleasantone/master
Add support for postfix/submission/smtpd matching.
2014-09-13 10:24:06 -04:00
Yaroslav Halchenko c58c4de9bc ENH: add empty ignoreregex to avoid a warning (Close #805) 2014-09-13 10:18:37 -04:00
Yaroslav Halchenko 8b2f0678a7 Merge commit '0.9.0a2-792-g1864f75' into debian-releases/experimental
* commit '0.9.0a2-792-g1864f75': (113 commits)
  Credits and notes from #806
  fixed encoding
  fixed encoding
  ENH: Ignore errors while unbaning in symbiosis firewall
  ENH: just a bit more descriptive exception ;-)
  ENH/BF(TST): making permissions restrictive is not sufficient -- really remove file to test
  changelog entry for postfix-sasl fix
  added systemd configuration for postfix-sasl.conf
  1.5 version of Fail2ban logwatch file
  minor typo
  Fxi jail.conf to use more syslog macros
  ENH: symbiosis-blacklist-allports action
  Fix typos.
  changelog and thanks for the preceding fix
  Added entry for Cloudflare action
  ChangeLog Added and entry about Cloudflare action
  Changed to Cloudflare JSON API
  Fix sieve filter to use correct option
  changelog entries for already merged and upcoming merge
  Update courier-smtp.conf
  ...
2014-09-12 14:14:24 -04:00
Paul Traina 249e169d8e Update test cases and also suport smtps per request. 2014-09-08 11:53:51 -07:00
Paul Traina 544cfaff2c Add support for postfix/submission/smtpd matching. 2014-09-06 10:23:38 -07:00
Yaroslav Halchenko b1c04f5fa2 ENH: print rebans stats even if no "Failures" are logged, and reduce indentation in output 2014-08-13 23:37:17 -04:00
Yaroslav Halchenko decea64cf9 ENH: untabified and reindented entire script for sane formatting (no functional changes) 2014-08-13 23:28:03 -04:00
Yaroslav Halchenko 8b62353ab0 BF: logwatch -- fixing up regex for 'already banned' 2014-08-13 23:24:38 -04:00
Yaroslav Halchenko 3bd36ba40a Sample logfiles to test logwatch services script 2014-08-13 23:15:31 -04:00
Yaroslav Halchenko b0f26fa391 Adjusting fail2ban logwatch script to match lines from 0.9 as well
File itself includes additional log information about changes
2014-08-11 12:45:50 -04:00
Yaroslav Halchenko 87703c4cfe Merge remote-tracking branch 'origin/master' into debian-releases/experimental
* origin/master:
  Clean up setup.py
  ENH: adding pruned with previous merge trailing \s* in nginx filter
  nginx-http-auth: match when "referrer" is present
  DOC: Update ChangeLog
  DOC: Fix jail.conf(5) man page which had duplicate {fail,ignore}regex
  Correct grammar
  DOC: add thanks for last commit
  DOC: nginx-http-auth filter
  nginx-http-auth filter: match server_name = ""
  ENH: Suppress configuration warnings if non-critical options are not set
  Update comments in shorewall.conf for new settings
  DOC: Improve error logging when specific backend set and fails
  BF: Fix getting jail name from exceptions in beautifier for Python 3+
  DOC: sphinx documentation
  BF: On jail restart reinstatement of bans, fetch one ticket per IP
  Fix 2 more typos that codespell didn't catch
  Add documentation link to systemd service file
2014-04-12 11:32:02 -04:00
87 changed files with 1365 additions and 2418 deletions
-1
View File
@@ -1,4 +1,3 @@
.pc/*
*~
build
dist
+2
View File
@@ -16,6 +16,8 @@ install:
- if [[ $TRAVIS_PYTHON_VERSION == 2.7 ]]; then cd ..; pip install -q coveralls; cd -; fi
script:
- if [[ $TRAVIS_PYTHON_VERSION == 2.7 ]]; then coverage run --rcfile=.travis_coveragerc setup.py test; else python setup.py test; fi
# test installation
- sudo python setup.py install
after_success:
# Coverage config file must be .coveragerc for coveralls
- if [[ $TRAVIS_PYTHON_VERSION == 2.7 ]]; then cp -v .travis_coveragerc .coveragerc; fi
-181
View File
@@ -1,181 +0,0 @@
#!/usr/bin/perl
##########################################################################
# $Id: fail2ban 150 2013-06-18 22:19:38Z mtremaine $
##########################################################################
# $Log: fail2ban,v $
# Revision 1.5 2008/08/18 16:07:46 mike
# Patches from Paul Gear <paul at libertysys.com> -mgt
#
# Revision 1.4 2008/06/30 23:07:51 kirk
# fixed copyright holders for files where I know who they should be
#
# Revision 1.3 2008/03/24 23:31:26 kirk
# added copyright/license notice to each script
#
# Revision 1.2 2006/12/15 04:53:59 bjorn
# Additional filtering, by Willi Mann.
#
# Revision 1.1 2006/05/30 19:04:26 bjorn
# Added fail2ban service, written by Yaroslav Halchenko.
#
# Written by Yaroslav Halchenko <debian@onerussian.com> for fail2ban
#
##########################################################################
########################################################
## Copyright (c) 2008 Yaroslav Halchenko
## Covered under the included MIT/X-Consortium License:
## http://www.opensource.org/licenses/mit-license.php
## All modifications and contributions by other persons to
## this script are assumed to have been donated to the
## Logwatch project and thus assume the above copyright
## and licensing terms. If you want to make contributions
## under your own copyright or a different license this
## must be explicitly stated in the contribution an the
## Logwatch project reserves the right to not accept such
## contributions. If you have made significant
## contributions to this script and want to claim
## copyright please contact logwatch-devel@lists.sourceforge.net.
#########################################################
use strict;
use Logwatch ':all';
my $Debug = $ENV{'LOGWATCH_DEBUG'} || 0;
my $Detail = $ENV{'LOGWATCH_DETAIL_LEVEL'} || 0;
my $IgnoreHost = $ENV{'sshd_ignore_host'} || "";
my $DebugCounter = 0;
my $ReInitializations = 0;
my @IptablesErrors = ();
my @ActionErrors = ();
my $NotValidIP = 0; # reported invalid IPs number
my @OtherList = ();
my %ServicesBans = ();
if ( $Debug >= 5 ) {
print STDERR "\n\nDEBUG: Inside Fail2Ban Filter \n\n";
$DebugCounter = 1;
}
while (defined(my $ThisLine = <STDIN>)) {
if ( $Debug >= 5 ) {
print STDERR "DEBUG($DebugCounter): $ThisLine";
$DebugCounter++;
}
chomp($ThisLine);
if ( ($ThisLine =~ /..,... DEBUG: /) or
($ThisLine =~ /..,... \S*\s*: DEBUG /) or # syntax of 0.7.? fail2ban
($ThisLine =~ /..,... INFO: (Fail2Ban v.* is running|Exiting|Enabled sections:)/) or
($ThisLine =~ /INFO\s+Log rotation detected for/) or
($ThisLine =~ /INFO\s+Jail.+(?:stopped|started|uses poller)/) or
($ThisLine =~ /INFO\s+Changed logging target to/) or
($ThisLine =~ /INFO\s+Creating new jail/) or
($ThisLine =~ /..,... \S+\s*: INFO\s+(Set |Socket|Exiting|Gamin|Created|Added|Using)/) or # syntax of 0.7.? fail2ban
($ThisLine =~ /..,... WARNING: Verbose level is /) or
($ThisLine =~ /..,... WARNING: Restoring firewall rules/)
)
{
if ( $Debug >= 6 ) {
print STDERR "DEBUG($DebugCounter): line ignored\n";
}
} elsif ( my ($Service,$Action,$Host) = ($ThisLine =~ m/WARNING:?\s\[?(.*?)[]:]?\s(Ban|Unban)[^\.]* (\S+)/)) {
if ( $Debug >= 6 ) {
print STDERR "DEBUG($DebugCounter): Found $Action for $Service from $Host\n";
}
$ServicesBans{$Service}{$Host}{$Action}++;
$ServicesBans{$Service}{"(all)"}{$Action}++;
} elsif ( my ($Service,$Host,$NumFailures) = ($ThisLine =~ m/INFO: (\S+): (.+) has (\d+) login failure\(s\). Banned./)) {
if ($Debug >= 4) {
print STDERR "DEBUG: Found host $Host trying to access $Service - failed $NumFailures times\n";
}
push @{$ServicesBans{$Service}{$Host}{'Failures'}}, $NumFailures;
} elsif ( my ($Service,$Host) = ($ThisLine =~ m/ ERROR:\s(.*):\s(\S+)\salready in ban list/)) {
$ServicesBans{$Service}{$Host}{'AlreadyInTheList'}++;
} elsif ( my ($Service,$Host) = ($ThisLine =~ m/WARNING\s*\[(.*)\]\s*(\S+)\s*already banned/)) {
$ServicesBans{$Service}{$Host}{'AlreadyInTheList'}++;
} elsif ( my ($Service,$Host) = ($ThisLine =~ m/ WARNING:\s(.*):\sReBan (\S+)/)) {
$ServicesBans{$Service}{$Host}{'ReBan'}++;
} elsif ($ThisLine =~ / ERROR:?\s*(Execution of command )?\'?iptables/) {
push @IptablesErrors, "$ThisLine\n";
} elsif ($ThisLine =~ /ERROR.*returned \d+$/) {
push @ActionErrors, "$ThisLine\n";
} elsif (($ThisLine =~ /..,... WARNING: \#\S+ reinitialization of firewalls/) or
($ThisLine =~ / ERROR\s*Invariant check failed. Trying to restore a sane environment/)) {
$ReInitializations++;
} elsif ($ThisLine =~ /..,... WARNING: is not a valid IP address/) {
# just ignore - this will be fixed within fail2ban and is harmless warning
}
else
{
# Report any unmatched entries...
push @OtherList, "$ThisLine\n";
}
}
###########################################################
if (keys %ServicesBans) {
printf("\nBanned services with Fail2Ban: Bans:Unbans\n");
foreach my $service (sort {$a cmp $b} keys %ServicesBans) {
printf(" %-55s [%3d:%-3d]\n", "$service:",
$ServicesBans{$service}{'(all)'}{'Ban'},
$ServicesBans{$service}{'(all)'}{'Unban'});
delete $ServicesBans{$service}{'(all)'};
my $totalSort = TotalCountOrder(%{$ServicesBans{$service}}, \&SortIP);
if ($Detail >= 5) {
foreach my $ip (sort $totalSort keys %{$ServicesBans{$service}}) {
my $name = LookupIP($ip);
printf(" %-53s %3d:%-3d\n",
$name,
$ServicesBans{$service}{$ip}{'Ban'},
$ServicesBans{$service}{$ip}{'Unban'});
if (($Detail >= 10) and ($ServicesBans{$service}{$ip}{'Failures'}>0)) {
print " Failed ";
foreach my $fails (@{$ServicesBans{$service}{$ip}{'Failures'}}) {
print " $fails";
}
print " times";
printf("\n %d Duplicate Ban attempts", $ServicesBans{$service}{$ip}{'AlreadyInTheList'}) ;
printf("\n %d ReBans due to rules reinitilizations", $ServicesBans{$service}{$ip}{'ReBan'}) ;
print "\n";
}
}
}
}
}
if ($Detail>0) {
if ($#IptablesErrors > 0) {
printf("\n%d faulty iptables invocation(s)", $#IptablesErrors);
if ($Detail > 5) {
print ":\n";
print @IptablesErrors ;
}
}
if ($#ActionErrors > 0) {
printf("\n%d error(s) returned from actions", $#ActionErrors);
if ($Detail > 5) {
print ":\n";
print @ActionErrors ;
}
}
if ($ReInitializations > 0) {
printf("\n%d fail2ban rules reinitialization(s)", $ReInitializations);
}
if ($#OtherList >= 0) {
print "\n**Unmatched Entries**\n";
print @OtherList;
}
}
exit(0);
# vi: shiftwidth=3 tabstop=3 syntax=perl et
# Local Variables:
# mode: perl
# perl-indent-level: 3
# indent-tabs-mode: nil
# End:
+14 -3
View File
@@ -4,10 +4,10 @@
|_| \__,_|_|_/___|_.__/\__,_|_||_|
================================================================================
Fail2Ban (version 0.9.0.dev) 2014/xx/xx
Fail2Ban (version 0.9.1) 2014/10/29
================================================================================
ver. 0.9.1 (2014/xx/xx) - better, faster, stronger
ver. 0.9.1 (2014/10/29) - better, faster, stronger
----------
- Refactoring (IMPORTANT -- Please review your setup and configuration):
@@ -16,6 +16,8 @@ ver. 0.9.1 (2014/xx/xx) - better, faster, stronger
provides defaults for the chain, port, protocol and name tags
- Fixes:
* start of file2ban aborted (on slow hosts, systemd considers the server has
been timed out and kills him), see gh-824
* UTF-8 fixes in pure-ftp thanks to Johannes Weberhofer. Closes gh-806.
* systemd backend error on bad utf-8 in python3
* badips.py action error when logging HTTP error raised with badips request
@@ -48,18 +50,26 @@ ver. 0.9.1 (2014/xx/xx) - better, faster, stronger
* cyrus-imap -- also catch also failed logins via secured (imaps/pop3s).
Regression was introduced while strengthening failregex in 0.8.11 (bd175f)
Debian bug #755173
* postfix-sasl -- added journalmatch. Thanks Luc Maisonobe
* postfix-sasl - added journalmatch. Thanks Luc Maisonobe
* postfix* - match with a new daemon string (postfix/submission/smtpd).
Closes gh-804 . Thanks Paul Traina
* apache - added filter for AH01630 client denied by server configuration.
- New features:
- New filters:
- monit Thanks Jason H Martin
- directadmin Thanks niorg
- apache-shellshock Thanks Eugene Hopkinson (SlowRiot)
- New actions:
- symbiosis-blacklist-allports for Bytemark symbiosis firewall
- fail2ban-client can fetch the running server version
- Added Cloudflare API action
- Enhancements
* Start performance of fail2ban-client (and tests) increased, start time
and cpu usage rapidly reduced. Introduced a shared storage logic, to
bypass reading lots of config files (see gh-824).
Thanks to Joost Molenaar for good catch (reported gh-820).
* Fail2ban-regex - add print-all-matched option. Closes gh-652
* Suppress fail2ban-client warnings for non-critical config options
* Match non "Bye Bye" disconnect messages for sshd locked account regex
@@ -71,6 +81,7 @@ ver. 0.9.1 (2014/xx/xx) - better, faster, stronger
not affect SYSLOG output
* Log unhandled exceptions
* cyrus-imap: catch "user not found" attempts
* Add support for Portsentry
ver. 0.9.0 (2014/03/14) - beta
----------
+12
View File
@@ -81,6 +81,18 @@ some quick commands::
status test
Testing with vagrant
--------------------
Testing can now be done inside a vagrant VM. Vagrantfile provided in
source code repository established two VMs:
- VM "secure" which can be used for testing fail2ban code.
- VM "attacker" which hcan be used to perform attack against our "secure" VM.
Both VMs are sharing the 192.168.200/24 network. If you are using this network
take a look into the Vagrantfile and change the IP.
Coding Standards
================
+190 -158
View File
@@ -1,11 +1,14 @@
README.md
README.Solaris
ChangeLog
TODO
THANKS
CONTRIBUTING.md
COPYING
ChangeLog
DEVELOP
FILTERS
README.Solaris
README.md
RELEASE
THANKS
TODO
Vagrantfile
fail2ban-2to3
fail2ban-testcases-all
fail2ban-testcases-all-python3
@@ -14,109 +17,108 @@ bin/fail2ban-server
bin/fail2ban-testcases
bin/fail2ban-regex
doc/run-rootless.txt
fail2ban/client/configreader.py
fail2ban/client/configparserinc.py
fail2ban/client/jailreader.py
fail2ban/client/fail2banreader.py
fail2ban/client/jailsreader.py
fail2ban/client/beautifier.py
fail2ban/client/filterreader.py
fail2ban/client/actionreader.py
fail2ban/client/__init__.py
fail2ban/client/actionreader.py
fail2ban/client/beautifier.py
fail2ban/client/configparserinc.py
fail2ban/client/configreader.py
fail2ban/client/configurator.py
fail2ban/client/csocket.py
fail2ban/server/asyncserver.py
fail2ban/server/database.py
fail2ban/server/filter.py
fail2ban/server/filterpyinotify.py
fail2ban/server/filtergamin.py
fail2ban/server/filterpoll.py
fail2ban/server/filtersystemd.py
fail2ban/server/iso8601.py
fail2ban/server/server.py
fail2ban/client/fail2banreader.py
fail2ban/client/filterreader.py
fail2ban/client/jailreader.py
fail2ban/client/jailsreader.py
fail2ban/server/__init__.py
fail2ban/server/action.py
fail2ban/server/actions.py
fail2ban/server/asyncserver.py
fail2ban/server/banmanager.py
fail2ban/server/database.py
fail2ban/server/datedetector.py
fail2ban/server/datetemplate.py
fail2ban/server/faildata.py
fail2ban/server/failmanager.py
fail2ban/server/datedetector.py
fail2ban/server/jailthread.py
fail2ban/server/transmitter.py
fail2ban/server/action.py
fail2ban/server/ticket.py
fail2ban/server/failregex.py
fail2ban/server/filter.py
fail2ban/server/filtergamin.py
fail2ban/server/filterpoll.py
fail2ban/server/filterpyinotify.py
fail2ban/server/filtersystemd.py
fail2ban/server/iso8601.py
fail2ban/server/jail.py
fail2ban/server/jails.py
fail2ban/server/__init__.py
fail2ban/server/banmanager.py
fail2ban/server/datetemplate.py
fail2ban/server/jailthread.py
fail2ban/server/mytime.py
fail2ban/server/failregex.py
fail2ban/server/database.py
fail2ban/tests/banmanagertestcase.py
fail2ban/tests/failmanagertestcase.py
fail2ban/tests/clientreadertestcase.py
fail2ban/tests/filtertestcase.py
fail2ban/server/server.py
fail2ban/server/strptime.py
fail2ban/server/ticket.py
fail2ban/server/transmitter.py
fail2ban/tests/__init__.py
fail2ban/tests/dummyjail.py
fail2ban/tests/samplestestcase.py
fail2ban/tests/datedetectortestcase.py
fail2ban/tests/action_d/__init__.py
fail2ban/tests/action_d/test_badips.py
fail2ban/tests/action_d/test_smtp.py
fail2ban/tests/actionstestcase.py
fail2ban/tests/actiontestcase.py
fail2ban/tests/servertestcase.py
fail2ban/tests/sockettestcase.py
fail2ban/tests/utils.py
fail2ban/tests/misctestcase.py
fail2ban/tests/databasetestcase.py
fail2ban/tests/config/jail.conf
fail2ban/tests/banmanagertestcase.py
fail2ban/tests/clientreadertestcase.py
fail2ban/tests/config/action.d/brokenaction.conf
fail2ban/tests/config/fail2ban.conf
fail2ban/tests/config/filter.d/simple.conf
fail2ban/tests/config/jail.conf
fail2ban/tests/config/paths-common.conf
fail2ban/tests/config/paths-debian.conf
fail2ban/tests/config/paths-freebsd.conf
fail2ban/tests/config/paths-osx.conf
fail2ban/tests/config/paths-debian.conf
fail2ban/tests/config/filter.d/simple.conf
fail2ban/tests/config/action.d/brokenaction.conf
fail2ban/tests/files/config/apache-auth/digest/.htaccess
fail2ban/tests/files/config/apache-auth/digest/.htpasswd
fail2ban/tests/files/config/apache-auth/digest_time/.htaccess
fail2ban/tests/files/config/apache-auth/digest_time/.htpasswd
fail2ban/tests/databasetestcase.py
fail2ban/tests/datedetectortestcase.py
fail2ban/tests/dummyjail.py
fail2ban/tests/failmanagertestcase.py
fail2ban/tests/files/action.d/action.py
fail2ban/tests/files/action.d/action_errors.py
fail2ban/tests/files/action.d/action_modifyainfo.py
fail2ban/tests/files/action.d/action_noAction.py
fail2ban/tests/files/action.d/action_nomethod.py
fail2ban/tests/files/config/apache-auth/README
fail2ban/tests/files/config/apache-auth/basic/authz_owner/.htaccess
fail2ban/tests/files/config/apache-auth/basic/authz_owner/cant_get_me.html
fail2ban/tests/files/config/apache-auth/basic/authz_owner/.htpasswd
fail2ban/tests/files/config/apache-auth/basic/authz_owner/cant_get_me.html
fail2ban/tests/files/config/apache-auth/basic/file/.htaccess
fail2ban/tests/files/config/apache-auth/basic/file/.htpasswd
fail2ban/tests/files/config/apache-auth/digest.py
fail2ban/tests/files/config/apache-auth/digest_wrongrelm/.htaccess
fail2ban/tests/files/config/apache-auth/digest_wrongrelm/.htpasswd
fail2ban/tests/files/config/apache-auth/digest/.htaccess
fail2ban/tests/files/config/apache-auth/digest/.htpasswd
fail2ban/tests/files/config/apache-auth/digest_anon/.htaccess
fail2ban/tests/files/config/apache-auth/digest_anon/.htpasswd
fail2ban/tests/files/config/apache-auth/README
fail2ban/tests/files/config/apache-auth/digest_time/.htaccess
fail2ban/tests/files/config/apache-auth/digest_time/.htpasswd
fail2ban/tests/files/config/apache-auth/digest_wrongrelm/.htaccess
fail2ban/tests/files/config/apache-auth/digest_wrongrelm/.htpasswd
fail2ban/tests/files/config/apache-auth/noentry/.htaccess
fail2ban/tests/files/database_v1.db
fail2ban/tests/files/ignorecommand.py
fail2ban/tests/files/filter.d/substition.conf
fail2ban/tests/files/filter.d/testcase-common.conf
fail2ban/tests/files/filter.d/testcase01.conf
fail2ban/tests/files/testcase01.log
fail2ban/tests/files/testcase02.log
fail2ban/tests/files/testcase03.log
fail2ban/tests/files/testcase04.log
fail2ban/tests/files/testcase-usedns.log
fail2ban/tests/files/testcase-journal.log
fail2ban/tests/files/testcase-multiline.log
fail2ban/tests/files/logs/bsd/syslog-plain.txt
fail2ban/tests/files/logs/bsd/syslog-v.txt
fail2ban/tests/files/logs/bsd/syslog-vv.txt
fail2ban/tests/files/ignorecommand.py
fail2ban/tests/files/logs/3proxy
fail2ban/tests/files/logs/apache-auth
fail2ban/tests/files/logs/apache-badbots
fail2ban/tests/files/logs/apache-botscripts
fail2ban/tests/files/logs/apache-botsearch
fail2ban/tests/files/logs/apache-modsecurity
fail2ban/tests/files/logs/apache-nohome
fail2ban/tests/files/logs/apache-noscript
fail2ban/tests/files/logs/apache-overflows
fail2ban/tests/files/logs/apache-shellshock
fail2ban/tests/files/logs/assp
fail2ban/tests/files/logs/asterisk
fail2ban/tests/files/logs/bsd/syslog-plain.txt
fail2ban/tests/files/logs/bsd/syslog-v.txt
fail2ban/tests/files/logs/bsd/syslog-vv.txt
fail2ban/tests/files/logs/counter-strike
fail2ban/tests/files/logs/courier-auth
fail2ban/tests/files/logs/courier-smtp
fail2ban/tests/files/logs/cyrus-imap
fail2ban/tests/files/logs/directadmin
fail2ban/tests/files/logs/dovecot
fail2ban/tests/files/logs/dropbear
fail2ban/tests/files/logs/ejabberd-auth
@@ -126,42 +128,60 @@ fail2ban/tests/files/logs/freeswitch
fail2ban/tests/files/logs/groupoffice
fail2ban/tests/files/logs/gssftpd
fail2ban/tests/files/logs/guacamole
fail2ban/tests/files/logs/horde
fail2ban/tests/files/logs/kerio
fail2ban/tests/files/logs/lighttpd-auth
fail2ban/tests/files/logs/monit
fail2ban/tests/files/logs/mysqld-auth
fail2ban/tests/files/logs/nagios
fail2ban/tests/files/logs/nsd
fail2ban/tests/files/logs/perdition
fail2ban/tests/files/logs/php-url-fopen
fail2ban/tests/files/logs/postfix-sasl
fail2ban/tests/files/logs/named-refused
fail2ban/tests/files/logs/nginx-http-auth
fail2ban/tests/files/logs/nsd
fail2ban/tests/files/logs/openwebmail
fail2ban/tests/files/logs/oracleims
fail2ban/tests/files/logs/pam-generic
fail2ban/tests/files/logs/perdition
fail2ban/tests/files/logs/php-url-fopen
fail2ban/tests/files/logs/portsentry
fail2ban/tests/files/logs/postfix
fail2ban/tests/files/logs/postfix-sasl
fail2ban/tests/files/logs/proftpd
fail2ban/tests/files/logs/pure-ftpd
fail2ban/tests/files/logs/qmail
fail2ban/tests/files/logs/recidive
fail2ban/tests/files/logs/roundcube-auth
fail2ban/tests/files/logs/selinux-ssh
fail2ban/tests/files/logs/sendmail-auth
fail2ban/tests/files/logs/sendmail-reject
fail2ban/tests/files/logs/sendmail-spam
fail2ban/tests/files/logs/sieve
fail2ban/tests/files/logs/squid
fail2ban/tests/files/logs/stunnel
fail2ban/tests/files/logs/suhosin
fail2ban/tests/files/logs/sogo-auth
fail2ban/tests/files/logs/solid-pop3d
fail2ban/tests/files/logs/squid
fail2ban/tests/files/logs/squirrelmail
fail2ban/tests/files/logs/sshd
fail2ban/tests/files/logs/sshd-ddos
fail2ban/tests/files/logs/stunnel
fail2ban/tests/files/logs/suhosin
fail2ban/tests/files/logs/tine20
fail2ban/tests/files/logs/uwimap-auth
fail2ban/tests/files/logs/vsftpd
fail2ban/tests/files/logs/webmin-auth
fail2ban/tests/files/logs/wuftpd
fail2ban/tests/files/logs/uwimap-auth
fail2ban/tests/files/logs/xinetd-fail
fail2ban/tests/config/jail.conf
fail2ban/tests/config/fail2ban.conf
fail2ban/tests/config/filter.d/simple.conf
fail2ban/tests/config/action.d/brokenaction.conf
fail2ban/tests/files/testcase-journal.log
fail2ban/tests/files/testcase-multiline.log
fail2ban/tests/files/testcase-usedns.log
fail2ban/tests/files/testcase01.log
fail2ban/tests/files/testcase02.log
fail2ban/tests/files/testcase03.log
fail2ban/tests/files/testcase04.log
fail2ban/tests/filtertestcase.py
fail2ban/tests/misctestcase.py
fail2ban/tests/samplestestcase.py
fail2ban/tests/servertestcase.py
fail2ban/tests/sockettestcase.py
fail2ban/tests/utils.py
setup.py
setup.cfg
fail2ban/__init__.py
@@ -169,126 +189,136 @@ fail2ban/exceptions.py
fail2ban/helpers.py
fail2ban/version.py
fail2ban/protocol.py
setup.py
setup.cfg
kill-server
config/jail.conf
config/action.d/apf.conf
config/action.d/badips.conf
config/action.d/badips.py
config/action.d/blocklist_de.conf
config/action.d/bsd-ipfw.conf
config/action.d/cloudflare.conf
config/action.d/complain.conf
config/action.d/dshield.conf
config/action.d/dummy.conf
config/action.d/firewallcmd-ipset.conf
config/action.d/firewallcmd-new.conf
config/action.d/hostsdeny.conf
config/action.d/ipfilter.conf
config/action.d/ipfw.conf
config/action.d/iptables-allports.conf
config/action.d/iptables-common.conf
config/action.d/iptables-ipset-proto4.conf
config/action.d/iptables-ipset-proto6-allports.conf
config/action.d/iptables-ipset-proto6.conf
config/action.d/iptables-multiport-log.conf
config/action.d/iptables-multiport.conf
config/action.d/iptables-new.conf
config/action.d/iptables-xt_recent-echo.conf
config/action.d/iptables.conf
config/action.d/mail-buffered.conf
config/action.d/mail-whois-lines.conf
config/action.d/mail-whois.conf
config/action.d/mail.conf
config/action.d/mynetwatchman.conf
config/action.d/osx-afctl.conf
config/action.d/osx-ipfw.conf
config/action.d/pf.conf
config/action.d/route.conf
config/action.d/sendmail-buffered.conf
config/action.d/sendmail-common.conf
config/action.d/sendmail-whois-ipjailmatches.conf
config/action.d/sendmail-whois-ipmatches.conf
config/action.d/sendmail-whois-lines.conf
config/action.d/sendmail-whois-matches.conf
config/action.d/sendmail-whois.conf
config/action.d/sendmail.conf
config/action.d/shorewall.conf
config/action.d/smtp.py
config/action.d/symbiosis-blacklist-allports.conf
config/action.d/ufw.conf
config/action.d/xarf-login-attack.conf
config/fail2ban.conf
config/filter.d/common.conf
config/filter.d/3proxy.conf
config/filter.d/apache-auth.conf
config/filter.d/apache-badbots.conf
config/filter.d/apache-botsearch.conf
config/filter.d/apache-common.conf
config/filter.d/apache-modsecurity.conf
config/filter.d/apache-nohome.conf
config/filter.d/apache-noscript.conf
config/filter.d/apache-overflows.conf
config/filter.d/nginx-http-auth.conf
config/filter.d/apache-shellshock.conf
config/filter.d/assp.conf
config/filter.d/asterisk.conf
config/filter.d/common.conf
config/filter.d/counter-strike.conf
config/filter.d/courier-auth.conf
config/filter.d/courier-smtp.conf
config/filter.d/cyrus-imap.conf
config/filter.d/directadmin.conf
config/filter.d/dovecot.conf
config/filter.d/dropbear.conf
config/filter.d/ejabberd-auth.conf
config/filter.d/exim-common.conf
config/filter.d/exim-spam.conf
config/filter.d/exim.conf
config/filter.d/freeswitch.conf
config/filter.d/groupoffice.conf
config/filter.d/gssftpd.conf
config/filter.d/kerio.conf
config/filter.d/guacamole.conf
config/filter.d/horde.conf
config/filter.d/suhosin.conf
config/filter.d/kerio.conf
config/filter.d/lighttpd-auth.conf
config/filter.d/monit.conf
config/filter.d/mysqld-auth.conf
config/filter.d/nagios.conf
config/filter.d/named-refused.conf
config/filter.d/nginx-http-auth.conf
config/filter.d/nsd.conf
config/filter.d/openwebmail.conf
config/filter.d/oracleims.conf
config/filter.d/pam-generic.conf
config/filter.d/pam-generic.conf
config/filter.d/pam-generic.conf
config/filter.d/perdition.conf
config/filter.d/php-url-fopen.conf
config/filter.d/php-url-fopen.conf
config/filter.d/php-url-fopen.conf
config/filter.d/portsentry.conf
config/filter.d/postfix-sasl.conf
config/filter.d/postfix-sasl.conf
config/filter.d/pam-generic.conf
config/filter.d/php-url-fopen.conf
config/filter.d/postfix-sasl.conf
config/filter.d/postfix.conf
config/filter.d/proftpd.conf
config/filter.d/pure-ftpd.conf
config/filter.d/qmail.conf
config/filter.d/pam-generic.conf
config/filter.d/php-url-fopen.conf
config/filter.d/postfix-sasl.conf
config/filter.d/recidive.conf
config/filter.d/roundcube-auth.conf
config/filter.d/selinux-common.conf
config/filter.d/selinux-ssh.conf
config/filter.d/sendmail-auth.conf
config/filter.d/sendmail-reject.conf
config/filter.d/sendmail-spam.conf
config/filter.d/sieve.conf
config/filter.d/sogo-auth.conf
config/filter.d/solid-pop3d.conf
config/filter.d/squid.conf
config/filter.d/sshd.conf
config/filter.d/squirrelmail.conf
config/filter.d/sshd-ddos.conf
config/filter.d/sshd.conf
config/filter.d/stunnel.conf
config/filter.d/suhosin.conf
config/filter.d/tine20.conf
config/filter.d/uwimap-auth.conf
config/filter.d/vsftpd.conf
config/filter.d/webmin-auth.conf
config/filter.d/wuftpd.conf
config/filter.d/xinetd-fail.conf
config/filter.d/asterisk.conf
config/filter.d/dovecot.conf
config/filter.d/dropbear.conf
config/filter.d/lighttpd-auth.conf
config/filter.d/recidive.conf
config/filter.d/roundcube-auth.conf
config/filter.d/assp.conf
config/filter.d/sogo-auth.conf
config/filter.d/mysqld-auth.conf
config/filter.d/selinux-common.conf
config/filter.d/selinux-ssh.conf
config/filter.d/3proxy.conf
config/filter.d/apache-common.conf
config/filter.d/exim-common.conf
config/filter.d/exim-spam.conf
config/filter.d/freeswitch.conf
config/filter.d/groupoffice.conf
config/filter.d/perdition.conf
config/filter.d/uwimap-auth.conf
config/filter.d/courier-auth.conf
config/filter.d/courier-smtp.conf
config/filter.d/ejabberd-auth.conf
config/filter.d/guacamole.conf
config/filter.d/sendmail-spam.conf
config/action.d/apf.conf
config/action.d/blocklist_de.conf
config/action.d/osx-afctl.conf
config/action.d/osx-ipfw.conf
config/action.d/sendmail-common.conf
config/action.d/badips.conf
config/action.d/bsd-ipfw.conf
config/action.d/dummy.conf
config/action.d/firewallcmd-new.conf
config/action.d/firewallcmd-ipset.conf
config/action.d/iptables-ipset-proto6-allports.conf
config/action.d/iptables-common.conf
config/action.d/iptables-ipset-proto4.conf
config/action.d/iptables-ipset-proto6.conf
config/action.d/iptables-xt_recent-echo.conf
config/action.d/route.conf
config/action.d/complain.conf
config/action.d/dshield.conf
config/action.d/hostsdeny.conf
config/action.d/ipfw.conf
config/action.d/ipfilter.conf
config/action.d/iptables.conf
config/action.d/iptables-allports.conf
config/action.d/iptables-multiport.conf
config/action.d/iptables-multiport-log.conf
config/action.d/iptables-new.conf
config/action.d/mail.conf
config/action.d/mail-buffered.conf
config/action.d/mail-whois.conf
config/action.d/mail-whois-lines.conf
config/action.d/mynetwatchman.conf
config/action.d/pf.conf
config/action.d/sendmail.conf
config/action.d/sendmail-buffered.conf
config/action.d/sendmail-whois-ipmatches.conf
config/action.d/sendmail-whois.conf
config/action.d/sendmail-whois-lines.conf
config/action.d/shorewall.conf
config/action.d/xarf-login-attack.conf
config/action.d/ufw.conf
config/fail2ban.conf
doc/run-rootless.txt
config/jail.conf
config/paths-common.conf
config/paths-debian.conf
config/paths-fedora.conf
config/paths-freebsd.conf
config/paths-osx.conf
man/fail2ban-client.1
man/fail2ban.1
man/jail.conf.5
@@ -306,6 +336,8 @@ files/solaris-fail2ban.xml
files/solaris-svc-fail2ban
files/suse-initd
files/fail2ban-logrotate
files/fail2ban.upstart
files/logwatch/fail2ban
files/cacti/fail2ban_stats.sh
files/cacti/cacti_host_template_fail2ban.xml
files/cacti/README
+1 -1
View File
@@ -1,4 +1,4 @@
include ChangeLog COPYING DEVELOP FILTERS README.* THANKS TODO
include ChangeLog COPYING DEVELOP FILTERS README.* THANKS TODO CONTRIBUTING* Vagrantfile
graft doc
graft files
recursive-include config *.conf *.py
+3 -3
View File
@@ -2,7 +2,7 @@
/ _|__ _(_) |_ ) |__ __ _ _ _
| _/ _` | | |/ /| '_ \/ _` | ' \
|_| \__,_|_|_/___|_.__/\__,_|_||_|
v0.9.0 2014/03/14
v0.9.1 2014/10/29
## Fail2Ban: ban hosts that cause multiple authentication errors
@@ -36,8 +36,8 @@ Optional:
To install, just do:
tar xvfj fail2ban-0.9.0.tar.bz2
cd fail2ban-0.9.0
tar xvfj fail2ban-0.9.1.tar.bz2
cd fail2ban-0.9.1
python setup.py install
This will install Fail2Ban into the python library directory. The executable
+9 -5
View File
@@ -47,6 +47,10 @@ Preparation
* Ensure the MANIFEST is complete
ad-hoc bash script to run in a clean clone:
find -type f | grep -v -e '\.git' -e '/doc/' -e '\.travis' -e MANIFEST | sed -e 's,^\./,,g' | while read f; do grep -ne "^$f\$" MANIFEST >/dev/null || echo "$f" ; done
* Run::
python setup.py sdist
@@ -57,24 +61,24 @@ Preparation
* Which indicates that testcases/files/logs/mysqld.log has been moved or is a directory::
tar -C /tmp -jxf dist/fail2ban-0.9.0.tar.bz2
tar -C /tmp -jxf dist/fail2ban-0.9.1.tar.bz2
* clean up current direcory::
diff -rul --exclude \*.pyc . /tmp/fail2ban-0.9.0/
diff -rul --exclude \*.pyc . /tmp/fail2ban-0.9.1/
* Only differences should be files that you don't want distributed.
* Ensure the tests work from the tarball::
cd /tmp/fail2ban-0.9.0/ && export PYTHONPATH=`pwd` && bin/fail2ban-testcases
cd /tmp/fail2ban-0.9.1/ && export PYTHONPATH=`pwd` && bin/fail2ban-testcases
* Add/finalize the corresponding entry in the ChangeLog
* To generate a list of committers use e.g.::
git shortlog -sn 0.8.12.. | sed -e 's,^[ 0-9\t]*,,g' | tr '\n' '\|' | sed -e 's:|:, :g'
git shortlog -sn 0.9.1.. | sed -e 's,^[ 0-9\t]*,,g' | tr '\n' '\|' | sed -e 's:|:, :g'
* Ensure the top of the ChangeLog has the right version and current date.
* Ensure the top entry of the ChangeLog has the right version and current date.
@@ -181,7 +185,7 @@ Post Release
Add the following to the top of the ChangeLog::
ver. 0.9.1 (2014/XX/XXX) - wanna-be-released
ver. 0.9.2 (2014/XX/XXX) - wanna-be-released
-----------
- Fixes:
+3
View File
@@ -26,6 +26,7 @@ Christian Rauch
Christophe Carles
Christoph Haas
Christos Psonis
craneworks
Cyril Jaquier
Daniel B. Cid
Daniel B.
@@ -34,6 +35,7 @@ David Nutter
Derek Atkins
Eric Gerbier
Enrico Labedzki
Eugene Hopkinson (SlowRiot)
ftoppi
François Boulogne
Frédéric
@@ -81,6 +83,7 @@ Mika (mkl)
Nick Munger
onorua
Paul Marrapese
Paul Traina
Noel Butler
Patrick Börjesson
Pressy
Vendored
-5
View File
@@ -1,10 +1,5 @@
Vagrant.configure("2") do |config|
config.vm.define "builder" do |builder|
builder.vm.box = "vm144"
builder.vm.provision "shell", path: "provision.sh"
end
config.vm.define "secure" do |secure|
secure.vm.box = "ubuntu/trusty64"
secure.vm.hostname = "secure.dev.fail2ban.org"
+46 -46
View File
@@ -59,53 +59,53 @@ class Fail2banClient:
self.__conf["pidfile"] = None
def dispVersion(self):
print("Fail2Ban v" + version)
print()
print("Copyright (c) 2004-2008 Cyril Jaquier, 2008- Fail2Ban Contributors")
print("Copyright of modifications held by their respective authors.")
print("Licensed under the GNU General Public License v2 (GPL).")
print()
print("Written by Cyril Jaquier <cyril.jaquier@fail2ban.org>.")
print("Many contributions by Yaroslav O. Halchenko <debian@onerussian.com>.")
print "Fail2Ban v" + version
print
print "Copyright (c) 2004-2008 Cyril Jaquier, 2008- Fail2Ban Contributors"
print "Copyright of modifications held by their respective authors."
print "Licensed under the GNU General Public License v2 (GPL)."
print
print "Written by Cyril Jaquier <cyril.jaquier@fail2ban.org>."
print "Many contributions by Yaroslav O. Halchenko <debian@onerussian.com>."
def dispUsage(self):
""" Prints Fail2Ban command line options and exits
"""
print("Usage: "+self.__argv[0]+" [OPTIONS] <COMMAND>")
print()
print("Fail2Ban v" + version + " reads log file that contains password failure report")
print("and bans the corresponding IP addresses using firewall rules.")
print()
print("Options:")
print(" -c <DIR> configuration directory")
print(" -s <FILE> socket path")
print(" -p <FILE> pidfile path")
print(" -d dump configuration. For debugging")
print(" -i interactive mode")
print(" -v increase verbosity")
print(" -q decrease verbosity")
print(" -x force execution of the server (remove socket file)")
print(" -b start server in background (default)")
print(" -f start server in foreground (note that the client forks once itself)")
print(" -h, --help display this help message")
print(" -V, --version print the version")
print()
print("Command:")
print "Usage: "+self.__argv[0]+" [OPTIONS] <COMMAND>"
print
print "Fail2Ban v" + version + " reads log file that contains password failure report"
print "and bans the corresponding IP addresses using firewall rules."
print
print "Options:"
print " -c <DIR> configuration directory"
print " -s <FILE> socket path"
print " -p <FILE> pidfile path"
print " -d dump configuration. For debugging"
print " -i interactive mode"
print " -v increase verbosity"
print " -q decrease verbosity"
print " -x force execution of the server (remove socket file)"
print " -b start server in background (default)"
print " -f start server in foreground (note that the client forks once itself)"
print " -h, --help display this help message"
print " -V, --version print the version"
print
print "Command:"
# Prints the protocol
printFormatted()
print()
print("Report bugs to https://github.com/fail2ban/fail2ban/issues")
print
print "Report bugs to https://github.com/fail2ban/fail2ban/issues"
def dispInteractive(self):
print("Fail2Ban v" + version + " reads log file that contains password failure report")
print("and bans the corresponding IP addresses using firewall rules.")
print()
print "Fail2Ban v" + version + " reads log file that contains password failure report"
print "and bans the corresponding IP addresses using firewall rules."
print
def __sigTERMhandler(self, signum, frame):
# Print a new line because we probably come from wait
print()
print
logSys.warning("Caught signal %d. Exiting" % signum)
sys.exit(-1)
@@ -152,19 +152,19 @@ class Fail2banClient:
client = CSocket(self.__conf["socket"])
ret = client.send(c)
if ret[0] == 0:
logSys.debug("OK : " + repr(ret[1]))
logSys.debug("OK : " + `ret[1]`)
if showRet:
print(beautifier.beautify(ret[1]))
print beautifier.beautify(ret[1])
else:
logSys.error("NOK: " + repr(ret[1].args))
logSys.error("NOK: " + `ret[1].args`)
if showRet:
print(beautifier.beautifyError(ret[1]))
print beautifier.beautifyError(ret[1])
streamRet = False
except socket.error:
if showRet:
logSys.error("Unable to contact server. Is it running?")
return False
except Exception as e:
except Exception, e:
if showRet:
logSys.error(e)
return False
@@ -383,7 +383,7 @@ class Fail2banClient:
readline.parse_and_bind("tab: complete")
self.dispInteractive()
while True:
cmd = input(self.PROMPT)
cmd = raw_input(self.PROMPT)
if cmd == "exit" or cmd == "quit":
# Exit
return True
@@ -392,10 +392,10 @@ class Fail2banClient:
elif not cmd == "":
try:
self.__processCommand(shlex.split(cmd))
except Exception as e:
except Exception, e:
logSys.error(e)
except (EOFError, KeyboardInterrupt):
print()
print
return True
# Single command mode
else:
@@ -409,21 +409,21 @@ class Fail2banClient:
# TODO: get away from stew of return codes and exception
# handling -- handle via exceptions
try:
self.__configurator.Reload()
self.__configurator.readAll()
ret = self.__configurator.getOptions(jail)
self.__configurator.convertToProtocol()
self.__stream = self.__configurator.getConfigStream()
except Exception as e:
except Exception, e:
logSys.error("Failed during configuration: %s" % e)
ret = False
return ret
#@staticmethod
@staticmethod
def dumpConfig(cmd):
for c in cmd:
print(c)
print c
return True
dumpConfig = staticmethod(dumpConfig)
class ServerExecutionException(Exception):
+46 -44
View File
@@ -29,10 +29,10 @@ __author__ = "Fail2Ban Developers"
__copyright__ = "Copyright (c) 2004-2008 Cyril Jaquier, 2012-2014 Yaroslav Halchenko"
__license__ = "GPL"
import getopt, sys, time, logging, os, locale, shlex, time, urllib.request, urllib.parse, urllib.error
import getopt, sys, time, logging, os, locale, shlex, time, urllib
from optparse import OptionParser, Option
from configparser import NoOptionError, NoSectionError, MissingSectionHeaderError
from ConfigParser import NoOptionError, NoSectionError, MissingSectionHeaderError
try:
from systemd import journal
@@ -50,7 +50,7 @@ from fail2ban.helpers import FormatterWithTraceBack, getLogger
logSys = getLogger("fail2ban")
def debuggexURL(sample, regex):
q = urllib.parse.urlencode({ 're': regex.replace('<HOST>', '(?&.ipv4)'),
q = urllib.urlencode({ 're': regex.replace('<HOST>', '(?&.ipv4)'),
'str': sample,
'flavor': 'python' })
return 'http://www.debuggex.com/?' + q
@@ -69,7 +69,7 @@ def pprint_list(l, header=None):
s = "|- %s\n" % header
else:
s = ''
print(s + "| " + "\n| ".join(l) + '\n`-')
print s + "| " + "\n| ".join(l) + '\n`-'
def file_lines_gen(hdlr):
for line in hdlr:
@@ -244,14 +244,14 @@ class Fail2banRegex(object):
self._filter.setDatePattern(pattern)
self._datepattern_set = True
if pattern is not None:
print("Use datepattern : %s" % (
self._filter.getDatePattern()[1], ))
print "Use datepattern : %s" % (
self._filter.getDatePattern()[1], )
def setMaxLines(self, v):
if not self._maxlines_set:
self._filter.setMaxLines(int(v))
self._maxlines_set = True
print("Use maxlines : %d" % self._filter.getMaxLines())
print "Use maxlines : %d" % self._filter.getMaxLines()
def setJournalMatch(self, v):
if self._journalmatch is None:
@@ -261,7 +261,7 @@ class Fail2banRegex(object):
assert(regextype in ('fail', 'ignore'))
regex = regextype + 'regex'
if os.path.isfile(value):
print("Use %11s file : %s" % (regex, value))
print "Use %11s file : %s" % (regex, value)
reader = FilterReader(value, 'fail2ban-regex-jail', {})
reader.setBaseDir(None)
@@ -270,7 +270,9 @@ class Fail2banRegex(object):
readercommands = reader.convert()
regex_values = [
RegexStat(m[3])
for m in [x for x in readercommands if x[0] == 'set' and x[2] == "add%sregex" % regextype]]
for m in filter(
lambda x: x[0] == 'set' and x[2] == "add%sregex" % regextype,
readercommands)]
# Read out and set possible value of maxlines
for command in readercommands:
if command[2] == "maxlines":
@@ -278,8 +280,8 @@ class Fail2banRegex(object):
try:
self.setMaxLines(maxlines)
except ValueError:
print("ERROR: Invalid value for maxlines (%(maxlines)r) " \
"read from %(value)s" % locals())
print "ERROR: Invalid value for maxlines (%(maxlines)r) " \
"read from %(value)s" % locals()
return False
elif command[2] == 'addjournalmatch':
journalmatch = command[3]
@@ -288,10 +290,10 @@ class Fail2banRegex(object):
datepattern = command[3]
self.setDatePattern(datepattern)
else:
print("ERROR: failed to read %s" % value)
print "ERROR: failed to read %s" % value
return False
else:
print("Use %11s line : %s" % (regex, shortstr(value)))
print "Use %11s line : %s" % (regex, shortstr(value))
regex_values = [RegexStat(value)]
setattr(self, "_" + regex, regex_values)
@@ -308,8 +310,8 @@ class Fail2banRegex(object):
if ret is not None:
found = True
regex = self._ignoreregex[ret].inc()
except RegexException as e:
print(e)
except RegexException, e:
print e
return False
return found
@@ -325,11 +327,11 @@ class Fail2banRegex(object):
regex = self._failregex[match[0]]
regex.inc()
regex.appendIP(match)
except RegexException as e:
print(e)
except RegexException, e:
print e
return False
except IndexError:
print("Sorry, but no <HOST> found in regex")
print "Sorry, but no <HOST> found in regex"
return False
for bufLine in orgLineBuffer[int(fullBuffer):]:
if bufLine not in self._filter._Filter__lineBuffer:
@@ -403,21 +405,21 @@ class Fail2banRegex(object):
ans = [[]]
for arg in [l, regexlist]:
ans = [ x + [y] for x in ans for y in arg ]
b = [a[0] + ' | ' + a[1].getFailRegex() + ' | ' + debuggexURL(a[0], a[1].getFailRegex()) for a in ans]
b = map(lambda a: a[0] + ' | ' + a[1].getFailRegex() + ' | ' + debuggexURL(a[0], a[1].getFailRegex()), ans)
pprint_list([x.rstrip() for x in b], header)
else:
print("%s too many to print. Use --print-all-%s " \
"to print all %d lines" % (header, ltype, lines))
print "%s too many to print. Use --print-all-%s " \
"to print all %d lines" % (header, ltype, lines)
elif lines < self._maxlines or getattr(self, '_print_all_' + ltype):
pprint_list([x.rstrip() for x in l], header)
else:
print("%s too many to print. Use --print-all-%s " \
"to print all %d lines" % (header, ltype, lines))
print "%s too many to print. Use --print-all-%s " \
"to print all %d lines" % (header, ltype, lines)
def printStats(self):
print()
print("Results")
print("=======")
print
print "Results"
print "======="
def print_failregexes(title, failregexes):
# Print title
@@ -438,7 +440,7 @@ class Fail2banRegex(object):
timeString,
ip[-1] and " (multiple regex matched)" or ""))
print("\n%s: %d total" % (title, total))
print "\n%s: %d total" % (title, total)
pprint_list(out, " #) [# of hits] regular expression")
return total
@@ -448,7 +450,7 @@ class Fail2banRegex(object):
if self._filter.dateDetector is not None:
print("\nDate template hits:")
print "\nDate template hits:"
out = []
for template in self._filter.dateDetector.templates:
if self._verbose or template.hits:
@@ -456,10 +458,10 @@ class Fail2banRegex(object):
template.hits, template.name))
pprint_list(out, "[# of hits] date format")
print("\nLines: %s" % self._line_stats, end=' ')
print "\nLines: %s" % self._line_stats,
if self._time_elapsed is not None:
print("[processed in %.2f sec]" % self._time_elapsed, end=' ')
print()
print "[processed in %.2f sec]" % self._time_elapsed,
print
if self._print_all_matched:
self.printLines('matched')
@@ -484,10 +486,10 @@ if __name__ == "__main__":
parser.print_help()
sys.exit(-1)
print()
print("Running tests")
print("=============")
print()
print
print "Running tests"
print "============="
print
fail2banRegex = Fail2banRegex(opts)
@@ -536,15 +538,15 @@ if __name__ == "__main__":
if os.path.isfile(cmd_log):
try:
hdlr = open(cmd_log, 'rb')
print("Use log file : %s" % cmd_log)
print("Use encoding : %s" % fail2banRegex.encoding)
print "Use log file : %s" % cmd_log
print "Use encoding : %s" % fail2banRegex.encoding
test_lines = file_lines_gen(hdlr)
except IOError as e:
print(e)
except IOError, e:
print e
sys.exit(-1)
elif cmd_log == "systemd-journal":
if not journal:
print("Error: systemd library not found. Exiting...")
print "Error: systemd library not found. Exiting..."
sys.exit(-1)
myjournal = journal.Reader(converters={'__CURSOR': lambda x: x})
journalmatch = fail2banRegex._journalmatch
@@ -557,14 +559,14 @@ if __name__ == "__main__":
else:
myjournal.add_match(element)
except ValueError:
print("Error: Invalid journalmatch: %s" % shortstr(" ".join(journalmatch)))
print "Error: Invalid journalmatch: %s" % shortstr(" ".join(journalmatch))
sys.exit(-1)
print("Use journal match : %s" % " ".join(journalmatch))
print "Use journal match : %s" % " ".join(journalmatch)
test_lines = journal_lines_gen(myjournal)
else:
print("Use single line : %s" % shortstr(cmd_log))
print "Use single line : %s" % shortstr(cmd_log)
test_lines = [ cmd_log ]
print()
print
fail2banRegex.process(test_lines)
+28 -28
View File
@@ -51,37 +51,37 @@ class Fail2banServer:
self.__conf["pidfile"] = "/var/run/fail2ban/fail2ban.pid"
def dispVersion(self):
print("Fail2Ban v" + version)
print()
print("Copyright (c) 2004-2008 Cyril Jaquier, 2008- Fail2Ban Contributors")
print("Copyright of modifications held by their respective authors.")
print("Licensed under the GNU General Public License v2 (GPL).")
print()
print("Written by Cyril Jaquier <cyril.jaquier@fail2ban.org>.")
print("Many contributions by Yaroslav O. Halchenko <debian@onerussian.com>.")
print "Fail2Ban v" + version
print
print "Copyright (c) 2004-2008 Cyril Jaquier, 2008- Fail2Ban Contributors"
print "Copyright of modifications held by their respective authors."
print "Licensed under the GNU General Public License v2 (GPL)."
print
print "Written by Cyril Jaquier <cyril.jaquier@fail2ban.org>."
print "Many contributions by Yaroslav O. Halchenko <debian@onerussian.com>."
def dispUsage(self):
""" Prints Fail2Ban command line options and exits
"""
print("Usage: "+self.__argv[0]+" [OPTIONS]")
print()
print("Fail2Ban v" + version + " reads log file that contains password failure report")
print("and bans the corresponding IP addresses using firewall rules.")
print()
print("Only use this command for debugging purpose. Start the server with")
print("fail2ban-client instead. The default behaviour is to start the server")
print("in background.")
print()
print("Options:")
print(" -b start in background")
print(" -f start in foreground")
print(" -s <FILE> socket path")
print(" -p <FILE> pidfile path")
print(" -x force execution of the server (remove socket file)")
print(" -h, --help display this help message")
print(" -V, --version print the version")
print()
print("Report bugs to https://github.com/fail2ban/fail2ban/issues")
print "Usage: "+self.__argv[0]+" [OPTIONS]"
print
print "Fail2Ban v" + version + " reads log file that contains password failure report"
print "and bans the corresponding IP addresses using firewall rules."
print
print "Only use this command for debugging purpose. Start the server with"
print "fail2ban-client instead. The default behaviour is to start the server"
print "in background."
print
print "Options:"
print " -b start in background"
print " -f start in foreground"
print " -s <FILE> socket path"
print " -p <FILE> pidfile path"
print " -x force execution of the server (remove socket file)"
print " -h, --help display this help message"
print " -V, --version print the version"
print
print "Report bugs to https://github.com/fail2ban/fail2ban/issues"
def __getCmdLineOptions(self, optList):
""" Gets the command line options
@@ -125,7 +125,7 @@ class Fail2banServer:
self.__conf["pidfile"],
self.__conf["force"])
return True
except Exception as e:
except Exception, e:
logSys.exception(e)
self.__server.quit()
return False
+2 -2
View File
@@ -114,8 +114,8 @@ logSys.addHandler(stdout)
# Let know the version
#
if not opts.log_level or opts.log_level != 'critical': # pragma: no cover
print(("Fail2ban %s test suite. Python %s. Please wait..." \
% (version, str(sys.version).replace('\n', ''))))
print("Fail2ban %s test suite. Python %s. Please wait..." \
% (version, str(sys.version).replace('\n', '')))
tests = gatherTests(regexps, opts.no_network)
#
+1 -1
View File
@@ -10,7 +10,7 @@ before = apache-common.conf
[Definition]
failregex = ^%(_apache_error_client)s (AH01797: )?client denied by server configuration: (uri )?\S*(, referer: \S+)?\s*$
failregex = ^%(_apache_error_client)s (AH(01797|01630): )?client denied by server configuration: (uri )?\S*(, referer: \S+)?\s*$
^%(_apache_error_client)s (AH01617: )?user .*? authentication failure for "\S*": Password Mismatch(, referer: \S+)?$
^%(_apache_error_client)s (AH01618: )?user .*? not found(: )?\S*(, referer: \S+)?\s*$
^%(_apache_error_client)s (AH01614: )?client used wrong authentication scheme: \S*(, referer: \S+)?\s*$
+26
View File
@@ -0,0 +1,26 @@
# Fail2Ban filter to block web requests containing custom headers attempting to exploit the shellshock bug
#
#
[INCLUDES]
# overwrite with apache-common.local if _apache_error_client is incorrect.
before = apache-common.conf
[Definition]
failregex = ^%(_apache_error_client)s (AH01215: )?/bin/(ba)?sh: warning: HTTP_.*?: ignoring function definition attempt(, referer: \S+)?\s*$
^%(_apache_error_client)s (AH01215: )?/bin/(ba)?sh: error importing function definition for `HTTP_.*?'(, referer: \S+)?\s*$
ignoreregex =
# DEV Notes:
#
# https://wiki.apache.org/httpd/ListOfErrors for apache error IDs
#
# example log lines:
# [Thu Sep 25 09:27:18.813902 2014] [cgi:error] [pid 16860] [client 89.207.132.76:59635] AH01215: /bin/bash: warning: HTTP_TEST: ignoring function definition attempt
# [Thu Sep 25 09:29:56.141832 2014] [cgi:error] [pid 16864] [client 162.247.73.206:41273] AH01215: /bin/bash: error importing function definition for `HTTP_TEST'
#
# Author: Eugene Hopkinson (riot@riot.so)
+10
View File
@@ -0,0 +1,10 @@
# Fail2Ban filter for failure attempts in Counter Strike-1.6
#
#
[Definition]
failregex = \/<HOST> Port\: [0-9]+ (TCP|UDP) Blocked$
# Author: Pacop <pacoparu@gmail.com>
+3 -1
View File
@@ -7,10 +7,12 @@ before = common.conf
[Definition]
_daemon = postfix/smtpd
_daemon = postfix/(submission/)?smtp(d|s)
failregex = ^%(__prefix_line)swarning: [-._\w]+\[<HOST>\]: SASL (?:LOGIN|PLAIN|(?:CRAM|DIGEST)-MD5) authentication failed(: [ A-Za-z0-9+/]*={0,2})?\s*$
ignoreregex =
[Init]
journalmatch = _SYSTEMD_UNIT=postfix.service
+1 -1
View File
@@ -10,7 +10,7 @@ before = common.conf
[Definition]
_daemon = postfix/smtpd
_daemon = postfix/(submission/)?smtp(d|s)
failregex = ^%(__prefix_line)sNOQUEUE: reject: RCPT from \S+\[<HOST>\]: 554 5\.7\.1 .*$
^%(__prefix_line)sNOQUEUE: reject: RCPT from \S+\[<HOST>\]: 450 4\.7\.1 : Helo command rejected: Host not found; from=<> to=<> proto=ESMTP helo= *$
+10
View File
@@ -283,6 +283,11 @@ port = http,https
logpath = %(apache_error_log)s
maxretry = 2
[apache-shellshock]
port = http,https
logpath = $(apache_error_log)s
maxretry = 1
[nginx-http-auth]
@@ -714,3 +719,8 @@ banaction = iptables-allports
enabled = false
logpath = /var/log/directadmin/login.log
port = 2222
[portsentry]
enabled = false
logpath = /var/lib/portsentry/portsentry.history
maxretry = 1
+19 -6
View File
@@ -1,12 +1,25 @@
fail2ban (0.9.X-python3) UNRELEASED; urgency=medium
fail2ban (0.9.1-1) unstable; urgency=medium
[ Vid Luther ]
* python3 for everything? .. I hope.
* To become fresh upstream release (Closes: #742976)
- 0.9 series is quite a big leap in development, especially since 0.8.6
which made it to previous Debian stable wheezy. Please consult upstream
ChangeLog about changes
* debian/control
- boost policy to 3.9.6
[ vagrant ]
* warning?
-- Yaroslav Halchenko <debian@onerussian.com> Mon, 27 Oct 2014 21:52:56 -0400
-- vagrant <vagrant@vagrant.vm> Sat, 13 Sep 2014 03:52:55 +0000
fail2ban (0.9.0+git252-g47441d1-1) experimental; urgency=medium
[ Yaroslav Halchenko ]
* New upstream snapshot from 0.9.0a2-814-g98dc084.
[ Daniel Schaal ]
* debian/{control,rules}
- switching to python3 as the interpreter for Fail2Ban so we could use
python3-systemd which is N/A for Python2 any longer
-- Yaroslav Halchenko <debian@onerussian.com> Sun, 12 Oct 2014 16:45:36 -0400
fail2ban (0.9.0+git48-gabcab00-1) experimental; urgency=medium
+4 -3
View File
@@ -2,18 +2,18 @@ Source: fail2ban
Section: net
Priority: optional
Maintainer: Yaroslav Halchenko <debian@onerussian.com>
Build-Depends: debhelper (>= 9), python3 (>= 3.0~), python3-pyinotify, dh-systemd
Build-Depends: debhelper (>= 9), python3, python3-pyinotify, dh-systemd
Homepage: http://www.fail2ban.org
Vcs-Git: git://github.com/fail2ban/fail2ban.git
Vcs-Browser: http://github.com/fail2ban/fail2ban
Standards-Version: 3.9.4
Standards-Version: 3.9.6
Package: fail2ban
Architecture: all
Depends: ${python3:Depends}, ${misc:Depends}, lsb-base (>=2.0-7)
Recommends: iptables, whois, python3-pyinotify
Suggests: python-gamin, mailx, system-log-daemon, python3-systemd
Suggests: mailx, system-log-daemon, python3-systemd
Description: ban hosts that cause multiple authentication errors
Fail2ban monitors log files (e.g. /var/log/auth.log,
/var/log/apache/access.log) and temporarily or persistently bans
@@ -27,3 +27,4 @@ Description: ban hosts that cause multiple authentication errors
easily extended for monitoring any other text file. All filters and
actions are given in the config files, thus fail2ban can be adopted
to be used with a variety of files and firewalls.
File diff suppressed because it is too large Load Diff
-46
View File
@@ -1,46 +0,0 @@
From: Yaroslav Halchenko <debian@onerussian.com>
Date: Thu, 6 Dec 2012 12:50:12 -0500
Subject: [PATCH] Patch for elderly Debian/Ubuntu (e.g. 10.04) releases without dh_python2
Use again pycentral etc
crafted post 0.8.8-1 release when a user complained about inability to upgrade
---
debian/control | 2 ++
debian/rules | 12 +++++-------
2 files changed, 7 insertions(+), 7 deletions(-)
--- a/debian/control
+++ b/debian/control
@@ -3,6 +3,8 @@ Section: net
Priority: optional
Maintainer: Yaroslav Halchenko <debian@onerussian.com>
Build-Depends: debhelper (>= 5.0.37.2), python (>= 2.5.4-1~), python-pyinotify
+Build-Depends-Indep: python-central (>= 0.5.6)
+XS-Python-Version: current, >= 2.4
Homepage: http://www.fail2ban.org
Vcs-Git: git://github.com/fail2ban/fail2ban.git
Vcs-Browser: http://github.com/fail2ban/fail2ban
--- a/debian/rules
+++ b/debian/rules
@@ -72,14 +72,12 @@ binary-indep: install
dh_installdocs
dh_installexamples config/jail.conf files/ipmasq-*
dh_installlogrotate
- dh_python2 /usr/share/fail2ban
+ dh_pycentral
dh_installinit -- defaults 99
-
- # perform swap of order of calls to init and pycentral (or even
- # bleedingly new dh_python2) in prerm to close #422655 --
- # python-cleanup section is cut and placed at the end of the file
- # since .init script would trigger their compilation again
- sed -i -e '/^#.*ed by dh_python2/,/# End auto/{H;d};$$G' \
+ # perform swap of order of calls to init and pycentral in prerm
+ # to close #422655 -- pycentral section is cut and placed at
+ # the end of the file
+ sed -i -e '/^#.*ed by dh_pycentral/,/# End auto/{H;d};$$G' \
debian/fail2ban.prerm.debhelper
dh_installman man/*.[15]
+1
View File
@@ -0,0 +1 @@
neurodebian_use_python2
+51
View File
@@ -0,0 +1,51 @@
--- a/debian/control
+++ b/debian/control
@@ -2,7 +2,7 @@ Source: fail2ban
Section: net
Priority: optional
Maintainer: Yaroslav Halchenko <debian@onerussian.com>
-Build-Depends: debhelper (>= 9), python3, python3-pyinotify, dh-systemd
+Build-Depends: debhelper (>= 9), python (>= 2.6.6-3~), python-pyinotify, dh-python
Homepage: http://www.fail2ban.org
Vcs-Git: git://github.com/fail2ban/fail2ban.git
Vcs-Browser: http://github.com/fail2ban/fail2ban
@@ -12,8 +12,8 @@ Standards-Version: 3.9.6
Package: fail2ban
Architecture: all
Depends: ${python3:Depends}, ${misc:Depends}, lsb-base (>=2.0-7)
-Recommends: iptables, whois, python3-pyinotify
-Suggests: mailx, system-log-daemon, python3-systemd
+Recommends: iptables, whois, python-pyinotify
+Suggests: mailx, system-log-daemon, python-systemd
Description: ban hosts that cause multiple authentication errors
Fail2ban monitors log files (e.g. /var/log/auth.log,
/var/log/apache/access.log) and temporarily or persistently bans
--- a/debian/rules
+++ b/debian/rules
@@ -9,13 +9,13 @@
# Uncomment this to turn on verbose mode.
#export DH_VERBOSE=1
-export PYBUILD_DISABLE_python2=1
+export PYBUILD_DISABLE_python3=1
%:
- dh $@ --with python3,systemd --buildsystem pybuild
+ dh $@ --with python2 --buildsystem pybuild
DESTDIR=$(CURDIR)/debian/fail2ban
-PYVERSION=$(shell py3versions -dv)
+PYVERSION=$(shell pyversions -dv)
override_dh_clean:
rm -rf fail2ban.egg-info
@@ -30,7 +30,8 @@ override_dh_install:
: # Install bash completion
install -d $(DESTDIR)/etc/bash_completion.d
install -m 644 files/bash-completion $(DESTDIR)/etc/bash_completion.d/fail2ban
- : # Install systemd files
+ : # Install systemd files, even in backport version just in case even though
+ : # other systemd preparation activities are not carried out
install -d $(DESTDIR)/lib/systemd/system
install -d $(DESTDIR)/usr/lib/tmpfiles.d
install -m 644 files/fail2ban.service $(DESTDIR)/lib/systemd/system
+1
View File
@@ -0,0 +1 @@
neurodebian_use_python2
-1
View File
@@ -1,2 +1 @@
deb_manpages_reportbug
convert-to-python3.patch
+1
View File
@@ -0,0 +1 @@
neurodebian_use_python2
+1
View File
@@ -0,0 +1 @@
neurodebian_use_python2
+1
View File
@@ -0,0 +1 @@
neurodebian_use_python2
+4 -2
View File
@@ -9,10 +9,13 @@
# Uncomment this to turn on verbose mode.
#export DH_VERBOSE=1
export PYBUILD_DISABLE_python2=1
%:
dh $@ --with python3,systemd --buildsystem pybuild
DESTDIR=$(CURDIR)/debian/fail2ban
PYVERSION=$(shell py3versions -dv)
override_dh_clean:
rm -rf fail2ban.egg-info
@@ -39,8 +42,7 @@ override_dh_install:
override_dh_auto_test:
ifeq (,$(filter nocheck,$(DEB_BUILD_OPTIONS)))
cd build && PYTHONPATH=../.pybuild/pythonX.Y_3.4/build/ scripts-*/fail2ban-testcases --no-network
cd build && FAIL2BAN_CONFIG_DIR="$(CURDIR)/config" PYTHONPATH="$(CURDIR)/.pybuild/pythonX.Y_$(PYVERSION)/build/" scripts-*/fail2ban-testcases --no-network
endif
override_dh_installexamples:
+8 -4
View File
@@ -26,7 +26,7 @@ __license__ = "GPL"
import os
from .configreader import ConfigReader, DefinitionInitConfigReader
from .configreader import DefinitionInitConfigReader
from ..helpers import getLogger
# Gets the instance of the logger.
@@ -47,15 +47,19 @@ class ActionReader(DefinitionInitConfigReader):
DefinitionInitConfigReader.__init__(
self, file_, jailName, initOpts, **kwargs)
def setFile(self, fileName):
self.__file = fileName
DefinitionInitConfigReader.setFile(self, os.path.join("action.d", fileName))
def getFile(self):
return self.__file
def setName(self, name):
self._name = name
def getName(self):
return self._name
def read(self):
return ConfigReader.read(self, os.path.join("action.d", self._file))
def convert(self):
head = ["set", self._jailName]
stream = list()
+5 -5
View File
@@ -45,7 +45,7 @@ class Beautifier:
return self.__inputCmd
def beautify(self, response):
logSys.debug("Beautify " + repr(response) + " with " + repr(self.__inputCmd))
logSys.debug("Beautify " + `response` + " with " + `self.__inputCmd`)
inC = self.__inputCmd
msg = response
try:
@@ -99,7 +99,7 @@ class Beautifier:
elif response == 4:
msg = msg + "DEBUG"
else:
msg = msg + repr(response)
msg = msg + `response`
elif inC[1] == "dbfile":
if response is None:
msg = "Database currently disabled"
@@ -180,13 +180,13 @@ class Beautifier:
msg += ", ".join(response)
except Exception:
logSys.warning("Beautifier error. Please report the error")
logSys.error("Beautify " + repr(response) + " with " + repr(self.__inputCmd) +
logSys.error("Beautify " + `response` + " with " + `self.__inputCmd` +
" failed")
msg = msg + repr(response)
msg = msg + `response`
return msg
def beautifyError(self, response):
logSys.debug("Beautify (error) " + repr(response) + " with " + repr(self.__inputCmd))
logSys.debug("Beautify (error) " + `response` + " with " + `self.__inputCmd`)
msg = response
if isinstance(response, UnknownJailException):
msg = "Sorry but the jail '" + response.args[0] + "' does not exist"
+104 -22
View File
@@ -58,10 +58,11 @@ if sys.version_info >= (3,2): # pragma: no cover
parser, option, accum, rest, section, map, depth)
else: # pragma: no cover
from configparser import SafeConfigParser
from ConfigParser import SafeConfigParser
# Gets the instance of the logger.
logSys = getLogger(__name__)
logLevel = 7
__all__ = ['SafeConfigParserWithIncludes']
@@ -98,31 +99,74 @@ after = 1.conf
if sys.version_info >= (3,2):
# overload constructor only for fancy new Python3's
def __init__(self, *args, **kwargs):
def __init__(self, share_config=None, *args, **kwargs):
kwargs = kwargs.copy()
kwargs['interpolation'] = BasicInterpolationWithName()
kwargs['inline_comment_prefixes'] = ";"
super(SafeConfigParserWithIncludes, self).__init__(
*args, **kwargs)
self._cfg_share = share_config
#@staticmethod
def getIncludes(resource, seen = []):
else:
def __init__(self, share_config=None, *args, **kwargs):
SafeConfigParser.__init__(self, *args, **kwargs)
self._cfg_share = share_config
@property
def share_config(self):
return self._cfg_share
def _getSharedSCPWI(self, filename):
SCPWI = SafeConfigParserWithIncludes
# read single one, add to return list, use sharing if possible:
if self._cfg_share:
# cache/share each file as include (ex: filter.d/common could be included in each filter config):
hashv = 'inc:'+(filename if not isinstance(filename, list) else '\x01'.join(filename))
cfg, i = self._cfg_share.get(hashv, (None, None))
if cfg is None:
cfg = SCPWI(share_config=self._cfg_share)
i = cfg.read(filename, get_includes=False)
self._cfg_share[hashv] = (cfg, i)
elif logSys.getEffectiveLevel() <= logLevel:
logSys.log(logLevel, " Shared file: %s", filename)
else:
# don't have sharing:
cfg = SCPWI()
i = cfg.read(filename, get_includes=False)
return (cfg, i)
def _getIncludes(self, filenames, seen=[]):
if not isinstance(filenames, list):
filenames = [ filenames ]
# retrieve or cache include paths:
if self._cfg_share:
# cache/share include list:
hashv = 'inc-path:'+('\x01'.join(filenames))
fileNamesFull = self._cfg_share.get(hashv)
if fileNamesFull is None:
fileNamesFull = []
for filename in filenames:
fileNamesFull += self.__getIncludesUncached(filename, seen)
self._cfg_share[hashv] = fileNamesFull
return fileNamesFull
# don't have sharing:
fileNamesFull = []
for filename in filenames:
fileNamesFull += self.__getIncludesUncached(filename, seen)
return fileNamesFull
def __getIncludesUncached(self, resource, seen=[]):
"""
Given 1 config resource returns list of included files
(recursively) with the original one as well
Simple loops are taken care about
"""
# Use a short class name ;)
SCPWI = SafeConfigParserWithIncludes
parser = SafeConfigParser()
try:
if sys.version_info >= (3,2): # pragma: no cover
parser.read(resource, encoding='utf-8')
else:
parser.read(resource)
except UnicodeDecodeError as e:
parser, i = self._getSharedSCPWI(resource)
if not i:
return []
except UnicodeDecodeError, e:
logSys.error("Error decoding config file '%s': %s" % (resource, e))
return []
@@ -141,22 +185,60 @@ after = 1.conf
if r in seen:
continue
s = seen + [resource]
option_list += SCPWI.getIncludes(r, s)
option_list += self._getIncludes(r, s)
# combine lists
return newFiles[0][1] + [resource] + newFiles[1][1]
#print "Includes list for " + resource + " is " + `resources`
getIncludes = staticmethod(getIncludes)
def get_defaults(self):
return self._defaults
def read(self, filenames):
fileNamesFull = []
def get_sections(self):
return self._sections
def read(self, filenames, get_includes=True):
if not isinstance(filenames, list):
filenames = [ filenames ]
for filename in filenames:
fileNamesFull += SafeConfigParserWithIncludes.getIncludes(filename)
logSys.debug("Reading files: %s" % fileNamesFull)
# retrieve (and cache) includes:
fileNamesFull = []
if get_includes:
fileNamesFull += self._getIncludes(filenames)
else:
fileNamesFull = filenames
if not fileNamesFull:
return []
logSys.info(" Loading files: %s", fileNamesFull)
if get_includes or len(fileNamesFull) > 1:
# read multiple configs:
ret = []
alld = self.get_defaults()
alls = self.get_sections()
for filename in fileNamesFull:
# read single one, add to return list, use sharing if possible:
cfg, i = self._getSharedSCPWI(filename)
if i:
ret += i
# merge defaults and all sections to self:
alld.update(cfg.get_defaults())
for n, s in cfg.get_sections().iteritems():
if isinstance(s, dict):
s2 = alls.get(n)
if isinstance(s2, dict):
s2.update(s)
else:
alls[n] = s.copy()
else:
alls[n] = s
return ret
# read one config :
if logSys.getEffectiveLevel() <= logLevel:
logSys.log(logLevel, " Reading file: %s", fileNamesFull[0])
# read file(s) :
if sys.version_info >= (3,2): # pragma: no cover
return SafeConfigParser.read(self, fileNamesFull, encoding='utf-8')
else:
return SafeConfigParser.read(self, fileNamesFull)
+129 -26
View File
@@ -25,26 +25,129 @@ __copyright__ = "Copyright (c) 2004 Cyril Jaquier"
__license__ = "GPL"
import glob, os
from configparser import NoOptionError, NoSectionError
from ConfigParser import NoOptionError, NoSectionError
from .configparserinc import SafeConfigParserWithIncludes
from .configparserinc import SafeConfigParserWithIncludes, logLevel
from ..helpers import getLogger
# Gets the instance of the logger.
logSys = getLogger(__name__)
class ConfigReader(SafeConfigParserWithIncludes):
class ConfigReader():
"""Generic config reader class.
A caching adapter which automatically reuses already shared configuration.
"""
def __init__(self, use_config=None, share_config=None, **kwargs):
# use given shared config if possible (see read):
self._cfg_share = None
self._cfg = None
if use_config is not None:
self._cfg = use_config
# share config if possible:
if share_config is not None:
self._cfg_share = share_config
self._cfg_share_kwargs = kwargs
self._cfg_share_basedir = None
elif self._cfg is None:
self._cfg = ConfigReaderUnshared(**kwargs)
def setBaseDir(self, basedir):
if self._cfg:
self._cfg.setBaseDir(basedir)
else:
self._cfg_share_basedir = basedir
def getBaseDir(self):
if self._cfg:
return self._cfg.getBaseDir()
else:
return self._cfg_share_basedir
@property
def share_config(self):
return self._cfg_share
def read(self, name, once=True):
""" Overloads a default (not shared) read of config reader.
To prevent mutiple reads of config files with it includes, reads into
the config reader, if it was not yet cached/shared by 'name'.
"""
# already shared ?
if not self._cfg:
self._create_unshared(name)
# performance feature - read once if using shared config reader:
if once and self._cfg.read_cfg_files is not None:
return self._cfg.read_cfg_files
# load:
logSys.info("Loading configs for %s under %s ", name, self._cfg.getBaseDir())
ret = self._cfg.read(name)
# save already read and return:
self._cfg.read_cfg_files = ret
return ret
def _create_unshared(self, name=''):
""" Allocates and share a config file by it name.
Automatically allocates unshared or reuses shared handle by given 'name' and
init arguments inside a given shared storage.
"""
if not self._cfg and self._cfg_share is not None:
self._cfg = self._cfg_share.get(name)
if not self._cfg:
self._cfg = ConfigReaderUnshared(share_config=self._cfg_share, **self._cfg_share_kwargs)
if self._cfg_share_basedir is not None:
self._cfg.setBaseDir(self._cfg_share_basedir)
self._cfg_share[name] = self._cfg
else:
self._cfg = ConfigReaderUnshared(**self._cfg_share_kwargs)
def sections(self):
if self._cfg is not None:
return self._cfg.sections()
return []
def has_section(self, sec):
if self._cfg is not None:
return self._cfg.has_section(sec)
return False
def options(self, *args):
if self._cfg is not None:
return self._cfg.options(*args)
return {}
def get(self, sec, opt):
if self._cfg is not None:
return self._cfg.get(sec, opt)
return None
def getOptions(self, *args, **kwargs):
if self._cfg is not None:
return self._cfg.getOptions(*args, **kwargs)
return {}
class ConfigReaderUnshared(SafeConfigParserWithIncludes):
"""Unshared config reader (previously ConfigReader).
Do not use this class (internal not shared/cached represenation).
Use ConfigReader instead.
"""
DEFAULT_BASEDIR = '/etc/fail2ban'
def __init__(self, basedir=None):
SafeConfigParserWithIncludes.__init__(self)
def __init__(self, basedir=None, *args, **kwargs):
SafeConfigParserWithIncludes.__init__(self, *args, **kwargs)
self.read_cfg_files = None
self.setBaseDir(basedir)
self.__opts = None
def setBaseDir(self, basedir):
if basedir is None:
basedir = ConfigReader.DEFAULT_BASEDIR # stock system location
basedir = ConfigReaderUnshared.DEFAULT_BASEDIR # stock system location
self._basedir = basedir.rstrip('/')
def getBaseDir(self):
@@ -55,7 +158,7 @@ class ConfigReader(SafeConfigParserWithIncludes):
raise ValueError("Base configuration directory %s does not exist "
% self._basedir)
basename = os.path.join(self._basedir, filename)
logSys.info("Reading configs for %s under %s " % (basename, self._basedir))
logSys.debug("Reading configs for %s under %s " , filename, self._basedir)
config_files = [ basename + ".conf" ]
# possible further customizations under a .conf.d directory
@@ -67,18 +170,18 @@ class ConfigReader(SafeConfigParserWithIncludes):
config_files += sorted(glob.glob('%s/*.local' % config_dir))
# choose only existing ones
config_files = list(filter(os.path.exists, config_files))
config_files = filter(os.path.exists, config_files)
if len(config_files):
# at least one config exists and accessible
logSys.debug("Reading config files: " + ', '.join(config_files))
logSys.debug("Reading config files: %s", ', '.join(config_files))
config_files_read = SafeConfigParserWithIncludes.read(self, config_files)
missed = [ cf for cf in config_files if cf not in config_files_read ]
if missed:
logSys.error("Could not read config files: " + ', '.join(missed))
logSys.error("Could not read config files: %s", ', '.join(missed))
if config_files_read:
return True
logSys.error("Found no accessible config files for %r under %s" %
logSys.error("Found no accessible config files for %r under %s",
( filename, self.getBaseDir() ))
return False
else:
@@ -98,7 +201,7 @@ class ConfigReader(SafeConfigParserWithIncludes):
# 1 -> the name of the option
# 2 -> the default value for the option
def getOptions(self, sec, options, pOptions = None):
def getOptions(self, sec, options, pOptions=None):
values = dict()
for option in options:
try:
@@ -111,7 +214,7 @@ class ConfigReader(SafeConfigParserWithIncludes):
if not pOptions is None and option[1] in pOptions:
continue
values[option[1]] = v
except NoSectionError as e:
except NoSectionError, e:
# No "Definition" section or wrong basedir
logSys.error(e)
values[option[1]] = option[2]
@@ -121,24 +224,22 @@ class ConfigReader(SafeConfigParserWithIncludes):
logSys.warning("'%s' not defined in '%s'. Using default one: %r"
% (option[1], sec, option[2]))
values[option[1]] = option[2]
else:
logSys.debug(
"Non essential option '%s' not defined in '%s'.",
option[1], sec)
elif logSys.getEffectiveLevel() <= logLevel:
logSys.log(logLevel, "Non essential option '%s' not defined in '%s'.", option[1], sec)
except ValueError:
logSys.warning("Wrong value for '" + option[1] + "' in '" + sec +
"'. Using default one: '" + repr(option[2]) + "'")
"'. Using default one: '" + `option[2]` + "'")
values[option[1]] = option[2]
return values
class DefinitionInitConfigReader(ConfigReader):
"""Config reader for files with options grouped in [Definition] and
[Init] sections.
[Init] sections.
Is a base class for readers of filters and actions, where definitions
in jails might provide custom values for options defined in [Init]
section.
"""
Is a base class for readers of filters and actions, where definitions
in jails might provide custom values for options defined in [Init]
section.
"""
_configOpts = []
@@ -166,7 +267,9 @@ class DefinitionInitConfigReader(ConfigReader):
# needed for fail2ban-regex that doesn't need fancy directories
def readexplicit(self):
return SafeConfigParserWithIncludes.read(self, self._file)
if not self._cfg:
self._create_unshared(self._file)
return SafeConfigParserWithIncludes.read(self._cfg, self._file)
def getOptions(self, pOpts):
self._opts = ConfigReader.getOptions(
@@ -174,7 +277,7 @@ class DefinitionInitConfigReader(ConfigReader):
if self.has_section("Init"):
for opt in self.options("Init"):
if opt not in self._initOpts:
if not self._initOpts.has_key(opt):
self._initOpts[opt] = self.get("Init", opt)
def convert(self):
+12 -4
View File
@@ -33,12 +33,20 @@ logSys = getLogger(__name__)
class Configurator:
def __init__(self):
def __init__(self, force_enable=False, share_config=None):
self.__settings = dict()
self.__streams = dict()
self.__fail2ban = Fail2banReader()
self.__jails = JailsReader()
# always share all config readers:
if share_config is None:
share_config = dict()
self.__share_config = share_config
self.__fail2ban = Fail2banReader(share_config=share_config)
self.__jails = JailsReader(force_enable=force_enable, share_config=share_config)
def Reload(self):
# clear all shared handlers:
self.__share_config.clear()
def setBaseDir(self, folderName):
self.__fail2ban.setBaseDir(folderName)
self.__jails.setBaseDir(folderName)
+2 -3
View File
@@ -57,13 +57,12 @@ class CSocket:
self.__csock.close()
return ret
#@staticmethod
@staticmethod
def receive(sock):
msg = EMPTY_BYTES
while msg.rfind(CSocket.END_STRING) == -1:
chunk = sock.recv(6)
if chunk == '':
raise RuntimeError("socket connection broken")
raise RuntimeError, "socket connection broken"
msg = msg + chunk
return loads(msg)
receive = staticmethod(receive)
+8 -4
View File
@@ -26,7 +26,7 @@ __license__ = "GPL"
import os, shlex
from .configreader import ConfigReader, DefinitionInitConfigReader
from .configreader import DefinitionInitConfigReader
from ..server.action import CommandAction
from ..helpers import getLogger
@@ -40,8 +40,12 @@ class FilterReader(DefinitionInitConfigReader):
["string", "failregex", ""],
]
def read(self):
return ConfigReader.read(self, os.path.join("filter.d", self._file))
def setFile(self, fileName):
self.__file = fileName
DefinitionInitConfigReader.setFile(self, os.path.join("filter.d", fileName))
def getFile(self):
return self.__file
def convert(self):
stream = list()
@@ -49,7 +53,7 @@ class FilterReader(DefinitionInitConfigReader):
opts = CommandAction.substituteRecursiveTags(combinedopts)
if not opts:
raise ValueError('recursive tag definitions unable to be resolved')
for opt, value in opts.items():
for opt, value in opts.iteritems():
if opt == "failregex":
for regex in value.split('\n'):
# Do not send a command if the rule is empty.
+6 -7
View File
@@ -27,7 +27,7 @@ __license__ = "GPL"
import re, glob, os.path
import json
from .configreader import ConfigReader
from .configreader import ConfigReaderUnshared, ConfigReader
from .filterreader import FilterReader
from .actionreader import ActionReader
from ..helpers import getLogger
@@ -111,7 +111,7 @@ class JailReader(ConfigReader):
filterName, filterOpt = JailReader.extractOptions(
self.__opts["filter"])
self.__filter = FilterReader(
filterName, self.__name, filterOpt, basedir=self.getBaseDir())
filterName, self.__name, filterOpt, share_config=self.share_config, basedir=self.getBaseDir())
ret = self.__filter.read()
if ret:
self.__filter.getOptions(self.__opts)
@@ -141,14 +141,14 @@ class JailReader(ConfigReader):
else:
action = ActionReader(
actName, self.__name, actOpt,
basedir=self.getBaseDir())
share_config=self.share_config, basedir=self.getBaseDir())
ret = action.read()
if ret:
action.getOptions(self.__opts)
self.__actions.append(action)
else:
raise AttributeError("Unable to read action")
except Exception as e:
except Exception, e:
logSys.error("Error in action definition " + act)
logSys.debug("Caught exception: %s" % (e,))
return False
@@ -213,14 +213,14 @@ class JailReader(ConfigReader):
if self.__filter:
stream.extend(self.__filter.convert())
for action in self.__actions:
if isinstance(action, ConfigReader):
if isinstance(action, (ConfigReaderUnshared, ConfigReader)):
stream.extend(action.convert())
else:
stream.append(action)
stream.insert(0, ["add", self.__name, backend])
return stream
#@staticmethod
@staticmethod
def extractOptions(option):
match = JailReader.optionCRE.match(option)
if not match:
@@ -235,4 +235,3 @@ class JailReader(ConfigReader):
val for val in optmatch.group(2,3,4) if val is not None][0]
option_opts[opt.strip()] = value.strip()
return option_name, option_opts
extractOptions = staticmethod(extractOptions)
+4 -3
View File
@@ -68,9 +68,10 @@ class JailsReader(ConfigReader):
for sec in sections:
if sec == 'INCLUDES':
continue
jail = JailReader(sec, basedir=self.getBaseDir(),
force_enable=self.__force_enable)
jail.read()
# use the cfg_share for filter/action caching and the same config for all
# jails (use_config=...), therefore don't read it here:
jail = JailReader(sec, force_enable=self.__force_enable,
share_config=self.share_config, use_config=self._cfg)
ret = jail.getOptions()
if ret:
if jail.isEnabled():
+13 -13
View File
@@ -128,7 +128,7 @@ def printFormatted():
firstHeading = False
for m in protocol:
if m[0] == '' and firstHeading:
print()
print
firstHeading = True
first = True
if len(m[0]) >= MARGIN:
@@ -139,7 +139,7 @@ def printFormatted():
first = False
else:
line = ' ' * (INDENT + MARGIN) + n.strip()
print(line)
print line
##
# Prints the protocol in a "mediawiki" format.
@@ -149,19 +149,19 @@ def printWiki():
for m in protocol:
if m[0] == '':
if firstHeading:
print("|}")
print "|}"
__printWikiHeader(m[1], m[2])
firstHeading = True
else:
print("|-")
print("| <span style=\"white-space:nowrap;\"><tt>" + m[0] + "</tt></span> || || " + m[1])
print("|}")
print "|-"
print "| <span style=\"white-space:nowrap;\"><tt>" + m[0] + "</tt></span> || || " + m[1]
print "|}"
def __printWikiHeader(section, desc):
print()
print("=== " + section + " ===")
print()
print(desc)
print()
print("{|")
print("| '''Command''' || || '''Description'''")
print
print "=== " + section + " ==="
print
print desc
print
print "{|"
print "| '''Command''' || || '''Description'''"
+9 -9
View File
@@ -27,7 +27,6 @@ from abc import ABCMeta
from collections import MutableMapping
from ..helpers import getLogger
import collections
# Gets the instance of the logger.
logSys = getLogger(__name__)
@@ -48,7 +47,7 @@ _RETCODE_HINTS = {
# Dictionary to lookup signal name from number
signame = dict((num, name)
for name, num in signal.__dict__.items() if name.startswith("SIG"))
for name, num in signal.__dict__.iteritems() if name.startswith("SIG"))
class CallingMap(MutableMapping):
"""A Mapping type which returns the result of callable values.
@@ -75,7 +74,7 @@ class CallingMap(MutableMapping):
def __getitem__(self, key):
value = self.data[key]
if isinstance(value, collections.Callable):
if callable(value):
return value()
else:
return value
@@ -95,7 +94,7 @@ class CallingMap(MutableMapping):
def copy(self):
return self.__class__(self.data.copy())
class ActionBase(object, metaclass=ABCMeta):
class ActionBase(object):
"""An abstract base class for actions in Fail2Ban.
Action Base is a base definition of what methods need to be in
@@ -125,6 +124,7 @@ class ActionBase(object, metaclass=ABCMeta):
Any additional arguments specified in `jail.conf` or passed
via `fail2ban-client` will be passed as keyword arguments.
"""
__metaclass__ = ABCMeta
@classmethod
def __subclasshook__(cls, C):
@@ -135,7 +135,7 @@ class ActionBase(object, metaclass=ABCMeta):
"unban",
)
for method in required:
if not isinstance(getattr(C, method, None), collections.Callable):
if not callable(getattr(C, method, None)):
return False
return True
@@ -242,7 +242,7 @@ class CommandAction(ActionBase):
return dict(
(key, getattr(self, key))
for key in dir(self)
if not key.startswith("_") and not isinstance(getattr(self, key), collections.Callable))
if not key.startswith("_") and not callable(getattr(self, key)))
@property
def actionstart(self):
@@ -379,7 +379,7 @@ class CommandAction(ActionBase):
within the values recursively replaced.
"""
t = re.compile(r'<([^ >]+)>')
for tag in tags.keys():
for tag in tags.iterkeys():
if tag in cls._escapedTags:
# Escaped so won't match
continue
@@ -398,7 +398,7 @@ class CommandAction(ActionBase):
# Escaped so won't match
continue
else:
if found_tag in tags:
if tags.has_key(found_tag):
value = value.replace('<%s>' % found_tag , tags[found_tag])
#logSys.log(5, 'value now: %s' % value)
done.append(found_tag)
@@ -563,7 +563,7 @@ class CommandAction(ActionBase):
os.kill(popen.pid, signal.SIGKILL) # Kill the process
time.sleep(0.1)
retcode = popen.poll()
except OSError as e:
except OSError, e:
logSys.error("%s -- failed with %s" % (realCmd, e))
finally:
_cmd_lock.release()
+4 -4
View File
@@ -213,7 +213,7 @@ class Actions(JailThread, Mapping):
bool
True when the thread exits nicely.
"""
for name, action in self._actions.items():
for name, action in self._actions.iteritems():
try:
action.start()
except Exception as e:
@@ -231,7 +231,7 @@ class Actions(JailThread, Mapping):
time.sleep(self.sleeptime)
self.__flushBan()
actions = list(self._actions.items())
actions = self._actions.items()
actions.reverse()
for name, action in actions:
try:
@@ -274,7 +274,7 @@ class Actions(JailThread, Mapping):
jail.database.getBansMerged(ip=ip, jail=jail).getAttempt()
if self.__banManager.addBanTicket(bTicket):
logSys.notice("[%s] Ban %s" % (self._jail.name, aInfo["ip"]))
for name, action in self._actions.items():
for name, action in self._actions.iteritems():
try:
action.ban(aInfo.copy())
except Exception as e:
@@ -323,7 +323,7 @@ class Actions(JailThread, Mapping):
aInfo["time"] = ticket.getTime()
aInfo["matches"] = "".join(ticket.getMatches())
logSys.notice("[%s] Unban %s" % (self._jail.name, aInfo["ip"]))
for name, action in self._actions.items():
for name, action in self._actions.iteritems():
try:
action.unban(aInfo.copy())
except Exception as e:
+3 -8
View File
@@ -149,12 +149,8 @@ class AsyncServer(asyncore.dispatcher):
self.__init = True
# TODO Add try..catch
# There's a bug report for Python 2.6/3.0 that use_poll=True yields some 2.5 incompatibilities:
if sys.version_info >= (2, 6): # if python 2.6 or greater...
logSys.debug("Detected Python 2.6 or greater. asyncore.loop() not using poll")
asyncore.loop(use_poll = False) # fixes the "Unexpected communication problem" issue on Python 2.6 and 3.0
else: # pragma: no cover
logSys.debug("NOT Python 2.6/3.* - asyncore.loop() using poll")
asyncore.loop(use_poll = True)
logSys.debug("Detected Python 2.6 or greater. asyncore.loop() not using poll")
asyncore.loop(use_poll=False) # fixes the "Unexpected communication problem" issue on Python 2.6 and 3.0
##
# Stops the communication server.
@@ -175,12 +171,11 @@ class AsyncServer(asyncore.dispatcher):
# @param sock: socket file.
#@staticmethod
@staticmethod
def __markCloseOnExec(sock):
fd = sock.fileno()
flags = fcntl.fcntl(fd, fcntl.F_GETFD)
fcntl.fcntl(fd, fcntl.F_SETFD, flags|fcntl.FD_CLOEXEC)
__markCloseOnExec = staticmethod(__markCloseOnExec)
##
# AsyncServerException is used to wrap communication exceptions.
+1 -2
View File
@@ -126,7 +126,7 @@ class BanManager:
# @param ticket the FailTicket
# @return a BanTicket
#@staticmethod
@staticmethod
def createBanTicket(ticket):
ip = ticket.getIP()
#lastTime = ticket.getTime()
@@ -134,7 +134,6 @@ class BanManager:
banTicket = BanTicket(ip, lastTime, ticket.getMatches())
banTicket.setAttempt(ticket.getAttempt())
return banTicket
createBanTicket = staticmethod(createBanTicket)
##
# Add a ban ticket.
+1 -1
View File
@@ -134,7 +134,7 @@ class Fail2BanDb(object):
logSys.info(
"Connected to fail2ban persistent database '%s'", filename)
except sqlite3.OperationalError as e:
except sqlite3.OperationalError, e:
logSys.error(
"Error connecting to fail2ban persistent database '%s': %s",
filename, e.args[0])
+2 -2
View File
@@ -168,7 +168,7 @@ class DatePatternRegex(DateTemplate):
regex
pattern
"""
_patternRE = r"%%(%%|[%s])" % "".join(list(timeRE.keys()))
_patternRE = r"%%(%%|[%s])" % "".join(timeRE.keys())
_patternName = {
'a': "DAY", 'A': "DAYNAME", 'b': "MON", 'B': "MONTH", 'd': "Day",
'H': "24hour", 'I': "12hour", 'j': "Yearday", 'm': "Month",
@@ -232,7 +232,7 @@ class DatePatternRegex(DateTemplate):
if dateMatch:
groupdict = dict(
(key, value)
for key, value in dateMatch.groupdict().items()
for key, value in dateMatch.groupdict().iteritems()
if value is not None)
return reGroupDictStrptime(groupdict), dateMatch
+3 -3
View File
@@ -91,7 +91,7 @@ class FailManager:
ip = ticket.getIP()
unixTime = ticket.getTime()
matches = ticket.getMatches()
if ip in self.__failList:
if self.__failList.has_key(ip):
fData = self.__failList[ip]
if fData.getLastReset() < unixTime - self.__maxTime:
fData.setLastReset(unixTime)
@@ -112,7 +112,7 @@ class FailManager:
# in case of having many active failures, it should be ran only
# if debug level is "low" enough
failures_summary = ', '.join(['%s:%d' % (k, v.getRetry())
for k,v in self.__failList.items()])
for k,v in self.__failList.iteritems()])
logSys.debug("Total # of detected failures: %d. Current failures from %d IPs (IP:count): %s"
% (self.__failTotal, len(self.__failList), failures_summary))
finally:
@@ -136,7 +136,7 @@ class FailManager:
self.__lock.release()
def __delFailure(self, ip):
if ip in self.__failList:
if self.__failList.has_key(ip):
del self.__failList[ip]
def toBan(self):
+18 -25
View File
@@ -100,7 +100,7 @@ class Filter(JailThread):
logSys.warning(
"Mutliline regex set for jail '%s' "
"but maxlines not greater than 1")
except RegexException as e:
except RegexException, e:
logSys.error(e)
raise e
@@ -134,7 +134,7 @@ class Filter(JailThread):
try:
regex = Regex(value)
self.__ignoreRegex.append(regex)
except RegexException as e:
except RegexException, e:
logSys.error(e)
raise e
@@ -310,7 +310,7 @@ class Filter(JailThread):
logSys.warning('Requested to manually ban an ignored IP %s. User knows best. Proceeding to ban it.' % ip)
unixTime = MyTime.time()
for i in range(self.failManager.getMaxRetry()):
for i in xrange(self.failManager.getMaxRetry()):
self.failManager.addFailure(FailTicket(ip, unixTime))
# Perform the banning of the IP now.
@@ -361,7 +361,7 @@ class Filter(JailThread):
elif "." in s[1]: # 255.255.255.0 style mask
s[1] = len(re.search(
"(?<=b)1+", bin(DNSUtils.addr2bin(s[1]))).group())
s[1] = int(s[1])
s[1] = long(s[1])
try:
a = DNSUtils.cidr(s[0], s[1])
b = DNSUtils.cidr(ip, s[1])
@@ -525,7 +525,7 @@ class Filter(JailThread):
failRegex.getMatchedLines()])
if not checkAllRegex:
break
except RegexException as e: # pragma: no cover - unsure if reachable
except RegexException, e: # pragma: no cover - unsure if reachable
logSys.error(e)
return failList
@@ -656,15 +656,15 @@ class FileFilter(Filter):
try:
has_content = container.open()
# see http://python.org/dev/peps/pep-3151/
except IOError as e:
except IOError, e:
logSys.error("Unable to open %s" % filename)
logSys.exception(e)
return False
except OSError as e: # pragma: no cover - requires race condition to tigger this
except OSError, e: # pragma: no cover - requires race condition to tigger this
logSys.error("Error opening %s" % filename)
logSys.exception(e)
return False
except OSError as e: # pragma: no cover - Requires implemention error in FileContainer to generate
except OSError, e: # pragma: no cover - Requires implemention error in FileContainer to generate
logSys.error("Internal errror in FileContainer open method - please report as a bug to https://github.com/fail2ban/fail2ban/issues")
logSys.exception(e)
return False
@@ -838,24 +838,23 @@ class DNSUtils:
IP_CRE = re.compile("^(?:\d{1,3}\.){3}\d{1,3}$")
#@staticmethod
@staticmethod
def dnsToIp(dns):
""" Convert a DNS into an IP address using the Python socket module.
Thanks to Kevin Drapel.
"""
try:
return set(socket.gethostbyname_ex(dns)[2])
except socket.error as e:
except socket.error, e:
logSys.warning("Unable to find a corresponding IP address for %s: %s"
% (dns, e))
return list()
except socket.error as e:
except socket.error, e:
logSys.warning("Socket error raised trying to resolve hostname %s: %s"
% (dns, e))
return list()
dnsToIp = staticmethod(dnsToIp)
#@staticmethod
@staticmethod
def searchIP(text):
""" Search if an IP address if directly available and return
it.
@@ -865,9 +864,8 @@ class DNSUtils:
return match
else:
return None
searchIP = staticmethod(searchIP)
#@staticmethod
@staticmethod
def isValidIP(string):
""" Return true if str is a valid IP
"""
@@ -877,9 +875,8 @@ class DNSUtils:
return True
except socket.error:
return False
isValidIP = staticmethod(isValidIP)
#@staticmethod
@staticmethod
def textToIp(text, useDns):
""" Return the IP of DNS found in a given text.
"""
@@ -901,28 +898,24 @@ class DNSUtils:
text, ipList)
return ipList
textToIp = staticmethod(textToIp)
#@staticmethod
@staticmethod
def cidr(i, n):
""" Convert an IP address string with a CIDR mask into a 32-bit
integer.
"""
# 32-bit IPv4 address mask
MASK = 0xFFFFFFFF
MASK = 0xFFFFFFFFL
return ~(MASK >> n) & MASK & DNSUtils.addr2bin(i)
cidr = staticmethod(cidr)
#@staticmethod
@staticmethod
def addr2bin(string):
""" Convert a string IPv4 address into an unsigned integer.
"""
return struct.unpack("!L", socket.inet_aton(string))[0]
addr2bin = staticmethod(addr2bin)
#@staticmethod
@staticmethod
def bin2addr(addr):
""" Convert a numeric IPv4 address into string n.n.n.n form.
"""
return socket.inet_ntoa(struct.pack("!L", addr))
bin2addr = staticmethod(bin2addr)
+1 -1
View File
@@ -62,7 +62,7 @@ class FilterGamin(FileFilter):
def callback(self, path, event):
logSys.debug("Got event: " + repr(event) + " for " + path)
logSys.debug("Got event: " + `event` + " for " + path)
if event in (gamin.GAMCreated, gamin.GAMChanged, gamin.GAMExists):
logSys.debug("File changed: " + path)
self.__modified = True
+1 -1
View File
@@ -136,7 +136,7 @@ class FilterPoll(FileFilter):
logSys.debug("%s has been modified", filename)
self.__prevStats[filename] = stats
return True
except OSError as e:
except OSError, e:
logSys.error("Unable to get stat on %s because of: %s"
% (filename, e))
self.__file404Cnt[filename] += 1
+1 -1
View File
@@ -44,7 +44,7 @@ if not hasattr(pyinotify, '__version__') \
try:
manager = pyinotify.WatchManager()
del manager
except Exception as e:
except Exception, e:
raise ImportError("Pyinotify is probably not functional on this system: %s"
% str(e))
+1 -1
View File
@@ -188,7 +188,7 @@ class FilterSystemd(JournalFilter): # pragma: systemd no cover
logelements.append(logentry.get('MESSAGE', ''))
try:
logline = " ".join(logelements)
logline = u" ".join(logelements)
except UnicodeDecodeError:
# Python 2, so treat as string
logline = " ".join([str(logline) for logline in logelements])
+8 -8
View File
@@ -23,7 +23,7 @@ __author__ = "Cyril Jaquier, Lee Clemens, Yaroslav Halchenko"
__copyright__ = "Copyright (c) 2004 Cyril Jaquier, 2011-2012 Lee Clemens, 2012 Yaroslav Halchenko"
__license__ = "GPL"
import queue, logging
import Queue, logging
from .actions import Actions
from ..helpers import getLogger
@@ -71,7 +71,7 @@ class Jail:
"might not function correctly. Please shorten"
% name)
self.__name = name
self.__queue = queue.Queue()
self.__queue = Queue.Queue()
self.__filter = None
logSys.info("Creating new jail '%s'" % self.name)
self._setBackend(backend)
@@ -104,7 +104,7 @@ class Jail:
logSys.info("Initiated %r backend" % b)
self.__actions = Actions(self)
return # we are done
except ImportError as e:
except ImportError, e:
# Log debug if auto, but error if specific
logSys.log(
logging.DEBUG if backend == "auto" else logging.ERROR,
@@ -117,25 +117,25 @@ class Jail:
def _initPolling(self):
from .filterpoll import FilterPoll
from filterpoll import FilterPoll
logSys.info("Jail '%s' uses poller" % self.name)
self.__filter = FilterPoll(self)
def _initGamin(self):
# Try to import gamin
from .filtergamin import FilterGamin
from filtergamin import FilterGamin
logSys.info("Jail '%s' uses Gamin" % self.name)
self.__filter = FilterGamin(self)
def _initPyinotify(self):
# Try to import pyinotify
from .filterpyinotify import FilterPyinotify
from filterpyinotify import FilterPyinotify
logSys.info("Jail '%s' uses pyinotify" % self.name)
self.__filter = FilterPyinotify(self)
def _initSystemd(self): # pragma: systemd no cover
# Try to import systemd
from .filtersystemd import FilterSystemd
from filtersystemd import FilterSystemd
logSys.info("Jail '%s' uses systemd" % self.name)
self.__filter = FilterSystemd(self)
@@ -199,7 +199,7 @@ class Jail:
"""
try:
return self.__queue.get(False)
except queue.Empty:
except Queue.Empty:
return False
def start(self):
+41 -35
View File
@@ -26,65 +26,71 @@ import time, datetime
##
# MyTime class.
#
# This class is a wrapper around time.time() and time.gmtime(). When
# performing unit test, it is very useful to get a fixed value from these
# functions.
# Thus, time.time() and time.gmtime() should never be called directly.
# This wrapper should be called instead. The API are equivalent.
class MyTime:
"""A wrapper around time module primarily for testing purposes
This class is a wrapper around time.time() and time.gmtime(). When
performing unit test, it is very useful to get a fixed value from
these functions. Thus, time.time() and time.gmtime() should never
be called directly. This wrapper should be called instead. The API
are equivalent.
"""
myTime = None
##
# Sets the current time.
#
# Use None in order to always get the real current time.
#
# @param t the time to set or None
#@staticmethod
@staticmethod
def setTime(t):
"""Set current time.
Use None in order to always get the real current time.
@param t the time to set or None
"""
MyTime.myTime = t
setTime = staticmethod(setTime)
##
# Equivalent to time.time()
#
# @return time.time() if setTime was called with None
#@staticmethod
@staticmethod
def time():
"""Decorate time.time() for the purpose of testing mocking
@return time.time() if setTime was called with None
"""
if MyTime.myTime is None:
return time.time()
else:
return MyTime.myTime
time = staticmethod(time)
##
# Equivalent to time.gmtime()
#
# @return time.gmtime() if setTime was called with None
#@staticmethod
@staticmethod
def gmtime():
"""Decorate time.gmtime() for the purpose of testing mocking
@return time.gmtime() if setTime was called with None
"""
if MyTime.myTime is None:
return time.gmtime()
else:
return time.gmtime(MyTime.myTime)
gmtime = staticmethod(gmtime)
#@staticmethod
@staticmethod
def now():
"""Decorate datetime.now() for the purpose of testing mocking
@return datetime.now() if setTime was called with None
"""
if MyTime.myTime is None:
return datetime.datetime.now()
else:
return datetime.datetime.fromtimestamp(MyTime.myTime)
now = staticmethod(now)
@staticmethod
def localtime(x=None):
"""Decorate time.localtime() for the purpose of testing mocking
@return time.localtime() if setTime was called with None
"""
if MyTime.myTime is None or x is not None:
return time.localtime(x)
else:
return time.localtime(MyTime.myTime)
localtime = staticmethod(localtime)
+7 -7
View File
@@ -74,7 +74,7 @@ class Server:
sys.excepthook = excepthook
# First set the mask to only allow access to owner
os.umask(0o077)
os.umask(0077)
if self.__daemon: # pragma: no cover
logSys.info("Starting in daemon mode")
ret = self.__createDaemon()
@@ -90,20 +90,20 @@ class Server:
pidFile = open(pidfile, 'w')
pidFile.write("%s\n" % os.getpid())
pidFile.close()
except IOError as e:
except IOError, e:
logSys.error("Unable to create PID file: %s" % e)
# Start the communication
logSys.debug("Starting communication")
try:
self.__asyncServer.start(sock, force)
except AsyncServerException as e:
except AsyncServerException, e:
logSys.error("Could not start server: %s", e)
# Removes the PID file.
try:
logSys.debug("Remove PID file %s" % pidfile)
os.remove(pidfile)
except OSError as e:
except OSError, e:
logSys.error("Unable to remove PID file: %s" % e)
logSys.info("Exiting Fail2ban")
@@ -159,7 +159,7 @@ class Server:
logSys.info("Stopping all jails")
try:
self.__lock.acquire()
for jail in list(self.__jails.keys()):
for jail in self.__jails.keys():
self.stopJail(jail)
finally:
self.__lock.release()
@@ -486,7 +486,7 @@ class Server:
# the child gets a new PID, making it impossible for its PID to equal its
# PGID.
pid = os.fork()
except OSError as e:
except OSError, e:
return((e.errno, e.strerror)) # ERROR (return a tuple)
if pid == 0: # The first child.
@@ -507,7 +507,7 @@ class Server:
# 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 as e:
except OSError, e:
return((e.errno, e.strerror)) # ERROR (return a tuple)
if (pid == 0): # The second child.
+1 -1
View File
@@ -57,7 +57,7 @@ def reGroupDictStrptime(found_dict):
# weekday and julian defaulted to -1 so as to signal need to calculate
# values
weekday = julian = -1
for group_key in list(found_dict.keys()):
for group_key in found_dict.keys():
# Directives not explicitly handled below:
# c, x, X
# handled by making out of other directives
+1 -1
View File
@@ -62,7 +62,7 @@ class Ticket:
return False
def setIP(self, value):
if isinstance(value, str):
if isinstance(value, basestring):
# guarantee using regular str instead of unicode for the IP
value = str(value)
self.__ip = value
+6 -7
View File
@@ -29,7 +29,6 @@ import json
from ..helpers import getLogger
from .. import version
import collections
# Gets the instance of the logger.
logSys = getLogger(__name__)
@@ -52,11 +51,11 @@ class Transmitter:
def proceed(self, command):
# Deserialize object
logSys.debug("Command: " + repr(command))
logSys.debug("Command: " + `command`)
try:
ret = self.__commandHandler(command)
ack = 0, ret
except Exception as e:
except Exception, e:
logSys.warning("Command %r has failed. Received %r"
% (command, e))
ack = 1, e
@@ -249,7 +248,7 @@ class Transmitter:
actionname = command[2]
actionkey = command[3]
action = self.__server.getAction(name, actionname)
if isinstance(getattr(action, actionkey, None), collections.Callable):
if callable(getattr(action, actionkey, None)):
actionvalue = json.loads(command[4]) if len(command)>4 else {}
return getattr(action, actionkey)(**actionvalue)
else:
@@ -307,7 +306,7 @@ class Transmitter:
elif command[1] == "bantime":
return self.__server.getBanTime(name)
elif command[1] == "actions":
return list(self.__server.getActions(name).keys())
return self.__server.getActions(name).keys()
elif command[1] == "action":
actionname = command[2]
actionvalue = command[3]
@@ -319,13 +318,13 @@ class Transmitter:
return [
key for key in dir(action)
if not key.startswith("_") and
not isinstance(getattr(action, key), collections.Callable)]
not callable(getattr(action, key))]
elif command[1] == "actionmethods":
actionname = command[2]
action = self.__server.getAction(name, actionname)
return [
key for key in dir(action)
if not key.startswith("_") and isinstance(getattr(action, key), collections.Callable)]
if not key.startswith("_") and callable(getattr(action, key))]
raise Exception("Invalid command (no get action or not yet implemented)")
def status(self, command):
+1 -5
View File
@@ -22,11 +22,7 @@ import unittest
import sys
from ..dummyjail import DummyJail
if os.path.exists('config/fail2ban.conf'):
CONFIG_DIR = "config"
else:
CONFIG_DIR='/etc/fail2ban'
from ..utils import CONFIG_DIR
if sys.version_info >= (2,7):
class BadIPsActionTest(unittest.TestCase):
+1 -4
View File
@@ -30,10 +30,7 @@ else:
from ..dummyjail import DummyJail
if os.path.exists('config/fail2ban.conf'):
CONFIG_DIR = "config"
else:
CONFIG_DIR='/etc/fail2ban'
from ..utils import CONFIG_DIR
class TestSMTPServer(smtpd.SMTPServer):
+4 -2
View File
@@ -186,8 +186,10 @@ class CommandActionTest(LogCaptureTestCase):
# Should take a minute
self.assertRaises(
RuntimeError, CommandAction.executeCmd, 'sleep 60', timeout=2)
self.assertAlmostEqual(time.time() - stime, 2, places=0)
self.assertTrue(self._is_logged('sleep 60 -- timed out after 2 seconds'))
# give a test still 1 second, because system could be too busy
self.assertTrue(time.time() >= stime + 2 and time.time() <= stime + 3)
self.assertTrue(self._is_logged('sleep 60 -- timed out after 2 seconds')
or self._is_logged('sleep 60 -- timed out after 3 seconds'))
self.assertTrue(self._is_logged('sleep 60 -- killed with SIGTERM'))
def testCaptureStdOutErr(self):
+81 -5
View File
@@ -21,9 +21,9 @@ __author__ = "Cyril Jaquier, Yaroslav Halchenko"
__copyright__ = "Copyright (c) 2004 Cyril Jaquier, 2011-2013 Yaroslav Halchenko"
__license__ = "GPL"
import os, glob, shutil, tempfile, unittest
from ..client.configreader import ConfigReader
import os, glob, shutil, tempfile, unittest, re, logging
from ..client.configreader import ConfigReaderUnshared
from ..client import configparserinc
from ..client.jailreader import JailReader
from ..client.filterreader import FilterReader
from ..client.jailsreader import JailsReader
@@ -32,8 +32,10 @@ from ..client.configurator import Configurator
from .utils import LogCaptureTestCase
TEST_FILES_DIR = os.path.join(os.path.dirname(__file__), "files")
from .utils import CONFIG_DIR
STOCK = os.path.exists(os.path.join('config','fail2ban.conf'))
CONFIG_DIR='config' if STOCK else '/etc/fail2ban'
IMPERFECT_CONFIG = os.path.join(os.path.dirname(__file__), 'config')
@@ -42,7 +44,7 @@ class ConfigReaderTest(unittest.TestCase):
def setUp(self):
"""Call before every test case."""
self.d = tempfile.mkdtemp(prefix="f2b-temp")
self.c = ConfigReader(basedir=self.d)
self.c = ConfigReaderUnshared(basedir=self.d)
def tearDown(self):
"""Call after every test case."""
@@ -332,6 +334,80 @@ class FilterReaderTest(unittest.TestCase):
filterReader.getOptions(None)
self.assertRaises(ValueError, FilterReader.convert, filterReader)
def testFilterReaderExplicit(self):
# read explicit uses absolute path:
path_ = os.path.abspath(os.path.join(TEST_FILES_DIR, "filter.d"))
filterReader = FilterReader(os.path.join(path_, "testcase01.conf"), "testcase01", {})
self.assertEqual(filterReader.readexplicit(),
[os.path.join(path_, "testcase-common.conf"), os.path.join(path_, "testcase01.conf")]
)
try:
filterReader.getOptions(None)
# from included common
filterReader.get('Definition', '__prefix_line')
# from testcase01
filterReader.get('Definition', 'failregex')
filterReader.get('Definition', 'ignoreregex')
except Exception, e: # pragma: no cover - failed if reachable
self.fail('unexpected options after readexplicit: %s' % (e))
class JailsReaderTestCache(LogCaptureTestCase):
def _readWholeConf(self, basedir, force_enable=False, share_config=None):
# read whole configuration like a file2ban-client ...
configurator = Configurator(force_enable=force_enable, share_config=share_config)
configurator.setBaseDir(basedir)
configurator.readEarly()
configurator.getEarlyOptions()
configurator.readAll()
# from here we test a cache with all includes / before / after :
self.assertTrue(configurator.getOptions(None))
def _getLoggedReadCount(self, filematch):
cnt = 0
for s in self.getLog().rsplit('\n'):
if re.match(r"^\s*Reading files?: .*/"+filematch, s):
cnt += 1
return cnt
def testTestJailConfCache(self):
saved_ll = configparserinc.logLevel
configparserinc.logLevel = logging.DEBUG
basedir = tempfile.mkdtemp("fail2ban_conf")
try:
shutil.rmtree(basedir)
shutil.copytree(CONFIG_DIR, basedir)
shutil.copy(CONFIG_DIR + '/jail.conf', basedir + '/jail.local')
shutil.copy(CONFIG_DIR + '/fail2ban.conf', basedir + '/fail2ban.local')
# common sharing handle for this test:
share_cfg = dict()
# read whole configuration like a file2ban-client ...
self._readWholeConf(basedir, share_config=share_cfg)
# how many times jail.local was read:
cnt = self._getLoggedReadCount('jail.local')
# if cnt > 1:
# self.printLog()
self.assertTrue(cnt == 1, "Unexpected count by reading of jail files, cnt = %s" % cnt)
# read whole configuration like a file2ban-client, again ...
# but this time force enable all jails, to check filter and action cached also:
self._readWholeConf(basedir, force_enable=True, share_config=share_cfg)
cnt = self._getLoggedReadCount(r'jail\.local')
# still one (no more reads):
self.assertTrue(cnt == 1, "Unexpected count by second reading of jail files, cnt = %s" % cnt)
# same with filter:
cnt = self._getLoggedReadCount(r'filter\.d/common\.conf')
self.assertTrue(cnt == 1, "Unexpected count by reading of filter files, cnt = %s" % cnt)
# same with action:
cnt = self._getLoggedReadCount(r'action\.d/iptables-common\.conf')
self.assertTrue(cnt == 1, "Unexpected count by reading of action files, cnt = %s" % cnt)
finally:
shutil.rmtree(basedir)
configparserinc.logLevel = saved_ll
class JailsReaderTest(LogCaptureTestCase):
+1 -1
View File
@@ -92,7 +92,7 @@ class DatabaseTest(unittest.TestCase):
self.db = Fail2BanDb(self.dbFilename)
self.assertEqual(self.db.getJailNames(), set(['DummyJail #29162448 with 0 tickets']))
self.assertEqual(self.db.getLogPaths(), set(['/tmp/Fail2BanDb_pUlZJh.log']))
ticket = FailTicket("127.0.0.1", 1388009242.26, ["abc\n"])
ticket = FailTicket("127.0.0.1", 1388009242.26, [u"abc\n"])
self.assertEqual(self.db.getBans()[0], ticket)
self.assertEqual(self.db.updateDb(Fail2BanDb.__version__), Fail2BanDb.__version__)
+2 -1
View File
@@ -86,6 +86,7 @@ class DateDetectorTest(unittest.TestCase):
(False, "23-Jan-2005 21:59:59.02"),
(False, "23-Jan-2005 21:59:59 +0100"),
(False, "23-01-2005 21:59:59"),
(True, "1106513999"), # Portsetry
(False, "01-23-2005 21:59:59.252"), # reported on f2b, causes Feb29 fix to break
(False, "@4000000041f4104f00000000"), # TAI64N
(False, "2005-01-23T20:59:59.252Z"), #ISO 8601 (UTC)
@@ -139,7 +140,7 @@ class DateDetectorTest(unittest.TestCase):
self.assertEqual(logMatch.group(), '2012/10/11 02:37:17')
self.__datedetector.sortTemplate()
# confuse it with year being at the end
for i in range(10):
for i in xrange(10):
( logTime, logMatch ) = self.__datedetector.getTime('11/10/2012 02:37:17 [error] 18434#0')
self.assertEqual(logTime, mu)
self.assertEqual(logMatch.group(), '11/10/2012 02:37:17')
+5 -5
View File
@@ -33,11 +33,11 @@ class AddFailure(unittest.TestCase):
def setUp(self):
"""Call before every test case."""
self.__items = [['193.168.0.128', 1167605999.0],
['193.168.0.128', 1167605999.0],
['193.168.0.128', 1167605999.0],
['193.168.0.128', 1167605999.0],
['193.168.0.128', 1167605999.0],
self.__items = [[u'193.168.0.128', 1167605999.0],
[u'193.168.0.128', 1167605999.0],
[u'193.168.0.128', 1167605999.0],
[u'193.168.0.128', 1167605999.0],
[u'193.168.0.128', 1167605999.0],
['87.142.124.10', 1167605999.0],
['87.142.124.10', 1167605999.0],
['87.142.124.10', 1167605999.0],
@@ -1,14 +1,21 @@
#!/bin/env python
import requests
import md5
try:
import hashlib
md5sum = hashlib.md5
except ImportError: # pragma: no cover
# hashlib was introduced in Python 2.5. For compatibility with those
# elderly Pythons, import from md5
import md5
md5sum = md5.new
def auth(v):
ha1 = md5.new(username + ':' + realm + ':' + password).hexdigest()
ha2 = md5.new("GET:" + url).hexdigest()
ha1 = md5sum(username + ':' + realm + ':' + password).hexdigest()
ha2 = md5sum("GET:" + url).hexdigest()
#response = md5.new(ha1 + ':' + v['nonce'][1:-1] + ':' + v['nc'] + ':' + v['cnonce'][1:-1]
#response = md5sum(ha1 + ':' + v['nonce'][1:-1] + ':' + v['nc'] + ':' + v['cnonce'][1:-1]
# + ':' + v['qop'][1:-1] + ':' + ha2).hexdigest()
nonce = v['nonce'][1:-1]
@@ -17,7 +24,7 @@ def auth(v):
#opaque = v.get('opaque') or ''
qop = v['qop'][1:-1]
algorithm = v['algorithm']
response = md5.new(ha1 + ':' + nonce + ':' + nc + ':' + cnonce + ':' + qop + ':' + ha2).hexdigest()
response = md5sum(ha1 + ':' + nonce + ':' + nc + ':' + cnonce + ':' + qop + ':' + ha2).hexdigest()
p = requests.Request('GET', host + url).prepare()
#p.headers['Authentication-Info'] = response
+3
View File
@@ -19,6 +19,9 @@
# failJSON: { "time": "2013-07-20T21:34:49", "match": true , "host": "127.0.0.1" }
[Sat Jul 20 21:34:49.453232 2013] [access_compat:error] [pid 17512:tid 140123104306944] [client 127.0.0.1:51380] AH01797: client denied by server configuration: /var/www/html/noentry/cant_get_me.html
# failJSON: { "time": "2014-09-14T21:44:43", "match": true , "host": "192.3.9.178" }
[Sun Sep 14 21:44:43.008606 2014] [authz_core:error] [pid 10691] [client 192.3.9.178:44271] AH01630: client denied by server configuration: /var/www/html/noentry/cant_get_me.html
# wget --http-user='' --http-password='' http://localhost/basic/file/cant_get_me.html -O /dev/null
# failJSON: { "time": "2013-07-17T23:14:37", "match": true , "host": "127.0.0.1" }
[Wed Jul 17 23:14:37 2013] [error] [client 127.0.0.1] user not found: /basic/anon/cant_get_me.html
@@ -0,0 +1,4 @@
# failJSON: { "time": "2014-09-25T09:27:18", "match": true , "host": "89.207.132.76" }
[Thu Sep 25 09:27:18.813902 2014] [cgi:error] [pid 16860] [client 89.207.132.76:59635] AH01215: /bin/bash: warning: HTTP_TEST: ignoring function definition attempt
# failJSON: { "time": "2014-09-25T09:29:56", "match": true , "host": "162.247.73.206" }
[Thu Sep 25 09:29:56.141832 2014] [cgi:error] [pid 16864] [client 162.247.73.206:41273] AH01215: /bin/bash: error importing function definition for `HTTP_TEST'
+4
View File
@@ -0,0 +1,4 @@
# failJSON: { "time": "2014-06-27T17:51:19", "match": true , "host": "192.168.56.1" }
1403884279 - 06/27/2014 17:51:19 Host: 192.168.56.1/192.168.56.1 Port: 1 TCP Blocked
# failJSON: { "time": "2014-06-27T17:51:19", "match": true , "host": "192.168.56.1" }
1403884279 - 06/27/2014 17:51:19 Host: 192.168.56.1/192.168.56.1 Port: 1 UDP Blocked
+3
View File
@@ -5,3 +5,6 @@ Dec 2 22:24:22 hel postfix/smtpd[7676]: warning: 114-44-142-233.dynamic.hinet.n
# failJSON: { "time": "2005-03-10T13:33:30", "match": true , "host": "1.1.1.1" }
Mar 10 13:33:30 gandalf postfix/smtpd[3937]: warning: HOSTNAME[1.1.1.1]: SASL LOGIN authentication failed: authentication failure
#3 Example from postfix post-debian changes to rename to add "submission" to syslog name
# failJSON: { "time": "2004-09-06T00:44:56", "match": true , "host": "82.221.106.233" }
Sep 6 00:44:56 trianon postfix/submission/smtpd[11538]: warning: unknown[82.221.106.233]: SASL LOGIN authentication failed: UGFzc3dvcmQ6
+9 -9
View File
@@ -22,7 +22,7 @@
__copyright__ = "Copyright (c) 2004 Cyril Jaquier; 2012 Yaroslav Halchenko"
__license__ = "GPL"
from builtins import open as fopen
from __builtin__ import open as fopen
import unittest
import getpass
import os
@@ -133,7 +133,7 @@ def _copy_lines_between_files(in_, fout, n=None, skip=0, mode='a', terminal_line
else:
fin = in_
# Skip
for i in range(skip):
for i in xrange(skip):
fin.readline()
# Read
i = 0
@@ -170,7 +170,7 @@ def _copy_lines_to_journal(in_, fields={},n=None, skip=0, terminal_line=""): # p
"PRIORITY": "7",
})
# Skip
for i in range(skip):
for i in xrange(skip):
fin.readline()
# Read/Write
i = 0
@@ -806,7 +806,7 @@ class GetFailures(unittest.TestCase):
# so that they could be reused by other tests
FAILURES_01 = ('193.168.0.128', 3, 1124013599.0,
['Aug 14 11:59:59 [sshd] error: PAM: Authentication failure for kevin from 193.168.0.128']*3)
[u'Aug 14 11:59:59 [sshd] error: PAM: Authentication failure for kevin from 193.168.0.128']*3)
def setUp(self):
"""Call before every test case."""
@@ -856,8 +856,8 @@ class GetFailures(unittest.TestCase):
def testGetFailures02(self):
output = ('141.3.81.106', 4, 1124013539.0,
['Aug 14 11:%d:59 i60p295 sshd[12365]: Failed publickey for roehl from ::ffff:141.3.81.106 port 51332 ssh2'
% m for m in (53, 54, 57, 58)])
[u'Aug 14 11:%d:59 i60p295 sshd[12365]: Failed publickey for roehl from ::ffff:141.3.81.106 port 51332 ssh2'
% m for m in 53, 54, 57, 58])
self.filter.addLogPath(GetFailures.FILENAME_02)
self.filter.addFailRegex("Failed .* from <HOST>")
@@ -889,11 +889,11 @@ class GetFailures(unittest.TestCase):
def testGetFailuresUseDNS(self):
# We should still catch failures with usedns = no ;-)
output_yes = ('93.184.216.119', 2, 1124013539.0,
['Aug 14 11:54:59 i60p295 sshd[12365]: Failed publickey for roehl from example.com port 51332 ssh2',
'Aug 14 11:58:59 i60p295 sshd[12365]: Failed publickey for roehl from ::ffff:93.184.216.119 port 51332 ssh2'])
[u'Aug 14 11:54:59 i60p295 sshd[12365]: Failed publickey for roehl from example.com port 51332 ssh2',
u'Aug 14 11:58:59 i60p295 sshd[12365]: Failed publickey for roehl from ::ffff:93.184.216.119 port 51332 ssh2'])
output_no = ('93.184.216.119', 1, 1124013539.0,
['Aug 14 11:58:59 i60p295 sshd[12365]: Failed publickey for roehl from ::ffff:93.184.216.119 port 51332 ssh2'])
[u'Aug 14 11:58:59 i60p295 sshd[12365]: Failed publickey for roehl from ::ffff:93.184.216.119 port 51332 ssh2'])
# Actually no exception would be raised -- it will be just set to 'no'
#self.assertRaises(ValueError,
+2 -2
View File
@@ -30,7 +30,7 @@ import shutil
import fnmatch
import datetime
from glob import glob
from io import StringIO
from StringIO import StringIO
from ..helpers import formatExceptionInfo, mbasename, TraceBack, FormatterWithTraceBack, getLogger
from ..server.datetemplate import DatePatternRegex
@@ -138,7 +138,7 @@ class TestsUtilsTest(unittest.TestCase):
else: func_raise()
try:
print(deep_function(3))
print deep_function(3)
except ValueError:
s = tb()
+5 -13
View File
@@ -24,21 +24,13 @@ __license__ = "GPL"
import unittest, sys, os, fileinput, re, time, datetime, inspect
if sys.version_info >= (2, 6):
import json
else:
import simplejson as json
next = lambda x: x.__next__()
import json
from ..server.filter import Filter
from ..client.filterreader import FilterReader
from .utils import setUpMyTime, tearDownMyTime
from .utils import setUpMyTime, tearDownMyTime, CONFIG_DIR
TEST_FILES_DIR = os.path.join(os.path.dirname(__file__), "files")
if os.path.exists('config/fail2ban.conf'):
CONFIG_DIR = "config"
else:
CONFIG_DIR='/etc/fail2ban'
class FilterSamplesRegex(unittest.TestCase):
@@ -94,7 +86,7 @@ def testSampleRegexsFactory(name):
if jsonREMatch:
try:
faildata = json.loads(jsonREMatch.group(1))
except ValueError as e:
except ValueError, e:
raise ValueError("%s: %s:%i" %
(e, logFile.filename(), logFile.filelineno()))
line = next(logFile)
@@ -116,7 +108,7 @@ def testSampleRegexsFactory(name):
"Line matched when shouldn't have: %s:%i %r" %
(logFile.filename(), logFile.filelineno(), line))
self.assertEqual(len(ret), 1, "Multiple regexs matched %r - %s:%i" %
([x[0] for x in ret],logFile.filename(), logFile.filelineno()))
(map(lambda x: x[0], ret),logFile.filename(), logFile.filelineno()))
# Verify timestamp and host as expected
failregex, host, fail2banTime, lines = ret[0]
@@ -149,7 +141,7 @@ def testSampleRegexsFactory(name):
return testFilter
for filter_ in [x for x in os.listdir(os.path.join(CONFIG_DIR, "filter.d")) if not x.endswith('common.conf')]:
for filter_ in filter(lambda x: not x.endswith('common.conf'), os.listdir(os.path.join(CONFIG_DIR, "filter.d"))):
filterName = filter_.rpartition(".")[0]
if not filterName.startswith('.'):
setattr(
+9 -9
View File
@@ -685,7 +685,7 @@ class TransmitterLogging(TransmitterBase):
def testLogTarget(self):
logTargets = []
for _ in range(3):
for _ in xrange(3):
tmpFile = tempfile.mkstemp("fail2ban", "transmitter")
logTargets.append(tmpFile[1])
os.close(tmpFile[0])
@@ -738,26 +738,26 @@ class TransmitterLogging(TransmitterBase):
self.assertEqual(self.transm.proceed(["flushlogs"]), (0, "rolled over"))
l.warning("After flushlogs")
with open(fn2,'r') as f:
line1 = next(f)
line1 = f.next()
if line1.find('Changed logging target to') >= 0:
line1 = next(f)
line1 = f.next()
self.assertTrue(line1.endswith("Before file moved\n"))
line2 = next(f)
line2 = f.next()
self.assertTrue(line2.endswith("After file moved\n"))
try:
n = next(f)
n = f.next()
if n.find("Command: ['flushlogs']") >=0:
self.assertRaises(StopIteration, f.__next__)
self.assertRaises(StopIteration, f.next)
else:
self.fail("Exception StopIteration or Command: ['flushlogs'] expected. Got: %s" % n)
except StopIteration:
pass # on higher debugging levels this is expected
with open(fn,'r') as f:
line1 = next(f)
line1 = f.next()
if line1.find('rollover performed on') >= 0:
line1 = next(f)
line1 = f.next()
self.assertTrue(line1.endswith("After flushlogs\n"))
self.assertRaises(StopIteration, f.__next__)
self.assertRaises(StopIteration, f.next)
f.close()
finally:
os.remove(fn2)
+21 -5
View File
@@ -25,15 +25,25 @@ __license__ = "GPL"
import logging
import os
import re
import sys
import time
import unittest
from io import StringIO
from StringIO import StringIO
from ..server.mytime import MyTime
from ..helpers import getLogger
logSys = getLogger(__name__)
CONFIG_DIR = os.environ.get('FAIL2BAN_CONFIG_DIR', None)
if not CONFIG_DIR:
# Use heuristic to figure out where configuration files are
if os.path.exists(os.path.join('config','fail2ban.conf')):
CONFIG_DIR = 'config'
else:
CONFIG_DIR = '/etc/fail2ban'
def mtimesleep():
# no sleep now should be necessary since polling tracks now not only
# mtime but also ino and size
@@ -102,6 +112,7 @@ def gatherTests(regexps=None, no_network=False):
tests.addTest(unittest.makeSuite(clientreadertestcase.JailReaderTest))
tests.addTest(unittest.makeSuite(clientreadertestcase.FilterReaderTest))
tests.addTest(unittest.makeSuite(clientreadertestcase.JailsReaderTest))
tests.addTest(unittest.makeSuite(clientreadertestcase.JailsReaderTestCache))
# CSocket and AsyncServer
tests.addTest(unittest.makeSuite(sockettestcase.Socket))
# Misc helpers
@@ -156,13 +167,13 @@ def gatherTests(regexps=None, no_network=False):
try:
from ..server.filtergamin import FilterGamin
filters.append(FilterGamin)
except Exception as e: # pragma: no cover
except Exception, e: # pragma: no cover
logSys.warning("Skipping gamin backend testing. Got exception '%s'" % e)
try:
from ..server.filterpyinotify import FilterPyinotify
filters.append(FilterPyinotify)
except Exception as e: # pragma: no cover
except Exception, e: # pragma: no cover
logSys.warning("I: Skipping pyinotify backend testing. Got exception '%s'" % e)
for Filter_ in filters:
@@ -171,7 +182,7 @@ def gatherTests(regexps=None, no_network=False):
try: # pragma: systemd no cover
from ..server.filtersystemd import FilterSystemd
tests.addTest(unittest.makeSuite(filtertestcase.get_monitor_failures_journal_testcase(FilterSystemd)))
except Exception as e: # pragma: no cover
except Exception, e: # pragma: no cover
logSys.warning("I: Skipping systemd backend testing. Got exception '%s'" % e)
@@ -195,6 +206,8 @@ class LogCaptureTestCase(unittest.TestCase):
# Let's log everything into a string
self._log = StringIO()
logSys.handlers = [logging.StreamHandler(self._log)]
if self._old_level < logging.DEBUG: # so if HEAVYDEBUG etc -- show them!
logSys.handlers += self._old_handlers
logSys.setLevel(getattr(logging, 'DEBUG'))
def tearDown(self):
@@ -207,5 +220,8 @@ class LogCaptureTestCase(unittest.TestCase):
def _is_logged(self, s):
return s in self._log.getvalue()
def getLog(self):
return self._log.getvalue()
def printLog(self):
print((self._log.getvalue()))
print(self._log.getvalue())
+1 -1
View File
@@ -24,4 +24,4 @@ __author__ = "Cyril Jaquier, Yaroslav Halchenko, Steven Hiscocks, Daniel Black"
__copyright__ = "Copyright (c) 2004 Cyril Jaquier, 2011-2014 Yaroslav Halchenko, 2013-2013 Steven Hiscocks, Daniel Black"
__license__ = "GPL-v2+"
version = "0.9.0.dev"
version = "0.9.1"
+209
View File
@@ -0,0 +1,209 @@
#!/usr/bin/perl
##########################################################################
# $Id: fail2ban 150 2013-06-18 22:19:38Z mtremaine $
##########################################################################
# $Log: fail2ban,v $
#
# Revision 1.6 2014/08/11 16:07:46 yoh
# Patches from Yaroslav Halchenko to match adjusted in 0.9.x lines.
# Also reports now total number of hits (matches) along with Ban:Unban
# and relaxed regular expressions for matching any log level
#
# Revision 1.5 2008/08/18 16:07:46 mike
# Patches from Paul Gear <paul at libertysys.com> -mgt
#
# Revision 1.4 2008/06/30 23:07:51 kirk
# fixed copyright holders for files where I know who they should be
#
# Revision 1.3 2008/03/24 23:31:26 kirk
# added copyright/license notice to each script
#
# Revision 1.2 2006/12/15 04:53:59 bjorn
# Additional filtering, by Willi Mann.
#
# Revision 1.1 2006/05/30 19:04:26 bjorn
# Added fail2ban service, written by Yaroslav Halchenko.
#
# Written by Yaroslav Halchenko <debian@onerussian.com> for fail2ban
#
##########################################################################
########################################################
## Copyright (c) 2008 Yaroslav Halchenko
## Covered under the included MIT/X-Consortium License:
## http://www.opensource.org/licenses/mit-license.php
## All modifications and contributions by other persons to
## this script are assumed to have been donated to the
## Logwatch project and thus assume the above copyright
## and licensing terms. If you want to make contributions
## under your own copyright or a different license this
## must be explicitly stated in the contribution an the
## Logwatch project reserves the right to not accept such
## contributions. If you have made significant
## contributions to this script and want to claim
## copyright please contact logwatch-devel@lists.sourceforge.net.
#########################################################
use strict;
use Logwatch ':all';
my $Debug = $ENV{'LOGWATCH_DEBUG'} || 0;
my $Detail = $ENV{'LOGWATCH_DETAIL_LEVEL'} || 0;
my $IgnoreHost = $ENV{'sshd_ignore_host'} || "";
my $DebugCounter = 0;
my $ReInitializations = 0;
my @ActionsErrors = ();
my @CommandsErrors = ();
my $NotValidIP = 0; # reported invalid IPs number
my @OtherList = ();
my %ServicesBans = ();
if ( $Debug >= 5 ) {
print STDERR "\n\nDEBUG: Inside Fail2Ban Filter \n\n";
$DebugCounter = 1;
}
while (defined(my $ThisLine = <STDIN>)) {
if ( $Debug >= 5 ) {
print STDERR "DEBUG($DebugCounter): $ThisLine";
$DebugCounter++;
}
chomp($ThisLine);
if ( ($ThisLine =~ /..,... DEBUG: /) or
($ThisLine =~ /..,... \S*\s*: DEBUG /) or # syntax of 0.7.? fail2ban
($ThisLine =~ /..,... \S+: (Fail2Ban v.* is running|Exiting|Enabled sections:)/) or
($ThisLine =~ /\S+\s+rollover performed on/) or
($ThisLine =~ /\S+\s+Connected to .* persistent database/) or
($ThisLine =~ /\S+\s+Jail '.*' uses .*/) or
($ThisLine =~ /\S+\s+Initiated '.*' backend/) or
($ThisLine =~ /\S+\s+Jail .* is not a JournalFilter instance/) or
($ThisLine =~ /\S+\s+Log rotation detected for/) or
($ThisLine =~ /\S+\s+Jail.+(?:stopped|started|uses poller)/) or
($ThisLine =~ /\S+\s+Changed logging target to/) or
($ThisLine =~ /\S+\s+Creating new jail/) or
($ThisLine =~ /..,... \S+\s*: INFO\s+(Set |Socket|Exiting|Gamin|Created|Added|Using)/) or # syntax of 0.7.? fail2ban
($ThisLine =~ /..,... \S+: Verbose level is /) or
($ThisLine =~ /..,... \S+: Restoring firewall rules/)
)
{
if ( $Debug >= 6 ) {
print STDERR "DEBUG($DebugCounter): line ignored\n";
}
} elsif ( my ($LogLevel,$Service,$Action,$Host) = ($ThisLine =~ m/(WARNING|NOTICE):?\s+\[?(.*?)[]:]?\s(Ban|Unban)[^\.]* (\S+)/)) {
if ( $Debug >= 6 ) {
print STDERR "DEBUG($DebugCounter): Found $Action for $Service from $Host\n";
}
$ServicesBans{$Service}{$Host}{$Action}++;
$ServicesBans{$Service}{"(all)"}{$Action}++;
} elsif ( my ($LogLevel,$Service,$Host) = ($ThisLine =~ m/(INFO|WARNING|NOTICE):?\s+\[?(.*?)[]:]?\sFound[^\.]* (\S+)/)) {
if ( $Debug >= 6 ) {
print STDERR "DEBUG($DebugCounter): Found hit for $Service from $Host\n";
}
$ServicesBans{$Service}{$Host}{"Hit"}++;
$ServicesBans{$Service}{"(all)"}{"Hit"}++;
} elsif ( my ($Service,$Host,$NumFailures) = ($ThisLine =~ m/\S+:\s+(\S+): (.+) has (\d+) login failure\(s\). Banned./)) {
if ($Debug >= 4) {
print STDERR "DEBUG: Found host $Host trying to access $Service - failed $NumFailures times\n";
}
push @{$ServicesBans{$Service}{$Host}{'Failures'}}, $NumFailures;
} elsif ( my ($Service,$Host) = ($ThisLine =~ m/ \S+:\s(.*):\s(\S+)\salready in ban list/)) {
$ServicesBans{$Service}{$Host}{'AlreadyInTheList'}++;
} elsif ( my ($Service,$Host) = ($ThisLine =~ m/\S+:?\s+\[?([^[]*?)[]:]?\s+(\S+)\salready banned/)) {
if ( $Debug >= 6 ) {
print STDERR "DEBUG($DebugCounter): Found hit for already banned $Host against $Service\n";
}
$ServicesBans{$Service}{$Host}{'AlreadyInTheList'}++;
} elsif ( my ($Service,$Host) = ($ThisLine =~ m/ \S+:\s(.*):\sReBan (\S+)/)) {
$ServicesBans{$Service}{$Host}{'ReBan'}++;
} elsif ($ThisLine =~ / ERROR:?\s*(Execution of command )?\'?iptables/) {
push @ActionsErrors, "$ThisLine\n";
} elsif ($ThisLine =~ / ERROR\s*Failed to execute.*action/) {
push @ActionsErrors, "$ThisLine\n";
} elsif ($ThisLine =~ / WARNING Command \[.*\] has failed. Received/) {
push @CommandsErrors, "$ThisLine\n";
} elsif ($ThisLine =~ /ERROR.*returned \d+$/) {
push @ActionsErrors, "$ThisLine\n";
} elsif (($ThisLine =~ /..,... WARNING: \#\S+ reinitialization of firewalls/) or
($ThisLine =~ / ERROR\s*Invariant check failed. Trying to restore a sane environment/)) {
$ReInitializations++;
} elsif ($ThisLine =~ /..,... WARNING: is not a valid IP address/) {
# just ignore - this will be fixed within fail2ban and is harmless warning
}
else
{
# Report any unmatched entries...
push @OtherList, "$ThisLine\n";
}
}
###########################################################
if (keys %ServicesBans) {
printf("\nBanned services with Fail2Ban: Bans:Unbans:Hits\n");
foreach my $service (sort {$a cmp $b} keys %ServicesBans) {
printf(" %-55s [%3d:%d:%-3d]\n", "$service:",
$ServicesBans{$service}{'(all)'}{'Ban'},
$ServicesBans{$service}{'(all)'}{'Unban'},
$ServicesBans{$service}{'(all)'}{'Hit'});
delete $ServicesBans{$service}{'(all)'};
my $totalSort = TotalCountOrder(%{$ServicesBans{$service}}, \&SortIP);
if ($Detail >= 5) {
foreach my $ip (sort $totalSort keys %{$ServicesBans{$service}}) {
my $name = LookupIP($ip);
printf(" %-53s %3d:%d:%-3d\n",
$name,
$ServicesBans{$service}{$ip}{'Ban'},
$ServicesBans{$service}{$ip}{'Unban'},
$ServicesBans{$service}{$ip}{'Hit'});
if (($Detail >= 10) and ($ServicesBans{$service}{$ip}{'Failures'}>0)) {
print " Failed ";
foreach my $fails (@{$ServicesBans{$service}{$ip}{'Failures'}}) {
print " $fails";
}
print " times\n";
}
if ($ServicesBans{$service}{$ip}{'AlreadyInTheList'}>0) {
printf(" %d Duplicate Ban attempt(s)\n", $ServicesBans{$service}{$ip}{'AlreadyInTheList'}) ;
}
if ($ServicesBans{$service}{$ip}{'ReBan'}>0) {
printf(" %d ReBan(s) due to rules reinitilizations\n", $ServicesBans{$service}{$ip}{'ReBan'}) ;
}
}
}
}
}
if ($Detail>0) {
if ($#ActionsErrors >= 0) {
printf("\n%d faulty action invocation(s)", $#ActionsErrors+1);
if ($Detail > 5) {
print ":\n";
print @ActionsErrors ;
}
}
if ($#CommandsErrors >= 0) {
printf("\n%d faulty command invocation(s) from client(s)", $#CommandsErrors+1);
if ($Detail > 5) {
print ":\n";
print @CommandsErrors ;
}
}
if ($ReInitializations > 0) {
printf("\n%d fail2ban rules reinitialization(s)", $ReInitializations);
}
if ($#OtherList >= 0) {
print "\n**Unmatched Entries**\n";
print @OtherList;
}
}
exit(0);
# vi: shiftwidth=3 tabstop=3 syntax=perl et
# Local Variables:
# mode: perl
# perl-indent-level: 3
# indent-tabs-mode: nil
# End:
+2
View File
@@ -0,0 +1,2 @@
2014-08-04 03:06:26,161 fail2ban.actions[4822]: WARNING [apache-badbots] Ban 37.152.91.34
2014-08-05 03:06:26,448 fail2ban.actions[4822]: WARNING [apache-badbots] Unban 37.152.91.34
+52
View File
@@ -0,0 +1,52 @@
2014-08-08 14:59:35,013 fail2ban.server.server[31122]: INFO Exiting Fail2ban
2014-08-08 14:59:36,041 fail2ban.server.server[21667]: INFO Changed logging target to /var/log/fail2ban.log for Fail2ban v0.9.0
2014-08-08 14:59:36,043 fail2ban.server.database[21667]: INFO Connected to fail2ban persistent database '/var/lib/fail2ban/fail2ban.sqlite3'
2014-08-08 14:59:36,072 fail2ban.server.jail[21667]: INFO Creating new jail 'exim'
2014-08-08 14:59:36,137 fail2ban.server.jail[21667]: INFO Jail 'exim' uses pyinotify
2014-08-08 14:59:36,172 fail2ban.server.filter[21667]: INFO Set jail log file encoding to UTF-8
2014-08-08 14:59:36,172 fail2ban.server.jail[21667]: INFO Initiated 'pyinotify' backend
2014-08-08 14:59:36,233 fail2ban.server.filter[21667]: INFO Added logfile = /var/log/exim4/mainlog
2014-08-08 14:59:36,249 fail2ban.server.filter[21667]: INFO Set maxRetry = 5
2014-08-08 14:59:36,251 fail2ban.server.filter[21667]: INFO Set jail log file encoding to UTF-8
2014-08-08 14:59:36,252 fail2ban.server.actions[21667]: INFO Set banTime = 600
2014-08-08 14:59:36,254 fail2ban.server.filter[21667]: INFO Set findtime = 600
2014-08-08 14:59:36,284 fail2ban.server.jail[21667]: INFO Creating new jail 'sshd'
2014-08-08 14:59:36,284 fail2ban.server.jail[21667]: INFO Jail 'sshd' uses pyinotify
2014-08-08 14:59:36,286 fail2ban.server.filter[21667]: INFO Set jail log file encoding to UTF-8
2014-08-08 14:59:36,286 fail2ban.server.jail[21667]: INFO Initiated 'pyinotify' backend
2014-08-08 14:59:36,499 fail2ban.server.filter[21667]: INFO Added logfile = /var/log/auth.log
2014-08-08 14:59:36,510 fail2ban.server.filter[21667]: INFO Set maxRetry = 5
2014-08-08 14:59:36,512 fail2ban.server.filter[21667]: INFO Set jail log file encoding to UTF-8
2014-08-08 14:59:36,513 fail2ban.server.actions[21667]: INFO Set banTime = 600
2014-08-08 14:59:36,514 fail2ban.server.filter[21667]: INFO Set findtime = 600
2014-08-08 14:59:36,515 fail2ban.server.filter[21667]: INFO Set maxlines = 10
2014-08-08 14:59:36,788 fail2ban.server.server[21667]: INFO Jail sshd is not a JournalFilter instance
2014-08-08 14:59:36,798 fail2ban.server.jail[21667]: INFO Jail 'exim' started
2014-08-08 14:59:36,802 fail2ban.server.jail[21667]: INFO Jail 'sshd' started
2014-08-08 15:01:30,120 fail2ban.server.transmitter[21667]: WARNING Command ['status', 'ssh'] has failed. Received UnknownJailException('ssh',)
2014-08-08 15:09:36,978 fail2ban.server.actions[21667]: NOTICE [sshd] Unban 116.10.191.199
2014-08-08 15:09:37,187 fail2ban.server.action[21667]: ERROR rm -f /etc/symbiosis/firewall/blacklist.d/116.10.191.199.auto
iptables -D INPUT -s 116.10.191.199 -j DROP -- stdout: ''
2014-08-08 15:09:37,188 fail2ban.server.action[21667]: ERROR rm -f /etc/symbiosis/firewall/blacklist.d/116.10.191.199.auto
iptables -D INPUT -s 116.10.191.199 -j DROP -- stderr: 'iptables: Bad rule (does a matching rule exist in that chain?).\n'
2014-08-08 15:09:37,188 fail2ban.server.action[21667]: ERROR rm -f /etc/symbiosis/firewall/blacklist.d/116.10.191.199.auto
iptables -D INPUT -s 116.10.191.199 -j DROP -- returned 1
2014-08-08 15:09:37,188 fail2ban.server.actions[21667]: ERROR Failed to execute unban jail 'sshd' action 'symbiosis-blacklist': Error unbanning 116.10.191.199
2014-08-10 02:27:27,235 fail2ban.server.server[21667]: INFO rollover performed on /var/log/fail2ban.log
2014-08-10 02:27:28,109 fail2ban.server.filter[21667]: INFO Log rotation detected for /var/log/exim4/mainlog
2014-08-10 02:28:01,747 fail2ban.server.filter[21667]: INFO Log rotation detected for /var/log/auth.log
2014-08-10 02:33:29,500 fail2ban.server.filter[21667]: INFO [sshd] Found 86.101.234.57
2014-08-10 02:46:06,846 fail2ban.server.filter[21667]: INFO [sshd] Found 220.130.163.247
2014-08-10 03:10:43,794 fail2ban.server.filter[21667]: INFO [sshd] Found 220.130.163.247
2014-08-10 06:49:27,446 fail2ban.server.actions[21667]: NOTICE [sshd] Ban 116.10.191.181
2014-08-10 06:59:28,375 fail2ban.server.actions[21667]: NOTICE [sshd] Unban 116.10.191.181
2014-08-10 20:06:41,576 fail2ban.server.actions[21667]: NOTICE [sshd] Unban 50.30.34.7
2014-08-13 17:55:50,401 fail2ban.server.actions[17436]: NOTICE [sshd] 144.0.0.25 already banned
2014-08-10 20:06:41,785 fail2ban.server.action[21667]: ERROR rm -f /etc/symbiosis/firewall/blacklist.d/50.30.34.7.auto
iptables -D INPUT -s 50.30.34.7 -j DROP -- stdout: ''
2014-08-10 20:06:41,785 fail2ban.server.action[21667]: ERROR rm -f /etc/symbiosis/firewall/blacklist.d/50.30.34.7.auto
iptables -D INPUT -s 50.30.34.7 -j DROP -- stderr: 'iptables: Bad rule (does a matching rule exist in that chain?).\n'
2014-08-10 20:06:41,786 fail2ban.server.action[21667]: ERROR rm -f /etc/symbiosis/firewall/blacklist.d/50.30.34.7.auto
iptables -D INPUT -s 50.30.34.7 -j DROP -- returned 1
2014-08-10 20:06:41,786 fail2ban.server.actions[21667]: ERROR Failed to execute unban jail 'sshd' action 'symbiosis-blacklist': Error unbanning 50.30.34.7
2014-08-11 02:27:35,433 fail2ban.server.filter[21667]: INFO Log rotation detected for /var/log/exim4/mainlog
+23 -31
View File
@@ -1,12 +1,12 @@
.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.41.2.
.TH FAIL2BAN-CLIENT "1" "March 2014" "fail2ban-client v0.9.0" "User Commands"
.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.46.4.
.TH FAIL2BAN-CLIENT "1" "October 2014" "fail2ban-client v0.9.1" "User Commands"
.SH NAME
fail2ban-client \- configure and control the server
.SH SYNOPSIS
.B fail2ban-client
[\fIOPTIONS\fR] \fI<COMMAND>\fR
[\fI\,OPTIONS\/\fR] \fI\,<COMMAND>\/\fR
.SH DESCRIPTION
Fail2Ban v0.9.0 reads log file that contains password failure report
Fail2Ban v0.9.1 reads log file that contains password failure report
and bans the corresponding IP addresses using firewall rules.
.SH OPTIONS
.TP
@@ -35,10 +35,10 @@ decrease verbosity
force execution of the server (remove socket file)
.TP
\fB\-b\fR
start the server in background mode (default)
start server in background (default)
.TP
\fB\-f\fR
start the server in foreground mode (note that the client forks once itself)
start server in foreground (note that the client forks once itself)
.TP
\fB\-h\fR, \fB\-\-help\fR
display this help message
@@ -217,9 +217,8 @@ for <JAIL>
\fBset <JAIL> maxlines <LINES>\fR
sets the number of <LINES> to
buffer for regex search for <JAIL>
.IP
set <JAIL> addaction <ACT>[ <PYTHONFILE> <JSONKWARGS>]
.IP
.TP
\fBset <JAIL> addaction <ACT>[ <PYTHONFILE> <JSONKWARGS>]\fR
adds a new action named <NAME> for
<JAIL>. Optionally for a Python
based action, a <PYTHONFILE> and
@@ -231,45 +230,38 @@ removes the action <ACT> from
<JAIL>
.IP
COMMAND ACTION CONFIGURATION
.IP
set <JAIL> action <ACT> actionstart <CMD>
.IP
.TP
\fBset <JAIL> action <ACT> actionstart <CMD>\fR
sets the start command <CMD> of
the action <ACT> for <JAIL>
.IP
set <JAIL> action <ACT> actionstop <CMD> sets the stop command <CMD> of the
.IP
.TP
\fBset <JAIL> action <ACT> actionstop <CMD> sets the stop command <CMD> of the\fR
action <ACT> for <JAIL>
.IP
set <JAIL> action <ACT> actioncheck <CMD>
.IP
.TP
\fBset <JAIL> action <ACT> actioncheck <CMD>\fR
sets the check command <CMD> of
the action <ACT> for <JAIL>
.TP
\fBset <JAIL> action <ACT> actionban <CMD>\fR
sets the ban command <CMD> of the
action <ACT> for <JAIL>
.IP
set <JAIL> action <ACT> actionunban <CMD>
.IP
.TP
\fBset <JAIL> action <ACT> actionunban <CMD>\fR
sets the unban command <CMD> of
the action <ACT> for <JAIL>
.IP
set <JAIL> action <ACT> timeout <TIMEOUT>
.IP
.TP
\fBset <JAIL> action <ACT> timeout <TIMEOUT>\fR
sets <TIMEOUT> as the command
timeout in seconds for the action
<ACT> for <JAIL>
.IP
GENERAL ACTION CONFIGURATION
.IP
set <JAIL> action <ACT> <PROPERTY> <VALUE>
.IP
.TP
\fBset <JAIL> action <ACT> <PROPERTY> <VALUE>\fR
sets the <VALUE> of <PROPERTY> for
the action <ACT> for <JAIL>
.IP
set <JAIL> action <ACT> <METHOD>[ <JSONKWARGS>]
.IP
.TP
\fBset <JAIL> action <ACT> <METHOD>[ <JSONKWARGS>]\fR
calls the <METHOD> with
<JSONKWARGS> for the action <ACT>
for <JAIL>
@@ -378,7 +370,7 @@ the action <ACT> for <JAIL>
Written by Cyril Jaquier <cyril.jaquier@fail2ban.org>.
Many contributions by Yaroslav O. Halchenko <debian@onerussian.com>.
.SH "REPORTING BUGS"
Report bugs via Debian bug tracking system \fIhttp://www.debian.org/Bugs/\fR .
Report bugs to https://github.com/fail2ban/fail2ban/issues
.SH COPYRIGHT
Copyright \(co 2004\-2008 Cyril Jaquier, 2008\- Fail2Ban Contributors
.br
+12 -9
View File
@@ -1,10 +1,10 @@
.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.41.2.
.TH FAIL2BAN-REGEX "1" "March 2014" "fail2ban-regex 0.9.0" "User Commands"
.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.46.4.
.TH FAIL2BAN-REGEX "1" "October 2014" "fail2ban-regex 0.9.1" "User Commands"
.SH NAME
fail2ban-regex \- test Fail2ban "failregex" option
.SH SYNOPSIS
.B fail2ban-regex
[\fIOPTIONS\fR] \fI<LOG> <REGEX> \fR[\fIIGNOREREGEX\fR]
[\fI\,OPTIONS\/\fR] \fI\,<LOG> <REGEX> \/\fR[\fI\,IGNOREREGEX\/\fR]
.SH DESCRIPTION
Fail2Ban reads log file that contains password failure report
and bans the corresponding IP addresses using firewall rules.
@@ -16,7 +16,7 @@ string
a string representing a log line
.TP
filename
path to a log file (\fI/var/log/auth.log\fP)
path to a log file (\fI\,/var/log/auth.log\/\fP)
.TP
"systemd\-journal"
search systemd journal (systemd\-python required)
@@ -42,20 +42,20 @@ show program's version number and exit
\fB\-h\fR, \fB\-\-help\fR
show this help message and exit
.TP
\fB\-d\fR DATEPATTERN, \fB\-\-datepattern\fR=\fIDATEPATTERN\fR
\fB\-d\fR DATEPATTERN, \fB\-\-datepattern\fR=\fI\,DATEPATTERN\/\fR
set custom pattern used to match date/times
.TP
\fB\-e\fR ENCODING, \fB\-\-encoding\fR=\fIENCODING\fR
\fB\-e\fR ENCODING, \fB\-\-encoding\fR=\fI\,ENCODING\/\fR
File encoding. Default: system locale
.TP
\fB\-L\fR MAXLINES, \fB\-\-maxlines\fR=\fIMAXLINES\fR
\fB\-L\fR MAXLINES, \fB\-\-maxlines\fR=\fI\,MAXLINES\/\fR
maxlines for multi\-line regex
.TP
\fB\-m\fR JOURNALMATCH, \fB\-\-journalmatch\fR=\fIJOURNALMATCH\fR
\fB\-m\fR JOURNALMATCH, \fB\-\-journalmatch\fR=\fI\,JOURNALMATCH\/\fR
journalctl style matches overriding filter file.
"systemd\-journal" only
.TP
\fB\-l\fR LOG_LEVEL, \fB\-\-log\-level\fR=\fILOG_LEVEL\fR
\fB\-l\fR LOG_LEVEL, \fB\-\-log\-level\fR=\fI\,LOG_LEVEL\/\fR
Log level for the Fail2Ban logger to use
.TP
\fB\-v\fR, \fB\-\-verbose\fR
@@ -70,6 +70,9 @@ Do not print any missed lines
\fB\-\-print\-no\-ignored\fR
Do not print any ignored lines
.TP
\fB\-\-print\-all\-matched\fR
Print all matched lines
.TP
\fB\-\-print\-all\-missed\fR
Print all missed lines, no matter how many
.TP
+5 -5
View File
@@ -1,12 +1,12 @@
.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.41.2.
.TH FAIL2BAN-SERVER "1" "March 2014" "fail2ban-server v0.9.0" "User Commands"
.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.46.4.
.TH FAIL2BAN-SERVER "1" "October 2014" "fail2ban-server v0.9.1" "User Commands"
.SH NAME
fail2ban-server \- start the server
.SH SYNOPSIS
.B fail2ban-server
[\fIOPTIONS\fR]
[\fI\,OPTIONS\/\fR]
.SH DESCRIPTION
Fail2Ban v0.9.0 reads log file that contains password failure report
Fail2Ban v0.9.1 reads log file that contains password failure report
and bans the corresponding IP addresses using firewall rules.
.PP
Only use this command for debugging purpose. Start the server with
@@ -38,7 +38,7 @@ print the version
Written by Cyril Jaquier <cyril.jaquier@fail2ban.org>.
Many contributions by Yaroslav O. Halchenko <debian@onerussian.com>.
.SH "REPORTING BUGS"
Report bugs via Debian bug tracking system \fIhttp://www.debian.org/Bugs/\fR .
Report bugs to https://github.com/fail2ban/fail2ban/issues
.SH COPYRIGHT
Copyright \(co 2004\-2008 Cyril Jaquier, 2008\- Fail2Ban Contributors
.br
+4
View File
@@ -1,5 +1,9 @@
#!/bin/bash
set -eu
export PYTHONPATH=..
# fail2ban-client
echo -n "Generating fail2ban-client "
help2man --section=1 --no-info --include=fail2ban-client.h2m --output fail2ban-client.1 ../bin/fail2ban-client
-4
View File
@@ -1,4 +0,0 @@
#!/bin/bash
sudo apt-get -y update
sudo apt-get -y install curl python-systemd dh-systemd python-pip python-inotifyx git build-essential autotools-dev libssl-dev devscripts debhelper git libpcre3-dev libssl-dev