Compare commits
79
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
408bed5464 | ||
|
|
4e543da4ba | ||
|
|
b1d7c3f3ff | ||
|
|
a0115ee458 | ||
|
|
d0a5fe620f | ||
|
|
564eb3389b | ||
|
|
987356d6c0 | ||
|
|
9e8e4dde69 | ||
|
|
fc145eb795 | ||
|
|
8a453018a9 | ||
|
|
b60e2bf42f | ||
|
|
e3a037ee3f | ||
|
|
3dac765598 | ||
|
|
0b5413ec0b | ||
|
|
3dabd5fc83 | ||
|
|
6293e44889 | ||
|
|
b2b5d0b41c | ||
|
|
e1a5decc00 | ||
|
|
caa6006a31 | ||
|
|
07d4badfd0 | ||
|
|
bef0502e6b | ||
|
|
0b0ea41f87 | ||
|
|
d4015d6566 | ||
|
|
e2f49b7334 | ||
|
|
78e1a13fad | ||
|
|
5ac496d030 | ||
|
|
fbce121967 | ||
|
|
6f4e542eff | ||
|
|
47441d1383 | ||
|
|
86a5f42f73 | ||
|
|
a33207bf87 | ||
|
|
eb6cc726ff | ||
|
|
cb662e2368 | ||
|
|
98dc0844ce | ||
|
|
7d3e6e9935 | ||
|
|
73a06d55a8 | ||
|
|
7f5d4aa7a6 | ||
|
|
95bdcdecaa | ||
|
|
02a46d0901 | ||
|
|
e0eb4f2358 | ||
|
|
c35b4b24d2 | ||
|
|
37952ab75f | ||
|
|
f67053c2ec | ||
|
|
f6723a12ff | ||
|
|
b62ce14ccd | ||
|
|
0c5f11079c | ||
|
|
f31607ded1 | ||
|
|
51cae63bf0 | ||
|
|
4244c87802 | ||
|
|
2a54e61238 | ||
|
|
af4b48e841 | ||
|
|
ce4f2d1c88 | ||
|
|
37acc6b832 | ||
|
|
97e01985a8 | ||
|
|
3f9859a127 | ||
|
|
d00af327c5 | ||
|
|
05fcb1f104 | ||
|
|
270ea363d3 | ||
|
|
b912d61ccb | ||
|
|
5d526bbeb1 | ||
|
|
7b5dc9f24f | ||
|
|
fc5f729f01 | ||
|
|
4f636eb0e3 | ||
|
|
bfaf33b6ba | ||
|
|
2c158fe168 | ||
|
|
caa851e5c8 | ||
|
|
8f521b8551 | ||
|
|
0e1f8f7f39 | ||
|
|
96c20c8379 | ||
|
|
c58c4de9bc | ||
|
|
8b2f0678a7 | ||
|
|
249e169d8e | ||
|
|
544cfaff2c | ||
|
|
b1c04f5fa2 | ||
|
|
decea64cf9 | ||
|
|
8b62353ab0 | ||
|
|
3bd36ba40a | ||
|
|
b0f26fa391 | ||
|
|
87703c4cfe |
@@ -1,4 +1,3 @@
|
||||
.pc/*
|
||||
*~
|
||||
build
|
||||
dist
|
||||
|
||||
@@ -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
|
||||
|
||||
Vendored
-181
@@ -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:
|
||||
@@ -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
|
||||
----------
|
||||
|
||||
@@ -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
|
||||
================
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
|
||||
|
||||
@@ -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)
|
||||
#
|
||||
|
||||
@@ -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*$
|
||||
|
||||
@@ -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)
|
||||
@@ -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>
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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= *$
|
||||
|
||||
@@ -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
|
||||
Vendored
+19
-6
@@ -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
|
||||
|
||||
|
||||
Vendored
+4
-3
@@ -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.
|
||||
|
||||
|
||||
-1556
File diff suppressed because it is too large
Load Diff
Vendored
-46
@@ -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
@@ -0,0 +1 @@
|
||||
neurodebian_use_python2
|
||||
+51
@@ -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
@@ -0,0 +1 @@
|
||||
neurodebian_use_python2
|
||||
Vendored
-1
@@ -1,2 +1 @@
|
||||
deb_manpages_reportbug
|
||||
convert-to-python3.patch
|
||||
|
||||
+1
@@ -0,0 +1 @@
|
||||
neurodebian_use_python2
|
||||
+1
@@ -0,0 +1 @@
|
||||
neurodebian_use_python2
|
||||
+1
@@ -0,0 +1 @@
|
||||
neurodebian_use_python2
|
||||
Vendored
+4
-2
@@ -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:
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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
@@ -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):
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
@@ -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'''"
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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])
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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))
|
||||
|
||||
|
||||
@@ -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])
|
||||
|
||||
@@ -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
@@ -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)
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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):
|
||||
|
||||
@@ -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):
|
||||
|
||||
@@ -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):
|
||||
|
||||
|
||||
@@ -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):
|
||||
|
||||
@@ -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):
|
||||
|
||||
|
||||
@@ -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__)
|
||||
|
||||
@@ -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')
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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'
|
||||
@@ -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
|
||||
@@ -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
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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()
|
||||
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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
@@ -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
@@ -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"
|
||||
|
||||
Executable
+209
@@ -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:
|
||||
@@ -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
|
||||
@@ -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
@@ -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
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
Reference in New Issue
Block a user