mirror of https://github.com/fail2ban/fail2ban
Merge remote-tracking branch 'upstream/master' into ban-time-incr
Conflicts resolved: fail2ban/server/database.py fail2ban/tests/servertestcase.py delBan modified (if manually unban): delete from "bips" also (bad ips) delete all tickets of this ip, also if currently not bannedpull/716/head
commit
62c755c1d5
|
@ -8,3 +8,4 @@ htmlcov
|
|||
*.rej
|
||||
*.bak
|
||||
__pycache__
|
||||
.vagrant/
|
||||
|
|
|
@ -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:
|
37
ChangeLog
37
ChangeLog
|
@ -4,9 +4,22 @@
|
|||
|_| \__,_|_|_/___|_.__/\__,_|_||_|
|
||||
|
||||
================================================================================
|
||||
Fail2Ban (version 0.9.0.dev) 2014/xx/xx
|
||||
Fail2Ban (version 0.9.2.dev) 2014/xx/xx
|
||||
================================================================================
|
||||
|
||||
ver. 0.9.2 (2014/xx/xx) - increment ban time
|
||||
----------
|
||||
|
||||
- New features:
|
||||
- increment ban time (+ observer) functionality introduced.
|
||||
Thanks Serg G. Brester (sebres)
|
||||
|
||||
- Fixes:
|
||||
- purge database will be executed now (within observer).
|
||||
- database functionality extended with bad ips.
|
||||
- restoring currently banned ip after service restart fixed
|
||||
(now < timeofban + bantime), ignore old log failures (already banned)
|
||||
|
||||
ver. 0.9.1 (2014/xx/xx) - better, faster, stronger
|
||||
----------
|
||||
|
||||
|
@ -37,18 +50,38 @@ ver. 0.9.1 (2014/xx/xx) - better, faster, stronger
|
|||
* Correct times for non-timezone date times formats during DST
|
||||
Thanks Serg G. Brester (sebres)
|
||||
* Pass a copy of, not original, aInfo into actions to avoid side-effects
|
||||
* Per-distribution paths to the exim's main log
|
||||
* Ignored IPs are no longer banned when being restored from persistent
|
||||
database
|
||||
* Manually unbanned IPs are now removed from persistent database, such they
|
||||
wont be banned again when Fail2Ban is restarted
|
||||
* Pass "bantime" parameter to the actions in default jail's action
|
||||
definition(s)
|
||||
* filters.d/sieve.conf - fixed typo in _daemon. Thanks Jisoo Park
|
||||
* cyrus-imap -- also catch also failed logins via secured (imaps/pop3s).
|
||||
Regression was introduced while strengthening failregex in 0.8.11 (bd175f)
|
||||
Debian bug #755173
|
||||
* postfix-sasl -- added journalmatch. Thanks Luc Maisonobe
|
||||
|
||||
- New features:
|
||||
- Added monit filter thanks Jason H Martin.
|
||||
- Added
|
||||
- monit filter. Thanks Jason H Martin
|
||||
- directadmin filter. Thanks niorg
|
||||
- fail2ban-client can fetch the running server version
|
||||
- Added Cloudflare API action
|
||||
|
||||
- Enhancements
|
||||
* Fail2ban-regex - add print-all-matched option. Closes gh-652
|
||||
* Suppress fail2ban-client warnings for non-critical config options
|
||||
* Match non "Bye Bye" disconnect messages for sshd locked account regex
|
||||
* courier-smtp filter:
|
||||
- match lines with user names
|
||||
- match lines containing "535 Authentication failed" attempts
|
||||
* Add <chain> tag to iptables-ipsets
|
||||
* Realign fail2ban log output with white space to improve readability. Does
|
||||
not affect SYSLOG output
|
||||
* Log unhandled exceptions
|
||||
* cyrus-imap: catch "user not found" attempts
|
||||
|
||||
ver. 0.9.0 (2014/03/14) - beta
|
||||
----------
|
||||
|
|
4
THANKS
4
THANKS
|
@ -49,6 +49,7 @@ John Thoe
|
|||
Jacques Lav!gnotte
|
||||
Ioan Indreias
|
||||
Jason H Martin
|
||||
Jisoo Park
|
||||
Joel M Snyder
|
||||
Jonathan Kamens
|
||||
Jonathan Lanning
|
||||
|
@ -62,6 +63,7 @@ kjohnsonecl
|
|||
kojiro
|
||||
Lars Kneschke
|
||||
Lee Clemens
|
||||
leftyfb (Mike Rushton)
|
||||
Manuel Arostegui Ramirez
|
||||
Marcel Dopita
|
||||
Mark Edgington
|
||||
|
@ -80,6 +82,7 @@ onorua
|
|||
Paul Marrapese
|
||||
Noel Butler
|
||||
Patrick Börjesson
|
||||
Pressy
|
||||
Raphaël Marichez
|
||||
RealRancor
|
||||
René Berber
|
||||
|
@ -88,6 +91,7 @@ Rolf Fokkens
|
|||
Roman Gelfand
|
||||
Russell Odom
|
||||
SATO Kentaro
|
||||
Sean DuBois
|
||||
Sebastian Arcus
|
||||
Serg G. Brester (sebres)
|
||||
Sireyessire
|
||||
|
|
|
@ -0,0 +1,30 @@
|
|||
Vagrant.configure("2") do |config|
|
||||
|
||||
config.vm.define "secure" do |secure|
|
||||
secure.vm.box = "ubuntu/trusty64"
|
||||
secure.vm.hostname = "secure.dev.fail2ban.org"
|
||||
secure.vm.network "private_network", ip: "192.168.200.100"
|
||||
|
||||
# secure.vm.synced_folder 'salt/roots', '/srv/salt'
|
||||
|
||||
# secure.vm.provision :salt do |salt|
|
||||
# salt.minion_config = 'salt/minion'
|
||||
# salt.run_highstate = true
|
||||
# salt.verbose = true
|
||||
# end
|
||||
end
|
||||
|
||||
config.vm.define "attacker" do |attacker|
|
||||
attacker.vm.box = "ubuntu/trusty64"
|
||||
attacker.vm.hostname = "attacker.dev.fail2ban.org"
|
||||
attacker.vm.network "private_network", ip: "192.168.200.150"
|
||||
|
||||
# attacker.vm.synced_folder 'salt/roots', '/srv/salt'
|
||||
|
||||
# attacker.vm.provision :salt do |salt|
|
||||
# salt.minion_config = 'salt/minion'
|
||||
# salt.run_highstate = true
|
||||
# salt.verbose = true
|
||||
# end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,55 @@
|
|||
#
|
||||
# Author: Mike Rushton
|
||||
#
|
||||
# Referenced from from http://www.normyee.net/blog/2012/02/02/adding-cloudflare-support-to-fail2ban by NORM YEE
|
||||
#
|
||||
# To get your Cloudflare API key: https://www.cloudflare.com/my-account
|
||||
#
|
||||
|
||||
[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: <ip> IP address
|
||||
# <failures> number of failures
|
||||
# <time> unix timestamp of the ban time
|
||||
# Values: CMD
|
||||
#
|
||||
actionban = curl https://www.cloudflare.com/api_json.html -d 'a=ban' -d 'tkn=<cftoken>' -d 'email=<cfuser>' -d 'key=<ip>'
|
||||
# Option: actionunban
|
||||
# Notes.: command executed when unbanning an IP. Take care that the
|
||||
# command is executed with Fail2Ban user rights.
|
||||
# Tags: <ip> IP address
|
||||
# <failures> number of failures
|
||||
# <time> unix timestamp of the ban time
|
||||
# Values: CMD
|
||||
#
|
||||
actionunban = curl https://www.cloudflare.com/api_json.html -d 'a=nul' -d 'tkn=<cftoken>' -d 'email=<cfuser>' -d 'key=<ip>'
|
||||
|
||||
|
||||
[Init]
|
||||
|
||||
# Default Cloudflare API token
|
||||
cftoken =
|
||||
|
||||
# Default Cloudflare username
|
||||
cfuser =
|
|
@ -1,9 +1,9 @@
|
|||
# Fail2Ban action configuration file for ufw
|
||||
#
|
||||
# You are required to run "ufw enable" before this will have an effect.
|
||||
# You are required to run "ufw enable" before this will have any effect.
|
||||
#
|
||||
# The insert position should be approprate to block the required traffic.
|
||||
# A number after an allow rule to the application won't be much use.
|
||||
# The insert position should be appropriate to block the required traffic.
|
||||
# A number after an allow rule to the application won't be of much use.
|
||||
|
||||
[Definition]
|
||||
|
||||
|
@ -19,7 +19,7 @@ actionunban = [ -n "<application>" ] && app="app <application>" ; ufw delete <bl
|
|||
|
||||
[Init]
|
||||
# Option: insertpos
|
||||
# Notes.: The postition number in the firewall list to insert the block rule
|
||||
# Notes.: The position number in the firewall list to insert the block rule
|
||||
insertpos = 1
|
||||
|
||||
# Option: blocktype
|
||||
|
|
|
@ -12,7 +12,8 @@ before = common.conf
|
|||
|
||||
_daemon = courieresmtpd
|
||||
|
||||
failregex = ^%(__prefix_line)serror,relay=<HOST>,.*: 550 User unknown\.$
|
||||
failregex = ^%(__prefix_line)serror,relay=<HOST>,.*: 550 User (<.*> )?unknown\.?$
|
||||
^%(__prefix_line)serror,relay=<HOST>,msg="535 Authentication failed\.",cmd:( AUTH \S+)?( [0-9a-zA-Z\+/=]+)?$
|
||||
|
||||
ignoreregex =
|
||||
|
||||
|
|
|
@ -11,9 +11,9 @@ before = common.conf
|
|||
|
||||
[Definition]
|
||||
|
||||
_daemon = (?:cyrus/)?(?:imapd?|pop3d?)
|
||||
_daemon = (?:cyrus/)?(?:imap(d|s)?|pop3(d|s)?)
|
||||
|
||||
failregex = ^%(__prefix_line)sbadlogin: \S+ ?\[<HOST>\] \S+ .*?\[?SASL\(-13\): authentication failure: .*\]?$
|
||||
failregex = ^%(__prefix_line)sbadlogin: \S+ ?\[<HOST>\] \S+ .*?\[?SASL\(-13\): (authentication failure|user not found): .*\]?$
|
||||
|
||||
ignoreregex =
|
||||
|
||||
|
|
|
@ -0,0 +1,23 @@
|
|||
# Fail2Ban configuration file for Directadmin
|
||||
#
|
||||
#
|
||||
#
|
||||
|
||||
[INCLUDES]
|
||||
|
||||
before = common.conf
|
||||
|
||||
[Definition]
|
||||
|
||||
failregex = ^: \'<HOST>\' \d{1,3} failed login attempt(s)?. \s*
|
||||
|
||||
ignoreregex =
|
||||
|
||||
[Init]
|
||||
datepattern = ^%%Y:%%m:%%d-%%H:%%M:%%S
|
||||
|
||||
#
|
||||
# Requires Directadmin v1.45.3 or higher. http://www.directadmin.com/features.php?id=1590
|
||||
#
|
||||
# Author: Cyril Roos
|
||||
|
|
@ -11,4 +11,9 @@ _daemon = postfix/smtpd
|
|||
|
||||
failregex = ^%(__prefix_line)swarning: [-._\w]+\[<HOST>\]: SASL (?:LOGIN|PLAIN|(?:CRAM|DIGEST)-MD5) authentication failed(: [ A-Za-z0-9+/]*={0,2})?\s*$
|
||||
|
||||
[Init]
|
||||
|
||||
journalmatch = _SYSTEMD_UNIT=postfix.service
|
||||
|
||||
|
||||
# Author: Yaroslav Halchenko
|
||||
|
|
|
@ -9,7 +9,7 @@ before = common.conf
|
|||
|
||||
[Definition]
|
||||
|
||||
_deamon = (?:cyrus/)?(?:tim)?sieved?
|
||||
_daemon = (?:cyrus/)?(?:tim)?sieved?
|
||||
|
||||
failregex = ^%(__prefix_line)sbadlogin: \S+ ?\[<HOST>\] \S+ authentication failure$
|
||||
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
#
|
||||
# YOU SHOULD NOT MODIFY THIS FILE.
|
||||
#
|
||||
# It will probably be overwitten or improved in a distribution update.
|
||||
# It will probably be overwritten or improved in a distribution update.
|
||||
#
|
||||
# Provide customizations in a jail.local file or a jail.d/customisation.local.
|
||||
# For example to change the default bantime for all jails and to enable the
|
||||
|
@ -189,22 +189,22 @@ port = 0:65535
|
|||
banaction = iptables-multiport
|
||||
|
||||
# The simplest action to take: ban only
|
||||
action_ = %(banaction)s[name=%(__name__)s, port="%(port)s", protocol="%(protocol)s", chain="%(chain)s"]
|
||||
action_ = %(banaction)s[name=%(__name__)s, bantime="%(bantime)s", port="%(port)s", protocol="%(protocol)s", chain="%(chain)s"]
|
||||
|
||||
# ban & send an e-mail with whois report to the destemail.
|
||||
action_mw = %(banaction)s[name=%(__name__)s, port="%(port)s", protocol="%(protocol)s", chain="%(chain)s"]
|
||||
action_mw = %(banaction)s[name=%(__name__)s, bantime="%(bantime)s", port="%(port)s", protocol="%(protocol)s", chain="%(chain)s"]
|
||||
%(mta)s-whois[name=%(__name__)s, dest="%(destemail)s", protocol="%(protocol)s", chain="%(chain)s"]
|
||||
|
||||
# ban & send an e-mail with whois report and relevant log lines
|
||||
# to the destemail.
|
||||
action_mwl = %(banaction)s[name=%(__name__)s, port="%(port)s", protocol="%(protocol)s", chain="%(chain)s"]
|
||||
action_mwl = %(banaction)s[name=%(__name__)s, bantime="%(bantime)s", port="%(port)s", protocol="%(protocol)s", chain="%(chain)s"]
|
||||
%(mta)s-whois-lines[name=%(__name__)s, dest="%(destemail)s", logpath=%(logpath)s, chain="%(chain)s"]
|
||||
|
||||
# See the IMPORTANT note in action.d/xarf-login-attack for when to use this action
|
||||
#
|
||||
# ban & send a xarf e-mail to abuse contact of IP address and include relevant log lines
|
||||
# to the destemail.
|
||||
action_xarf = %(banaction)s[name=%(__name__)s, port="%(port)s", protocol="%(protocol)s", chain="%(chain)s"]
|
||||
action_xarf = %(banaction)s[name=%(__name__)s, bantime="%(bantime)s", port="%(port)s", protocol="%(protocol)s", chain="%(chain)s"]
|
||||
xarf-login-attack[service=%(__name__)s, sender="%(sender)s", logpath=%(logpath)s, port="%(port)s"]
|
||||
|
||||
|
||||
|
@ -539,13 +539,13 @@ logpath = %(solidpop3d_log)s
|
|||
[exim]
|
||||
|
||||
port = smtp,465,submission
|
||||
logpath = /var/log/exim/mainlog
|
||||
logpath = %(exim_main_log)s
|
||||
|
||||
|
||||
[exim-spam]
|
||||
|
||||
port = smtp,465,submission
|
||||
logpath = /var/log/exim/mainlog
|
||||
logpath = %(exim_main_log)s
|
||||
|
||||
|
||||
[kerio]
|
||||
|
@ -747,3 +747,8 @@ enabled = false
|
|||
logpath = /opt/sun/comms/messaging64/log/mail.log_current
|
||||
maxretry = 6
|
||||
banaction = iptables-allports
|
||||
|
||||
[directadmin]
|
||||
enabled = false
|
||||
logpath = /var/log/directadmin/login.log
|
||||
port = 2222
|
||||
|
|
|
@ -12,7 +12,7 @@ sshd_log = %(syslog_authpriv)s
|
|||
dropbear_log = %(syslog_authpriv)s
|
||||
|
||||
# There is no sensible generic defaults for syslog log targets, thus
|
||||
# leaving them empty here so that no errors while parsing/interpollatin configs
|
||||
# leaving them empty here so that no errors while parsing/interpolating configs
|
||||
syslog_daemon =
|
||||
syslog_ftp =
|
||||
syslog_local0 =
|
||||
|
@ -22,6 +22,7 @@ syslog_user =
|
|||
# from /etc/audit/auditd.conf
|
||||
auditd_log = /var/log/audit/audit.log
|
||||
|
||||
exim_main_log = /var/log/exim/mainlog
|
||||
|
||||
nginx_error_log = /var/log/nginx/error.log
|
||||
|
||||
|
|
|
@ -30,6 +30,7 @@ apache_error_log = /var/log/apache2/*error.log
|
|||
|
||||
apache_access_log = /var/log/apache2/*access.log
|
||||
|
||||
exim_main_log = /var/log/exim4/mainlog
|
||||
|
||||
# was in debian squeezy but not in wheezy
|
||||
# /etc/proftpd/proftpd.conf (SystemLog)
|
||||
|
|
|
@ -32,4 +32,6 @@ apache_access_log = /var/log/httpd/*access_log
|
|||
# proftpd_log = /var/log/proftpd/auth.log
|
||||
# Tested and it worked out in /var/log/messages so assuming syslog_ftp for now.
|
||||
|
||||
exim_main_log = /var/log/exim/main.log
|
||||
|
||||
mysql_log = /var/lib/mysql/mysqld.log
|
||||
|
|
|
@ -51,6 +51,8 @@ class Beautifier:
|
|||
try:
|
||||
if inC[0] == "ping":
|
||||
msg = "Server replied: " + response
|
||||
elif inC[0] == "version":
|
||||
msg = response
|
||||
elif inC[0] == "start":
|
||||
msg = "Jail started"
|
||||
elif inC[0] == "stop":
|
||||
|
|
|
@ -38,6 +38,7 @@ protocol = [
|
|||
["status", "gets the current status of the server"],
|
||||
["ping", "tests if the server is alive"],
|
||||
["help", "return this output"],
|
||||
["version", "return the server version"],
|
||||
['', "LOGGING", ""],
|
||||
["set loglevel <LEVEL>", "sets logging level to <LEVEL>. Levels: CRITICAL, ERROR, WARNING, NOTICE, INFO, DEBUG"],
|
||||
["get loglevel", "gets the logging level"],
|
||||
|
|
|
@ -194,6 +194,9 @@ class Actions(JailThread, Mapping):
|
|||
ValueError
|
||||
If `ip` is not banned
|
||||
"""
|
||||
# Always delete ip from database (also if currently not banned)
|
||||
if self._jail.database is not None:
|
||||
self._jail.database.delBan(self._jail, ip)
|
||||
# Find the ticket with the IP.
|
||||
ticket = self.__banManager.getTicketByIP(ip)
|
||||
if ticket is not None:
|
||||
|
|
|
@ -400,15 +400,34 @@ class Fail2BanDb(object):
|
|||
#TODO: Implement data parts once arbitrary match keys completed
|
||||
cur.execute(
|
||||
"INSERT INTO bans(jail, ip, timeofban, bantime, bancount, data) VALUES(?, ?, ?, ?, ?, ?)",
|
||||
(jail.name, ticket.getIP(), ticket.getTime(), ticket.getBanTime(jail.actions.getBanTime()), ticket.getBanCount(),
|
||||
(jail.name, ticket.getIP(), int(round(ticket.getTime())), ticket.getBanTime(jail.actions.getBanTime()), ticket.getBanCount(),
|
||||
{"matches": ticket.getMatches(),
|
||||
"failures": ticket.getAttempt()}))
|
||||
cur.execute(
|
||||
"INSERT OR REPLACE INTO bips(ip, jail, timeofban, bantime, bancount, data) VALUES(?, ?, ?, ?, ?, ?)",
|
||||
(ticket.getIP(), jail.name, ticket.getTime(), ticket.getBanTime(jail.actions.getBanTime()), ticket.getBanCount(),
|
||||
(ticket.getIP(), jail.name, int(round(ticket.getTime())), ticket.getBanTime(jail.actions.getBanTime()), ticket.getBanCount(),
|
||||
{"matches": ticket.getMatches(),
|
||||
"failures": ticket.getAttempt()}))
|
||||
|
||||
@commitandrollback
|
||||
def delBan(self, cur, jail, ip):
|
||||
"""Delete a ban from the database.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
jail : Jail
|
||||
Jail in which the ban has occurred.
|
||||
ticket : BanTicket
|
||||
Ticket of the ban to be removed.
|
||||
"""
|
||||
queryArgs = (jail.name, ip);
|
||||
cur.execute(
|
||||
"DELETE FROM bips WHERE jail = ? AND ip = ?",
|
||||
queryArgs)
|
||||
cur.execute(
|
||||
"DELETE FROM bans WHERE jail = ? AND ip = ?",
|
||||
queryArgs);
|
||||
|
||||
@commitandrollback
|
||||
def _getBans(self, cur, jail=None, bantime=None, ip=None):
|
||||
query = "SELECT ip, timeofban, data FROM bans WHERE 1"
|
||||
|
|
|
@ -28,6 +28,7 @@ import time
|
|||
import json
|
||||
|
||||
from ..helpers import getLogger
|
||||
from .. import version
|
||||
|
||||
# Gets the instance of the logger.
|
||||
logSys = getLogger(__name__)
|
||||
|
@ -102,7 +103,9 @@ class Transmitter:
|
|||
elif command[0] == "get":
|
||||
return self.__commandGet(command[1:])
|
||||
elif command[0] == "status":
|
||||
return self.status(command[1:])
|
||||
return self.status(command[1:])
|
||||
elif command[0] == "version":
|
||||
return version.version
|
||||
raise Exception("Invalid command")
|
||||
|
||||
def __commandSet(self, command):
|
||||
|
|
|
@ -173,6 +173,12 @@ class DatabaseTest(unittest.TestCase):
|
|||
self.assertTrue(
|
||||
isinstance(self.db.getBans(jail=self.jail)[0], FailTicket))
|
||||
|
||||
def testDelBan(self):
|
||||
self.testAddBan()
|
||||
ticket = self.db.getBans(jail=self.jail)[0]
|
||||
self.db.delBan(self.jail, ticket.getIP())
|
||||
self.assertEqual(len(self.db.getBans(jail=self.jail)), 0)
|
||||
|
||||
def testGetBansWithTime(self):
|
||||
if Fail2BanDb is None: # pragma: no cover
|
||||
return
|
||||
|
|
|
@ -1,5 +1,9 @@
|
|||
# failJSON: { "time": "2005-04-10T03:47:57", "match": true , "host": "1.2.3.4" }
|
||||
Apr 10 03:47:57 web courieresmtpd: error,relay=::ffff:1.2.3.4,ident=tmf,from=<tmf@example.com>,to=<mailman-subscribe@example.com>: 550 User unknown.
|
||||
# failJSON: { "time": "2005-07-03T23:07:20", "match": true , "host": "1.2.3.4" }
|
||||
Jul 3 23:07:20 szerver courieresmtpd: error,relay=::ffff:1.2.3.4,msg="535 Authentication failed.",cmd: YWRvYmVhZG9iZQ==
|
||||
# failJSON: { "time": "2005-07-04T18:39:39", "match": true , "host": "1.2.3.4" }
|
||||
Jul 4 18:39:39 mail courieresmtpd: error,relay=::ffff:1.2.3.4,from=<picaro@astroboymail.com>,to=<user@update.net>: 550 User <benny> unknown
|
||||
# failJSON: { "time": "2005-07-06T03:42:28", "match": true , "host": "1.2.3.4" }
|
||||
Jul 6 03:42:28 whistler courieresmtpd: error,relay=::ffff:1.2.3.4,from=<>,to=<admin at memcpy>: 550 User unknown.
|
||||
# failJSON: { "time": "2004-11-21T23:16:17", "match": true , "host": "1.2.3.4" }
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
# failJSON: { "time": "2005-01-04T21:51:05", "match": true , "host": "127.0.0.1" }
|
||||
Jan 4 21:51:05 hostname cyrus/imap[5355]: badlogin: localhost.localdomain [127.0.0.1] plaintext cyrus@localdomain SASL(-13): authentication failure: checkpass failed
|
||||
# failJSON: { "time": "2005-01-04T21:51:05", "match": true , "host": "127.0.0.1", "desc": "For secure imaps" }
|
||||
Jan 4 21:51:05 hostname cyrus/imaps[5355]: badlogin: localhost.localdomain [127.0.0.1] plaintext cyrus@localdomain SASL(-13): authentication failure: checkpass failed
|
||||
# failJSON: { "time": "2005-02-20T17:23:32", "match": true , "host": "198.51.100.23" }
|
||||
Feb 20 17:23:32 domain cyrus/pop3[18635]: badlogin: localhost [198.51.100.23] plaintext administrator SASL(-13): authentication failure: checkpass failed
|
||||
# failJSON: { "time": "2005-02-20T17:23:32", "match": true , "host": "1.2.3.4" }
|
||||
|
@ -10,4 +12,7 @@ Jun 8 18:11:13 lampserver imap[4480]: badlogin: example.com [198.51.100.45] DIGE
|
|||
Dec 21 10:01:57 hostname imapd[18454]: badlogin: example.com [198.51.100.57] CRAM-MD5 [SASL(-13): authentication failure: incorrect digest response]
|
||||
# failJSON: { "time": "2004-12-30T16:03:27", "match": true , "host": "1.2.3.4" }
|
||||
Dec 30 16:03:27 somehost imapd[2517]: badlogin: local-somehost[1.2.3.4] OTP [SASL(-13): authentication failure: External SSF not good enough]
|
||||
|
||||
# failJSON: { "time": "2005-07-17T22:55:56", "match": true , "host": "1.2.3.4" }
|
||||
Jul 17 22:55:56 derry cyrus/imaps[7568]: badlogin: serafinat.xxxxxx [1.2.3.4] plain [SASL(-13): user not found: user: pressy@derry property: cmusaslsecretPLAIN not found in sasldb]
|
||||
# failJSON: { "time": "2005-07-18T16:46:42", "match": true , "host": "1.2.3.4" }
|
||||
Jul 18 16:46:42 derry cyrus/imaps[27449]: badlogin: serafinat.xxxxxx [1.2.3.4] PLAIN [SASL(-13): user not found: Password verification failed]
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
# failJSON: { "time": "2014-07-02T00:17:45", "match": true , "host": "3.2.1.4" }
|
||||
2014:07:02-00:17:45: '3.2.1.4' 2 failed login attempts. Account 'test'
|
||||
|
||||
# failJSON: { "time": "2014-07-02T13:07:40", "match": true , "host": "40.40.123.231" }
|
||||
2014:07:02-13:07:40: '40.40.123.231' 13 failed login attempts. Account 'admin'
|
||||
|
||||
# failJSON: { "time": "2014-07-02T13:07:50", "match": true , "host": "40.40.123.231" }
|
||||
2014:07:02-13:07:50: '40.40.123.231' 5 failed login attempt. Invalid account 'user%2Ename'
|
||||
|
||||
# failJSON: { "time": "2014-07-02T13:28:39", "match": false , "host": "12.12.123.231" }
|
||||
2014:07:02-13:28:39: '12.12.123.231' successful login to 'nobody' after 1 attempts
|
||||
|
||||
# failJSON: { "time": "2014-07-02T13:29:38", "match": true , "host": "1.2.3.4" }
|
||||
2014:07:02-13:29:38: '1.2.3.4' 2 failed login attempts. Account 'user' via 'admin'
|
|
@ -24,6 +24,7 @@ __license__ = "GPL"
|
|||
|
||||
from __builtin__ import open as fopen
|
||||
import unittest
|
||||
import getpass
|
||||
import os
|
||||
import sys
|
||||
import time
|
||||
|
@ -349,10 +350,20 @@ class LogFileMonitor(LogCaptureTestCase):
|
|||
# shorter wait time for not modified status
|
||||
return not self.isModified(0.4)
|
||||
|
||||
def testNoLogFile(self):
|
||||
def testUnaccessibleLogFile(self):
|
||||
os.chmod(self.name, 0)
|
||||
self.filter.getFailures(self.name)
|
||||
self.assertTrue(self._is_logged('Unable to open %s' % self.name))
|
||||
failure_was_logged = self._is_logged('Unable to open %s' % self.name)
|
||||
is_root = getpass.getuser() == 'root'
|
||||
# If ran as root, those restrictive permissions would not
|
||||
# forbid log to be read.
|
||||
self.assertTrue(failure_was_logged != is_root)
|
||||
|
||||
def testNoLogFile(self):
|
||||
_killfile(self.file, self.name)
|
||||
self.filter.getFailures(self.name)
|
||||
failure_was_logged = self._is_logged('Unable to open %s' % self.name)
|
||||
self.assertTrue(failure_was_logged)
|
||||
|
||||
def testRemovingFailRegex(self):
|
||||
self.filter.delFailRegex(0)
|
||||
|
|
|
@ -37,6 +37,7 @@ from ..server.jail import Jail
|
|||
from ..server.jailthread import JailThread
|
||||
from .utils import LogCaptureTestCase
|
||||
from ..helpers import getLogger
|
||||
from .. import version
|
||||
|
||||
try:
|
||||
from ..server import filtersystemd
|
||||
|
@ -148,6 +149,9 @@ class Transmitter(TransmitterBase):
|
|||
def testPing(self):
|
||||
self.assertEqual(self.transm.proceed(["ping"]), (0, "pong"))
|
||||
|
||||
def testVersion(self):
|
||||
self.assertEqual(self.transm.proceed(["version"]), (0, version.version))
|
||||
|
||||
def testSleep(self):
|
||||
t0 = time.time()
|
||||
self.assertEqual(self.transm.proceed(["sleep", "1"]), (0, None))
|
||||
|
|
|
@ -71,6 +71,9 @@ tests if the server is alive
|
|||
.TP
|
||||
\fBhelp\fR
|
||||
return this output
|
||||
.TP
|
||||
\fBversion\fR
|
||||
return the server version
|
||||
.IP
|
||||
LOGGING
|
||||
.TP
|
||||
|
|
Loading…
Reference in New Issue