Compare commits

..
Author SHA1 Message Date
Vid Luther 49a44c6a82 changelog for debian packager. 2014-09-12 23:00:30 -05:00
Vid Luther d14d68d56c gitignore 2014-09-12 22:27:43 -05:00
Vid Luther 6830497241 changed requirements to python3 2014-09-12 22:25:55 -05:00
Vid Luther 5da1104701 custom Vagrantfile and provisioner
This allows me to build in a VM on a Mac.
2014-09-12 22:25:40 -05:00
Vid Luther 38ab997cb3 ran the fail2ban-2to3 script. 2014-09-12 22:24:52 -05:00
Vid Luther 587e626710 Merge branch 'debian-releases/experimental' into pressable/debian 2014-09-12 21:54:01 -05:00
157 changed files with 2818 additions and 3183 deletions
+1 -1
View File
@@ -1,3 +1,4 @@
.pc/*
*~
build
dist
@@ -9,4 +10,3 @@ htmlcov
*.bak
__pycache__
.vagrant/
.idea/
+4 -11
View File
@@ -8,21 +8,14 @@ python:
- "3.3"
- "3.4"
- "pypy"
- "pypy3"
before_install:
- if [[ $TRAVIS_PYTHON_VERSION == 2.7 ]]; then travis_retry sudo apt-get update -qq; fi
- if [[ $TRAVIS_PYTHON_VERSION == 2.7 ]]; then sudo apt-get update -qq; fi
install:
- travis_retry pip install pyinotify
- if [[ $TRAVIS_PYTHON_VERSION == 2* || $TRAVIS_PYTHON_VERSION == 'pypy' ]]; then travis_retry pip install dnspython; fi
- if [[ $TRAVIS_PYTHON_VERSION == 3* || $TRAVIS_PYTHON_VERSION == 'pypy3' ]]; then travis_retry pip install dnspython3; fi
- if [[ $TRAVIS_PYTHON_VERSION == 2.7 ]]; then travis_retry sudo apt-get install -qq python-gamin; cp /usr/share/pyshared/gamin.py /usr/lib/pyshared/python2.7/_gamin.so $VIRTUAL_ENV/lib/python2.7/site-packages/; fi
- if [[ $TRAVIS_PYTHON_VERSION == 2.7 ]]; then cd ..; travis_retry pip install -q coveralls; cd -; fi
# overcome buggy pypy
- if [[ $TRAVIS_PYTHON_VERSION == pypy ]] ; then dpkg --compare-versions $(pypy --version 2>&1 | awk '/PyPy/{print $2;}') ge 2.5.1 || { d=$PWD; cd /tmp; wget http://buildbot.pypy.org/nightly/trunk/pypy-c-jit-latest-linux64.tar.bz2; tar -xjvf pypy*bz2; cd pypy-*/bin/; export PATH=$PWD:$PATH; cd $d; } ; fi
- pip install pyinotify
- if [[ $TRAVIS_PYTHON_VERSION == 2.7 ]]; then sudo apt-get install -qq python-gamin; cp /usr/share/pyshared/gamin.py /usr/lib/pyshared/python2.7/_gamin.so $VIRTUAL_ENV/lib/python2.7/site-packages/; fi
- 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 Executable
+181
View File
@@ -0,0 +1,181 @@
#!/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:
-10
View File
@@ -15,13 +15,3 @@ join the [mailing list](https://lists.sourceforge.net/lists/listinfo/fail2ban-us
### You would like to contribute (new filters/actions/code/documentation)?
send a [pull request](https://github.com/fail2ban/fail2ban/pulls)
Pull requests guidelines
========================
- If there is an issue on github to be closed by the pull request, include
```Closes #ISSUE``` (where ISSUE is issue's number)
- Add a brief summary of the change to the ChangeLog file into a corresponding
section out of Fixes, New Features or Enhancements (improvements to existing
features)
+5 -98
View File
@@ -3,93 +3,11 @@
| _/ _` | | |/ /| '_ \/ _` | ' \
|_| \__,_|_|_/___|_.__/\__,_|_||_|
Fail2Ban: Changelog
===================
================================================================================
Fail2Ban (version 0.9.0.dev) 2014/xx/xx
================================================================================
ver. 0.9.2 (2015/04/29) - better-quick-now-than-later
----------
- Fixes:
* Fix ufw action commands
* infinite busy loop on _escapedTags match in substituteRecursiveTags gh-907.
Thanks TonyThompson
* port[s] typo in jail.conf/nginx-http-auth gh-913. Thanks Frederik Wagner
(fnerdwq)
* $ typo in jail.conf. Thanks Skibbi. Debian bug #767255
* grep'ing for IP in *mail-whois-lines.conf should now match also
at the beginning and EOL. Thanks Dean Lee
* jail.conf
- php-url-fopen: separate logpath entries by newline
* failregex declared direct in jail was joined to single line (specifying of
multiple expressions was not possible).
* filters.d/exim.conf - cover different settings of exim logs
details. Thanks bes.internal
* filter.d/postfix-sasl.conf - failregex is now case insensitive
* filters.d/postfix.conf - add 'Client host rejected error message' failregex
* fail2ban/__init__.py - add strptime thread safety hack-around
* recidive uses iptables-allports banaction by default now.
Avoids problems with iptables versions not understanding 'all' for
protocols and ports
* filter.d/dovecot.conf
- match pam_authenticate line from EL7
- match unknown user line from EL7
* Use use_poll=True for Python 2.7 and >=3.4 to overcome "Bad file
descriptor" msgs issue (gh-161)
* filter.d/postfix-sasl.conf - tweak failregex and add ignoreregex to ignore
system authentication issues
* fail2ban-regex reads filter file(s) completely, incl. '.local' file etc.
(gh-954)
* firewallcmd-* actions: split output into separate lines for grepping (gh-908)
* Guard unicode encode/decode issues while storing records in the database.
Fixes "binding parameter error (unsupported type)" (gh-973), thanks to kot
for reporting
* filter.d/sshd added regex for matching openSUSE ssh authentication failure
* filter.d/asterisk.conf:
- Dropped "Sending fake auth rejection" failregex since it incorrectly
targets the asterisk server itself
- match "hacking attempt detected" logs
- New Features:
- New filters:
- postfix-rbl Thanks Lee Clemens
- apache-fakegooglebot.conf Thanks Lee Clemens
- nginx-botsearch Thanks Frantisek Sumsal
- drupal-auth Thanks Lee Clemens
- New recursive embedded substitution feature added:
- `<<PREF>HOST>` becomes `<IPV4HOST>` for PREF=`IPV4`;
- `<<PREF>HOST>` becomes `1.2.3.4` for PREF=`IPV4` and IPV4HOST=`1.2.3.4`;
- New interpolation feature for config readers - `%(known/parameter)s`.
(means last known option with name `parameter`). This interpolation makes
possible to extend a stock filter or jail regexp in .local file
(opposite to simply set failregex/ignoreregex that overwrites it),
see gh-867.
- Monit config for fail2ban in files/monit/
- New actions:
- action.d/firewallcmd-multiport and action.d/firewallcmd-allports Thanks Donald Yandt
- action.d/sendmail-geoip-lines.conf
- action.d/nsupdate to update DNSBL. Thanks Andrew St. Jean
- New status argument for fail2ban-client -- flavor:
fail2ban-client status <jail> [flavor]
- empty or "basic" works as-is
- "cymru" additionally prints (ASN, Country RIR) per banned IP
(requires dnspython or dnspython3)
- Flush log at USR1 signal
- Enhancements:
* Enable multiport for firewallcmd-new action. Closes gh-834
* files/debian-initd migrated from the debian branch and should be
suitable for manual installations now (thanks Juan Karlo de Guzman)
* Define empty ignoreregex in filters which didn't have it to avoid
warnings (gh-934)
* action.d/{sendmail-*,xarf-login-attack}.conf - report local
timezone not UTC time/zone. Closes gh-911
* Conditionally log Ignore IP with reason (dns, ip, command). Closes gh-916
* Absorbed DNSUtils.cidr into addr2bin in filter.py, added unittests
* Added syslogsocket configuration to fail2ban.conf
* Note in the jail.conf for the recidive jail to increase dbpurgeage (gh-964)
ver. 0.9.1 (2014/10/29) - better, faster, stronger
ver. 0.9.1 (2014/xx/xx) - better, faster, stronger
----------
- Refactoring (IMPORTANT -- Please review your setup and configuration):
@@ -98,8 +16,6 @@ ver. 0.9.1 (2014/10/29) - 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
@@ -132,26 +48,18 @@ ver. 0.9.1 (2014/10/29) - 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* - 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.
* postfix-sasl -- added journalmatch. Thanks Luc Maisonobe
- 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
@@ -163,7 +71,6 @@ ver. 0.9.1 (2014/10/29) - better, faster, stronger
not affect SYSLOG output
* Log unhandled exceptions
* cyrus-imap: catch "user not found" attempts
* Add support for Portsentry
ver. 0.9.0 (2014/03/14) - beta
----------
-12
View File
@@ -81,18 +81,6 @@ 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
================
+229 -280
View File
@@ -1,272 +1,122 @@
CONTRIBUTING.md
COPYING
README.md
README.Solaris
ChangeLog
TODO
THANKS
COPYING
DEVELOP
FILTERS
README.Solaris
README.md
RELEASE
THANKS
TODO
Vagrantfile
bin/fail2ban-client
bin/fail2ban-regex
bin/fail2ban-server
bin/fail2ban-testcases
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-allports.conf
config/action.d/firewallcmd-ipset.conf
config/action.d/firewallcmd-multiport.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/nsupdate.conf
config/action.d/nsupdate.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-geoip-lines.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/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-fakegooglebot.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/apache-shellshock.conf
config/filter.d/assp.conf
config/filter.d/asterisk.conf
config/filter.d/botsearch-common.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/guacamole.conf
config/filter.d/horde.conf
config/filter.d/ignorecommands
config/filter.d/ignorecommands/apache-fakegooglebot
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-botsearch.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-rbl.conf
config/filter.d/postfix-sasl.conf
config/filter.d/postfix-sasl.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/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/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/jail.conf
config/paths-common.conf
config/paths-debian.conf
config/paths-fedora.conf
config/paths-freebsd.conf
config/paths-osx.conf
doc/run-rootless.txt
fail2ban-2to3
fail2ban-testcases-all
fail2ban-testcases-all-python3
fail2ban/__init__.py
fail2ban/client/__init__.py
fail2ban/client/actionreader.py
fail2ban/client/beautifier.py
fail2ban/client/configparserinc.py
bin/fail2ban-client
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/configurator.py
fail2ban/client/csocket.py
fail2ban/client/fail2banreader.py
fail2ban/client/filterreader.py
fail2ban/client/jailreader.py
fail2ban/client/jailsreader.py
fail2ban/exceptions.py
fail2ban/helpers.py
fail2ban/protocol.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/failregex.py
fail2ban/server/filter.py
fail2ban/server/filterpyinotify.py
fail2ban/server/filtergamin.py
fail2ban/server/filterpoll.py
fail2ban/server/filterpyinotify.py
fail2ban/server/filtersystemd.py
fail2ban/server/iso8601.py
fail2ban/server/server.py
fail2ban/server/actions.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/jail.py
fail2ban/server/jails.py
fail2ban/server/jailthread.py
fail2ban/server/__init__.py
fail2ban/server/banmanager.py
fail2ban/server/datetemplate.py
fail2ban/server/mytime.py
fail2ban/server/server.py
fail2ban/server/strptime.py
fail2ban/server/ticket.py
fail2ban/server/transmitter.py
fail2ban/tests/__init__.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/server/failregex.py
fail2ban/server/database.py
fail2ban/tests/banmanagertestcase.py
fail2ban/tests/failmanagertestcase.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/filter.d/test.conf
fail2ban/tests/config/filter.d/test.local
fail2ban/tests/filtertestcase.py
fail2ban/tests/__init__.py
fail2ban/tests/dummyjail.py
fail2ban/tests/samplestestcase.py
fail2ban/tests/datedetectortestcase.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/config/fail2ban.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/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_checkainfo.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/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/files/config/apache-auth/basic/authz_owner/.htaccess
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/authz_owner/.htpasswd
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/.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/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/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/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/ignorecommand.py
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/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-fakegooglebot
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
@@ -276,94 +126,193 @@ 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/named-refused
fail2ban/tests/files/logs/nginx-botsearch
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-rbl
fail2ban/tests/files/logs/postfix-sasl
fail2ban/tests/files/logs/named-refused
fail2ban/tests/files/logs/nginx-http-auth
fail2ban/tests/files/logs/pam-generic
fail2ban/tests/files/logs/postfix
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/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/sogo-auth
fail2ban/tests/files/logs/solid-pop3d
fail2ban/tests/files/logs/sshd
fail2ban/tests/files/logs/sshd-ddos
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/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
fail2ban/tests/config/jail.conf
fail2ban/tests/config/fail2ban.conf
fail2ban/tests/config/filter.d/simple.conf
fail2ban/tests/config/action.d/brokenaction.conf
setup.py
setup.cfg
fail2ban/__init__.py
fail2ban/exceptions.py
fail2ban/helpers.py
fail2ban/version.py
files/bash-completion
files/cacti/README
files/cacti/cacti_host_template_fail2ban.xml
files/cacti/fail2ban_stats.sh
files/debian-initd
files/fail2ban-logrotate
files/fail2ban-tmpfiles.conf
files/fail2ban.service
files/fail2ban.upstart
files/gen_badbots
files/gentoo-confd
fail2ban/protocol.py
setup.py
setup.cfg
kill-server
config/jail.conf
config/fail2ban.conf
config/filter.d/common.conf
config/filter.d/apache-auth.conf
config/filter.d/apache-badbots.conf
config/filter.d/apache-botsearch.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/counter-strike.conf
config/filter.d/courier-auth.conf
config/filter.d/courier-smtp.conf
config/filter.d/cyrus-imap.conf
config/filter.d/ejabberd-auth.conf
config/filter.d/exim.conf
config/filter.d/freeswitch.conf
config/filter.d/gssftpd.conf
config/filter.d/kerio.conf
config/filter.d/horde.conf
config/filter.d/suhosin.conf
config/filter.d/nagios.conf
config/filter.d/named-refused.conf
config/filter.d/nsd.conf
config/filter.d/openwebmail.conf
config/filter.d/pam-generic.conf
config/filter.d/php-url-fopen.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/sendmail-auth.conf
config/filter.d/sendmail-reject.conf
config/filter.d/sieve.conf
config/filter.d/solid-pop3d.conf
config/filter.d/squid.conf
config/filter.d/sshd.conf
config/filter.d/sshd-ddos.conf
config/filter.d/stunnel.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
man/fail2ban-client.1
man/fail2ban.1
man/jail.conf.5
man/fail2ban-client.h2m
man/fail2ban-server.1
man/fail2ban-server.h2m
man/fail2ban-regex.1
man/fail2ban-regex.h2m
man/generate-man
files/gentoo-initd
files/ipmasq-ZZZzzz_fail2ban.rul
files/logwatch/fail2ban
files/macosx-initd
files/monit/fail2ban
files/nagios/README
files/nagios/check_fail2ban
files/gentoo-confd
files/redhat-initd
files/macosx-initd
files/solaris-fail2ban.xml
files/solaris-svc-fail2ban
files/suse-initd
kill-server
man/fail2ban-client.1
man/fail2ban-client.h2m
man/fail2ban-regex.1
man/fail2ban-regex.h2m
man/fail2ban-server.1
man/fail2ban-server.h2m
man/fail2ban.1
man/generate-man
man/jail.conf.5
setup.cfg
setup.py
files/fail2ban-logrotate
files/cacti/fail2ban_stats.sh
files/cacti/cacti_host_template_fail2ban.xml
files/cacti/README
files/nagios/check_fail2ban
files/nagios/README
files/bash-completion
files/fail2ban-tmpfiles.conf
files/fail2ban.service
files/ipmasq-ZZZzzz_fail2ban.rul
files/gen_badbots
+1 -2
View File
@@ -1,5 +1,4 @@
include ChangeLog COPYING DEVELOP FILTERS README.* THANKS TODO CONTRIBUTING* Vagrantfile
include ChangeLog COPYING DEVELOP FILTERS README.* THANKS TODO
graft doc
graft files
recursive-include config *.conf *.py
recursive-include config/filter.d/ignorecommands *
+3 -4
View File
@@ -2,7 +2,7 @@
/ _|__ _(_) |_ ) |__ __ _ _ _
| _/ _` | | |/ /| '_ \/ _` | ' \
|_| \__,_|_|_/___|_.__/\__,_|_||_|
v0.9.2 2015/04/29
v0.9.0 2014/03/14
## Fail2Ban: ban hosts that cause multiple authentication errors
@@ -33,12 +33,11 @@ Optional:
- Linux >= 2.6.13
- [gamin >= 0.0.21](http://www.gnome.org/~veillard/gamin)
- [systemd >= 204](http://www.freedesktop.org/wiki/Software/systemd)
- [dnspython](http://www.dnspython.org/)
To install, just do:
tar xvfj fail2ban-0.9.2.tar.bz2
cd fail2ban-0.9.2
tar xvfj fail2ban-0.9.0.tar.bz2
cd fail2ban-0.9.0
python setup.py install
This will install Fail2Ban into the python library directory. The executable
+7 -11
View File
@@ -47,10 +47,6 @@ 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
@@ -61,24 +57,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.2.tar.bz2
tar -C /tmp -jxf dist/fail2ban-0.9.0.tar.bz2
* clean up current direcory::
diff -rul --exclude \*.pyc . /tmp/fail2ban-0.9.2/
diff -rul --exclude \*.pyc . /tmp/fail2ban-0.9.0/
* Only differences should be files that you don't want distributed.
* Ensure the tests work from the tarball::
cd /tmp/fail2ban-0.9.2/ && bin/fail2ban-testcases
cd /tmp/fail2ban-0.9.0/ && 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.9.2.. | sed -e 's,^[ 0-9\t]*,,g' | tr '\n' '\|' | sed -e 's:|:, :g'
git shortlog -sn 0.8.12.. | 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.
@@ -101,7 +97,7 @@ Preparation
* Tag the release by using a signed (and annotated) tag. Cut/paste
release ChangeLog entry as tag annotation::
git tag -s 0.9.2
git tag -s 0.9.1
Pre Release
===========
@@ -144,7 +140,7 @@ Pre Release
* https://bugs.mageia.org/buglist.cgi?quicksearch=fail2ban
* And potentially to the fail2ban-users email list.
* An potentially to the fail2ban-users email list.
* Wait for feedback from distributors
@@ -185,7 +181,7 @@ Post Release
Add the following to the top of the ChangeLog::
ver. 0.9.3 (2014/XX/XXX) - wanna-be-released
ver. 0.9.1 (2014/XX/XXX) - wanna-be-released
-----------
- Fixes:
-8
View File
@@ -6,7 +6,6 @@ the project. If you have been left off, please let us know
(preferably send a pull request on github with the "fix") and you will
be added
Aaron Brice
Adam Tkac
Adrien Clerc
ache
@@ -14,7 +13,6 @@ ag4ve (Shawn)
Alasdair D. Campbell
Amir Caspi
Amy
Andrew St. Jean
Andrey G. Grozin
Andy Fragen
Arturo 'Buanzo' Busleiman
@@ -28,20 +26,16 @@ Christian Rauch
Christophe Carles
Christoph Haas
Christos Psonis
craneworks
Cyril Jaquier
Daniel B. Cid
Daniel B.
Daniel Black
David Nutter
Derek Atkins
Donald Yandt
Eric Gerbier
Enrico Labedzki
Eugene Hopkinson (SlowRiot)
ftoppi
François Boulogne
Frantisek Sumsal
Frédéric
Georgiy Mernov
Guilhem Lettron
@@ -86,9 +80,7 @@ Michael Hanselmann
Mika (mkl)
Nick Munger
onorua
Orion Poplawski
Paul Marrapese
Paul Traina
Noel Butler
Patrick Börjesson
Pressy
Vendored
+5
View File
@@ -1,5 +1,10 @@
Vagrant.configure("2") do |config|
config.vm.define "builder" do |builder|
builder.vm.box = "vm144"
builder.vm.provision "shell", path: "provision.sh"
end
config.vm.define "secure" do |secure|
secure.vm.box = "ubuntu/trusty64"
secure.vm.hostname = "secure.dev.fail2ban.org"
+46 -46
View File
@@ -59,53 +59,53 @@ class Fail2banClient:
self.__conf["pidfile"] = None
def dispVersion(self):
print "Fail2Ban v" + version
print
print "Copyright (c) 2004-2008 Cyril Jaquier, 2008- Fail2Ban Contributors"
print "Copyright of modifications held by their respective authors."
print "Licensed under the GNU General Public License v2 (GPL)."
print
print "Written by Cyril Jaquier <cyril.jaquier@fail2ban.org>."
print "Many contributions by Yaroslav O. Halchenko <debian@onerussian.com>."
print("Fail2Ban v" + version)
print()
print("Copyright (c) 2004-2008 Cyril Jaquier, 2008- Fail2Ban Contributors")
print("Copyright of modifications held by their respective authors.")
print("Licensed under the GNU General Public License v2 (GPL).")
print()
print("Written by Cyril Jaquier <cyril.jaquier@fail2ban.org>.")
print("Many contributions by Yaroslav O. Halchenko <debian@onerussian.com>.")
def dispUsage(self):
""" Prints Fail2Ban command line options and exits
"""
print "Usage: "+self.__argv[0]+" [OPTIONS] <COMMAND>"
print
print "Fail2Ban v" + version + " reads log file that contains password failure report"
print "and bans the corresponding IP addresses using firewall rules."
print
print "Options:"
print " -c <DIR> configuration directory"
print " -s <FILE> socket path"
print " -p <FILE> pidfile path"
print " -d dump configuration. For debugging"
print " -i interactive mode"
print " -v increase verbosity"
print " -q decrease verbosity"
print " -x force execution of the server (remove socket file)"
print " -b start server in background (default)"
print " -f start server in foreground (note that the client forks once itself)"
print " -h, --help display this help message"
print " -V, --version print the version"
print
print "Command:"
print("Usage: "+self.__argv[0]+" [OPTIONS] <COMMAND>")
print()
print("Fail2Ban v" + version + " reads log file that contains password failure report")
print("and bans the corresponding IP addresses using firewall rules.")
print()
print("Options:")
print(" -c <DIR> configuration directory")
print(" -s <FILE> socket path")
print(" -p <FILE> pidfile path")
print(" -d dump configuration. For debugging")
print(" -i interactive mode")
print(" -v increase verbosity")
print(" -q decrease verbosity")
print(" -x force execution of the server (remove socket file)")
print(" -b start server in background (default)")
print(" -f start server in foreground (note that the client forks once itself)")
print(" -h, --help display this help message")
print(" -V, --version print the version")
print()
print("Command:")
# Prints the protocol
printFormatted()
print
print "Report bugs to https://github.com/fail2ban/fail2ban/issues"
print()
print("Report bugs to https://github.com/fail2ban/fail2ban/issues")
def dispInteractive(self):
print "Fail2Ban v" + version + " reads log file that contains password failure report"
print "and bans the corresponding IP addresses using firewall rules."
print
print("Fail2Ban v" + version + " reads log file that contains password failure report")
print("and bans the corresponding IP addresses using firewall rules.")
print()
def __sigTERMhandler(self, signum, frame):
# Print a new line because we probably come from wait
print
print()
logSys.warning("Caught signal %d. Exiting" % signum)
sys.exit(-1)
@@ -152,19 +152,19 @@ class Fail2banClient:
client = CSocket(self.__conf["socket"])
ret = client.send(c)
if ret[0] == 0:
logSys.debug("OK : " + `ret[1]`)
logSys.debug("OK : " + repr(ret[1]))
if showRet:
print beautifier.beautify(ret[1])
print(beautifier.beautify(ret[1]))
else:
logSys.error("NOK: " + `ret[1].args`)
logSys.error("NOK: " + repr(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, e:
except Exception as 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 = raw_input(self.PROMPT)
cmd = 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, e:
except Exception as 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, e:
except Exception as 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):
+68 -80
View File
@@ -29,10 +29,10 @@ __author__ = "Fail2Ban Developers"
__copyright__ = "Copyright (c) 2004-2008 Cyril Jaquier, 2012-2014 Yaroslav Halchenko"
__license__ = "GPL"
import getopt, sys, time, logging, os, locale, shlex, time, urllib
import getopt, sys, time, logging, os, locale, shlex, time, urllib.request, urllib.parse, urllib.error
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.urlencode({ 're': regex.replace('<HOST>', '(?&.ipv4)'),
q = urllib.parse.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:
@@ -220,7 +220,6 @@ class Fail2banRegex(object):
self._datepattern_set = False
self._journalmatch = None
self.share_config=dict()
self._filter = Filter(None)
self._ignoreregex = list()
self._failregex = list()
@@ -245,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,49 +260,38 @@ class Fail2banRegex(object):
def readRegex(self, value, regextype):
assert(regextype in ('fail', 'ignore'))
regex = regextype + 'regex'
if os.path.isfile(value) or os.path.isfile(value + '.conf'):
if os.path.basename(os.path.dirname(value)) == 'filter.d':
## within filter.d folder - use standard loading algorithm to load filter completely (with .local etc.):
basedir = os.path.dirname(os.path.dirname(value))
value = os.path.splitext(os.path.basename(value))[0]
print "Use %11s filter file : %s, basedir: %s" % (regex, value, basedir)
reader = FilterReader(value, 'fail2ban-regex-jail', {}, share_config=self.share_config, basedir=basedir)
if not reader.read():
print "ERROR: failed to load filter %s" % value
return False
if os.path.isfile(value):
print("Use %11s file : %s" % (regex, value))
reader = FilterReader(value, 'fail2ban-regex-jail', {})
reader.setBaseDir(None)
if reader.readexplicit():
reader.getOptions(None)
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]]
# Read out and set possible value of maxlines
for command in readercommands:
if command[2] == "maxlines":
maxlines = int(command[3])
try:
self.setMaxLines(maxlines)
except ValueError:
print("ERROR: Invalid value for maxlines (%(maxlines)r) " \
"read from %(value)s" % locals())
return False
elif command[2] == 'addjournalmatch':
journalmatch = command[3]
self.setJournalMatch(shlex.split(journalmatch))
elif command[2] == 'datepattern':
datepattern = command[3]
self.setDatePattern(datepattern)
else:
## foreign file - readexplicit this file and includes if possible:
print "Use %11s file : %s" % (regex, value)
reader = FilterReader(value, 'fail2ban-regex-jail', {}, share_config=self.share_config)
reader.setBaseDir(None)
if not reader.readexplicit():
print "ERROR: failed to read %s" % value
return False
reader.getOptions(None)
readercommands = reader.convert()
regex_values = [
RegexStat(m[3])
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":
maxlines = int(command[3])
try:
self.setMaxLines(maxlines)
except ValueError:
print "ERROR: Invalid value for maxlines (%(maxlines)r) " \
"read from %(value)s" % locals()
return False
elif command[2] == 'addjournalmatch':
journalmatch = command[3]
self.setJournalMatch(shlex.split(journalmatch))
elif command[2] == 'datepattern':
datepattern = command[3]
self.setDatePattern(datepattern)
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)
@@ -320,8 +308,8 @@ class Fail2banRegex(object):
if ret is not None:
found = True
regex = self._ignoreregex[ret].inc()
except RegexException, e:
print e
except RegexException as e:
print(e)
return False
return found
@@ -337,11 +325,11 @@ class Fail2banRegex(object):
regex = self._failregex[match[0]]
regex.inc()
regex.appendIP(match)
except RegexException, e:
print e
except RegexException as 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:
@@ -415,21 +403,21 @@ class Fail2banRegex(object):
ans = [[]]
for arg in [l, regexlist]:
ans = [ x + [y] for x in ans for y in arg ]
b = map(lambda a: a[0] + ' | ' + a[1].getFailRegex() + ' | ' + debuggexURL(a[0], a[1].getFailRegex()), ans)
b = [a[0] + ' | ' + a[1].getFailRegex() + ' | ' + debuggexURL(a[0], a[1].getFailRegex()) for a in 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
@@ -450,7 +438,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
@@ -460,7 +448,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:
@@ -468,10 +456,10 @@ class Fail2banRegex(object):
template.hits, template.name))
pprint_list(out, "[# of hits] date format")
print "\nLines: %s" % self._line_stats,
print("\nLines: %s" % self._line_stats, end=' ')
if self._time_elapsed is not None:
print "[processed in %.2f sec]" % self._time_elapsed,
print
print("[processed in %.2f sec]" % self._time_elapsed, end=' ')
print()
if self._print_all_matched:
self.printLines('matched')
@@ -496,10 +484,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)
@@ -548,15 +536,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, e:
print e
except IOError as 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
@@ -569,14 +557,14 @@ if __name__ == "__main__":
else:
myjournal.add_match(element)
except ValueError:
print "Error: Invalid journalmatch: %s" % shortstr(" ".join(journalmatch))
print("Error: Invalid journalmatch: %s" % shortstr(" ".join(journalmatch)))
sys.exit(-1)
print "Use journal match : %s" % " ".join(journalmatch)
print("Use journal match : %s" % " ".join(journalmatch))
test_lines = journal_lines_gen(myjournal)
else:
print "Use single line : %s" % shortstr(cmd_log)
print("Use single line : %s" % shortstr(cmd_log))
test_lines = [ cmd_log ]
print
print()
fail2banRegex.process(test_lines)
+28 -28
View File
@@ -51,37 +51,37 @@ class Fail2banServer:
self.__conf["pidfile"] = "/var/run/fail2ban/fail2ban.pid"
def dispVersion(self):
print "Fail2Ban v" + version
print
print "Copyright (c) 2004-2008 Cyril Jaquier, 2008- Fail2Ban Contributors"
print "Copyright of modifications held by their respective authors."
print "Licensed under the GNU General Public License v2 (GPL)."
print
print "Written by Cyril Jaquier <cyril.jaquier@fail2ban.org>."
print "Many contributions by Yaroslav O. Halchenko <debian@onerussian.com>."
print("Fail2Ban v" + version)
print()
print("Copyright (c) 2004-2008 Cyril Jaquier, 2008- Fail2Ban Contributors")
print("Copyright of modifications held by their respective authors.")
print("Licensed under the GNU General Public License v2 (GPL).")
print()
print("Written by Cyril Jaquier <cyril.jaquier@fail2ban.org>.")
print("Many contributions by Yaroslav O. Halchenko <debian@onerussian.com>.")
def dispUsage(self):
""" Prints Fail2Ban command line options and exits
"""
print "Usage: "+self.__argv[0]+" [OPTIONS]"
print
print "Fail2Ban v" + version + " reads log file that contains password failure report"
print "and bans the corresponding IP addresses using firewall rules."
print
print "Only use this command for debugging purpose. Start the server with"
print "fail2ban-client instead. The default behaviour is to start the server"
print "in background."
print
print "Options:"
print " -b start in background"
print " -f start in foreground"
print " -s <FILE> socket path"
print " -p <FILE> pidfile path"
print " -x force execution of the server (remove socket file)"
print " -h, --help display this help message"
print " -V, --version print the version"
print
print "Report bugs to https://github.com/fail2ban/fail2ban/issues"
print("Usage: "+self.__argv[0]+" [OPTIONS]")
print()
print("Fail2Ban v" + version + " reads log file that contains password failure report")
print("and bans the corresponding IP addresses using firewall rules.")
print()
print("Only use this command for debugging purpose. Start the server with")
print("fail2ban-client instead. The default behaviour is to start the server")
print("in background.")
print()
print("Options:")
print(" -b start in background")
print(" -f start in foreground")
print(" -s <FILE> socket path")
print(" -p <FILE> pidfile path")
print(" -x force execution of the server (remove socket file)")
print(" -h, --help display this help message")
print(" -V, --version print the version")
print()
print("Report bugs to https://github.com/fail2ban/fail2ban/issues")
def __getCmdLineOptions(self, optList):
""" Gets the command line options
@@ -125,7 +125,7 @@ class Fail2banServer:
self.__conf["pidfile"],
self.__conf["force"])
return True
except Exception, e:
except Exception as e:
logSys.exception(e)
self.__server.quit()
return False
+2 -2
View File
@@ -114,8 +114,8 @@ logSys.addHandler(stdout)
# Let know the version
#
if not opts.log_level or opts.log_level != 'critical': # pragma: no cover
print("Fail2ban %s test suite. Python %s. Please wait..." \
% (version, str(sys.version).replace('\n', '')))
print(("Fail2ban %s test suite. Python %s. Please wait..." \
% (version, str(sys.version).replace('\n', ''))))
tests = gatherTests(regexps, opts.no_network)
#
+1 -9
View File
@@ -111,8 +111,6 @@ class BadIPsAction(ActionBase):
------
HTTPError
Any issues with badips.com request.
ValueError
If badips.com response didn't contain necessary information
"""
try:
response = urlopen(
@@ -124,13 +122,7 @@ class BadIPsAction(ActionBase):
messages['err'])
raise
else:
response_json = json.loads(response.read().decode('utf-8'))
if not 'categories' in response_json:
err = "badips.com response lacked categories specification. Response was: %s" \
% (response_json,)
self._logSys.error(err)
raise ValueError(err)
categories = response_json['categories']
categories = json.loads(response.read().decode('utf-8'))['categories']
categories_names = set(
value['Name'] for value in categories)
if incParents:
+2 -2
View File
@@ -38,7 +38,7 @@ actioncheck =
# Values: CMD
#
# requires an ipfw rule like "deny ip from table(1) to me"
actionban = e=`ipfw table <table> add <ip> 2>&1`; x=$?; [ $x -eq 0 -o "$e" = 'ipfw: setsockopt(IP_FW_TABLE_XADD): File exists' ] || { echo "$e" 1>&2; exit $x; }
actionban = ipfw table <table> add <ip>
# Option: actionunban
@@ -47,7 +47,7 @@ actionban = e=`ipfw table <table> add <ip> 2>&1`; x=$?; [ $x -eq 0 -o "$e" = 'ip
# Tags: See jail.conf(5) man page
# Values: CMD
#
actionunban = e=`ipfw table <table> delete <ip> 2>&1`; x=$?; [ $x -eq 0 -o "$e" = 'ipfw: setsockopt(IP_FW_TABLE_XDEL): No such process' ] || { echo "$e" 1>&2; exit $x; }
actionunban = ipfw table <table> delete <ip>
[Init]
# Option: table
-53
View File
@@ -1,53 +0,0 @@
# Fail2Ban configuration file
#
# Author: Donald Yandt
# Because of the --remove-rules in stop this action requires firewalld-0.3.8+
[INCLUDES]
before = iptables-blocktype.conf
[Definition]
actionstart = firewall-cmd --direct --add-chain ipv4 filter f2b-<name>
firewall-cmd --direct --add-rule ipv4 filter f2b-<name> 1000 -j RETURN
firewall-cmd --direct --add-rule ipv4 filter <chain> 0 -j f2b-<name>
actionstop = firewall-cmd --direct --remove-rule ipv4 filter <chain> 0 -j f2b-<name>
firewall-cmd --direct --remove-rules ipv4 filter f2b-<name>
firewall-cmd --direct --remove-chain ipv4 filter f2b-<name>
# Example actioncheck: firewall-cmd --direct --get-chains ipv4 filter | sed -e 's, ,\n,g' | grep -q '^f2b-recidive$'
actioncheck = firewall-cmd --direct --get-chains ipv4 filter | sed -e 's, ,\n,g' | grep -q '^f2b-<name>$'
actionban = firewall-cmd --direct --add-rule ipv4 filter f2b-<name> 0 -s <ip> -j <blocktype>
actionunban = firewall-cmd --direct --remove-rule ipv4 filter f2b-<name> 0 -s <ip> -j <blocktype>
[Init]
# Default name of the chain
#
name = default
chain = INPUT_direct
# DEV NOTES:
#
# Author: Donald Yandt
# Uses "FirewallD" instead of the "iptables daemon".
#
#
# Output:
# actionstart:
# $ firewall-cmd --direct --add-chain ipv4 filter f2b-recidive
# success
# $ firewall-cmd --direct --add-rule ipv4 filter f2b-recidive 1000 -j RETURN
# success
# $ sudo firewall-cmd --direct --add-rule ipv4 filter INPUT_direct 0 -j f2b-recidive
# success
@@ -1,63 +0,0 @@
# Fail2Ban configuration file
#
# Author: Donald Yandt
# Because of the --remove-rules in stop this action requires firewalld-0.3.8+
[INCLUDES]
before = iptables-blocktype.conf
[Definition]
actionstart = firewall-cmd --direct --add-chain ipv4 filter f2b-<name>
firewall-cmd --direct --add-rule ipv4 filter f2b-<name> 1000 -j RETURN
firewall-cmd --direct --add-rule ipv4 filter <chain> 0 -m state --state NEW -p <protocol> -m multiport --dports <port> -j f2b-<name>
actionstop = firewall-cmd --direct --remove-rule ipv4 filter <chain> 0 -m state --state NEW -p <protocol> -m multiport --dports <port> -j f2b-<name>
firewall-cmd --direct --remove-rules ipv4 filter f2b-<name>
firewall-cmd --direct --remove-chain ipv4 filter f2b-<name>
# Example actioncheck: firewall-cmd --direct --get-chains ipv4 filter | sed -e 's, ,\n,g' | grep -q '^f2b-apache-modsecurity$'
actioncheck = firewall-cmd --direct --get-chains ipv4 filter | sed -e 's, ,\n,g' | grep -q '^f2b-<name>$'
actionban = firewall-cmd --direct --add-rule ipv4 filter f2b-<name> 0 -s <ip> -j <blocktype>
actionunban = firewall-cmd --direct --remove-rule ipv4 filter f2b-<name> 0 -s <ip> -j <blocktype>
[Init]
# Default name of the chain
name = default
chain = INPUT_direct
# Could also use port numbers separated by a comma.
port = 1:65535
# Option: protocol
# Values: [ tcp | udp | icmp | all ]
protocol = tcp
# DEV NOTES:
#
# Author: Donald Yandt
# Uses "FirewallD" instead of the "iptables daemon".
#
#
# Output:
# actionstart:
# $ firewall-cmd --direct --add-chain ipv4 filter f2b-apache-modsecurity
# success
# $ firewall-cmd --direct --add-rule ipv4 filter f2b-apache-modsecurity 1000 -j RETURN
# success
# $ sudo firewall-cmd --direct --add-rule ipv4 filter INPUT_direct 0 -m state --state NEW -p tcp -m multiport --dports 80,443 -j f2b-apache-modsecurity
# success
# actioncheck:
# $ firewall-cmd --direct --get-chains ipv4 filter f2b-apache-modsecurity | sed -e 's, ,\n,g' | grep -q '^f2b-apache-modsecurity$'
# f2b-apache-modsecurity
+3 -3
View File
@@ -10,9 +10,9 @@ before = iptables-common.conf
actionstart = firewall-cmd --direct --add-chain ipv4 filter f2b-<name>
firewall-cmd --direct --add-rule ipv4 filter f2b-<name> 1000 -j RETURN
firewall-cmd --direct --add-rule ipv4 filter <chain> 0 -m state --state NEW -p <protocol> -m multiport --dports <port> -j f2b-<name>
firewall-cmd --direct --add-rule ipv4 filter <chain> 0 -m state --state NEW -p <protocol> --dport <port> -j f2b-<name>
actionstop = firewall-cmd --direct --remove-rule ipv4 filter <chain> 0 -m state --state NEW -p <protocol> -m multiport --dports <port> -j f2b-<name>
actionstop = firewall-cmd --direct --remove-rule ipv4 filter <chain> 0 -m state --state NEW -p <protocol> --dport <port> -j f2b-<name>
firewall-cmd --direct --remove-rules ipv4 filter f2b-<name>
firewall-cmd --direct --remove-chain ipv4 filter f2b-<name>
@@ -43,7 +43,7 @@ chain = INPUT_direct
# success
# $ firewall-cmd --direct --add-rule ipv4 filter fail2ban-name 1000 -j RETURN
# success
# $ sudo firewall-cmd --direct --add-rule ipv4 filter INPUT_direct 0 -m state --state NEW -p tcp -m multiport --dports 22 -j fail2ban-name
# $ sudo firewall-cmd --direct --add-rule ipv4 filter INPUT_direct 0 -m state --state NEW -p tcp --dport 22 -j fail2ban-name
# success
# $ firewall-cmd --direct --get-chains ipv4 filter
# fail2ban-name
+1 -1
View File
@@ -42,7 +42,7 @@ actionban = printf %%b "Hi,\n
Here is more information about <ip>:\n
`whois <ip> || echo missing whois program`\n\n
Lines containing IP:<ip> in <logpath>\n
`grep -E '(^|[^0-9])<ip>([^0-9]|$)' <logpath>`\n\n
`grep '[^0-9]<ip>[^0-9]' <logpath>`\n\n
Regards,\n
Fail2Ban"|mail -s "[Fail2Ban] <name>: banned <ip> from `uname -n`" <dest>
-114
View File
@@ -1,114 +0,0 @@
# Fail2Ban configuration file
#
# Author: Andrew St. Jean
#
# Use nsupdate to perform dynamic DNS updates on a BIND zone file.
# One may want to do this to update a local RBL with banned IP addresses.
#
# Options
#
# domain DNS domain that will appear in nsupdate add and delete
# commands.
#
# ttl The time to live (TTL) in seconds of the TXT resource
# record.
#
# rdata Data portion of the TXT resource record.
#
# nsupdatecmd Full path to the nsupdate command.
#
# keyfile Full path to TSIG key file used for authentication between
# nsupdate and BIND.
#
# Create an nsupdate.local to set at least the <domain> and <keyfile>
# options as they don't have default values.
#
# The ban and unban commands assume nsupdate will authenticate to the BIND
# server using a TSIG key. The full path to the key file must be specified
# in the <keyfile> parameter. Use this command to generate your TSIG key.
#
# dnssec-keygen -a HMAC-MD5 -b 256 -n HOST <key_name>
#
# Replace <key_name> with some meaningful name.
#
# This command will generate two files. Specify the .private file in the
# <keyfile> option. Note that the .key file must also be present in the same
# directory for nsupdate to use the key.
#
# Don't forget to add the key and appropriate allow-update or update-policy
# option to your named.conf file.
#
[Definition]
# Option: actionstart
# Notes.: command executed once at the start of Fail2Ban.
# Values: CMD
#
actionstart =
# Option: actionstop
# Notes.: command executed once at the end of Fail2Ban
# Values: CMD
#
actionstop =
# Option: actioncheck
# Notes.: command executed once before each actionban command
# Values: CMD
#
actioncheck =
# Option: actionban
# Notes.: command executed when banning an IP. Take care that the
# command is executed with Fail2Ban user rights.
# Tags: See jail.conf(5) man page
# Values: CMD
#
actionban = echo <ip> | awk -F. '{print "prereq nxrrset "$4"."$3"."$2"."$1".<domain> TXT"; print "update add "$4"."$3"."$2"."$1".<domain> <ttl> IN TXT \"<rdata>\""; print "send"}' | <nsupdatecmd> -k <keyfile>
# Option: actionunban
# Notes.: command executed when unbanning an IP. Take care that the
# command is executed with Fail2Ban user rights.
# Tags: See jail.conf(5) man page
# Values: CMD
#
actionunban = echo <ip> | awk -F. '{print "update delete "$4"."$3"."$2"."$1".<domain>"; print "send"}' | <nsupdatecmd> -k <keyfile>
[Init]
# Option: domain
# Notes.: DNS domain that nsupdate will update.
# Values: STRING
#
domain =
# Option: ttl
# Notes.: time to live (TTL) in seconds of TXT resource record
# added by nsupdate.
# Values: NUM
#
ttl = 60
# Option: rdata
# Notes.: data portion of the TXT resource record added by nsupdate.
# Values: STRING
#
rdata = Your IP has been banned
# Option: nsupdatecmd
# Notes.: specifies the full path to the nsupdate program that dynamically
# updates BIND zone files.
# Values: CMD
#
nsupdatecmd = /usr/bin/nsupdate
# Option: keyfile
# Notes.: specifies the full path to the file containing the
# TSIG key for communicating with BIND.
# Values: STRING
#
keyfile =
+2 -2
View File
@@ -15,7 +15,7 @@ after = sendmail-common.local
# Values: CMD
#
actionstart = printf %%b "Subject: [Fail2Ban] <name>: started on `uname -n`
Date: `LC_TIME=C date +"%%a, %%d %%h %%Y %%T %%z"`
Date: `LC_TIME=C date -u +"%%a, %%d %%h %%Y %%T +0000"`
From: <sendername> <<sender>>
To: <dest>\n
Hi,\n
@@ -28,7 +28,7 @@ actionstart = printf %%b "Subject: [Fail2Ban] <name>: started on `uname -n`
# Values: CMD
#
actionstop = printf %%b "Subject: [Fail2Ban] <name>: stopped on `uname -n`
Date: `LC_TIME=C date +"%%a, %%d %%h %%Y %%T %%z"`
Date: `LC_TIME=C date -u +"%%a, %%d %%h %%Y %%T +0000"`
From: <sendername> <<sender>>
To: <dest>\n
Hi,\n
-49
View File
@@ -1,49 +0,0 @@
# Fail2Ban configuration file
#
# Author: Viktor Szépe
#
#
[INCLUDES]
before = sendmail-common.conf
[Definition]
# Option: actionban
# Notes.: Command executed when banning an IP. Take care that the
# command is executed with Fail2Ban user rights.
# You need to install geoiplookup and the GeoLite or GeoIP databases.
# (geoip-bin and geoip-database in Debian)
# The host command comes from bind9-host package.
# Tags: See jail.conf(5) man page
# Values: CMD
#
actionban = printf %%b "Subject: [Fail2Ban] <name>: banned <ip> from `uname -n`
Date: `LC_TIME=C date +"%%a, %%d %%h %%Y %%T %%z"`
From: <sendername> <<sender>>
To: <dest>\n
Hi,\n
The IP <ip> has just been banned by Fail2Ban after
<failures> attempts against <name>.\n\n
Here is more information about <ip>:\n
http://bgp.he.net/ip/<ip>
http://www.projecthoneypot.org/ip_<ip>
http://whois.domaintools.com/<ip>\n\n
Country:`geoiplookup -f /usr/share/GeoIP/GeoIP.dat "<ip>" | cut -d':' -f2-`
AS:`geoiplookup -f /usr/share/GeoIP/GeoIPASNum.dat "<ip>" | cut -d':' -f2-`
hostname: `host -t A <ip> 2>&1`\n\n
Lines containing IP:<ip> in <logpath>\n
`grep -E '(^|[^0-9])<ip>([^0-9]|$)' <logpath>`\n\n
Regards,\n
Fail2Ban" | /usr/sbin/sendmail -f <sender> <dest>
[Init]
# Default name of the chain
#
name = default
# Path to the log files which contain relevant lines for the abuser IP
#
logpath = /dev/null
@@ -17,13 +17,13 @@ before = sendmail-common.conf
# Values: CMD
#
actionban = printf %%b "Subject: [Fail2Ban] <name>: banned <ip> from `uname -n`
Date: `LC_TIME=C date +"%%a, %%d %%h %%Y %%T %%z"`
Date: `LC_TIME=C date -u +"%%a, %%d %%h %%Y %%T +0000"`
From: <sendername> <<sender>>
To: <dest>\n
Hi,\n
The IP <ip> has just been banned by Fail2Ban after
<failures> attempts against <name>.\n\n
Here is more information about <ip>:\n
Here are more information about <ip>:\n
`/usr/bin/whois <ip>`\n\n
Matches for <name> with <ipjailfailures> failures IP:<ip>\n
<ipjailmatches>\n\n
@@ -17,13 +17,13 @@ before = sendmail-common.conf
# Values: CMD
#
actionban = printf %%b "Subject: [Fail2Ban] <name>: banned <ip> from `uname -n`
Date: `LC_TIME=C date +"%%a, %%d %%h %%Y %%T %%z"`
Date: `LC_TIME=C date -u +"%%a, %%d %%h %%Y %%T +0000"`
From: <sendername> <<sender>>
To: <dest>\n
Hi,\n
The IP <ip> has just been banned by Fail2Ban after
<failures> attempts against <name>.\n\n
Here is more information about <ip>:\n
Here are more information about <ip>:\n
`/usr/bin/whois <ip>`\n\n
Matches with <ipfailures> failures IP:<ip>\n
<ipmatches>\n\n
+2 -2
View File
@@ -17,7 +17,7 @@ before = sendmail-common.conf
# Values: CMD
#
actionban = printf %%b "Subject: [Fail2Ban] <name>: banned <ip> from `uname -n`
Date: `LC_TIME=C date +"%%a, %%d %%h %%Y %%T %%z"`
Date: `LC_TIME=C date -u +"%%a, %%d %%h %%Y %%T +0000"`
From: <sendername> <<sender>>
To: <dest>\n
Hi,\n
@@ -26,7 +26,7 @@ actionban = printf %%b "Subject: [Fail2Ban] <name>: banned <ip> from `uname -n`
Here is more information about <ip>:\n
`/usr/bin/whois <ip> || echo missing whois program`\n\n
Lines containing IP:<ip> in <logpath>\n
`grep -E '(^|[^0-9])<ip>([^0-9]|$)' <logpath>`\n\n
`grep '[^0-9]<ip>[^0-9]' <logpath>`\n\n
Regards,\n
Fail2Ban" | /usr/sbin/sendmail -f <sender> <dest>
+2 -2
View File
@@ -17,13 +17,13 @@ before = sendmail-common.conf
# Values: CMD
#
actionban = printf %%b "Subject: [Fail2Ban] <name>: banned <ip> from `uname -n`
Date: `LC_TIME=C date +"%%a, %%d %%h %%Y %%T %%z"`
Date: `LC_TIME=C date -u +"%%a, %%d %%h %%Y %%T +0000"`
From: <sendername> <<sender>>
To: <dest>\n
Hi,\n
The IP <ip> has just been banned by Fail2Ban after
<failures> attempts against <name>.\n\n
Here is more information about <ip>:\n
Here are more information about <ip>:\n
`/usr/bin/whois <ip>`\n\n
Matches:\n
<matches>\n\n
+1 -1
View File
@@ -17,7 +17,7 @@ before = sendmail-common.conf
# Values: CMD
#
actionban = printf %%b "Subject: [Fail2Ban] <name>: banned <ip> from `uname -n`
Date: `LC_TIME=C date +"%%a, %%d %%h %%Y %%T %%z"`
Date: `LC_TIME=C date -u +"%%a, %%d %%h %%Y %%T +0000"`
From: <sendername> <<sender>>
To: <dest>\n
Hi,\n
+1 -1
View File
@@ -17,7 +17,7 @@ before = sendmail-common.conf
# Values: CMD
#
actionban = printf %%b "Subject: [Fail2Ban] <name>: banned <ip> from `uname -n`
Date: `LC_TIME=C date +"%%a, %%d %%h %%Y %%T %%z"`
Date: `LC_TIME=C date -u +"%%a, %%d %%h %%Y %%T +0000"`
From: <sendername> <<sender>>
To: <dest>\n
Hi,\n
+2 -4
View File
@@ -13,11 +13,9 @@ actionstop =
actioncheck =
actionban = [ -n "<application>" ] && app="app <application>"
ufw insert <insertpos> <blocktype> from <ip> to <destination> $app
actionban = [ -n "<application>" ] && app="app <application>" ; ufw insert <insertpos> <blocktype> from <ip> to <destination> $app
actionunban = [ -n "<application>" ] && app="app <application>"
ufw delete <blocktype> from <ip> to <destination> $app
actionunban = [ -n "<application>" ] && app="app <application>" ; ufw delete <blocktype> from <ip> to <destination> $app
[Init]
# Option: insertpos
+1 -1
View File
@@ -46,7 +46,7 @@ actionban = oifs=${IFS}; IFS=.;SEP_IP=( <ip> ); set -- ${SEP_IP}; ADDRESSES=$(di
REPORTID=<time>@`uname -n`
TLP=<tlp>
PORT=<port>
DATE=`LC_TIME=C date --date=@<time> +"%%a, %%d %%h %%Y %%T %%z"`
DATE=`LC_TIME=C date -u --date=@<time> +"%%a, %%d %%h %%Y %%T +0000"`
if [ ! -z "$ADDRESSES" ]; then
(printf -- %%b "<header>\n<message>\n<report>\n";
date '+Note: Local timezone is %%z (%%Z)';
-6
View File
@@ -34,12 +34,6 @@ loglevel = INFO
#
logtarget = /var/log/fail2ban.log
# Option: syslogsocket
# Notes: Set the syslog socket file. Only used when logtarget is SYSLOG
# auto uses platform.system() to determine predefined paths
# Values: [ auto | FILE ] Default: auto
syslogsocket = auto
# Option: socket
# Notes.: Set the socket file. This is used to communicate with the daemon. Do
# not remove this file when Fail2ban runs. It will not be possible to
+1 -1
View File
@@ -10,7 +10,7 @@ before = apache-common.conf
[Definition]
failregex = ^%(_apache_error_client)s (AH(01797|01630): )?client denied by server configuration: (uri )?\S*(, referer: \S+)?\s*$
failregex = ^%(_apache_error_client)s (AH01797: )?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*$
+11 -3
View File
@@ -17,9 +17,7 @@
[INCLUDES]
# overwrite with apache-common.local if _apache_error_client is incorrect.
# Load regexes for filtering from botsearch-common.conf
before = apache-common.conf
botsearch-common.conf
[Definition]
@@ -33,8 +31,18 @@ ignoreregex =
# Webroot represents the webroot on which all other files are based
webroot = /var/www/
# Block is the actual non-found directories to block
block = (<webmail>|<phpmyadmin>|<wordpress>)[^,]*
# These are just convient definitions that assist the blocking of stuff that
# isn't installed
webmail = roundcube|(ext)?mail|horde|(v-?)?webmail
phpmyadmin = (typo3/|xampp/|admin/|)(pma|(php)?[Mm]y[Aa]dmin)
wordpress = wp-(login|signup)\.php
# DEV Notes:
#
# Author: Daniel Black
# Author: Daniel Black
-14
View File
@@ -1,14 +0,0 @@
# Fail2Ban filter for fake Googlebot User Agents
[Definition]
failregex = ^<HOST> .*Googlebot.*$
ignoreregex =
# DEV Notes:
#
# Author: Lee Clemens
# Thanks: Johannes B. Ullrich, Ph.D.
# Reference: https://isc.sans.edu/forums/diary/When+Google+isnt+Google/15968/
-26
View File
@@ -1,26 +0,0 @@
# 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)
+1 -1
View File
@@ -22,7 +22,7 @@ failregex = ^(%(__prefix_line)s|\[\]\s*)%(log_prefix)s Registration from '[^']*'
^(%(__prefix_line)s|\[\]\s*)%(log_prefix)s No registration for peer '[^']*' \(from <HOST>\)$
^(%(__prefix_line)s|\[\]\s*)%(log_prefix)s Host <HOST> failed MD5 authentication for '[^']*' \([^)]+\)$
^(%(__prefix_line)s|\[\]\s*)%(log_prefix)s Failed to authenticate (user|device) [^@]+@<HOST>\S*$
^(%(__prefix_line)s|\[\]\s*)%(log_prefix)s hacking attempt detected '<HOST>'$
^(%(__prefix_line)s|\[\]\s*)%(log_prefix)s (?:handle_request_subscribe: )?Sending fake auth rejection for (device|user) \d*<sip:[^@]+@<HOST>>;tag=\w+\S*$
^(%(__prefix_line)s|\[\]\s*)%(log_prefix)s SecurityEvent="(FailedACL|InvalidAccountID|ChallengeResponseFailed|InvalidPassword)",EventTV="[\d-]+",Severity="[\w]+",Service="[\w]+",EventVersion="\d+",AccountID="\d*",SessionID="0x[\da-f]+",LocalAddress="IPV[46]/(UD|TC)P/[\da-fA-F:.]+/\d+",RemoteAddress="IPV[46]/(UD|TC)P/<HOST>/\d+"(,Challenge="\w+",ReceivedChallenge="\w+")?(,ReceivedHash="[\da-f]+")?(,ACLName="\w+")?$
^(%(__prefix_line)s|\[\]\s*WARNING%(__pid_re)s:?(?:\[C-[\da-f]*\])? )Ext\. s: "Rejecting unknown SIP connection from <HOST>"$
-19
View File
@@ -1,19 +0,0 @@
# Generic configuration file for -botsearch filters
[Init]
# Block is the actual non-found directories to block
block = \/?(<webmail>|<phpmyadmin>|<wordpress>|cgi-bin|mysqladmin)[^,]*
# These are just convient definitions that assist the blocking of stuff that
# isn't installed
webmail = roundcube|(ext)?mail|horde|(v-?)?webmail
phpmyadmin = (typo3/|xampp/|admin/|)(pma|(php)?[Mm]y[Aa]dmin)
wordpress = wp-(login|signup)\.php
# DEV Notes:
# Taken from apache-botsearch filter
#
# Author: Frantisek Sumsal
-4
View File
@@ -53,8 +53,4 @@ __bsd_syslog_verbose = (<[^.]+\.[^.]+>)
# This can be optional (for instance if we match named native log files)
__prefix_line = \s*%(__bsd_syslog_verbose)s?\s*(?:%(__hostname)s )?(?:%(__kernel_prefix)s )?(?:@vserver_\S+ )?%(__daemon_combs_re)s?\s%(__daemon_extra_re)s?\s*
# PAM authentication mechanism check for failures, e.g.: pam_unix, pam_sss,
# pam_ldap
__pam_auth = pam_unix
# Author: Yaroslav Halchenko
-1
View File
@@ -6,7 +6,6 @@
failregex = ^: Bad Rcon: "rcon \d+ "\S+" sv_contact ".*?"" from "<HOST>:\d+"$
ignoreregex =
[Init]
+2 -3
View File
@@ -9,10 +9,9 @@ before = common.conf
_daemon = (auth|dovecot(-auth)?|auth-worker)
failregex = ^%(__prefix_line)s(%(__pam_auth)s(\(dovecot:auth\))?:)?\s+authentication failure; logname=\S* uid=\S* euid=\S* tty=dovecot ruser=\S* rhost=<HOST>(\s+user=\S*)?\s*$
failregex = ^%(__prefix_line)s(pam_unix(\(dovecot:auth\))?:)?\s+authentication failure; logname=\S* uid=\S* euid=\S* tty=dovecot ruser=\S* rhost=<HOST>(\s+user=\S*)?\s*$
^%(__prefix_line)s(pop3|imap)-login: (Info: )?(Aborted login|Disconnected)(: Inactivity)? \(((auth failed, \d+ attempts)( in \d+ secs)?|tried to use (disabled|disallowed) \S+ auth)\):( user=<\S*>,)?( method=\S+,)? rip=<HOST>(, lip=(\d{1,3}\.){3}\d{1,3})?(, TLS( handshaking(: SSL_accept\(\) failed: error:[\dA-F]+:SSL routines:[TLS\d]+_GET_CLIENT_HELLO:unknown protocol)?)?(: Disconnected)?)?(, session=<\S+>)?\s*$
^%(__prefix_line)s(Info|dovecot: auth\(default\)|auth-worker\(\d+\)): pam\(\S+,<HOST>\): pam_authenticate\(\) failed: (User not known to the underlying authentication module: \d+ Time\(s\)|Authentication failure \(password mismatch\?\))\s*$
^%(__prefix_line)sauth-worker\(\d+\): pam\(\S+,<HOST>\): unknown user\s*$
^%(__prefix_line)s(Info|dovecot: auth\(default\)): pam\(\S+,<HOST>\): pam_authenticate\(\) failed: (User not known to the underlying authentication module: \d+ Time\(s\)|Authentication failure \(password mismatch\?\))\s*$
ignoreregex =
-26
View File
@@ -1,26 +0,0 @@
# Fail2Ban filter to block repeated failed login attempts to Drupal site(s)
#
#
# Drupal must be setup to use Syslog, which defaults to the following format:
#
# !base_url|!timestamp|!type|!ip|!request_uri|!referer|!uid|!link|!message
#
#
[INCLUDES]
before = common.conf
[Definition]
failregex = ^%(__prefix_line)s(https?:\/\/)([\da-z\.-]+)\.([a-z\.]{2,6})(\/[\w\.-]+)*\|\d{10}\|user\|<HOST>\|.+\|.+\|\d\|.*\|Login attempt failed for .+\.$
ignoreregex =
# DEV Notes:
#
# https://www.drupal.org/documentation/modules/syslog
#
# Author: Lee Clemens
+2 -2
View File
@@ -14,10 +14,10 @@ before = exim-common.conf
[Definition]
failregex = ^%(pid)s %(host_info)ssender verify fail for <\S+>: (?:Unknown user|Unrouteable address|all relevant MX records point to non-existent hosts)\s*$
^%(pid)s \w+ authenticator failed for (\S+ )?\(\S+\) \[<HOST>\](:\d+)?( I=\[\S+\](:\d+)?)?: 535 Incorrect authentication data( \(set_id=.*\)|: \d+ Time\(s\))?\s*$
^%(pid)s \w+ authenticator failed for (\S+ )?\(\S+\) \[<HOST>\]: 535 Incorrect authentication data( \(set_id=.*\)|: \d+ Time\(s\))?\s*$
^%(pid)s %(host_info)sF=(<>|[^@]+@\S+) rejected RCPT [^@]+@\S+: (relay not permitted|Sender verify failed|Unknown user)\s*$
^%(pid)s SMTP protocol synchronization error \([^)]*\): rejected (connection from|"\S+") %(host_info)s(next )?input=".*"\s*$
^%(pid)s SMTP call from \S+ \[<HOST>\](:\d+)? (I=\[\S+\](:\d+)? )?dropped: too many nonmail commands \(last was "\S+"\)\s*$
^%(pid)s SMTP call from \S+ \[<HOST>\](:\d+)? (I=\[\S+\]:\d+ )?dropped: too many nonmail commands \(last was "\S+"\)\s*$
ignoreregex =
+1 -1
View File
@@ -8,7 +8,7 @@
failregex = ^\[\]LOGIN FAILED for user: "\S+" from IP: <HOST>$
ignoreregex =
# Author: Daniel Black
@@ -1,32 +0,0 @@
#!/usr/bin/python
# Inspired by https://isc.sans.edu/forums/diary/When+Google+isnt+Google/15968/
#
# Written in Python to reuse built-in Python batteries and not depend on
# presence of host and cut commands
#
import sys
def process_args(argv):
if len(argv) != 2:
sys.stderr.write("Please provide a single IP as an argument. Got: %s\n"
% (argv[1:]))
sys.exit(2)
ip = argv[1]
from fail2ban.server.filter import DNSUtils
if not DNSUtils.isValidIP(ip):
sys.stderr.write("Argument must be a single valid IP. Got: %s\n"
% ip)
sys.exit(3)
return ip
def is_googlebot(ip):
import re
from fail2ban.server.filter import DNSUtils
host = DNSUtils.ipToName(ip)
sys.exit(0 if (host and re.match('crawl-.*\.googlebot\.com', host)) else 1)
if __name__ == '__main__':
is_googlebot(process_args(sys.argv))
-3
View File
@@ -6,9 +6,6 @@ failregex = ^ SMTP Spam attack detected from <HOST>,
^ IP address <HOST> found in DNS blacklist \S+, mail from \S+ to \S+$
^ Relay attempt from IP address <HOST>
^ Attempt to deliver to unknown recipient \S+, from \S+, IP address <HOST>$
ignoreregex =
[Init]
datepattern = ^\[%%d/%%b/%%Y %%H:%%M:%%S\]
-1
View File
@@ -7,4 +7,3 @@
failregex = ^\[[A-Z]+\s+\]\s*error\s*:\s*Warning:\s+Client '<HOST>' supplied unknown user '\w+' accessing monit httpd$
^\[[A-Z]+\s+\]\s*error\s*:\s*Warning:\s+Client '<HOST>' supplied wrong password for user '\w+' accessing monit httpd$
ignoreregex =
-2
View File
@@ -38,8 +38,6 @@ failregex = ^%(__line_prefix)s( error:)?\s*client <HOST>#\S+( \([\S.]+\))?: (vie
^%(__line_prefix)s( error:)?\s*client <HOST>#\S+( \([\S.]+\))?: zone transfer '\S+/AXFR/\w+' denied\s*$
^%(__line_prefix)s( error:)?\s*client <HOST>#\S+( \([\S.]+\))?: bad zone transfer request: '\S+/IN': non-authoritative zone \(NOTAUTH\)\s*$
ignoreregex =
# DEV Notes:
# Trying to generalize the
# structure which is general to capture general patterns in log
-20
View File
@@ -1,20 +0,0 @@
# Fail2Ban filter to match web requests for selected URLs that don't exist
#
[INCLUDES]
# Load regexes for filtering
before = botsearch-common.conf
[Definition]
failregex = ^<HOST> \- \S+ \[\] \"(GET|POST) \/<block> \S+\" 404 .+$
^ \[error\] \d+#\d+: \*\d+ (\S+ )?\"\S+\" (failed|is not found) \(2\: No such file or directory\), client\: <HOST>\, server\: \S*\, request: \"(GET|POST) \/<block> \S+\"\, .*?$
ignoreregex =
# DEV Notes:
# Based on apache-botsearch filter
#
# Author: Frantisek Sumsal
-2
View File
@@ -24,5 +24,3 @@ _daemon = nsd
failregex = ^\[\]%(__prefix_line)sinfo: ratelimit block .* query <HOST> TYPE255$
^\[\]%(__prefix_line)sinfo: .* <HOST> refused, no acl matches\.$
ignoreregex =
+1 -1
View File
@@ -13,7 +13,7 @@ before = common.conf
# Default: catch all failed logins
_ttys_re=\S*
__pam_re=\(?%(__pam_auth)s(?:\(\S+\))?\)?:?
__pam_re=\(?pam_unix(?:\(\S+\))?\)?:?
_daemon = \S+
failregex = ^%(__prefix_line)s%(__pam_re)s\s+authentication failure; logname=\S* uid=\S* euid=\S* tty=%(_ttys_re)s ruser=\S* rhost=<HOST>(?:\s+user=.*)?\s*$
-12
View File
@@ -1,12 +0,0 @@
# Fail2Ban filter for failure attempts in Counter Strike-1.6
#
#
[Definition]
failregex = \/<HOST> Port\: [0-9]+ (TCP|UDP) Blocked$
ignoreregex =
# Author: Pacop <pacoparu@gmail.com>
-19
View File
@@ -1,19 +0,0 @@
# Fail2Ban filter for Postfix's RBL based Blocked hosts
#
#
[INCLUDES]
# Read common prefixes. If any customizations available -- read them from
# common.local
before = common.conf
[Definition]
_daemon = postfix/smtpd
failregex = ^%(__prefix_line)sNOQUEUE: reject: RCPT from \S+\[<HOST>\]: 454 4\.7\.1 Service unavailable; Client host \[\S+\] blocked using .* from=<\S*> to=<\S+> proto=ESMTP helo=<\S*>$
ignoreregex =
# Author: Lee Clemens
+2 -4
View File
@@ -7,11 +7,9 @@ before = common.conf
[Definition]
_daemon = postfix/(submission/)?smtp(d|s)
_daemon = postfix/smtpd
failregex = ^%(__prefix_line)swarning: [-._\w]+\[<HOST>\]: SASL ((?i)LOGIN|PLAIN|(?:CRAM|DIGEST)-MD5) authentication failed(: [ A-Za-z0-9+/:]*={0,2})?\s*$
ignoreregex = authentication failed: Connection lost to authentication server$
failregex = ^%(__prefix_line)swarning: [-._\w]+\[<HOST>\]: SASL (?:LOGIN|PLAIN|(?:CRAM|DIGEST)-MD5) authentication failed(: [ A-Za-z0-9+/]*={0,2})?\s*$
[Init]
+1 -2
View File
@@ -10,10 +10,9 @@ before = common.conf
[Definition]
_daemon = postfix/(submission/)?smtp(d|s)
_daemon = postfix/smtpd
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 Client host rejected: cannot find your hostname, (\[\S*\]); from=<\S*> to=<\S+> proto=ESMTP helo=<\S*>$
^%(__prefix_line)sNOQUEUE: reject: RCPT from \S+\[<HOST>\]: 450 4\.7\.1 : Helo command rejected: Host not found; from=<> to=<> proto=ESMTP helo= *$
^%(__prefix_line)sNOQUEUE: reject: VRFY from \S+\[<HOST>\]: 550 5\.1\.1 .*$
^%(__prefix_line)simproper command pipelining after \S+ from [^[]*\[<HOST>\]:?$
-2
View File
@@ -29,8 +29,6 @@ _jailname = recidive
failregex = ^(%(__prefix_line)s| %(_daemon)s%(__pid_re)s?:\s+)NOTICE\s+\[(?!%(_jailname)s\])(?:.*)\]\s+Ban\s+<HOST>\s*$
ignoreregex =
[Init]
journalmatch = _SYSTEMD_UNIT=fail2ban.service PRIORITY=5
+1 -1
View File
@@ -7,7 +7,7 @@
failregex = ^\s+\d\s<HOST>\s+[A-Z_]+_DENIED/403 .*$
^\s+\d\s<HOST>\s+NONE/405 .*$
ignoreregex =
# Author: Daniel Black
-1
View File
@@ -3,7 +3,6 @@
failregex = ^ \[LOGIN_ERROR\].*from <HOST>: Unknown user or password incorrect\.$
ignoreregex =
[Init]
-1
View File
@@ -33,7 +33,6 @@ failregex = ^%(__prefix_line)s(?:error: PAM: )?[aA]uthentication (?:failure|erro
^(?P<__prefix>%(__prefix_line)s)User .+ not allowed because account is locked<SKIPLINES>(?P=__prefix)(?:error: )?Received disconnect from <HOST>: 11: .+ \[preauth\]$
^(?P<__prefix>%(__prefix_line)s)Disconnecting: Too many authentication failures for .+? \[preauth\]<SKIPLINES>(?P=__prefix)(?:error: )?Connection closed by <HOST> \[preauth\]$
^(?P<__prefix>%(__prefix_line)s)Connection from <HOST> port \d+(?: on \S+ port \d+)?<SKIPLINES>(?P=__prefix)Disconnecting: Too many authentication failures for .+? \[preauth\]$
^%(__prefix_line)spam_unix\(sshd:auth\):\s+authentication failure;\s*logname=\S*\s*uid=\d*\s*euid=\d*\s*tty=\S*\s*ruser=\S*\s*rhost=<HOST>\s.*$
ignoreregex =
-2
View File
@@ -4,8 +4,6 @@
failregex = ^ LOG\d\[\d+:\d+\]:\ SSL_accept from <HOST>:\d+ : (?P<CODE>[\dA-F]+): error:(?P=CODE):SSL routines:SSL3_GET_CLIENT_CERTIFICATE:peer did not return a certificate$
ignoreregex =
# DEV NOTES:
#
# Author: Daniel Black
+1 -1
View File
@@ -10,7 +10,7 @@ before = common.conf
[Definition]
__pam_re=\(?%(__pam_auth)s(?:\(\S+\))?\)?:?
__pam_re=\(?pam_unix(?:\(\S+\))?\)?:?
_daemon = vsftpd
failregex = ^%(__prefix_line)s%(__pam_re)s\s+authentication failure; logname=\S* uid=\S* euid=\S* tty=(ftp)? ruser=\S* rhost=<HOST>(?:\s+user=.*)?\s*$
+1 -1
View File
@@ -11,7 +11,7 @@ before = common.conf
[Definition]
_daemon = wu-ftpd
__pam_re=\(?%(__pam_auth)s(?:\(wu-ftpd:auth\))?\)?:?
__pam_re=\(?pam_unix(?:\(wu-ftpd:auth\))?\)?:?
failregex = ^%(__prefix_line)sfailed login from \S+ \[<HOST>\]\s*$
^%(__prefix_line)s%(__pam_re)s\s+authentication failure; logname=\S* uid=\S* euid=\S* tty=(ftp)? ruser=\S* rhost=<HOST>(?:\s+user=.*)?\s*$
+8 -50
View File
@@ -79,11 +79,6 @@ maxretry = 5
# See "journalmatch" in the jails associated filter config
# auto: will try to use the following backends, in order:
# pyinotify, gamin, polling.
#
# Note: if systemd backend is choses as the default but you enable a jail
# for which logs are present only in its own log files, specify some other
# backend for that jail (e.g. polling) and provide empty value for
# journalmatch. See https://github.com/fail2ban/fail2ban/issues/959#issuecomment-74901200
backend = auto
# "usedns" specifies if jails should trust hostnames in logs,
@@ -282,36 +277,18 @@ logpath = %(apache_error_log)s
maxretry = 2
[apache-fakegooglebot]
port = http,https
logpath = %(apache_access_log)s
maxretry = 1
ignorecommand = %(ignorecommands_dir)s/apache-fakegooglebot <ip>
[apache-modsecurity]
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]
port = http,https
ports = http,https
logpath = %(nginx_error_log)s
[nginx-botsearch]
port = http,https
logpath = %(nginx_error_log)s
maxretry = 2
# Ban attackers that try to use PHP's URL-fopen() functionality
# through GET/POST variables. - Experimental, with more than a year
@@ -320,8 +297,7 @@ maxretry = 2
[php-url-fopen]
port = http,https
logpath = %(nginx_access_log)s
%(apache_access_log)s
logpath = %(nginx_access_log)s %(apache_access_log)s
[suhosin]
@@ -385,11 +361,6 @@ maxretry = 5
#
#
[drupal-auth]
port = http,https
logpath = %(syslog_daemon)s
[guacamole]
port = http,https
@@ -488,13 +459,6 @@ port = smtp,465,submission
logpath = %(postfix_log)s
[postfix-rbl]
port = smtp,465,submission
logpath = %(syslog_mail)s
maxretry = 1
[sendmail-auth]
port = submission,465,smtp
@@ -679,16 +643,15 @@ maxretry = 5
# Jail for more extended banning of persistent abusers
# !!! WARNINGS !!!
# 1. Make sure that your loglevel specified in fail2ban.conf/.local
# is not at DEBUG level -- which might then cause fail2ban to fall into
# an infinite loop constantly feeding itself with non-informative lines
# 2. Increase dbpurgeage defined in fail2ban.conf to e.g. 648000 (7.5 days)
# to maintain entries for failed logins for sufficient amount of time
# !!! WARNING !!!
# Make sure that your loglevel specified in fail2ban.conf/.local
# is not at DEBUG level -- which might then cause fail2ban to fall into
# an infinite loop constantly feeding itself with non-informative lines
[recidive]
logpath = /var/log/fail2ban.log
banaction = iptables-allports
port = all
protocol = all
bantime = 604800 ; 1 week
findtime = 86400 ; 1 day
maxretry = 5
@@ -751,8 +714,3 @@ banaction = iptables-allports
enabled = false
logpath = /var/log/directadmin/login.log
port = 2222
[portsentry]
enabled = false
logpath = /var/lib/portsentry/portsentry.history
maxretry = 1
-3
View File
@@ -61,6 +61,3 @@ dovecot_log = %(syslog_mail_warn)s
solidpop3d_log = %(syslog_local0)s
mysql_log = %(syslog_daemon)s
# Directory with ignorecommand scripts
ignorecommands_dir = /etc/fail2ban/filter.d/ignorecommands
+6 -50
View File
@@ -1,56 +1,12 @@
fail2ban (0.9.2-1) unstable; urgency=medium
fail2ban (0.9.X-python3) UNRELEASED; urgency=medium
* Fresh release to celebrate jessie release and upload to unstable
* Moved python3-systemd to Recommends from Suggests given that systemd is
the default init system now. Should help people upgrading on Ubuntu 15.04
as well
* Added regular python to Recommends since apache-fakegooglebot still python2
[ Vid Luther ]
* python3 for everything? .. I hope.
-- Yaroslav Halchenko <debian@onerussian.com> Wed, 29 Apr 2015 00:00:07 -0400
[ vagrant ]
* warning?
fail2ban (0.9.1+git44-gd65c4f8-1) experimental; urgency=medium
[ Christoph Anton Mitterer ]
* Do not install the following configuration files which are not used within
the Debian package of fail2ban:
/etc/fail2ban/paths-fedora.conf
/etc/fail2ban/paths-freebsd.conf
/etc/fail2ban/paths-osx.conf
Closes: #767123
[ Yaroslav Halchenko ]
* New upstream snapshot from 0.9.1-44-gd65c4f8
- carries a lot of fixes and improvements. Consult upstream ChangeLog
- debian's init file is now maintained in upstream codebase (for manual
deployments)
- provides monit (now Suggest'ed) file which is now gets installed
but not enabled by default: ln -s /etc/monit/{monitrc,conf}.d/fail2ban
to assure that fail2ban process is running
-- Yaroslav Halchenko <debian@onerussian.com> Tue, 30 Dec 2014 18:32:16 -0500
fail2ban (0.9.1-1) unstable; urgency=medium
* 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
-- Yaroslav Halchenko <debian@onerussian.com> Mon, 27 Oct 2014 21:52:56 -0400
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
-- vagrant <vagrant@vagrant.vm> Sat, 13 Sep 2014 03:52:55 +0000
fail2ban (0.9.0+git48-gabcab00-1) experimental; urgency=medium
+4 -5
View File
@@ -2,18 +2,18 @@ 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), python3 (>= 3.0~), 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.6
Standards-Version: 3.9.4
Package: fail2ban
Architecture: all
Depends: ${python3:Depends}, ${misc:Depends}, lsb-base (>=2.0-7)
Recommends: python, iptables, whois, python3-pyinotify, python3-systemd
Suggests: mailx, system-log-daemon, monit
Recommends: iptables, whois, python3-pyinotify
Suggests: python-gamin, 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,4 +27,3 @@ 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.
+4 -8
View File
@@ -3,8 +3,8 @@
# Provides: fail2ban
# Required-Start: $local_fs $remote_fs
# Required-Stop: $local_fs $remote_fs
# Should-Start: $time $network $syslog $named iptables firehol shorewall ipmasq arno-iptables-firewall iptables-persistent ferm ufw
# Should-Stop: $network $syslog $named iptables firehol shorewall ipmasq arno-iptables-firewall iptables-persistent ferm ufw
# Should-Start: $time $network $syslog iptables firehol shorewall ipmasq arno-iptables-firewall iptables-persistent ferm
# Should-Stop: $network $syslog iptables firehol shorewall ipmasq arno-iptables-firewall iptables-persistent ferm
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: Start/stop fail2ban
@@ -17,10 +17,6 @@
# reindented + minor corrections + to work on sarge without modifications
# Modified: by Glenn Aaldering <glenn@openvideo.nl>
# added exit codes for status command
# Modified: by Juan Karlo de Guzman <jkarlodg@gmail.com>
# corrected the DAEMON's path and the SOCKFILE
# rename this file: (sudo) mv /etc/init.d/fail2ban.init /etc/init.d/fail2ban
# same with the logrotate file: (sudo) mv /etc/logrotate.d/fail2ban.logrotate /etc/logrotate.d/fail2ban
#
PATH=/usr/sbin:/usr/bin:/sbin:/bin
DESC="authentication failure monitor"
@@ -28,13 +24,13 @@ NAME=fail2ban
# fail2ban-client is not a daemon itself but starts a daemon and
# loads its with configuration
DAEMON=/usr/local/bin/$NAME-client
DAEMON=/usr/bin/$NAME-client
SCRIPTNAME=/etc/init.d/$NAME
# Ad-hoc way to parse out socket file name
SOCKFILE=`grep -h '^[^#]*socket *=' /etc/$NAME/$NAME.conf /etc/$NAME/$NAME.local 2>/dev/null \
| tail -n 1 | sed -e 's/.*socket *= *//g' -e 's/ *$//g'`
[ -z "$SOCKFILE" ] && SOCKFILE='/var/run/fail2ban.sock'
[ -z "$SOCKFILE" ] && SOCKFILE='/tmp/fail2ban.sock'
# Exit if the package is not installed
[ -x "$DAEMON" ] || exit 0
File diff suppressed because it is too large Load Diff
-11
View File
@@ -1,11 +0,0 @@
--- a/files/debian-initd
+++ b/files/debian-initd
@@ -28,7 +28,7 @@ NAME=fail2ban
# fail2ban-client is not a daemon itself but starts a daemon and
# loads its with configuration
-DAEMON=/usr/local/bin/$NAME-client
+DAEMON=/usr/bin/$NAME-client
SCRIPTNAME=/etc/init.d/$NAME
# Ad-hoc way to parse out socket file name
+2 -2
View File
@@ -4,7 +4,7 @@ Subject: tune ups in upstream manpages to direct users to use reportbug
--- a/man/fail2ban-client.1
+++ b/man/fail2ban-client.1
@@ -380,7 +380,7 @@ the action <ACT> for <JAIL>
@@ -369,7 +369,7 @@
Written by Cyril Jaquier <cyril.jaquier@fail2ban.org>.
Many contributions by Yaroslav O. Halchenko <debian@onerussian.com>.
.SH "REPORTING BUGS"
@@ -15,7 +15,7 @@ Subject: tune ups in upstream manpages to direct users to use reportbug
.br
--- a/man/fail2ban-server.1
+++ b/man/fail2ban-server.1
@@ -38,7 +38,7 @@ print the version
@@ -38,7 +38,7 @@
Written by Cyril Jaquier <cyril.jaquier@fail2ban.org>.
Many contributions by Yaroslav O. Halchenko <debian@onerussian.com>.
.SH "REPORTING BUGS"
+46
View File
@@ -0,0 +1,46 @@
From: Yaroslav Halchenko <debian@onerussian.com>
Date: Thu, 6 Dec 2012 12:50:12 -0500
Subject: [PATCH] Patch for elderly Debian/Ubuntu (e.g. 10.04) releases without dh_python2
Use again pycentral etc
crafted post 0.8.8-1 release when a user complained about inability to upgrade
---
debian/control | 2 ++
debian/rules | 12 +++++-------
2 files changed, 7 insertions(+), 7 deletions(-)
--- a/debian/control
+++ b/debian/control
@@ -3,6 +3,8 @@ Section: net
Priority: optional
Maintainer: Yaroslav Halchenko <debian@onerussian.com>
Build-Depends: debhelper (>= 5.0.37.2), python (>= 2.5.4-1~), python-pyinotify
+Build-Depends-Indep: python-central (>= 0.5.6)
+XS-Python-Version: current, >= 2.4
Homepage: http://www.fail2ban.org
Vcs-Git: git://github.com/fail2ban/fail2ban.git
Vcs-Browser: http://github.com/fail2ban/fail2ban
--- a/debian/rules
+++ b/debian/rules
@@ -72,14 +72,12 @@ binary-indep: install
dh_installdocs
dh_installexamples config/jail.conf files/ipmasq-*
dh_installlogrotate
- dh_python2 /usr/share/fail2ban
+ dh_pycentral
dh_installinit -- defaults 99
-
- # perform swap of order of calls to init and pycentral (or even
- # bleedingly new dh_python2) in prerm to close #422655 --
- # python-cleanup section is cut and placed at the end of the file
- # since .init script would trigger their compilation again
- sed -i -e '/^#.*ed by dh_python2/,/# End auto/{H;d};$$G' \
+ # perform swap of order of calls to init and pycentral in prerm
+ # to close #422655 -- pycentral section is cut and placed at
+ # the end of the file
+ sed -i -e '/^#.*ed by dh_pycentral/,/# End auto/{H;d};$$G' \
debian/fail2ban.prerm.debhelper
dh_installman man/*.[15]
-1
View File
@@ -1 +0,0 @@
neurodebian_use_python2
-53
View File
@@ -1,53 +0,0 @@
--- 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
@@ -11,9 +11,9 @@ Standards-Version: 3.9.6
Package: fail2ban
Architecture: all
-Depends: ${python3:Depends}, ${misc:Depends}, lsb-base (>=2.0-7)
-Recommends: python, iptables, whois, python3-pyinotify, python3-systemd
-Suggests: mailx, system-log-daemon, monit
+Depends: ${python:Depends}, ${misc:Depends}, lsb-base (>=2.0-7)
+Recommends: iptables, whois, python-pyinotify
+Suggests: mailx, system-log-daemon, monit, 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
@@ -37,7 +37,8 @@ override_dh_install:
: # Install bash completion
install -d $(DESTDIR)/etc/bash_completion.d
install -m 644 files/bash-completion $(DESTDIR)/etc/bash_completion.d/fail2ban
- : # Install systemd files
+ : # Install systemd files, even in backport version just in case even though
+ : # other systemd preparation activities are not carried out
install -d $(DESTDIR)/lib/systemd/system
install -d $(DESTDIR)/usr/lib/tmpfiles.d
install -m 644 files/fail2ban.service $(DESTDIR)/lib/systemd/system
-1
View File
@@ -1 +0,0 @@
neurodebian_use_python2
+1 -1
View File
@@ -1,2 +1,2 @@
deb_init_paths
deb_manpages_reportbug
convert-to-python3.patch
-1
View File
@@ -1 +0,0 @@
neurodebian_use_python2
-1
View File
@@ -1 +0,0 @@
neurodebian_use_python2
-1
View File
@@ -1 +0,0 @@
neurodebian_use_python2
+3 -13
View File
@@ -9,31 +9,21 @@
# 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
-rm debian/fail2ban.init
dh_clean
override_dh_install:
rm -f $(DESTDIR)/usr/share/doc/fail2ban/README.Solaris
rm -f $(DESTDIR)/etc/fail2ban/paths-fedora.conf
rm -f $(DESTDIR)/etc/fail2ban/paths-freebsd.conf
rm -f $(DESTDIR)/etc/fail2ban/paths-osx.conf
: # Remove explicitely created /var/run/fail2ban
: # just to please lintian since init file will
: # take care about it anyways
rm -rf $(DESTDIR)/var/run/
: # Install monit configuration
install -d $(DESTDIR)/etc/monit/monitrc.d
install -m 644 files/monit/fail2ban $(DESTDIR)/etc/monit/monitrc.d/fail2ban
: # Install bash completion
install -d $(DESTDIR)/etc/bash_completion.d
install -m 644 files/bash-completion $(DESTDIR)/etc/bash_completion.d/fail2ban
@@ -44,19 +34,19 @@ override_dh_install:
install -m 644 files/fail2ban-tmpfiles.conf $(DESTDIR)/usr/lib/tmpfiles.d
install -d $(DESTDIR)/lib/systemd/system
: # Install default jail enabler
install -m 644 debian/debian-files/jail.d_defaults-debian.conf $(DESTDIR)/etc/fail2ban/jail.d/defaults-debian.conf
install -m 644 debian/source/jail.d_defaults-debian.conf $(DESTDIR)/etc/fail2ban/jail.d/defaults-debian.conf
dh_install
override_dh_auto_test:
ifeq (,$(filter nocheck,$(DEB_BUILD_OPTIONS)))
cd build && LC_ALL=C.UTF-8 FAIL2BAN_CONFIG_DIR="$(CURDIR)/config" PYTHONPATH="$(CURDIR)/.pybuild/pythonX.Y_$(PYVERSION)/build/" scripts-*/fail2ban-testcases --no-network
cd build && PYTHONPATH=../.pybuild/pythonX.Y_3.4/build/ scripts-*/fail2ban-testcases --no-network
endif
override_dh_installexamples:
dh_installexamples files/ipmasq-* files/nagios files/cacti
override_dh_installinit:
cp -p files/debian-initd debian/fail2ban.init
dh_installinit -- defaults 99
override_dh_installman:
-4
View File
@@ -68,7 +68,3 @@ logging.notice = _root_notice
# add NOTICE to the priority map of all the levels
logging.handlers.SysLogHandler.priority_map['NOTICE'] = 'notice'
from time import strptime
# strptime thread safety hack-around - http://bugs.python.org/issue7980
strptime("2012", "%Y")
+4 -8
View File
@@ -26,7 +26,7 @@ __license__ = "GPL"
import os
from .configreader import DefinitionInitConfigReader
from .configreader import ConfigReader, DefinitionInitConfigReader
from ..helpers import getLogger
# Gets the instance of the logger.
@@ -47,19 +47,15 @@ class ActionReader(DefinitionInitConfigReader):
DefinitionInitConfigReader.__init__(
self, file_, jailName, initOpts, **kwargs)
def setFile(self, fileName):
self.__file = fileName
DefinitionInitConfigReader.setFile(self, os.path.join("action.d", fileName))
def getFile(self):
return self.__file
def setName(self, name):
self._name = name
def getName(self):
return self._name
def read(self):
return ConfigReader.read(self, os.path.join("action.d", self._file))
def convert(self):
head = ["set", self._jailName]
stream = list()
+5 -8
View File
@@ -45,7 +45,7 @@ class Beautifier:
return self.__inputCmd
def beautify(self, response):
logSys.debug("Beautify " + `response` + " with " + `self.__inputCmd`)
logSys.debug("Beautify " + repr(response) + " with " + repr(self.__inputCmd))
inC = self.__inputCmd
msg = response
try:
@@ -85,9 +85,6 @@ class Beautifier:
val = " ".join(res1[1]) if isinstance(res1[1], list) else res1[1]
msg.append("%s %s:\t%s" % (prefix1, res1[0], val))
msg = "\n".join(msg)
elif inC[1] == "syslogsocket":
msg = "Current syslog socket is:\n"
msg = msg + "`- " + response
elif inC[1] == "logtarget":
msg = "Current logging target is:\n"
msg = msg + "`- " + response
@@ -102,7 +99,7 @@ class Beautifier:
elif response == 4:
msg = msg + "DEBUG"
else:
msg = msg + `response`
msg = msg + repr(response)
elif inC[1] == "dbfile":
if response is None:
msg = "Database currently disabled"
@@ -183,13 +180,13 @@ class Beautifier:
msg += ", ".join(response)
except Exception:
logSys.warning("Beautifier error. Please report the error")
logSys.error("Beautify " + `response` + " with " + `self.__inputCmd` +
logSys.error("Beautify " + repr(response) + " with " + repr(self.__inputCmd) +
" failed")
msg = msg + `response`
msg = msg + repr(response)
return msg
def beautifyError(self, response):
logSys.debug("Beautify (error) " + `response` + " with " + `self.__inputCmd`)
logSys.debug("Beautify (error) " + repr(response) + " with " + repr(self.__inputCmd))
msg = response
if isinstance(response, UnknownJailException):
msg = "Sorry but the jail '" + response.args[0] + "' does not exist"
+21 -119
View File
@@ -58,11 +58,10 @@ 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']
@@ -99,74 +98,31 @@ after = 1.conf
if sys.version_info >= (3,2):
# overload constructor only for fancy new Python3's
def __init__(self, share_config=None, *args, **kwargs):
def __init__(self, *args, **kwargs):
kwargs = kwargs.copy()
kwargs['interpolation'] = BasicInterpolationWithName()
kwargs['inline_comment_prefixes'] = ";"
super(SafeConfigParserWithIncludes, self).__init__(
*args, **kwargs)
self._cfg_share = share_config
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=[]):
#@staticmethod
def getIncludes(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:
parser, i = self._getSharedSCPWI(resource)
if not i:
return []
except UnicodeDecodeError, e:
if sys.version_info >= (3,2): # pragma: no cover
parser.read(resource, encoding='utf-8')
else:
parser.read(resource)
except UnicodeDecodeError as e:
logSys.error("Error decoding config file '%s': %s" % (resource, e))
return []
@@ -185,76 +141,22 @@ after = 1.conf
if r in seen:
continue
s = seen + [resource]
option_list += self._getIncludes(r, s)
option_list += SCPWI.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 get_sections(self):
return self._sections
def read(self, filenames, get_includes=True):
def read(self, filenames):
fileNamesFull = []
if not isinstance(filenames, list):
filenames = [ filenames ]
# 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):
# save previous known values, for possible using in local interpolations later:
sk = {}
for k, v in s2.iteritems():
if not k.startswith('known/'):
sk['known/'+k] = v
s2.update(sk)
# merge section
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) :
for filename in filenames:
fileNamesFull += SafeConfigParserWithIncludes.getIncludes(filename)
logSys.debug("Reading files: %s" % fileNamesFull)
if sys.version_info >= (3,2): # pragma: no cover
return SafeConfigParser.read(self, fileNamesFull, encoding='utf-8')
else:
return SafeConfigParser.read(self, fileNamesFull)
def merge_section(self, section, options, pref='known/'):
alls = self.get_sections()
sk = {}
for k, v in options.iteritems():
if pref == '' or not k.startswith(pref):
sk[pref+k] = v
alls[section].update(sk)
+26 -133
View File
@@ -25,133 +25,26 @@ __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, logLevel
from .configparserinc import SafeConfigParserWithIncludes
from ..helpers import getLogger
# Gets the instance of the logger.
logSys = getLogger(__name__)
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 merge_section(self, *args, **kwargs):
if self._cfg is not None:
return self._cfg.merge_section(*args, **kwargs)
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.
"""
class ConfigReader(SafeConfigParserWithIncludes):
DEFAULT_BASEDIR = '/etc/fail2ban'
def __init__(self, basedir=None, *args, **kwargs):
SafeConfigParserWithIncludes.__init__(self, *args, **kwargs)
self.read_cfg_files = None
def __init__(self, basedir=None):
SafeConfigParserWithIncludes.__init__(self)
self.setBaseDir(basedir)
self.__opts = None
def setBaseDir(self, basedir):
if basedir is None:
basedir = ConfigReaderUnshared.DEFAULT_BASEDIR # stock system location
basedir = ConfigReader.DEFAULT_BASEDIR # stock system location
self._basedir = basedir.rstrip('/')
def getBaseDir(self):
@@ -162,7 +55,7 @@ class ConfigReaderUnshared(SafeConfigParserWithIncludes):
raise ValueError("Base configuration directory %s does not exist "
% self._basedir)
basename = os.path.join(self._basedir, filename)
logSys.debug("Reading configs for %s under %s " , filename, self._basedir)
logSys.info("Reading configs for %s under %s " % (basename, self._basedir))
config_files = [ basename + ".conf" ]
# possible further customizations under a .conf.d directory
@@ -174,18 +67,18 @@ class ConfigReaderUnshared(SafeConfigParserWithIncludes):
config_files += sorted(glob.glob('%s/*.local' % config_dir))
# choose only existing ones
config_files = filter(os.path.exists, config_files)
config_files = list(filter(os.path.exists, config_files))
if len(config_files):
# at least one config exists and accessible
logSys.debug("Reading config files: %s", ', '.join(config_files))
logSys.debug("Reading config files: " + ', '.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: %s", ', '.join(missed))
logSys.error("Could not read config files: " + ', '.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:
@@ -205,7 +98,7 @@ class ConfigReaderUnshared(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:
@@ -218,7 +111,7 @@ class ConfigReaderUnshared(SafeConfigParserWithIncludes):
if not pOptions is None and option[1] in pOptions:
continue
values[option[1]] = v
except NoSectionError, e:
except NoSectionError as e:
# No "Definition" section or wrong basedir
logSys.error(e)
values[option[1]] = option[2]
@@ -228,22 +121,24 @@ class ConfigReaderUnshared(SafeConfigParserWithIncludes):
logSys.warning("'%s' not defined in '%s'. Using default one: %r"
% (option[1], sec, option[2]))
values[option[1]] = option[2]
elif logSys.getEffectiveLevel() <= logLevel:
logSys.log(logLevel, "Non essential option '%s' not defined in '%s'.", option[1], sec)
else:
logSys.debug(
"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: '" + `option[2]` + "'")
"'. Using default one: '" + repr(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 = []
@@ -271,9 +166,7 @@ class DefinitionInitConfigReader(ConfigReader):
# needed for fail2ban-regex that doesn't need fancy directories
def readexplicit(self):
if not self._cfg:
self._create_unshared(self._file)
return SafeConfigParserWithIncludes.read(self._cfg, self._file)
return SafeConfigParserWithIncludes.read(self, self._file)
def getOptions(self, pOpts):
self._opts = ConfigReader.getOptions(
@@ -281,7 +174,7 @@ class DefinitionInitConfigReader(ConfigReader):
if self.has_section("Init"):
for opt in self.options("Init"):
if not self._initOpts.has_key(opt):
if opt not in self._initOpts:
self._initOpts[opt] = self.get("Init", opt)
def convert(self):
+4 -12
View File
@@ -33,20 +33,12 @@ logSys = getLogger(__name__)
class Configurator:
def __init__(self, force_enable=False, share_config=None):
def __init__(self):
self.__settings = dict()
self.__streams = dict()
# 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()
self.__fail2ban = Fail2banReader()
self.__jails = JailsReader()
def setBaseDir(self, folderName):
self.__fail2ban.setBaseDir(folderName)
self.__jails.setBaseDir(folderName)
+3 -2
View File
@@ -57,12 +57,13 @@ 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)
-3
View File
@@ -46,7 +46,6 @@ class Fail2banReader(ConfigReader):
def getOptions(self):
opts = [["string", "loglevel", "INFO" ],
["string", "logtarget", "STDERR"],
["string", "syslogsocket", "auto"],
["string", "dbfile", "/var/lib/fail2ban/fail2ban.sqlite3"],
["int", "dbpurgeage", 86400]]
self.__opts = ConfigReader.getOptions(self, "Definition", opts)
@@ -58,8 +57,6 @@ class Fail2banReader(ConfigReader):
stream.append(["set", "loglevel", self.__opts[opt]])
elif opt == "logtarget":
stream.append(["set", "logtarget", self.__opts[opt]])
elif opt == "syslogsocket":
stream.append(["set", "syslogsocket", self.__opts[opt]])
elif opt == "dbfile":
stream.append(["set", "dbfile", self.__opts[opt]])
elif opt == "dbpurgeage":
+9 -21
View File
@@ -26,7 +26,7 @@ __license__ = "GPL"
import os, shlex
from .configreader import DefinitionInitConfigReader
from .configreader import ConfigReader, DefinitionInitConfigReader
from ..server.action import CommandAction
from ..helpers import getLogger
@@ -40,28 +40,16 @@ class FilterReader(DefinitionInitConfigReader):
["string", "failregex", ""],
]
def setFile(self, fileName):
self.__file = fileName
DefinitionInitConfigReader.setFile(self, os.path.join("filter.d", fileName))
def getFile(self):
return self.__file
def getCombined(self):
combinedopts = dict(list(self._opts.items()) + list(self._initOpts.items()))
if not len(combinedopts):
return {}
opts = CommandAction.substituteRecursiveTags(combinedopts)
if not opts:
raise ValueError('recursive tag definitions unable to be resolved')
return opts
def read(self):
return ConfigReader.read(self, os.path.join("filter.d", self._file))
def convert(self):
stream = list()
opts = self.getCombined()
if not len(opts):
return stream
for opt, value in opts.iteritems():
combinedopts = dict(list(self._opts.items()) + list(self._initOpts.items()))
opts = CommandAction.substituteRecursiveTags(combinedopts)
if not opts:
raise ValueError('recursive tag definitions unable to be resolved')
for opt, value in opts.items():
if opt == "failregex":
for regex in value.split('\n'):
# Do not send a command if the rule is empty.
@@ -71,7 +59,7 @@ class FilterReader(DefinitionInitConfigReader):
for regex in value.split('\n'):
# Do not send a command if the rule is empty.
if regex != '':
stream.append(["set", self._jailName, "addignoreregex", regex])
stream.append(["set", self._jailName, "addignoreregex", regex])
if self._initOpts:
if 'maxlines' in self._initOpts:
# We warn when multiline regex is used without maxlines > 1
+12 -28
View File
@@ -27,7 +27,7 @@ __license__ = "GPL"
import re, glob, os.path
import json
from .configreader import ConfigReaderUnshared, ConfigReader
from .configreader import ConfigReader
from .filterreader import FilterReader
from .actionreader import ActionReader
from ..helpers import getLogger
@@ -87,8 +87,6 @@ class JailReader(ConfigReader):
return pathList
def getOptions(self):
opts1st = [["bool", "enabled", False],
["string", "filter", ""]]
opts = [["bool", "enabled", False],
["string", "logpath", None],
["string", "logencoding", None],
@@ -103,9 +101,7 @@ class JailReader(ConfigReader):
["string", "ignoreip", None],
["string", "filter", ""],
["string", "action", ""]]
# Read first options only needed for merge defaults ('known/...' from filter):
self.__opts = ConfigReader.getOptions(self, self.__name, opts1st)
self.__opts = ConfigReader.getOptions(self, self.__name, opts)
if not self.__opts:
return False
@@ -115,26 +111,16 @@ class JailReader(ConfigReader):
filterName, filterOpt = JailReader.extractOptions(
self.__opts["filter"])
self.__filter = FilterReader(
filterName, self.__name, filterOpt, share_config=self.share_config, basedir=self.getBaseDir())
filterName, self.__name, filterOpt, basedir=self.getBaseDir())
ret = self.__filter.read()
# merge options from filter as 'known/...':
self.__filter.getOptions(self.__opts)
ConfigReader.merge_section(self, self.__name, self.__filter.getCombined(), 'known/')
if not ret:
if ret:
self.__filter.getOptions(self.__opts)
else:
logSys.error("Unable to read the filter")
return False
else:
self.__filter = None
logSys.warning("No filter set for jail %s" % self.__name)
# Read second all options (so variables like %(known/param) can be interpolated):
self.__opts = ConfigReader.getOptions(self, self.__name, opts)
if not self.__opts:
return False
# cumulate filter options again (ignore given in jail):
if self.__filter:
self.__filter.getOptions(self.__opts)
# Read action
for act in self.__opts["action"].split('\n'):
@@ -155,14 +141,14 @@ class JailReader(ConfigReader):
else:
action = ActionReader(
actName, self.__name, actOpt,
share_config=self.share_config, basedir=self.getBaseDir())
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, e:
except Exception as e:
logSys.error("Error in action definition " + act)
logSys.debug("Caught exception: %s" % (e,))
return False
@@ -216,10 +202,7 @@ class JailReader(ConfigReader):
elif opt == "usedns":
stream.append(["set", self.__name, "usedns", self.__opts[opt]])
elif opt == "failregex":
for regex in self.__opts[opt].split('\n'):
# Do not send a command if the rule is empty.
if regex != '':
stream.append(["set", self.__name, "addfailregex", regex])
stream.append(["set", self.__name, "addfailregex", self.__opts[opt]])
elif opt == "ignorecommand":
stream.append(["set", self.__name, "ignorecommand", self.__opts[opt]])
elif opt == "ignoreregex":
@@ -230,14 +213,14 @@ class JailReader(ConfigReader):
if self.__filter:
stream.extend(self.__filter.convert())
for action in self.__actions:
if isinstance(action, (ConfigReaderUnshared, ConfigReader)):
if isinstance(action, 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:
@@ -252,3 +235,4 @@ 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)
+3 -4
View File
@@ -68,10 +68,9 @@ class JailsReader(ConfigReader):
for sec in sections:
if sec == 'INCLUDES':
continue
# 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)
jail = JailReader(sec, basedir=self.getBaseDir(),
force_enable=self.__force_enable)
jail.read()
ret = jail.getOptions()
if ret:
if jail.isEnabled():
+14 -16
View File
@@ -44,8 +44,6 @@ protocol = [
["get loglevel", "gets the logging level"],
["set logtarget <TARGET>", "sets logging target to <TARGET>. Can be STDOUT, STDERR, SYSLOG or a file"],
["get logtarget", "gets logging target"],
["set syslogsocket auto|<SOCKET>", "sets the syslog socket path to auto or <SOCKET>. Only used if logtarget is SYSLOG"],
["get syslogsocket", "gets syslog socket path"],
["flushlogs", "flushes the logtarget if a file and reopens it. For log rotation."],
['', "DATABASE", ""],
["set dbfile <FILE>", "set the location of fail2ban persistent datastore. Set to \"None\" to disable"],
@@ -56,7 +54,7 @@ protocol = [
["add <JAIL> <BACKEND>", "creates <JAIL> using <BACKEND>"],
["start <JAIL>", "starts the jail <JAIL>"],
["stop <JAIL>", "stops the jail <JAIL>. The jail is removed"],
["status <JAIL> [FLAVOR]", "gets the current status of <JAIL>, with optional flavor or extended info"],
["status <JAIL>", "gets the current status of <JAIL>"],
['', "JAIL CONFIGURATION", ""],
["set <JAIL> idle on|off", "sets the idle state of <JAIL>"],
["set <JAIL> addignoreip <IP>", "adds <IP> to the ignore list of <JAIL>"],
@@ -130,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:
@@ -141,7 +139,7 @@ def printFormatted():
first = False
else:
line = ' ' * (INDENT + MARGIN) + n.strip()
print line
print(line)
##
# Prints the protocol in a "mediawiki" format.
@@ -151,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'''")
+36 -45
View File
@@ -27,6 +27,7 @@ from abc import ABCMeta
from collections import MutableMapping
from ..helpers import getLogger
import collections
# Gets the instance of the logger.
logSys = getLogger(__name__)
@@ -47,7 +48,7 @@ _RETCODE_HINTS = {
# Dictionary to lookup signal name from number
signame = dict((num, name)
for name, num in signal.__dict__.iteritems() if name.startswith("SIG"))
for name, num in signal.__dict__.items() if name.startswith("SIG"))
class CallingMap(MutableMapping):
"""A Mapping type which returns the result of callable values.
@@ -74,7 +75,7 @@ class CallingMap(MutableMapping):
def __getitem__(self, key):
value = self.data[key]
if callable(value):
if isinstance(value, collections.Callable):
return value()
else:
return value
@@ -94,7 +95,7 @@ class CallingMap(MutableMapping):
def copy(self):
return self.__class__(self.data.copy())
class ActionBase(object):
class ActionBase(object, metaclass=ABCMeta):
"""An abstract base class for actions in Fail2Ban.
Action Base is a base definition of what methods need to be in
@@ -124,7 +125,6 @@ class ActionBase(object):
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):
"unban",
)
for method in required:
if not callable(getattr(C, method, None)):
if not isinstance(getattr(C, method, None), collections.Callable):
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 callable(getattr(self, key)))
if not key.startswith("_") and not isinstance(getattr(self, key), collections.Callable))
@property
def actionstart(self):
@@ -362,7 +362,6 @@ class CommandAction(ActionBase):
@classmethod
def substituteRecursiveTags(cls, tags):
"""Sort out tag definitions within other tags.
Since v.0.9.2 supports embedded interpolation (see test cases for examples).
so: becomes:
a = 3 a = 3
@@ -379,46 +378,38 @@ class CommandAction(ActionBase):
Dictionary of tags(keys) and their values, with tags
within the values recursively replaced.
"""
t = re.compile(r'<([^ <>]+)>')
# repeat substitution while embedded-recursive (repFlag is True)
while True:
repFlag = False
# substitute each value:
for tag in tags.iterkeys():
if tag in cls._escapedTags:
t = re.compile(r'<([^ >]+)>')
for tag in tags.keys():
if tag in cls._escapedTags:
# Escaped so won't match
continue
value = str(tags[tag])
m = t.search(value)
done = []
#logSys.log(5, 'TAG: %s, value: %s' % (tag, value))
while m:
found_tag = m.group(1)
#logSys.log(5, 'found: %s' % found_tag)
if found_tag == tag or found_tag in done:
# recursive definitions are bad
#logSys.log(5, 'recursion fail tag: %s value: %s' % (tag, value) )
return False
elif found_tag in cls._escapedTags:
# Escaped so won't match
continue
value = str(tags[tag])
# search and replace all tags within value, that can be interpolated using other tags:
m = t.search(value)
done = []
#logSys.log(5, 'TAG: %s, value: %s' % (tag, value))
while m:
found_tag = m.group(1)
#logSys.log(5, 'found: %s' % found_tag)
if found_tag == tag or found_tag in done:
# recursive definitions are bad
#logSys.log(5, 'recursion fail tag: %s value: %s' % (tag, value) )
return False
if found_tag in cls._escapedTags or not tags.has_key(found_tag):
# Escaped or missing tags - just continue on searching after end of match
# Missing tags are ok - cInfo can contain aInfo elements like <HOST> and valid shell
else:
if found_tag in tags:
value = value.replace('<%s>' % found_tag , tags[found_tag])
#logSys.log(5, 'value now: %s' % value)
done.append(found_tag)
m = t.search(value, m.start())
else:
# Missing tags are ok so we just continue on searching.
# cInfo can contain aInfo elements like <HOST> and valid shell
# constructs like <STDIN>.
m = t.search(value, m.end())
continue
value = value.replace('<%s>' % found_tag , tags[found_tag])
#logSys.log(5, 'value now: %s' % value)
done.append(found_tag)
m = t.search(value, m.start())
#logSys.log(5, 'TAG: %s, newvalue: %s' % (tag, value))
# was substituted?
if tags[tag] != value:
# check still contains any tag - should be repeated (possible embedded-recursive substitution):
if t.search(value):
repFlag = True
tags[tag] = value
if not repFlag:
break
m = t.search(value, m.start() + 1)
#logSys.log(5, 'TAG: %s, newvalue: %s' % (tag, value))
tags[tag] = value
return tags
@staticmethod
@@ -572,7 +563,7 @@ class CommandAction(ActionBase):
os.kill(popen.pid, signal.SIGKILL) # Kill the process
time.sleep(0.1)
retcode = popen.poll()
except OSError, e:
except OSError as e:
logSys.error("%s -- failed with %s" % (realCmd, e))
finally:
_cmd_lock.release()
+16 -63
View File
@@ -213,7 +213,7 @@ class Actions(JailThread, Mapping):
bool
True when the thread exits nicely.
"""
for name, action in self._actions.iteritems():
for name, action in self._actions.items():
try:
action.start()
except Exception as e:
@@ -231,7 +231,7 @@ class Actions(JailThread, Mapping):
time.sleep(self.sleeptime)
self.__flushBan()
actions = self._actions.items()
actions = list(self._actions.items())
actions.reverse()
for name, action in actions:
try:
@@ -243,45 +243,6 @@ class Actions(JailThread, Mapping):
logSys.debug(self._jail.name + ": action terminated")
return True
def __getBansMerged(self, mi, overalljails=False):
"""Gets bans merged once, a helper for lambda(s), prevents stop of executing action by any exception inside.
This function never returns None for ainfo lambdas - always a ticket (merged or single one)
and prevents any errors through merging (to guarantee ban actions will be executed).
[TODO] move merging to observer - here we could wait for merge and read already merged info from a database
Parameters
----------
mi : dict
merge info, initial for lambda should contains {ip, ticket}
overalljails : bool
switch to get a merged bans :
False - (default) bans merged for current jail only
True - bans merged for all jails of current ip address
Returns
-------
BanTicket
merged or self ticket only
"""
idx = 'all' if overalljails else 'jail'
if idx in mi:
return mi[idx] if mi[idx] is not None else mi['ticket']
try:
jail=self._jail
ip=mi['ip']
mi[idx] = None
if overalljails:
mi[idx] = jail.database.getBansMerged(ip=ip)
else:
mi[idx] = jail.database.getBansMerged(ip=ip, jail=jail)
except Exception as e:
logSys.error(
"Failed to get %s bans merged, jail '%s': %s",
idx, jail.name, e,
exc_info=logSys.getEffectiveLevel()<=logging.DEBUG)
return mi[idx] if mi[idx] is not None else mi['ticket']
def __checkBan(self):
"""Check for IP address to ban.
@@ -303,15 +264,17 @@ class Actions(JailThread, Mapping):
aInfo["time"] = bTicket.getTime()
aInfo["matches"] = "\n".join(bTicket.getMatches())
if self._jail.database is not None:
mi4ip = lambda overalljails=False, self=self, \
mi={'ip':ip, 'ticket':bTicket}: self.__getBansMerged(mi, overalljails)
aInfo["ipmatches"] = lambda: "\n".join(mi4ip(True).getMatches())
aInfo["ipjailmatches"] = lambda: "\n".join(mi4ip().getMatches())
aInfo["ipfailures"] = lambda: mi4ip(True).getAttempt()
aInfo["ipjailfailures"] = lambda: mi4ip().getAttempt()
aInfo["ipmatches"] = lambda jail=self._jail: "\n".join(
jail.database.getBansMerged(ip=ip).getMatches())
aInfo["ipjailmatches"] = lambda jail=self._jail: "\n".join(
jail.database.getBansMerged(ip=ip, jail=jail).getMatches())
aInfo["ipfailures"] = lambda jail=self._jail: \
jail.database.getBansMerged(ip=ip).getAttempt()
aInfo["ipjailfailures"] = lambda jail=self._jail: \
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.iteritems():
for name, action in self._actions.items():
try:
action.ban(aInfo.copy())
except Exception as e:
@@ -360,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.iteritems():
for name, action in self._actions.items():
try:
action.unban(aInfo.copy())
except Exception as e:
@@ -370,21 +333,11 @@ class Actions(JailThread, Mapping):
self._jail.name, name, aInfo, e,
exc_info=logSys.getEffectiveLevel()<=logging.DEBUG)
def status(self, flavor="basic"):
"""Status of current and total ban counts and current banned IP list.
@property
def status(self):
"""Status of active bans, and total ban counts.
"""
# TODO: Allow this list to be printed as 'status' output
supported_flavors = ["basic", "cymru"]
if flavor is None or flavor not in supported_flavors:
logSys.warning("Unsupported extended jail status flavor %r. Supported: %s" % (flavor, supported_flavors))
# Always print this information (basic)
ret = [("Currently banned", self.__banManager.size()),
ret = [("Currently banned", self.__banManager.size()),
("Total banned", self.__banManager.getBanTotal()),
("Banned IP list", self.__banManager.getBanList())]
if flavor == "cymru":
cymru_info = self.__banManager.getBanListExtendedCymruInfo()
ret += \
[("Banned ASN list", self.__banManager.geBanListExtendedASN(cymru_info)),
("Banned Country list", self.__banManager.geBanListExtendedCountry(cymru_info)),
("Banned RIR list", self.__banManager.geBanListExtendedRIR(cymru_info))]
return ret
+8 -7
View File
@@ -149,12 +149,12 @@ 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, 7) and sys.version_info < (2, 8)) \
or (sys.version_info >= (3, 4)): # if python 2.7 ...
logSys.debug("Detected Python 2.7. asyncore.loop() using poll")
asyncore.loop(use_poll=True) # workaround for the "Bad file descriptor" issue on Python 2.7, gh-161
else:
asyncore.loop(use_poll=False) # fixes the "Unexpected communication problem" issue on Python 2.6 and 3.0
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)
##
# Stops the communication server.
@@ -175,11 +175,12 @@ 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.
+2 -119
View File
@@ -118,124 +118,6 @@ class BanManager:
finally:
self.__lock.release()
##
# Returns normalized value
#
# @return value or "unknown" if value is None or empty string
@staticmethod
def handleBlankResult(value):
if value is None or len(value) == 0:
return "unknown"
else:
return value
##
# Returns Cymru DNS query information
#
# @return {"asn": [], "country": [], "rir": []} dict for self.__banList IPs
def getBanListExtendedCymruInfo(self):
return_dict = {"asn": [], "country": [], "rir": []}
try:
import dns.exception
import dns.resolver
except ImportError:
logSys.error("dnspython package is required but could not be imported")
return_dict["asn"].append("error")
return_dict["country"].append("error")
return_dict["rir"].append("error")
return return_dict
self.__lock.acquire()
try:
for banData in self.__banList:
ip = banData.getIP()
# Reference: http://www.team-cymru.org/Services/ip-to-asn.html#dns
# TODO: IPv6 compatibility
reversed_ip = ".".join(reversed(ip.split(".")))
question = "%s.origin.asn.cymru.com" % reversed_ip
try:
answers = dns.resolver.query(question, "TXT")
for rdata in answers:
asn, net, country, rir, changed =\
[answer.strip("'\" ") for answer in rdata.to_text().split("|")]
asn = self.handleBlankResult(asn)
country = self.handleBlankResult(country)
rir = self.handleBlankResult(rir)
return_dict["asn"].append(self.handleBlankResult(asn))
return_dict["country"].append(self.handleBlankResult(country))
return_dict["rir"].append(self.handleBlankResult(rir))
except dns.resolver.NXDOMAIN:
return_dict["asn"].append("nxdomain")
return_dict["country"].append("nxdomain")
return_dict["rir"].append("nxdomain")
except dns.exception.DNSException as dnse:
logSys.error("Unhandled DNSException querying Cymru for %s TXT" % question)
logSys.exception(dnse)
except Exception as e:
logSys.error("Unhandled Exception querying Cymru for %s TXT" % question)
logSys.exception(e)
except Exception as e:
logSys.error("Failure looking up extended Cymru info")
logSys.exception(e)
finally:
self.__lock.release()
return return_dict
##
# Returns list of Banned ASNs from Cymru info
#
# Use getBanListExtendedCymruInfo() to provide cymru_info
#
# @return list of Banned ASNs
def geBanListExtendedASN(self, cymru_info):
self.__lock.acquire()
try:
return [asn for asn in cymru_info["asn"]]
except Exception as e:
logSys.error("Failed to lookup ASN")
logSys.exception(e)
return []
finally:
self.__lock.release()
##
# Returns list of Banned Countries from Cymru info
#
# Use getBanListExtendedCymruInfo() to provide cymru_info
#
# @return list of Banned Countries
def geBanListExtendedCountry(self, cymru_info):
self.__lock.acquire()
try:
return [country for country in cymru_info["country"]]
except Exception as e:
logSys.error("Failed to lookup Country")
logSys.exception(e)
return []
finally:
self.__lock.release()
##
# Returns list of Banned RIRs from Cymru info
#
# Use getBanListExtendedCymruInfo() to provide cymru_info
#
# @return list of Banned RIRs
def geBanListExtendedRIR(self, cymru_info):
self.__lock.acquire()
try:
return [rir for rir in cymru_info["rir"]]
except Exception as e:
logSys.error("Failed to lookup RIR")
logSys.exception(e)
return []
finally:
self.__lock.release()
##
# Create a ban ticket.
#
@@ -244,7 +126,7 @@ class BanManager:
# @param ticket the FailTicket
# @return a BanTicket
@staticmethod
#@staticmethod
def createBanTicket(ticket):
ip = ticket.getIP()
#lastTime = ticket.getTime()
@@ -252,6 +134,7 @@ class BanManager:
banTicket = BanTicket(ip, lastTime, ticket.getMatches())
banTicket.setAttempt(ticket.getAttempt())
return banTicket
createBanTicket = staticmethod(createBanTicket)
##
# Add a ban ticket.
+47 -86
View File
@@ -27,7 +27,7 @@ import sqlite3
import json
import locale
from functools import wraps
from threading import RLock
from threading import Lock
from .mytime import MyTime
from .ticket import FailTicket
@@ -37,51 +37,17 @@ from ..helpers import getLogger
logSys = getLogger(__name__)
if sys.version_info >= (3,):
def _json_dumps_safe(x):
try:
x = json.dumps(x, ensure_ascii=False).encode(
locale.getpreferredencoding(), 'replace')
except Exception, e: # pragma: no cover
logSys.error('json dumps failed: %s', e)
x = '{}'
return x
def _json_loads_safe(x):
try:
x = json.loads(x.decode(
locale.getpreferredencoding(), 'replace'))
except Exception, e: # pragma: no cover
logSys.error('json loads failed: %s', e)
x = {}
return x
sqlite3.register_adapter(
dict,
lambda x: json.dumps(x, ensure_ascii=False).encode(
locale.getpreferredencoding(), 'replace'))
sqlite3.register_converter(
"JSON",
lambda x: json.loads(x.decode(
locale.getpreferredencoding(), 'replace')))
else:
def _normalize(x):
if isinstance(x, dict):
return dict((_normalize(k), _normalize(v)) for k, v in x.iteritems())
elif isinstance(x, list):
return [_normalize(element) for element in x]
elif isinstance(x, unicode):
return x.encode(locale.getpreferredencoding())
else:
return x
def _json_dumps_safe(x):
try:
x = json.dumps(_normalize(x), ensure_ascii=False).decode(
locale.getpreferredencoding(), 'replace')
except Exception, e: # pragma: no cover
logSys.error('json dumps failed: %s', e)
x = '{}'
return x
def _json_loads_safe(x):
try:
x = _normalize(json.loads(x.decode(
locale.getpreferredencoding(), 'replace')))
except Exception, e: # pragma: no cover
logSys.error('json loads failed: %s', e)
x = {}
return x
sqlite3.register_adapter(dict, _json_dumps_safe)
sqlite3.register_converter("JSON", _json_loads_safe)
sqlite3.register_adapter(dict, json.dumps)
sqlite3.register_converter("JSON", json.loads)
def commitandrollback(f):
@wraps(f)
@@ -157,7 +123,7 @@ class Fail2BanDb(object):
def __init__(self, filename, purgeAge=24*60*60):
try:
self._lock = RLock()
self._lock = Lock()
self._db = sqlite3.connect(
filename, check_same_thread=False,
detect_types=sqlite3.PARSE_DECLTYPES)
@@ -168,7 +134,7 @@ class Fail2BanDb(object):
logSys.info(
"Connected to fail2ban persistent database '%s'", filename)
except sqlite3.OperationalError, e:
except sqlite3.OperationalError as e:
logSys.error(
"Error connecting to fail2ban persistent database '%s': %s",
filename, e.args[0])
@@ -399,16 +365,12 @@ class Fail2BanDb(object):
del self._bansMergedCache[(ticket.getIP(), jail)]
except KeyError:
pass
try:
del self._bansMergedCache[(ticket.getIP(), None)]
except KeyError:
pass
#TODO: Implement data parts once arbitrary match keys completed
cur.execute(
"INSERT INTO bans(jail, ip, timeofban, data) VALUES(?, ?, ?, ?)",
(jail.name, ticket.getIP(), int(round(ticket.getTime())),
{"matches": ticket.getMatches(),
"failures": ticket.getAttempt()}))
"failures": ticket.getAttempt()}))
@commitandrollback
def delBan(self, cur, jail, ticket):
@@ -465,8 +427,8 @@ class Fail2BanDb(object):
tickets = []
for ip, timeofban, data in self._getBans(**kwargs):
#TODO: Implement data parts once arbitrary match keys completed
tickets.append(FailTicket(ip, timeofban, data.get('matches')))
tickets[-1].setAttempt(data.get('failures', 1))
tickets.append(FailTicket(ip, timeofban, data['matches']))
tickets[-1].setAttempt(data['failures'])
return tickets
def getBansMerged(self, ip=None, jail=None, bantime=None):
@@ -493,41 +455,40 @@ class Fail2BanDb(object):
in a list. When `ip` argument passed, a single `Ticket` is
returned.
"""
with self._lock:
cacheKey = None
if bantime is None or bantime < 0:
cacheKey = (ip, jail)
if cacheKey in self._bansMergedCache:
return self._bansMergedCache[cacheKey]
cacheKey = None
if bantime is None or bantime < 0:
cacheKey = (ip, jail)
if cacheKey in self._bansMergedCache:
return self._bansMergedCache[cacheKey]
tickets = []
ticket = None
tickets = []
ticket = None
results = list(self._getBans(ip=ip, jail=jail, bantime=bantime))
if results:
prev_banip = results[0][0]
matches = []
failures = 0
for banip, timeofban, data in results:
#TODO: Implement data parts once arbitrary match keys completed
if banip != prev_banip:
ticket = FailTicket(prev_banip, prev_timeofban, matches)
ticket.setAttempt(failures)
tickets.append(ticket)
# Reset variables
prev_banip = banip
matches = []
failures = 0
matches.extend(data.get('matches', []))
failures += data.get('failures', 1)
prev_timeofban = timeofban
ticket = FailTicket(banip, prev_timeofban, matches)
ticket.setAttempt(failures)
tickets.append(ticket)
results = list(self._getBans(ip=ip, jail=jail, bantime=bantime))
if results:
prev_banip = results[0][0]
matches = []
failures = 0
for banip, timeofban, data in results:
#TODO: Implement data parts once arbitrary match keys completed
if banip != prev_banip:
ticket = FailTicket(prev_banip, prev_timeofban, matches)
ticket.setAttempt(failures)
tickets.append(ticket)
# Reset variables
prev_banip = banip
matches = []
failures = 0
matches.extend(data['matches'])
failures += data['failures']
prev_timeofban = timeofban
ticket = FailTicket(banip, prev_timeofban, matches)
ticket.setAttempt(failures)
tickets.append(ticket)
if cacheKey:
self._bansMergedCache[cacheKey] = tickets if ip is None else ticket
return tickets if ip is None else ticket
if cacheKey:
self._bansMergedCache[cacheKey] = tickets if ip is None else ticket
return tickets if ip is None else ticket
@commitandrollback
def purge(self, cur):
+2 -2
View File
@@ -168,7 +168,7 @@ class DatePatternRegex(DateTemplate):
regex
pattern
"""
_patternRE = r"%%(%%|[%s])" % "".join(timeRE.keys())
_patternRE = r"%%(%%|[%s])" % "".join(list(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().iteritems()
for key, value in dateMatch.groupdict().items()
if value is not None)
return reGroupDictStrptime(groupdict), dateMatch

Some files were not shown because too many files have changed in this diff Show More