Merge branch 'master' into 0.9

Conflicts:
	ChangeLog
	bin/fail2ban-regex
	bin/fail2ban-testcases
	config/jail.conf
	fail2ban/server/failregex.py
	fail2ban/server/filter.py
	fail2ban/tests/files/logs/lighttpd
	fail2ban/tests/files/logs/mysqld.log
	fail2ban/tests/files/logs/wu-ftpd
	fail2ban/tests/filtertestcase.py
	fail2ban/tests/utils.py
	testcases/files/logs/lighttpd
	testcases/files/logs/lighttpd-auth
	testcases/files/logs/mysqld-auth
	testcases/files/logs/mysqld.log
	testcases/files/logs/wu-ftpd
	testcases/files/logs/wuftpd
pull/300/head
Steven Hiscocks 2013-07-16 23:16:22 +01:00
commit 1eea0dcec8
55 changed files with 805 additions and 228 deletions

View File

@ -41,28 +41,58 @@ code-review and minor additions from Yaroslav Halchenko.
* [..e019ab7] Multiple instances of the same action are allowed in the
same jail -- use actname option to disambiguate.
ver. 0.8.11 (2013/XX/XXX) - wanna-be-released
ver. 0.8.11 (2013/XX/XXX) - loves-unittests
-----------
- Fixes:
Yaroslav Halchenko
* filter.d/common.conf -- make colon after [daemon] optional. Closes gh-267
* filter.d/apache-common.conf -- support apache 2.4 more detailed error
log format. Closes gh-268
* Backends changes detection and parsing. Close gh-223 and gh-103:
- Polling backend: detect changes in the files not only based on
mtime, but also on the size and inode. It should allow for
better detection of changes and log rotations on busy servers,
older python 2.4, and file systems with precision of mtime only
up to a second (e.g. ext3).
- All backends, possible race condition: do not read from a file
initially reported empty. Originally could have lead to
accounting for detected log lines multiple times.
Daniel Black & Мернов Георгий
* filter.d/dovecot.conf -- Fix when no TLS enabled - line doesn't end in ,
Daniel Black
* action.d/hostsdeny -- NOTE: new dependancy 'ed'. Switched to use 'ed' across
all platforms to ensure permissions are the same before and after a ban -
closes gh-266
- New Features:
Daniel Black & ykimon
* filter.d/3proxy.conf -- filter added
Daniel Black
* filter.d/exim-spam.conf -- a splitout of exim's spam regexes
with additions for greater control over filtering spam.
- Enhancements:
Daniel Black
* filter.d/{asterisk,assp,dovecot,proftpd}.conf -- regex hardening
and extra failure examples in sample logs
Daniel Black & Georgiy Mernov & ftoppi
Daniel Black & Georgiy Mernov & ftoppi & Мернов Георгий
* filter.d/exim.conf -- regex hardening and extra failure examples in
sample logs
Daniel Black & Sebastian Arcus
* filter.d/asterisk -- more regexes
Yaroslav Halchenko
* fail2ban-regex -- refactored to provide more details (missing and
ignored lines, control over logging, etc) while maintaining look&feel
* fail2ban-client -- log to standard error. Closes gh-264
* Fail to configure if not a single log file was found for an
enabled jail. Closes gh-63
* <HOST> is now enforced to end with an alphanumeric
* filter.d/roundcube-auth.conf -- anchored version
Alexander Dietrich
* action.d/sendmail-common.conf -- added common sendmail settings file
and made the sender display name configurable
Steven Hiscocks
* filter.d/dovecot - Addition of session, time values and possible blank
user
ver. 0.8.10 (2013/06/12) - wanna-be-secure
-----------

125
DEVELOP
View File

@ -39,10 +39,123 @@ Filters
* Include sample logs with 1.2.3.4 used for IP addresses and
example.com/example.org used for DNS names
* Ensure ./fail2ban-regex testcases/files/logs/{samplelog} config/filter.d/{filter}.conf
has matches for EVERY regex
* Ensure regexs end with a $ and are restrictive as possible. E.g. not .* if
[0-9]+ is sufficient
* Ensure sample log is provided in testcases/files/logs/ with same name as the
filter. Each log line should include match meta data for time & IP above
every line (see other sample log files for examples)
* Ensure regexs start with a ^ and are restrictive as possible. E.g. not .* if
\d+ is sufficient
* Use the functionality of regexs http://docs.python.org/2/library/re.html
* Take a look at the source code of the application. You may see optional or
extra log messages, or parts there of, that need to form part of your regex.
If you only have a basic knowledge of regular repressions read
http://docs.python.org/2/library/re.html first.
Filter Security
---------------
Poor filter regular expressions are suseptable to DoS attacks.
When a remote user has the ability to introduce text that will match the
filter regex, such that the inserted text matches the <HOST> part, they have the
ability to deny any host they choose.
So the <HOST> part must be anchored on text generated by the application, and not
the user, to a sufficient extent that the user cannot insert the entire text.
Filters are matched against the log line with their date removed.
Ideally filter regex should anchor to the beginning and end of the log line
however as more applications log at the beginning than the end, achoring the
beginning is more important. If the log file used by the application is shared
with other applications, like system logs, ensure the other application that
use that log file do not log user generated text at the beginning of the line,
or, if they do, ensure the regexs of the filter are sufficient to mitigate the
risk of insertion.
When creating a regex that extends back to the begining remember the date part
has been removed within fail2ban so theres no need to match that. If the format
is like '<date...> error 1.2.3.4 is evil' then you will need to match the < at
the start so here the regex would start like '^<> <HOST> is evil$'.
Some applications log spaces at the end. If you're not sure add \s*$ as the
end part of the regex.
Examples of poor filters
------------------------
1. Too restrictive
We find a log message:
Apr-07-13 07:08:36 Invalid command fial2ban from 1.2.3.4
We make a failregex
^Invalid command \S+ from <HOST>
Now think evil. The user does the command 'blah from 1.2.3.44'
The program diliently logs:
Apr-07-13 07:08:36 Invalid command blah from 1.2.3.44 from 1.2.3.4
And fail2ban matches 1.2.3.44 as the IP that it ban. A DoS attack was successful.
The fix here is that the command can be anything so .* is approprate.
^Invalid command .* from <HOST>
Here the .* will match until the end of the string. Then realise it has more to
match, i.e. "from <HOST>" and go back until it find this. Then it will ban
1.2.3.4 correctly. Since the <HOST> is always at the end, end the regex with a $.
^Invalid command .* from <HOST>$
Note if we'd just had the expression:
^Invalid command \S+ from <HOST>$
Then provided the user put a space in their command they would have never been
banned.
2. Filter regex can match other user injected data
From the apache vulnerability CVE-2013-2178
( original ref: https://vndh.net/note:fail2ban-089-denial-service ).
An example bad regex for apache:
failregex = [[]client <HOST>[]] user .* not found
Since the user can do a get request on:
GET /[client%20192.168.0.1]%20user%20root%20not%20found HTTP/1.0
Host: remote.site
Now the log line will be:
[Sat Jun 01 02:17:42 2013] [error] [client 192.168.33.1] File does not exist: /srv/http/site/[client 192.168.0.1] user root not found
As this log line doesn't match other expressions hence it matches the above
regex and blocks 192.168.33.1 as a denial of service from the HTTP requester.
3. Applicaiton generates two identical log messages with different meanings
If the application generates the following two messages under different
circmstances:
client <IP>: authentication failed
client <USER>: authentication failed
Then it's obvious that a regex of "^client <HOST>: authentication
failed$" will still cause problems if the user can trigger the second
log message with a <USER> of 123.1.1.1.
Here there's nothing to do except request/change the application so it logs
messages differently.
Code Testing
============
@ -136,6 +249,10 @@ Use the following tags in your commit messages:
Multiple tags could be joined with +, e.g. "BF+TST:".
Use the text "closes #333"/"resolves #333 "/"fixes #333" where 333 represents
an issue that is closed. Other text and details in link below.
See: https://help.github.com/articles/closing-issues-via-commit-messages
Adding Actions
--------------

View File

@ -69,27 +69,10 @@ FAIL2BAN CONFIGURATION
OPT: Create /etc/fail2ban/fail2ban.local containing:
# Fail2Ban main configuration file
#
# Comments: use '#' for comment lines and ';' (following a space) for inline comments
#
# Changes: in most of the cases you should not modify this
# file, but provide customizations in fail2ban.local file, e.g.:
#
# [Definition]
# loglevel = 4
# Fail2Ban configuration file for logging fail2ban on Solaris
#
[Definition]
# Option: logtarget
# Notes.: Set the log target. This could be a file, SYSLOG, STDERR or STDOUT.
# Only one log target can be specified.
# If you change logtarget from the default value and you are
# using logrotate -- also adjust or disable rotation in the
# corresponding configuration file
# (e.g. /etc/logrotate.d/fail2ban on Debian systems)
# Values: STDOUT STDERR SYSLOG file Default: /var/log/fail2ban.log
#
logtarget = /var/adm/fail2ban.log
@ -105,7 +88,7 @@ ignoreregex = for myuser from
logpath = /var/adm/auth.log
Set the sendmail dest address to something useful or drop the line to stop it spamming you.
Set 'myuser' to your username to avoid banning yourself or drop it.
Set 'myuser' to your username to avoid banning yourself or remove the line.
START (OR RESTART) FAIL2BAN
@ -128,7 +111,7 @@ GOTCHAS AND FIXMES
svcadm enable fail2ban
* If svcs -xv says that fail2ban failed to start or svcs says it's in maintenance mode
chcek /var/svc/log/network-fail2ban:default.log for clues.
check /var/svc/log/network-fail2ban:default.log for clues.
Check permissions on /var/adm, /var/adm/auth.log /var/adm/fail2ban.log and /var/run/fail2ban
You may need to:

2
THANKS
View File

@ -33,6 +33,7 @@ Mark Edgington
Markus Hoffmann
Marvin Rouge
mEDI
Мернов Георгий
Michael C. Haller
Michael Hanselmann
NickMunger
@ -41,6 +42,7 @@ Raphaël Marichez
René Berber
Robert Edeker
Russell Odom
Sebastian Arcus
Sireyessire
silviogarbes
Stephen Gildea

View File

@ -138,7 +138,7 @@ class RegexStat(object):
return self._failregex
def appendIP(self, value):
self._ipList.extend(value)
self._ipList.append(value)
def getIPList(self):
return self._ipList
@ -254,63 +254,47 @@ class Fail2banRegex(object):
regex_values = [RegexStat(value)]
setattr(self, "_" + regex, regex_values)
for regex in regex_values:
getattr(
self._filter,
'add%sRegex' % regextype.title())(regex.getFailRegex())
return True
def testIgnoreRegex(self, line):
found = False
for regex in self._ignoreregex:
try:
self._filter.addIgnoreRegex(regex.getFailRegex())
try:
ret = self._filter.ignoreLine(line)
if ret:
found = True
regex.inc()
except RegexException, e:
print e
return False
finally:
self._filter.delIgnoreRegex(0)
try:
ret = self._filter.ignoreLine(line)
if ret is not None:
found = True
regex = self._ignoreregex[ret].inc()
except RegexException, e:
print e
return False
return found
def testRegex(self, line):
found = False
for regex in self._ignoreregex:
self._filter.addIgnoreRegex(regex.getFailRegex())
orgLineBuffer = self._filter._Filter__lineBuffer
for regex in self._failregex:
try:
self._filter.addFailRegex(regex.getFailRegex())
try:
ret = self._filter.processLine(line)
if len(ret):
if found == True:
ret[0].append(True)
else:
found = True
ret[0].append(False)
regex.inc()
regex.appendIP(ret)
except RegexException, e:
print e
return False
except IndexError:
print "Sorry, but no <host> found in regex"
return False
finally:
self._filter.delFailRegex(0)
self._filter._Filter__lineBuffer = orgLineBuffer
if not found:
self._filter.processLine(line)
for regex in self._ignoreregex:
self._filter.delIgnoreRegex(0)
return found
try:
ret = self._filter.processLine(line, checkAllRegex=True)
for match in ret:
# Append True/False flag depending if line was matched by
# more than one regex
match.append(len(ret)>1)
regex = self._failregex[match[0]]
regex.inc()
regex.appendIP(match)
except RegexException, e:
print e
return False
except IndexError:
print "Sorry, but no <host> found in regex"
return False
return len(ret) > 0
def process(self, test_lines):
for line in test_lines:
if line.startswith('# ') or not line.strip():
if line.startswith('#') or not line.strip():
# skip comment and empty lines
continue
is_ignored = fail2banRegex.testIgnoreRegex(line)
@ -353,10 +337,13 @@ class Fail2banRegex(object):
if self._verbose and len(failregex.getIPList()):
for ip in failregex.getIPList():
timeTuple = time.localtime(ip[1])
timeTuple = time.localtime(ip[2])
timeString = time.strftime("%a %b %d %H:%M:%S %Y", timeTuple)
out.append(" %s %s%s" % (
ip[0], timeString, ip[2] and " (already matched)" or ""))
out.append(
" %s %s%s" % (
ip[1],
timeString,
ip[3] and " (multiple regex matched)" or ""))
print "\n%s: %d total" % (title, total)
pprint_list(out, " #) [# of hits] regular expression")

View File

@ -75,7 +75,7 @@ logSys = logging.getLogger("fail2ban")
verbosity = {'heavydebug': 3,
'debug': 3,
'info': 2,
'warn': 1,
'warning': 1,
'error': 1,
'fatal': 0,
None: 1}[opts.log_level]

View File

@ -39,7 +39,7 @@ actionban = IP=<ip> &&
# Tags: See jail.conf(5) man page
# Values: CMD
#
actionunban = IP=<ip> && sed /ALL:\ $IP/d <file> > <file>.new && mv <file>.new <file>
actionunban = echo "/ALL: <ip>$/<br>d<br>w<br>q" | ed <file>
[Init]

View File

@ -4,6 +4,10 @@
#
#
[INCLUDES]
before = sendmail-common.conf
[Definition]
# Option: actionstart
@ -11,7 +15,7 @@
# Values: CMD
#
actionstart = printf %%b "Subject: [Fail2Ban] <name>: started
From: Fail2Ban <<sender>>
From: <sendername> <<sender>>
To: <dest>\n
Hi,\n
The jail <name> has been started successfully.\n
@ -25,7 +29,7 @@ actionstart = printf %%b "Subject: [Fail2Ban] <name>: started
#
actionstop = if [ -f <tmpfile> ]; then
printf %%b "Subject: [Fail2Ban] <name>: summary
From: Fail2Ban <<sender>>
From: <sendername> <<sender>>
To: <dest>\n
Hi,\n
These hosts have been banned by Fail2Ban.\n
@ -58,7 +62,7 @@ actionban = printf %%b "`date`: <ip> (<failures> failures)\n" >> <tmpfile>
LINE=$( wc -l <tmpfile> | awk '{ print $1 }' )
if [ $LINE -ge <lines> ]; then
printf %%b "Subject: [Fail2Ban] <name>: summary
From: Fail2Ban <<sender>>
From: <sendername> <<sender>>
To: <dest>\n
Hi,\n
These hosts have been banned by Fail2Ban.\n
@ -82,14 +86,6 @@ actionunban =
#
name = default
# Destination/Addressee of the mail
#
dest = root
# Sender of the mail
#
sender = fail2ban
# Default number of lines that are buffered
#
lines = 5

View File

@ -0,0 +1,23 @@
# Fail2Ban configuration file
#
# Common settings for sendmail actions
#
# Users can override the defaults in sendmail-common.local
[INCLUDES]
after = sendmail-common.local
[Init]
# Recipient mail address
#
dest = root
# Sender mail address
#
sender = fail2ban
# Sender display name
#
sendername = Fail2Ban

View File

@ -4,6 +4,10 @@
#
#
[INCLUDES]
before = sendmail-common.conf
[Definition]
# Option: actionstart
@ -12,7 +16,7 @@
#
actionstart = printf %%b "Subject: [Fail2Ban] <name>: started
Date: `LC_TIME=C date -u +"%%a, %%d %%h %%Y %%T +0000"`
From: Fail2Ban <<sender>>
From: <sendername> <<sender>>
To: <dest>\n
Hi,\n
The jail <name> has been started successfully.\n
@ -25,7 +29,7 @@ actionstart = printf %%b "Subject: [Fail2Ban] <name>: started
#
actionstop = printf %%b "Subject: [Fail2Ban] <name>: stopped
Date: `LC_TIME=C date -u +"%%a, %%d %%h %%Y %%T +0000"`
From: Fail2Ban <<sender>>
From: <sendername> <<sender>>
To: <dest>\n
Hi,\n
The jail <name> has been stopped.\n
@ -46,7 +50,7 @@ actioncheck =
#
actionban = printf %%b "Subject: [Fail2Ban] <name>: banned <ip>
Date: `LC_TIME=C date -u +"%%a, %%d %%h %%Y %%T +0000"`
From: Fail2Ban <<sender>>
From: <sendername> <<sender>>
To: <dest>\n
Hi,\n
The IP <ip> has just been banned by Fail2Ban after
@ -72,14 +76,6 @@ actionunban =
#
name = default
# Destination/Addressee of the mail
#
dest = root
# Sender of the mail
#
sender = fail2ban
# Path to the log files which contain relevant lines for the abuser IP
#
logpath = /dev/null

View File

@ -4,6 +4,10 @@
#
#
[INCLUDES]
before = sendmail-common.conf
[Definition]
# Option: actionstart
@ -12,7 +16,7 @@
#
actionstart = printf %%b "Subject: [Fail2Ban] <name>: started
Date: `LC_TIME=C date -u +"%%a, %%d %%h %%Y %%T +0000"`
From: Fail2Ban <<sender>>
From: <sendername> <<sender>>
To: <dest>\n
Hi,\n
The jail <name> has been started successfully.\n
@ -25,7 +29,7 @@ actionstart = printf %%b "Subject: [Fail2Ban] <name>: started
#
actionstop = printf %%b "Subject: [Fail2Ban] <name>: stopped
Date: `LC_TIME=C date -u +"%%a, %%d %%h %%Y %%T +0000"`
From: Fail2Ban <<sender>>
From: <sendername> <<sender>>
To: <dest>\n
Hi,\n
The jail <name> has been stopped.\n
@ -46,7 +50,7 @@ actioncheck =
#
actionban = printf %%b "Subject: [Fail2Ban] <name>: banned <ip>
Date: `LC_TIME=C date -u +"%%a, %%d %%h %%Y %%T +0000"`
From: Fail2Ban <<sender>>
From: <sendername> <<sender>>
To: <dest>\n
Hi,\n
The IP <ip> has just been banned by Fail2Ban after
@ -70,11 +74,3 @@ actionunban =
#
name = default
# Destination/Addressee of the mail
#
dest = root
# Sender of the mail
#
sender = fail2ban

View File

@ -4,6 +4,10 @@
#
#
[INCLUDES]
before = sendmail-common.conf
[Definition]
# Option: actionstart
@ -12,7 +16,7 @@
#
actionstart = printf %%b "Subject: [Fail2Ban] <name>: started
Date: `LC_TIME=C date -u +"%%a, %%d %%h %%Y %%T +0000"`
From: Fail2Ban <<sender>>
From: <sendername> <<sender>>
To: <dest>\n
Hi,\n
The jail <name> has been started successfully.\n
@ -25,7 +29,7 @@ actionstart = printf %%b "Subject: [Fail2Ban] <name>: started
#
actionstop = printf %%b "Subject: [Fail2Ban] <name>: stopped
Date: `LC_TIME=C date -u +"%%a, %%d %%h %%Y %%T +0000"`
From: Fail2Ban <<sender>>
From: <sendername> <<sender>>
To: <dest>\n
Hi,\n
The jail <name> has been stopped.\n
@ -46,7 +50,7 @@ actioncheck =
#
actionban = printf %%b "Subject: [Fail2Ban] <name>: banned <ip>
Date: `LC_TIME=C date -u +"%%a, %%d %%h %%Y %%T +0000"`
From: Fail2Ban <<sender>>
From: <sendername> <<sender>>
To: <dest>\n
Hi,\n
The IP <ip> has just been banned by Fail2Ban after
@ -68,11 +72,3 @@ actionunban =
#
name = default
# Destination/Addressee of the mail
#
dest = root
# Sender of the mail
#
sender = fail2ban

View File

@ -14,4 +14,8 @@ after = apache-common.local
[DEFAULT]
# Common prefix for [error] apache messages which also would include <HOST>
_apache_error_client = \[[^]]+\] \[error\] \[client <HOST>\]
# Depending on the version it could be
# 2.2: [Sat Jun 01 11:23:08 2013] [error] [client 1.2.3.4]
# 2.4: [Thu Jun 27 11:55:44.569531 2013] [core:info] [pid 4101:tid 2992634688] [client 1.2.3.4:46652]
# Reference: https://github.com/fail2ban/fail2ban/issues/268
_apache_error_client = \[[^]]+\] \[(error|core:\S+)\]( \[pid \d+:\S+ \d+\])? \[client <HOST>(:\d{1,5})?\]( \S+:)?

View File

@ -17,19 +17,22 @@ before = common.conf
# Notes.: regex to match the password failures messages in the logfile.
# Values: TEXT
#
failregex = ^\[\]\s*NOTICE%(__pid_re)s \S+: Registration from '[^']*' failed for '<HOST>(:\d+)?' - Wrong password$
^\[\]\s*NOTICE%(__pid_re)s \S+: Registration from '[^']*' failed for '<HOST>(:\d+)?' - No matching peer found$
^\[\]\s*NOTICE%(__pid_re)s \S+: Registration from '[^']*' failed for '<HOST>(:\d+)?' - Username/auth name mismatch$
^\[\]\s*NOTICE%(__pid_re)s \S+: Registration from '[^']*' failed for '<HOST>(:\d+)?' - Device does not match ACL$
^\[\]\s*NOTICE%(__pid_re)s \S+: Registration from '[^']*' failed for '<HOST>(:\d+)?' - Peer is not supposed to register$
^\[\]\s*NOTICE%(__pid_re)s \S+: Registration from '[^']*' failed for '<HOST>(:\d+)?' - ACL error \(permit/deny\)$
^\[\]\s*NOTICE%(__pid_re)s \S+: Registration from '[^']*' failed for '<HOST>(:\d+)?' - Not a local domain$
^\[\]\s*NOTICE%(__pid_re)s\[\S+\] \S+: Call from '[^']*' \(<HOST>:\d+\) to extension '\d+' rejected because extension not found in context 'default'\.$
^\[\]\s*NOTICE%(__pid_re)s \S+: Host <HOST> failed to authenticate as '[^']*'$
^\[\]\s*NOTICE%(__pid_re)s \S+: No registration for peer '[^']*' \(from <HOST>\)$
^\[\]\s*NOTICE%(__pid_re)s \S+: Host <HOST> failed MD5 authentication for '[^']*' \([^)]+\)$
^\[\]\s*NOTICE%(__pid_re)s \S+: Failed to authenticate user [^@]+@<HOST>\S*$
^\[\]\s*SECURITY%(__pid_re)s \S+: SecurityEvent="InvalidAccountID",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+"$
log_prefix= \[\]\s*(?:NOTICE|SECURITY)%(__pid_re)s:?(?:\[\S+\d*\])? \S+:\d*
failregex = ^%(log_prefix)s Registration from '[^']*' failed for '<HOST>(:\d+)?' - Wrong password$
^%(log_prefix)s Registration from '[^']*' failed for '<HOST>(:\d+)?' - No matching peer found$
^%(log_prefix)s Registration from '[^']*' failed for '<HOST>(:\d+)?' - Username/auth name mismatch$
^%(log_prefix)s Registration from '[^']*' failed for '<HOST>(:\d+)?' - Device does not match ACL$
^%(log_prefix)s Registration from '[^']*' failed for '<HOST>(:\d+)?' - Peer is not supposed to register$
^%(log_prefix)s Registration from '[^']*' failed for '<HOST>(:\d+)?' - ACL error \(permit/deny\)$
^%(log_prefix)s Registration from '[^']*' failed for '<HOST>(:\d+)?' - Not a local domain$
^%(log_prefix)s Call from '[^']*' \(<HOST>:\d+\) to extension '\d+' rejected because extension not found in context 'default'\.$
^%(log_prefix)s Host <HOST> failed to authenticate as '[^']*'$
^%(log_prefix)s No registration for peer '[^']*' \(from <HOST>\)$
^%(log_prefix)s Host <HOST> failed MD5 authentication for '[^']*' \([^)]+\)$
^%(log_prefix)s Failed to authenticate user [^@]+@<HOST>\S*$
^%(log_prefix)s (?:handle_request_subscribe: )?Sending fake auth rejection for (device|user) \d*<sip:[^@]+@<HOST>>;tag=\w+\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]+")?$
# Option: ignoreregex
# Notes.: regex to ignore. If this regex matches, the line is ignored.

View File

@ -16,8 +16,8 @@ _daemon = dovecot(-auth)?
# first regex is essentially a copy of pam-generic.conf
# Values: TEXT
#
failregex = ^%(__prefix_line)s(pam_unix(?:\(\S+\))?:)?\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)? \((no auth attempts|auth failed, \d+ attempts|tried to use disabled \S+ auth)\):( user=<\S+>,)?( method=\S+,)? rip=<HOST>, lip=(\d{1,3}\.){3}\d{1,3},( TLS( handshaking)?(: Disconnected)?)?\s*$
failregex = ^%(__prefix_line)s(pam_unix(\(\S+\))?:)?\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)? \(((no auth attempts|auth failed, \d+ attempts)( in \d+ secs)?|tried to use disabled \S+ auth)\):( user=<\S*>,)?( method=\S+,)? rip=<HOST>, lip=(\d{1,3}\.){3}\d{1,3}(, session=<\w+>)?(, TLS( handshaking)?(: Disconnected)?)?\s*$
# Option: ignoreregex
# Notes.: regex to ignore. If this regex matches, the line is ignored.

View File

@ -0,0 +1,17 @@
# Fail2Ban configuration file for exim
#
# Author: Daniel Black
#
[INCLUDES]
# Load customizations if any available
#
after = exim-common.local
[Definition]
# From exim source code: ./src/receive.c:add_host_info_for_log
host_info = H=([\w.-]+ )?(\(\S+\) )?\[<HOST>\](:\d+)? (I=\[\S+\]:\d+ )?(U=\S+ )?(P=e?smtp )?
pid = ( \[\d+\])?

View File

@ -0,0 +1,29 @@
# Fail2Ban configuration file
#
# Author: Cyril Jaquier
# Daniel Black (rewrote with strong regexs)
#
[INCLUDES]
# Read common prefixes. If any customizations available -- read them from
# exim-common.local
before = exim-common.conf
[Definition]
# Option: failregex
# Notes.: This includes the spam rejection messages of exim.
# Note the %(host_info) defination contains a <HOST> match
failregex = ^%(pid)s \S+ F=(<>|\S+@\S+) %(host_info)srejected by local_scan\(\): .{0,256}$
^%(pid)s %(host_info)sF=(<>|[^@]+@\S+) rejected RCPT [^@]+@\S+: .*dnsbl.*\s*$
^%(pid)s \S+ %(host_info)sF=(<>|[^@]+@\S+) rejected after DATA: This message contains a virus \(\S+\)\.\s*$
# Option: ignoreregex
# Notes.: regex to ignore. If this regex matches, the line is ignored.
# Values: TEXT
#
ignoreregex =

View File

@ -4,25 +4,24 @@
# Daniel Black (rewrote with strong regexs)
#
[INCLUDES]
# Read common prefixes. If any customizations available -- read them from
# exim-common.local
before = exim-common.conf
[Definition]
# Option: failregex
# Notes.: regex to match the password failures messages in the logfile. The
# host must be matched by a group named "host". The tag "<HOST>" can
# be used for standard IP/hostname matching and is only an alias for
# (?:::f{4,6}:)?(?P<host>[\w\-.^_]+)
# Values: TEXT
#
# Notes.: This includes the rejection messages of exim. For spam and filter
# related bans use the exim-spam.conf
# Note the %(host_info) defination contains a <HOST> match
# From exim source code: ./src/receive.c:add_host_info_for_log
host_info = H=([\w.-]+ )?(\(\S+\) )?\[<HOST>\](:\d+)? (?:I=\[\S+\]:\d+ )?(?:U=\S+ )?(P=e?smtp )?
pid = ( \[\d+\])?
failregex = ^%(pid)s %(host_info)ssender verify fail for <\S+>: Unrouteable address\s*$
^%(pid)s \S+ F=(?:<>|\S+@\S+) %(host_info)s(?:temporarily )?rejected by local_scan\(\): .{0,256}$
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 login 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+: (rejected found in dnsbl \S+|relay not permitted)\s*$
^%(pid)s \S+ %(host_info)sF=(?:<>|[^@]+@\S+) rejected after DATA: This message contains a virus \(\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*$

View File

@ -4,6 +4,10 @@
#
#
[INCLUDES]
before = common.conf
[Definition]
# Option: failregex
@ -13,7 +17,7 @@
# (?:::f{4,6}:)?(?P<host>[\w\-.^_]+)
# Values: TEXT
#
failregex = (FAILED login|Login failed) for .* from <HOST>\s*$
failregex = ^\s*(\[(\s\+[0-9]{4})?\])?(%(__hostname)s roundcube: IMAP Error)?: (FAILED login|Login failed) for .*? from <HOST>(\. AUTHENTICATE .*)?\s*$
# Option: ignoreregex
# Notes.: regex to ignore. If this regex matches, the line is ignored.

View File

@ -526,6 +526,17 @@ maxretry=5
enabled = false
filter = 3proxy
action = iptables-multiport[name=3proxy, port=3128, protocol=tcp]
action = iptables[name=3proxy, port=3128, protocol=tcp]
logpath = /var/log/3proxy.log
[exim]
enabled = false
filter = exim
action = iptables-multiport[name=exim,port="25,465,587"]
logpath = /var/log/exim/mainlog
[exim-spam]
enabled = false
filter = exim-spam
action = iptables-multiport[name=exim-spam,port="25,465,587"]
logpath = /var/log/exim/mainlog

View File

@ -180,6 +180,7 @@ class DateDetector:
match = template.matchDate(line)
if not match is None:
logSys.debug("Matched time template %s" % template.getName())
template.incHits()
return match
return None
finally:

View File

@ -59,11 +59,12 @@ class DateTemplate:
def getHits(self):
return self.__hits
def incHits(self):
self.__hits += 1
def matchDate(self, line):
dateMatch = self.__cRegex.search(line)
if not dateMatch is None:
self.__hits += 1
return dateMatch
def getDate(self, line):

View File

@ -41,7 +41,7 @@ class Regex:
self._matchCache = None
# Perform shortcuts expansions.
# Replace "<HOST>" with default regular expression for host.
regex = regex.replace("<HOST>", "(?:::f{4,6}:)?(?P<host>[\w\-.^_]+)")
regex = regex.replace("<HOST>", "(?:::f{4,6}:)?(?P<host>[\w\-.^_]*\w)")
# Replace "<SKIPLINES>" with regular expression for multiple lines.
regexSplit = regex.split("<SKIPLINES>")
regex = regexSplit[0]
@ -55,7 +55,8 @@ class Regex:
except sre_constants.error:
raise RegexException("Unable to compile regular expression '%s'" %
regex)
def __str__(self):
return "%s(%r)" % (self.__class__.__name__, self._regex)
##
# Gets the regular expression.
#

View File

@ -21,6 +21,8 @@ __author__ = "Cyril Jaquier and Fail2Ban Contributors"
__copyright__ = "Copyright (c) 2004 Cyril Jaquier, 2011-2013 Yaroslav Halchenko"
__license__ = "GPL"
import sys
from failmanager import FailManagerEmpty
from failmanager import FailManager
from ticket import FailTicket
@ -307,11 +309,11 @@ class Filter(JailThread):
return False
def processLine(self, line):
def processLine(self, line, returnRawHost=False, checkAllRegex=False):
"""Split the time portion from log msg and return findFailures on them
"""
line = line.rstrip('\r\n')
logSys.log(5, "Working on line %r", line)
logSys.log(7, "Working on line %r", line)
timeMatch = self.dateDetector.matchTime(line)
if timeMatch:
@ -327,14 +329,16 @@ class Filter(JailThread):
logLine = line
self.__lineBuffer = ((self.__lineBuffer +
[logLine])[-self.__lineBufferSize:])
return self.findFailure(timeLine, "\n".join(self.__lineBuffer) + "\n")
return self.findFailure(timeLine, "\n".join(self.__lineBuffer) + "\n",
returnRawHost, checkAllRegex)
def processLineAndAdd(self, line):
"""Processes the line for failures and populates failManager
"""
for element in self.processLine(line):
ip = element[0]
unixTime = element[1]
failregex = element[0]
ip = element[1]
unixTime = element[2]
logSys.debug("Processing line with time:%s and ip:%s"
% (unixTime, ip))
if unixTime < MyTime.time() - self.getFindTime():
@ -345,6 +349,7 @@ class Filter(JailThread):
logSys.debug("Ignore %s" % ip)
continue
logSys.debug("Found %s" % ip)
## print "D: Adding a ticket for %s" % ((ip, unixTime, [line]),)
self.failManager.addFailure(FailTicket(ip, unixTime, [line]))
##
@ -355,11 +360,11 @@ class Filter(JailThread):
# @return: a boolean
def ignoreLine(self, line):
for ignoreRegex in self.__ignoreRegex:
for ignoreRegexIndex, ignoreRegex in enumerate(self.__ignoreRegex):
ignoreRegex.search(line)
if ignoreRegex.hasMatched():
return True
return False
return ignoreRegexIndex
return None
##
# Finds the failure in a line given split into time and log parts.
@ -368,22 +373,25 @@ class Filter(JailThread):
# to find the logging time.
# @return a dict with IP and timestamp.
def findFailure(self, timeLine, logLine):
def findFailure(self, timeLine, logLine,
returnRawHost=False, checkAllRegex=False):
logSys.log(5, "Date: %r, message: %r", timeLine, logLine)
failList = list()
date = self.dateDetector.getUnixTime(timeLine)
# Iterates over all the regular expressions.
for failRegex in self.__failRegex:
for failRegexIndex, failRegex in enumerate(self.__failRegex):
failRegex.search(logLine)
if failRegex.hasMatched():
# Checks if we must ignore this match.
if self.ignoreLine(
"\n".join(failRegex.getMatchedLines()) + "\n"):
"\n".join(failRegex.getMatchedLines()) + "\n") \
is not None:
# The ignoreregex matched. Remove ignored match.
self.__lineBuffer = failRegex.getUnmatchedLines()
logSys.log(7, "Matched ignoreregex and was ignored")
continue
# The failregex matched.
date = self.dateDetector.getUnixTime(timeLine)
logSys.log(7, "Date: %r, message: %r",
timeLine, logLine)
logSys.log(7, "Matched %s", failRegex)
if date is None:
logSys.debug("Found a match for %r but no valid date/time "
"found for %r. Please file a detailed issue on"
@ -394,12 +402,17 @@ class Filter(JailThread):
self.__lineBuffer = failRegex.getUnmatchedLines()
try:
host = failRegex.getHost()
ipMatch = DNSUtils.textToIp(host, self.__useDns)
if ipMatch:
for ip in ipMatch:
failList.append([ip, date])
# We matched a regex, it is enough to stop.
break
if returnRawHost:
failList.append([failRegexIndex, host, date])
if not checkAllRegex:
break
else:
ipMatch = DNSUtils.textToIp(host, self.__useDns)
if ipMatch:
for ip in ipMatch:
failList.append([failRegexIndex, ip, date])
if not checkAllRegex:
break
except RegexException, e: # pragma: no cover - unsure if reachable
logSys.error(e)
return failList
@ -526,7 +539,7 @@ class FileFilter(Filter):
return False
# Try to open log file.
try:
container.open()
has_content = container.open()
# see http://python.org/dev/peps/pep-3151/
except IOError, e:
logSys.error("Unable to open %s" % filename)
@ -541,7 +554,12 @@ class FileFilter(Filter):
logSys.exception(e)
return False
while True:
# yoh: has_content is just a bool, so do not expect it to
# change -- loop is exited upon break, and is not entered at
# all if upon container opening that one was empty. If we
# start reading tested to be empty container -- race condition
# might occur leading at least to tests failures.
while has_content:
line = container.readline()
if not line or not self._isActive():
# The jail reached the bottom or has been stopped
@ -612,10 +630,20 @@ class FileContainer:
fd = self.__handler.fileno()
flags = fcntl.fcntl(fd, fcntl.F_GETFD)
fcntl.fcntl(fd, fcntl.F_SETFD, flags | fcntl.FD_CLOEXEC)
# Stat the file before even attempting to read it
stats = os.fstat(self.__handler.fileno())
if not stats.st_size:
# yoh: so it is still an empty file -- nothing should be
# read from it yet
# print "D: no content -- return"
return False
firstLine = self.__handler.readline()
# Computes the MD5 of the first line.
myHash = md5sum(firstLine).digest()
stats = os.fstat(self.__handler.fileno())
## print "D: fn=%s hashes=%s/%s inos=%s/%s pos=%s rotate=%s" % (
## self.__filename, self.__hash, myHash, stats.st_ino, self.__ino, self.__pos,
## self.__hash != myHash or self.__ino != stats.st_ino)
## sys.stdout.flush()
# Compare hash and inode
if self.__hash != myHash or self.__ino != stats.st_ino:
logSys.debug("Log rotation detected for %s" % self.__filename)
@ -624,6 +652,7 @@ class FileContainer:
self.__pos = 0
# Sets the file pointer to the last position.
self.__handler.seek(self.__pos)
return True
def readline(self):
if self.__handler is None:
@ -645,6 +674,8 @@ class FileContainer:
# Closes the file.
self.__handler.close()
self.__handler = None
## print "D: Closed %s with pos %d" % (handler, self.__pos)
## sys.stdout.flush()
##
@ -682,9 +713,9 @@ class DNSUtils:
"""
try:
return socket.gethostbyname_ex(dns)[2]
except socket.gaierror:
logSys.warning("Unable to find a corresponding IP address for %s"
% dns)
except socket.error, e:
logSys.warn("Unable to find a corresponding IP address for %s: %s"
% (dns, e))
return list()
except socket.error, e:
logSys.warning("Socket error raised trying to resolve hostname %s: %s"

View File

@ -52,7 +52,7 @@ class FilterPoll(FileFilter):
FileFilter.__init__(self, jail)
self.__modified = False
## The time of the last modification of the file.
self.__lastModTime = dict()
self.__prevStats = dict()
self.__file404Cnt = dict()
logSys.debug("Created FilterPoll")
@ -62,7 +62,7 @@ class FilterPoll(FileFilter):
# @param path log file path
def _addLogPath(self, path):
self.__lastModTime[path] = 0
self.__prevStats[path] = (0, None, None) # mtime, ino, size
self.__file404Cnt[path] = 0
##
@ -71,7 +71,7 @@ class FilterPoll(FileFilter):
# @param path the log file to delete
def _delLogPath(self, path):
del self.__lastModTime[path]
del self.__prevStats[path]
del self.__file404Cnt[path]
##
@ -84,6 +84,9 @@ class FilterPoll(FileFilter):
def run(self):
self.setActive(True)
while self._isActive():
if logSys.getEffectiveLevel() <= 6:
logSys.log(6, "Woke up idle=%s with %d files monitored",
self.getIdle(), len(self.getLogPath()))
if not self.getIdle():
# Get file modification
for container in self.getLogPath():
@ -118,12 +121,20 @@ class FilterPoll(FileFilter):
def isModified(self, filename):
try:
logStats = os.stat(filename)
stats = logStats.st_mtime, logStats.st_ino, logStats.st_size
pstats = self.__prevStats[filename]
self.__file404Cnt[filename] = 0
if self.__lastModTime[filename] == logStats.st_mtime:
if logSys.getEffectiveLevel() <= 7:
# we do not want to waste time on strftime etc if not necessary
dt = logStats.st_mtime - pstats[0]
logSys.log(7, "Checking %s for being modified. Previous/current stats: %s / %s. dt: %s",
filename, pstats, stats, dt)
# os.system("stat %s | grep Modify" % filename)
if pstats == stats:
return False
else:
logSys.debug(filename + " has been modified")
self.__lastModTime[filename] = logStats.st_mtime
logSys.debug("%s has been modified", filename)
self.__prevStats[filename] = stats
return True
except OSError, e:
logSys.error("Unable to get stat on %s because of: %s"

View File

@ -56,7 +56,7 @@ class JailThread(Thread):
def setSleepTime(self, value):
self.__sleepTime = value
logSys.info("Set sleeptime = " + value)
logSys.info("Set sleeptime %s" % value)
##
# Get the time that the thread sleeps.

View File

@ -1,3 +1,6 @@
# failJSON: { "time": "2013-06-11T02:09:40", "match": true , "host": "1.2.3.4" }
11-06-2013 02:09:40 +0300 PROXY.3128 00004 - 1.2.3.4:28783 0.0.0.0:0 0 0 0 GET http://www.yandex.ua/?ncrnd=2169807731 HTTP/1.1
# failJSON: { "time": "2013-06-11T02:09:43", "match": true , "host": "1.2.3.4" }
11-06-2013 02:09:43 +0300 PROXY.3128 00005 ewr 1.2.3.4:28788 0.0.0.0:0 0 0 0 GET http://www.yandex.ua/?ncrnd=2169807731 HTTP/1.1
# failJSON: { "time": "2013-06-13T01:39:34", "match": true , "host": "1.2.3.4" }
13-06-2013 01:39:34 +0300 PROXY.3128 00508 - 1.2.3.4:28938 0.0.0.0:0 0 0 0

View File

@ -1,5 +1,7 @@
# Should not match -- DoS vector https://vndh.net/note:fail2ban-089-denial-service
# failJSON: { "match": false }
[Sat Jun 01 02:17:42 2013] [error] [client 192.168.33.1] File does not exist: /srv/http/site/[client 192.168.0.1] user root not found
# should match
# failJSON: { "time": "2005-06-01T02:17:42", "match": true , "host": "192.168.0.2" }
[Sat Jun 01 02:17:42 2013] [error] [client 192.168.0.2] user root not found

View File

@ -0,0 +1,6 @@
# Apache 2.2
# failJSON: { "time": "2005-06-01T11:23:08", "match": true , "host": "1.2.3.4" }
[Sat Jun 01 11:23:08 2013] [error] [client 1.2.3.4] File does not exist: /xxx/~
# Apache 2.4
# failJSON: { "time": "2005-06-27T11:55:44", "match": true , "host": "192.0.2.12" }
[Thu Jun 27 11:55:44.569531 2013] [core:info] [pid 4101:tid 2992634688] [client 192.0.2.12:46652] AH00128: File does not exist: /xxx/~

View File

@ -1 +1,2 @@
# failJSON: { "time": "2005-06-09T07:57:47", "match": true , "host": "192.0.43.10" }
[Sun Jun 09 07:57:47 2013] [error] [client 192.0.43.10] script '/usr/lib/cgi-bin/gitweb.cgiwp-login.php' not found or unable to stat

View File

@ -1,2 +1,4 @@
# failJSON: { "time": "2005-03-16T15:39:29", "match": true , "host": "58.179.109.179" }
[Tue Mar 16 15:39:29 2010] [error] [client 58.179.109.179] Invalid URI in request \xf9h\xa9\xf3\x88\x8cXKj \xbf-l*4\x87n\xe4\xfe\xd4\x1d\x06\x8c\xf8m\\rS\xf6n\xeb\x8
# failJSON: { "time": "2005-03-15T15:44:47", "match": true , "host": "121.222.2.133" }
[Mon Mar 15 15:44:47 2010] [error] [client 121.222.2.133] Invalid URI in request n\xed*\xbe*\xab\xefd\x80\xb5\xae\xf6\x01\x10M?\xf2\xce\x13\x9c\xd7\xa0N\xa7\xdb%0\xde\xe0\xfc\xd2\xa0\xfe\xe9w\xee\xc4`v\x9b[{\x0c:\xcb\x93\xc6\xa0\x93\x9c`l\\\x8d\xc9

View File

@ -1,13 +1,25 @@
# failJSON: { "time": "2013-04-07T07:08:36", "match": true , "host": "68.171.223.68" }
Apr-07-13 07:08:36 [SSL-out] 68.171.223.68 SSL negotiation with client failed: SSL accept attempt failed with unknown errorerror:140760FC:SSL routines:SSL23_GET_CLIENT_HELLO:unknown protocol;
# failJSON: { "time": "2013-04-07T07:08:36", "match": true , "host": "68.171.223.68" }
Apr-07-13 07:08:36 [SSL-out] 68.171.223.68 SSL negotiation with client failed: SSL accept attempt failed with unknown errorerror:140760FC:SSL routines:SSL23_GET_CLIENT_HELLO:unknown protocol;
# failJSON: { "time": "2013-04-07T07:10:37", "match": true , "host": "68.171.223.68" }
Apr-07-13 07:10:37 [SSL-out] 68.171.223.68 SSL negotiation with client failed: SSL accept attempt failed with unknown errorerror:140760FC:SSL routines:SSL23_GET_CLIENT_HELLO:unknown protocol;
# failJSON: { "time": "2013-04-07T07:12:37", "match": true , "host": "68.171.223.68" }
Apr-07-13 07:12:37 [SSL-out] 68.171.223.68 SSL negotiation with client failed: SSL accept attempt failed with unknown errorerror:140760FC:SSL routines:SSL23_GET_CLIENT_HELLO:unknown protocol;
# failJSON: { "time": "2013-04-07T07:14:36", "match": true , "host": "68.171.223.68" }
Apr-07-13 07:14:36 [SSL-out] 68.171.223.68 SSL negotiation with client failed: SSL accept attempt failed with unknown errorerror:140760FC:SSL routines:SSL23_GET_CLIENT_HELLO:unknown protocol;
# failJSON: { "time": "2013-04-27T02:25:09", "match": true , "host": "217.194.197.97" }
Apr-27-13 02:25:09 Blocking 217.194.197.97 - too much AUTH errors (8);
# failJSON: { "time": "2013-04-27T02:25:09", "match": true , "host": "217.194.197.97" }
Apr-27-13 02:25:09 Blocking 217.194.197.97 - too much AUTH errors (9);
# failJSON: { "time": "2013-04-27T02:25:09", "match": true , "host": "217.194.197.97" }
Apr-27-13 02:25:09 Blocking 217.194.197.97 - too much AUTH errors (10);
# failJSON: { "time": "2013-04-27T02:25:10", "match": true , "host": "217.194.197.97" }
Apr-27-13 02:25:10 [SSL-out] 217.194.197.97 max sender authentication errors (5) exceeded -- dropping connection - after reply: 535 5.7.8 Error: authentication failed: UGFzc3dvcmQ6;
# failJSON: { "time": "2013-04-27T02:25:10", "match": true , "host": "217.194.197.97" }
Apr-27-13 02:25:10 [SSL-out] 217.194.197.97 max sender authentication errors (5) exceeded -- dropping connection - after reply: 535 5.7.8 Error: authentication failed: UGFzc3dvcmQ6;
# failJSON: { "time": "2013-04-27T02:25:10", "match": true , "host": "217.194.197.97" }
Apr-27-13 02:25:10 [SSL-out] 217.194.197.97 max sender authentication errors (5) exceeded -- dropping connection - after reply: 535 5.7.8 Error: authentication failed: UGFzc3dvcmQ6;
# failJSON: { "time": "2013-04-27T02:25:11", "match": true , "host": "217.194.197.97" }
Apr-27-13 02:25:11 [SSL-out] 217.194.197.97 max sender authentication errors (5) exceeded -- dropping connection - after reply: 535 5.7.8 Error: authentication failed: UGFzc3dvcmQ6;

View File

@ -1,15 +1,40 @@
# Sample log files for asterisk
# failJSON: { "time": "2012-02-13T17:21:54", "match": true , "host": "1.2.3.4" }
[2012-02-13 17:21:54] NOTICE[1638] chan_sip.c: Registration from '<sip:301@example.com>' failed for '1.2.3.4' - Wrong password
# failJSON: { "time": "2012-02-13T17:18:22", "match": true , "host": "1.2.3.4" }
[2012-02-13 17:18:22] NOTICE[1638] chan_sip.c: Registration from '<sip:301@example.com>' failed for '1.2.3.4' - No matching peer found
# failJSON: { "time": "2012-02-13T17:21:21", "match": true , "host": "1.2.3.4" }
[2012-02-13 17:21:21] NOTICE[1638] chan_sip.c: Registration from '<sip:301@example.com>' failed for '1.2.3.4' - Username/auth name mismatch
# failJSON: { "time": "2012-02-13T17:32:01", "match": true , "host": "1.2.3.4" }
[2012-02-13 17:32:01] NOTICE[1638] chan_sip.c: Registration from '<sip:301@example.com>' failed for '1.2.3.4' - Device does not match ACL
# failJSON: { "time": "2012-02-13T17:34:10", "match": true , "host": "1.2.3.4" }
[2012-02-13 17:34:10] NOTICE[1638] chan_sip.c: Registration from '<sip:301@example.com>' failed for '1.2.3.4' - Peer is not supposed to register
# failJSON: { "time": "2012-02-13T17:36:23", "match": true , "host": "1.2.3.4" }
[2012-02-13 17:36:23] NOTICE[1638] chan_sip.c: Registration from '<sip:301@example.com>' failed for '1.2.3.4' - ACL error (permit/deny)
# failJSON: { "time": "2012-02-13T17:53:59", "match": true , "host": "1.2.3.4" }
[2012-02-13 17:53:59] NOTICE[1638] chan_iax2.c: Host 1.2.3.4 failed to authenticate as 'Fail2ban'
# failJSON: { "time": "2012-02-13T17:39:20", "match": true , "host": "1.2.3.4" }
[2012-02-13 17:39:20] NOTICE[1638] chan_iax2.c: No registration for peer 'Fail2ban' (from 1.2.3.4)
# failJSON: { "time": "2012-02-13T17:44:26", "match": true , "host": "1.2.3.4" }
[2012-02-13 17:44:26] NOTICE[1638] chan_iax2.c: Host 1.2.3.4 failed MD5 authentication for 'Fail2ban' (e7df7cd2ca07f4f1ab415d457a6e1c13 != 53ac4bc41ee4ec77888ed4aa50677247)
# failJSON: { "time": "2012-02-13T17:37:07", "match": true , "host": "1.2.3.4" }
[2012-02-13 17:37:07] NOTICE[1638] chan_sip.c: Failed to authenticate user "Fail2ban" <sip:301@1.2.3.4>;tag=1r698745234
# failJSON: { "time": "2013-02-05T23:44:42", "match": true , "host": "1.2.3.4" }
[2013-02-05 23:44:42] NOTICE[436][C-00000fa9] chan_sip.c: Call from '' (1.2.3.4:10836) to extension '0972598285108' rejected because extension not found in context 'default'.
# failJSON: { "time": "2013-03-26T15:47:54", "match": true , "host": "1.2.3.4" }
[2013-03-26 15:47:54] NOTICE[1237] chan_sip.c: Registration from '"100"sip:100@1.2.3.4' failed for '1.2.3.4:23930' - No matching peer found
# failJSON: { "time": "2013-05-13T07:10:53", "match": true , "host": "1.2.3.4" }
[2013-05-13 07:10:53] SECURITY[1204] res_security_log.c: SecurityEvent="InvalidAccountID",EventTV="1368439853-500975",Severity="Error",Service="SIP",EventVersion="1",AccountID="00972599580679",SessionID="0x7f8ecc0421f8",LocalAddress="IPV4/UDP/1.2.3.4/5060",RemoteAddress="IPV4/UDP/1.2.3.4/5070"
# failJSON: { "time": "2013-06-10T18:15:03", "match": true , "host": "1.2.3.4" }
[2013-06-10 18:15:03] NOTICE[2723] chan_sip.c: Registration from '"100"<sip:100@192.168.0.2:5060>' failed for '1.2.3.4' - Not a local domain
# http://forum.4psa.com/showthread.php?t=6601
# failJSON: { "time": "2009-12-22T16:35:24", "match": true , "host": "192.168.2.102" }
[2009-12-22 16:35:24] NOTICE[6163] chan_sip.c: Sending fake auth rejection for device <sip:0004*001@192.168.2.102>;tag=e3793a95e1acbc69o
# http://www.freepbx.org/forum/general-help/fake-auth-rejection
# failJSON: { "time": "2009-12-22T16:35:24", "match": true , "host": "192.168.2.102" }
[2009-12-22 16:35:24] NOTICE[1570][C-00000086] chan_sip.c: Sending fake auth rejection for device 1022<sip:1022@192.168.2.102>;tag=5d8b6f92
# http://www.spinics.net/lists/asterisk/msg127381.html
# failJSON: { "time": "2009-12-22T16:35:24", "match": true , "host": "192.168.2.102" }
[2009-12-22 16:35:24] NOTICE[14916]: chan_sip.c:15644 handle_request_subscribe: Sending fake auth rejection for user <sip:CS@192.168.2.102>;tag=6pwd6erg54
# failJSON: { "time": "2013-07-06T09:09:25", "match": true , "host": "141.255.164.106" }
[2013-07-06 09:09:25] SECURITY[3308] res_security_log.c: SecurityEvent="InvalidPassword",EventTV="1373098165-824497",Severity="Error",Service="SIP",EventVersion="2",AccountID="972592891005",SessionID="0x88aab6c",LocalAddress="IPV4/UDP/92.28.73.180/5060",RemoteAddress="IPV4/UDP/141.255.164.106/5084",Challenge="41d26de5",ReceivedChallenge="41d26de5",ReceivedHash="7a6a3a2e95a05260aee612896e1b4a39"

View File

@ -1,15 +1,31 @@
# failJSON: { "time": "2010-09-16T07:51:00", "match": true , "host": "80.187.101.33" }
@400000004c91b044077a9e94 imap-login: Info: Aborted login (auth failed, 1 attempts): user=<martin@waschbuesch.de>, method=CRAM-MD5, rip=80.187.101.33, lip=80.254.129.240, TLS
@e040c6d8a3bfa62d358083300119c259cd44dcd0 dovecot-auth: pam_unix(dovecot:auth): authentication failure; logname= uid=0 euid=0 tty=dovecot ruser=web rhost=176.61.140.224
# failJSON: { "time": "2010-09-16T07:51:00", "match": true , "host": "176.61.140.224" }
@400000004c91b044077a9e94 dovecot-auth: pam_unix(dovecot:auth): authentication failure; logname= uid=0 euid=0 tty=dovecot ruser=web rhost=176.61.140.224
# Above example with injected rhost into ruser -- should not match for 1.2.3.4
@e040c6d8a3bfa62d358083300119c259cd44dcd0 dovecot-auth: pam_unix(dovecot:auth): authentication failure; logname= uid=0 euid=0 tty=dovecot ruser=rhost=1.2.3.4 rhost=192.0.43.10
@e040c6d8a3bfa62d358083300119c259cd44dcd0 dovecot-auth: pam_unix(dovecot:auth): authentication failure; logname= uid=0 euid=0 tty=dovecot ruser=root rhost=176.61.140.225 user=root
# failJSON: { "time": "2010-09-16T07:51:00", "match": true , "host": "192.0.43.10" }
@400000004c91b044077a9e94 dovecot-auth: pam_unix(dovecot:auth): authentication failure; logname= uid=0 euid=0 tty=dovecot ruser=rhost=1.2.3.4 rhost=192.0.43.10
# failJSON: { "time": "2010-09-16T07:51:00", "match": true , "host": "176.61.140.225" }
@400000004c91b044077a9e94 dovecot-auth: pam_unix(dovecot:auth): authentication failure; logname= uid=0 euid=0 tty=dovecot ruser=root rhost=176.61.140.225 user=root
# failJSON: { "time": "2004-12-12T11:19:11", "match": true , "host": "190.210.136.21" }
Dec 12 11:19:11 dunnart dovecot: pop3-login: Aborted login (tried to use disabled plaintext auth): rip=190.210.136.21, lip=113.212.99.193
# failJSON: { "time": "2005-06-13T16:30:54", "match": true , "host": "49.176.98.87" }
Jun 13 16:30:54 platypus dovecot: imap-login: Disconnected (auth failed, 2 attempts): user=<username.bob>, method=PLAIN, rip=49.176.98.87, lip=113.212.99.194, TLS
# failJSON: { "time": "2005-06-14T00:48:21", "match": true , "host": "59.167.242.100" }
Jun 14 00:48:21 platypus dovecot: imap-login: Disconnected (auth failed, 1 attempts): method=PLAIN, rip=59.167.242.100, lip=113.212.99.194, TLS: Disconnected
# failJSON: { "time": "2005-06-13T20:48:11", "match": true , "host": "121.44.24.254" }
Jun 13 20:48:11 platypus dovecot: pop3-login: Disconnected (no auth attempts): rip=121.44.24.254, lip=113.212.99.194, TLS: Disconnected
# failJSON: { "time": "2005-06-13T21:48:06", "match": true , "host": "180.200.180.81" }
Jun 13 21:48:06 platypus dovecot: pop3-login: Disconnected: Inactivity (no auth attempts): rip=180.200.180.81, lip=113.212.99.194, TLS
# failJSON: { "time": "2005-06-13T20:20:21", "match": true , "host": "180.189.168.166" }
Jun 13 20:20:21 platypus dovecot: imap-login: Disconnected (no auth attempts): rip=180.189.168.166, lip=113.212.99.194, TLS handshaking: Disconnected
# failJSON: { "time": "2005-06-23T00:52:43", "match": true , "host": "193.95.245.163" }
Jun 23 00:52:43 vhost1-ua dovecot: pop3-login: Disconnected: Inactivity (auth failed, 1 attempts): user=<info>, method=PLAIN, rip=193.95.245.163, lip=176.214.13.210
# failJSON: { "time": "2005-07-02T13:49:31", "match": true , "host": "192.51.100.13" }
Jul 02 13:49:31 hostname dovecot[442]: pop3-login: Aborted login (auth failed, 1 attempts in 17 secs): user=<test>, method=PLAIN, rip=192.51.100.13, lip=203.0.113.17, session=<YADINsQCDs5BH8Pg>
# failJSON: { "time": "2005-07-02T13:49:32", "match": true , "host": "192.51.100.13" }
Jul 02 13:49:32 hostname dovecot[442]: pop3-login: Disconnected (no auth attempts in 58 secs): user=<>, rip=192.51.100.13, lip=203.0.113.17, session=<LgDINsQCkttVIMPg>

View File

@ -1,20 +1,31 @@
# From IRC 2013-01-04
# failJSON: { "time": "2013-01-04T17:03:46", "match": true , "host": "24.106.174.74" }
2013-01-04 17:03:46 login authenticator failed for rrcs-24-106-174-74.se.biz.rr.com ([192.168.2.33]) [24.106.174.74]: 535 Incorrect authentication data (set_id=brian)
# From IRC 2013-06-13 XATRIX (Georgiy Mernov)
# failJSON: { "time": "2013-06-12T03:57:58", "match": true , "host": "120.196.140.45" }
2013-06-12 03:57:58 login authenticator failed for (ylmf-pc) [120.196.140.45]: 535 Incorrect authentication data: 1 Time(s)
# failJSON: { "time": "2013-06-12T13:18:11", "match": true , "host": "101.66.165.86" }
2013-06-12 13:18:11 login authenticator failed for (USER-KVI9FGS9KP) [101.66.165.86]: 535 Incorrect authentication data
# failJSON: { "time": "2013-06-10T10:10:59", "match": true , "host": "193.169.56.211" }
2013-06-10 10:10:59 H=ufficioestampa.it (srv.ufficioestampa.it) [193.169.56.211] sender verify fail for <user@example.com>: Unrouteable address
# http://forum.lissyara.su/viewtopic.php?f=20&t=2985
2010-11-24 21:48:41 1PLKOW-00046U-EW F=wvhluo@droolindog.com H=93-143-146-237.adsl.net.t-com.hr (droolindog.com) [93.143.146.237] I=[10.10.10.32]:25 P=esmtp temporarily rejected by local_scan(): Temporary local problem
# http://forum.lissyara.su/viewtopic.php?f=20&t=29857
# 2010-11-24 21:48:41 1PLKOW-00046U-EW F=wvhluo@droolindog.com H=93-143-146-237.adsl.net.t-com.hr (droolindog.com) [93.143.146.237] I=[10.10.10.32]:25 P=esmtp temporarily rejected by local_scan(): Temporary local problem
# http://us.generation-nt.com/answer/exim-spamassassin-2010-0-x64-help-204020461.html
2011-07-07 15:44:16 1QexIu-0006dj-PX F=XXXXXX@XXXXXXXXXXXX H=localhost (saf.bio.caltech.edu) [127.0.0.1] P=esmtp temporarily rejected by local_scan(): Local configuration error - local_scan() library failure/usr/lib/exim/sa-exim.so: cannot open shared object file: No such file or directory
# http://www.clues.ltd.uk/howto/debian-sa-fprot-HOWTO.html
2004-01-18 07:15:35 1Ai79e-0000Dq-8i F=uzwltcmwto24@melissacam.biz H=lsanca1-ar3-4-47-028-040.lsanca1.elnk.dsl.genuity.net [4.47.28.40] P=smtp rejected by local_scan(): Rejected: hits=7.5 required=5.0 trigger=5.0
# https://github.com/fail2ban/fail2ban/pull/251#issuecomment-19493875
2013-06-15 11:19:33 [2249] H=([2.181.148.95]) [2.181.148.95]:52391 I=[1.2.3.4]:25 F=fantasizesg4@google.com rejected RCPT some@email.com: rejected found in dnsbl zen.spamhaus.org
# 2011-07-07 15:44:16 1QexIu-0006dj-PX F=XXXXXX@XXXXXXXXXXXX H=localhost (saf.bio.caltech.edu) [127.0.0.1] P=esmtp temporarily rejected by local_scan(): Local configuration error - local_scan() library failure/usr/lib/exim/sa-exim.so: cannot open shared object file: No such file or directory
# failJSON: { "time": "2013-06-10T18:33:32", "match": true , "host": "202.132.70.178" }
2013-06-10 18:33:32 [10099] H=(yakult.com.tw) [202.132.70.178]:3755 I=[1.2.3.4]:25 F=menacedsj04@listserv.eurasia.org rejected RCPT dir@ml3.ru: relay not permitted
2013-06-09 10:21:28 [14127] 1UlasQ-0003fr-45 F=mcorporation4@aol.com H=(mail38.fssprus.ru) [46.254.240.82]:43671 I=[1.2.3.4]:25 P=esmtp rejected by local_scan(): Rejected
2013-06-15 11:20:36 [2516] 1Unmew-0000ea-SE H=egeftech.static.otenet.gr [83.235.177.148]:32706 I=[1.2.3.4]:25 F=auguriesvbd40@google.com rejected after DATA: This message contains a virus (Sanesecurity.Junk.39934.UNOFFICIAL).
# failJSON: { "time": "2013-06-02T06:54:20", "match": true , "host": "211.148.195.192" }
2013-06-02 06:54:20 [13314] SMTP protocol synchronization error (input sent without waiting for greeting): rejected connection from H=[211.148.195.192]:25936 I=[1.2.3.4]:25 input="GET / HTTP/1.1\r\n\r\n"
# failJSON: { "time": "2013-06-02T09:05:48", "match": true , "host": "82.96.160.77" }
2013-06-02 09:05:48 [18505] SMTP protocol synchronization error (next input sent too soon: pipelining was not advertised): rejected "RSET" H=ba77.mx83.fr [82.96.160.77]:58302 I=[1.2.3.4]:25 next input="QUIT\r\n"
# failJSON: { "time": "2013-06-02T09:22:05", "match": true , "host": "163.14.21.161" }
2013-06-02 09:22:05 [19591] SMTP call from pc012-6201.spo.scu.edu.tw [163.14.21.161]:3767 I=[1.2.3.4]:25 dropped: too many nonmail commands (last was "RSET")
# failJSON: { "time": "2013-06-02T15:06:18", "match": true , "host": "46.20.35.114" }
2013-06-02 15:06:18 H=(VM-WIN2K3-1562) [46.20.35.114] sender verify fail for <usfh@technological-systems.com>: Unknown user
# failJSON: { "time": "2013-06-07T02:02:09", "match": true , "host": "91.232.21.92" }
2013-06-07 02:02:09 H=treeladders.kiev.ua [91.232.21.92] sender verify fail for <mailer@treeladders.kiev.ua>: all relevant MX records point to non-existent hosts
# failJSON: { "time": "2013-06-15T16:34:55", "match": true , "host": "182.18.24.93" }
2013-06-15 16:34:55 H=mx.tillions.com [182.18.24.93] F=<buh@caladan.ebay.sun.com> rejected RCPT <ruslan@maslovskiy.com.ua>: Sender verify failed
# failJSON: { "time": "2013-06-15T16:36:49", "match": true , "host": "111.67.203.116" }
2013-06-15 16:36:49 H=altmx.marsukov.com [111.67.203.116] F=<kadrofutcheti@mail.ru> rejected RCPT <oksana@birzhatm.ua>: Unknown user

View File

@ -0,0 +1,17 @@
# http://forum.lissyara.su/viewtopic.php?f=20&t=29857
# 2010-11-24 21:48:41 1PLKOW-00046U-EW F=wvhluo@droolindog.com H=93-143-146-237.adsl.net.t-com.hr (droolindog.com) [93.143.146.237] I=[10.10.10.32]:25 P=esmtp temporarily rejected by local_scan(): Temporary local problem
# http://us.generation-nt.com/answer/exim-spamassassin-2010-0-x64-help-204020461.html
# 2011-07-07 15:44:16 1QexIu-0006dj-PX F=XXXXXX@XXXXXXXXXXXX H=localhost (saf.bio.caltech.edu) [127.0.0.1] P=esmtp temporarily rejected by local_scan(): Local configuration error - local_scan() library failure/usr/lib/exim/sa-exim.so: cannot open shared object file: No such file or directory
# http://www.clues.ltd.uk/howto/debian-sa-fprot-HOWTO.html
# failJSON: { "time": "2004-01-18T07:15:35", "match": true , "host": "4.47.28.40" }
2004-01-18 07:15:35 1Ai79e-0000Dq-8i F=uzwltcmwto24@melissacam.biz H=lsanca1-ar3-4-47-028-040.lsanca1.elnk.dsl.genuity.net [4.47.28.40] P=smtp rejected by local_scan(): Rejected: hits=7.5 required=5.0 trigger=5.0
# https://github.com/fail2ban/fail2ban/pull/251#issuecomment-19493875
# failJSON: { "time": "2013-06-15T11:19:33", "match": true , "host": "2.181.148.95" }
2013-06-15 11:19:33 [2249] H=([2.181.148.95]) [2.181.148.95]:52391 I=[1.2.3.4]:25 F=fantasizesg4@google.com rejected RCPT some@email.com: rejected found in dnsbl zen.spamhaus.org
# failJSON: { "time": "2013-06-09T10:21:28", "match": true , "host": "46.254.240.82" }
2013-06-09 10:21:28 [14127] 1UlasQ-0003fr-45 F=mcorporation4@aol.com H=(mail38.fssprus.ru) [46.254.240.82]:43671 I=[1.2.3.4]:25 P=esmtp rejected by local_scan(): Rejected
# failJSON: { "time": "2013-06-15T11:20:36", "match": true , "host": "83.235.177.148" }
2013-06-15 11:20:36 [2516] 1Unmew-0000ea-SE H=egeftech.static.otenet.gr [83.235.177.148]:32706 I=[1.2.3.4]:25 F=auguriesvbd40@google.com rejected after DATA: This message contains a virus (Sanesecurity.Junk.39934.UNOFFICIAL).
# failJSON: { "time": "2013-06-16T02:50:43", "match": true , "host": "111.67.203.114" }
2013-06-16 02:50:43 H=dbs.marsukov.com [111.67.203.114] F=<trudofspiori@mail.ru> rejected RCPT <info@nanomedtech.ua>: rejected because 111.67.203.114 is in a black list at dnsbl.sorbs.net\nCurrently Sending Spam See: http://www.sorbs.net/lookup.shtml?111.67.203.114

View File

@ -1,3 +1,5 @@
#authentification failure (mod_auth)
# failJSON: { "time": "2011-12-25T17:09:20", "match": true , "host": "4.4.4.4" }
2011-12-25 17:09:20: (http_auth.c.875) password doesn't match for /gitweb/ username: francois, IP: 4.4.4.4
# failJSON: { "time": "2012-09-26T10:24:35", "match": true , "host": "4.4.4.4" }
2012-09-26 10:24:35: (http_auth.c.1136) digest: auth failed for xxx : wrong password, IP: 4.4.4.4

View File

@ -1,6 +1,12 @@
# failJSON: { "time": "2013-03-24T00:04:00", "match": true , "host": "192.168.1.35" }
130324 0:04:00 [Warning] Access denied for user 'root'@'192.168.1.35' (using password: NO)
# failJSON: { "time": "2013-03-24T08:24:09", "match": true , "host": "220.95.238.171" }
130324 8:24:09 [Warning] Access denied for user 'root'@'220.95.238.171' (using password: NO)
# failJSON: { "time": "2013-03-24T17:56:13", "match": true , "host": "61.160.223.112" }
130324 17:56:13 [Warning] Access denied for user 'root'@'61.160.223.112' (using password: NO)
# failJSON: { "time": "2013-03-24T17:56:14", "match": true , "host": "61.160.223.112" }
130324 17:56:14 [Warning] Access denied for user 'root'@'61.160.223.112' (using password: YES)
# failJSON: { "time": "2013-03-24T19:01:39", "match": true , "host": "61.147.108.35" }
130324 19:01:39 [Warning] Access denied for user 'root'@'61.147.108.35' (using password: NO)
# failJSON: { "time": "2013-03-24T19:01:40", "match": true , "host": "61.147.108.35" }
130324 19:01:40 [Warning] Access denied for user 'root'@'61.147.108.35' (using password: YES)

View File

@ -1,6 +1,12 @@
# failJSON: { "time": "2005-07-24T14:16:55", "match": true , "host": "194.145.196.18" }
Jul 24 14:16:55 raid5 named[3935]: client 194.145.196.18#4795: query 'ricreig.com/NS/IN' denied
# failJSON: { "time": "2005-07-24T14:16:56", "match": true , "host": "62.123.164.113" }
Jul 24 14:16:56 raid5 named[3935]: client 62.123.164.113#32768: query 'ricreig.com/NS/IN' denied
# failJSON: { "time": "2005-07-24T14:17:13", "match": true , "host": "148.160.29.6" }
Jul 24 14:17:13 raid5 named[3935]: client 148.160.29.6#33081: query (cache) 'geo-mueller.de/NS/IN' denied
# failJSON: { "time": "2005-07-24T14:20:25", "match": true , "host": "148.160.29.6" }
Jul 24 14:20:25 raid5 named[3935]: client 148.160.29.6#33081: query (cache) 'shivaree.de/NS/IN' denied
# failJSON: { "time": "2005-07-24T14:23:36", "match": true , "host": "148.160.29.6" }
Jul 24 14:23:36 raid5 named[3935]: client 148.160.29.6#33081: query (cache) 'mietberatung.de/NS/IN' denied
# failJSON: { "time": "2005-07-24T14:23:36", "match": true , "host": "62.109.4.89" }
Jul 24 14:23:36 raid5 named[3935]: client 62.109.4.89#9334: view external: query (cache) './NS/IN' denied

View File

@ -1,7 +1,14 @@
# failJSON: { "time": "2005-02-07T15:10:42", "match": true , "host": "192.168.1.1" }
Feb 7 15:10:42 example pure-ftpd: (pam_unix) authentication failure; logname= uid=0 euid=0 tty=pure-ftpd ruser=sample-user rhost=192.168.1.1
# failJSON: { "time": "2005-05-12T09:47:54", "match": true , "host": "71-13-115-12.static.mdsn.wi.charter.com" }
May 12 09:47:54 vaio sshd[16004]: (pam_unix) authentication failure; logname= uid=0 euid=0 tty=ssh ruser= rhost=71-13-115-12.static.mdsn.wi.charter.com user=root
# failJSON: { "time": "2005-05-12T09:48:03", "match": true , "host": "71-13-115-12.static.mdsn.wi.charter.com" }
May 12 09:48:03 vaio sshd[16021]: (pam_unix) authentication failure; logname= uid=0 euid=0 tty=ssh ruser= rhost=71-13-115-12.static.mdsn.wi.charter.com
# failJSON: { "time": "2005-05-15T18:02:12", "match": true , "host": "66.232.129.62" }
May 15 18:02:12 localhost proftpd: (pam_unix) authentication failure; logname= uid=0 euid=0 tty= ruser= rhost=66.232.129.62 user=mark
# failJSON: { "time": "2004-11-25T17:12:13", "match": true , "host": "192.168.10.3" }
Nov 25 17:12:13 webmail pop(pam_unix)[4920]: authentication failure; logname= uid=0 euid=0 tty= ruser= rhost=192.168.10.3 user=mailuser
# failJSON: { "time": "2005-07-19T18:11:26", "match": true , "host": "www3.google.com" }
Jul 19 18:11:26 srv2 vsftpd: pam_unix(vsftpd:auth): authentication failure; logname= uid=0 euid=0 tty=ftp ruser=an8767 rhost=www3.google.com
# failJSON: { "time": "2005-07-19T18:11:26", "match": true , "host": "www3.google.com" }
Jul 19 18:11:26 srv2 vsftpd: pam_unix: authentication failure; logname= uid=0 euid=0 tty=ftp ruser=an8767 rhost=www3.google.com

View File

@ -1,3 +1,4 @@
# per https://github.com/fail2ban/fail2ban/issues/125
# and https://github.com/fail2ban/fail2ban/issues/126
# failJSON: { "time": "2005-02-21T09:21:54", "match": true , "host": "192.0.43.10" }
Feb 21 09:21:54 xxx postfix/smtpd[14398]: NOQUEUE: reject: RCPT from example.com[192.0.43.10]: 450 4.7.1 : Helo command rejected: Host not found; from=<> to=<> proto=ESMTP helo=

View File

@ -1,8 +1,14 @@
# failJSON: { "time": "2005-01-10T00:00:00", "match": true , "host": "123.123.123.123" }
Jan 10 00:00:00 myhost proftpd[12345] myhost.domain.com (123.123.123.123[123.123.123.123]): USER username (Login failed): User in /etc/ftpusers
# failJSON: { "time": "2005-02-01T00:00:00", "match": true , "host": "123.123.123.123" }
Feb 1 00:00:00 myhost proftpd[12345] myhost.domain.com (123.123.123.123[123.123.123.123]): USER username: no such user found from 123.123.123.123 [123.123.123.123] to 234.234.234.234:21
# failJSON: { "time": "2005-06-09T07:30:58", "match": true , "host": "67.227.224.66" }
Jun 09 07:30:58 platypus.ace-hosting.com.au proftpd[11864] platypus.ace-hosting.com.au (mail.bloodymonster.net[::ffff:67.227.224.66]): USER username (Login failed): Incorrect password.
# failJSON: { "time": "2005-06-09T11:15:43", "match": true , "host": "101.71.143.238" }
Jun 09 11:15:43 platypus.ace-hosting.com.au proftpd[17424] platypus.ace-hosting.com.au (::ffff:101.71.143.238[::ffff:101.71.143.238]): USER god: no such user found from ::ffff:101.71.143.238 [::ffff:101.71.143.238] to ::ffff:123.212.99.194:21
# failJSON: { "time": "2005-06-13T22:07:23", "match": true , "host": "59.167.242.100" }
Jun 13 22:07:23 platypus.ace-hosting.com.au proftpd[15719] platypus.ace-hosting.com.au (::ffff:59.167.242.100[::ffff:59.167.242.100]): SECURITY VIOLATION: root login attempted.
# failJSON: { "time": "2005-06-14T00:09:59", "match": true , "host": "59.167.242.100" }
Jun 14 00:09:59 platypus.ace-hosting.com.au proftpd[17839] platypus.ace-hosting.com.au (::ffff:59.167.242.100[::ffff:59.167.242.100]): USER platypus.ace-hosting.com.au proftpd[17424] platypus.ace-hosting.com.au (hihoinjection[1.2.3.44]): no such user found from ::ffff:59.167.242.100 [::ffff:59.167.242.100] to ::ffff:113.212.99.194:21

View File

@ -1,2 +1,4 @@
# failJSON: { "time": "2005-01-31T16:54:07", "match": true , "host": "24.79.92.194" }
Jan 31 16:54:07 desktop pure-ftpd: (?@24.79.92.194) [WARNING] Authentication failed for user [Administrator]
# failJSON: { "time": "2004-11-05T18:54:02", "match": true , "host": "server202181210195.ixlink.net" }
Nov 5 18:54:02 pure-ftpd: (?@server202181210195.ixlink.net) [WARNING] Authentication failed for user [Administrator]

View File

@ -1,2 +1,6 @@
# failJSON: { "time": "2013-01-22T22:28:21", "match": true , "host": "192.0.43.10" }
[22-Jan-2013 22:28:21 +0200]: FAILED login for user1 from 192.0.43.10
# failJSON: { "time": "2005-05-26T07:12:40", "match": true , "host": "10.1.1.47" }
May 26 07:12:40 hamster roundcube: IMAP Error: Login failed for sales@example.com from 10.1.1.47
# failJSON: { "time": "2005-07-11T03:06:37", "match": true , "host": "1.2.3.4" }
Jul 11 03:06:37 myhostname roundcube: IMAP Error: Login failed for admin from 1.2.3.4. AUTHENTICATE PLAIN: A0002 NO Login failed. in /usr/share/roundcube/program/include/rcube_imap.php on line 205 (POST /wmail/?_task=login&_action=login)

View File

@ -1,5 +1,7 @@
#1 Example from postfix from dbts #507990
# failJSON: { "time": "2004-12-02T22:24:22", "match": true , "host": "114.44.142.233" }
Dec 2 22:24:22 hel postfix/smtpd[7676]: warning: 114-44-142-233.dynamic.hinet.net[114.44.142.233]: SASL CRAM-MD5 authentication failed: PDc3OTEwNTkyNTEyMzA2NDIuMTIyODI1MzA2MUBoZWw+
#2 Example from postfix from dbts #573314
# failJSON: { "time": "2005-03-10T13:33:30", "match": true , "host": "1.1.1.1" }
Mar 10 13:33:30 gandalf postfix/smtpd[3937]: warning: HOSTNAME[1.1.1.1]: SASL LOGIN authentication failed: authentication failure

View File

@ -1,17 +1,31 @@
# yoh: Kept original apache log lines as well, just in case they might come useful
# for (testing) multiline regular expressions which would further constraint
# SOGo log lines
# failJSON: { "match": false }
Mar 24 08:58:32 sogod [26818]: <0x0xb8537990[LDAPSource]> <NSException: 0xb87c3008> NAME:LDAPException REASON:operation bind failed: Invalid credentials (0x31) INFO:{login = "uid=hack0r,ou=users,dc=mail,dc=example,dc=org"; }
# failJSON: { "time": "2005-03-24T08:58:32", "match": true , "host": "173.194.44.31" }
Mar 24 08:58:32 sogod [26818]: SOGoRootPage Login from '173.194.44.31' for user 'hack0r' might not have worked - password policy: 65535 grace: -1 expire: -1 bound: 0
# failJSON: { "match": false }
173.194.44.31 - - [24/Mar/2013:08:58:32 GMT] "POST /SOGo/connect HTTP/1.1" 403 34/38 0.311 - - 2M
# failJSON: { "match": false }
Mar 24 08:58:40 sogod [26818]: <0x0xb8537990[LDAPSource]> <NSException: 0xb87bb8d8> NAME:LDAPException REASON:operation bind failed: Invalid credentials (0x31) INFO:{login = "uid=kiddy,ou=users,dc=mail,dc=example,dc=org"; }
# failJSON: { "time": "2005-03-24T08:58:40", "match": true , "host": "173.194.44.31" }
Mar 24 08:58:40 sogod [26818]: SOGoRootPage Login from '173.194.44.31' for user 'kiddy' might not have worked - password policy: 65535 grace: -1 expire: -1 bound: 0
# failJSON: { "match": false }
173.194.44.31 - - [24/Mar/2013:08:58:40 GMT] "POST /SOGo/connect HTTP/1.1" 403 34/37 0.007 - - 32K
# failJSON: { "match": false }
Mar 24 08:58:50 sogod [26818]: <0x0xb8537990[LDAPSource]> <NSException: 0xb87c27f8> NAME:LDAPException REASON:operation bind failed: Invalid credentials (0x31) INFO:{login = "uid=plsBanMe,ou=users,dc=mail,dc=example,dc=org"; }
# failJSON: { "time": "2005-03-24T08:58:50", "match": true , "host": "173.194.44.31" }
Mar 24 08:58:50 sogod [26818]: SOGoRootPage Login from '173.194.44.31' for user 'plsBanMe' might not have worked - password policy: 65535 grace: -1 expire: -1 bound: 0
# failJSON: { "match": false }
173.194.44.31 - - [24/Mar/2013:08:58:50 GMT] "POST /SOGo/connect HTTP/1.1" 403 34/40 0.008 - - 0
# failJSON: { "match": false }
Mar 24 08:58:59 sogod [26818]: <0x0xb8537990[LDAPSource]> <NSException: 0xb87be830> NAME:LDAPException REASON:operation bind failed: Invalid credentials (0x31) INFO:{login = "uid=root,ou=users,dc=mail,dc=example,dc=org"; }
# failJSON: { "time": "2005-03-24T08:58:59", "match": true , "host": "173.194.44.31" }
Mar 24 08:58:59 sogod [26818]: SOGoRootPage Login from '173.194.44.31' for user 'root' might not have worked - password policy: 65535 grace: -1 expire: -1 bound: 0
# failJSON: { "match": false }
173.194.44.31 - - [24/Mar/2013:08:58:59 GMT] "POST /SOGo/connect HTTP/1.1" 403 34/36 0.007 - - 0
# failJSON: { "match": false }
Mar 24 08:59:04 sogod [26818]: <0x0xb8537990[LDAPSource]> <NSException: 0xb87bc088> NAME:LDAPException REASON:operation bind failed: Invalid credentials (0x31) INFO:{login = "uid=admin,ou=users,dc=mail,dc=example,dc=org"; }
# failJSON: { "time": "2005-03-24T08:59:04", "match": true , "host": "173.194.44.31" }
Mar 24 08:59:04 sogod [26818]: SOGoRootPage Login from '173.194.44.31' for user 'admin' might not have worked - password policy: 65535 grace: -1 expire: -1 bound: 0

View File

@ -1,53 +1,81 @@
#1
# failJSON: { "time": "2005-06-21T16:47:48", "match": true , "host": "192.030.0.6" }
Jun 21 16:47:48 digital-mlhhyiqscv sshd[13709]: error: PAM: Authentication failure for myhlj1374 from 192.030.0.6
# failJSON: { "time": "2005-05-29T20:56:52", "match": true , "host": "example.com" }
May 29 20:56:52 imago sshd[28732]: error: PAM: Authentication failure for stefanor from example.com
#2
# failJSON: { "time": "2005-02-25T14:34:10", "match": true , "host": "194.117.26.69" }
Feb 25 14:34:10 belka sshd[31602]: Failed password for invalid user ROOT from 194.117.26.69 port 50273 ssh2
# failJSON: { "time": "2005-02-25T14:34:10", "match": true , "host": "194.117.26.70" }
Feb 25 14:34:10 belka sshd[31602]: Failed password for invalid user ROOT from 194.117.26.70 port 12345
#3
# failJSON: { "time": "2005-01-05T01:31:41", "match": true , "host": "1.2.3.4" }
Jan 5 01:31:41 www sshd[1643]: ROOT LOGIN REFUSED FROM 1.2.3.4
# failJSON: { "time": "2005-01-05T01:31:41", "match": true , "host": "1.2.3.4" }
Jan 5 01:31:41 www sshd[1643]: ROOT LOGIN REFUSED FROM ::ffff:1.2.3.4
#4
# failJSON: { "time": "2005-07-20T14:42:11", "match": true , "host": "211.114.51.213" }
Jul 20 14:42:11 localhost sshd[22708]: Invalid user ftp from 211.114.51.213
#5 new filter introduced after looking at 44087D8C.9090407@bluewin.ch
# yoh: added ':' after [sshd] since the case without is not really common any more
# failJSON: { "time": "2005-03-03T00:17:22", "match": true , "host": "211.188.220.49" }
Mar 3 00:17:22 [sshd]: User root from 211.188.220.49 not allowed because not listed in AllowUsers
# failJSON: { "time": "2005-02-25T14:34:11", "match": true , "host": "example.com" }
Feb 25 14:34:11 belka sshd[31607]: User root from example.com not allowed because not listed in AllowUsers
#6 ew filter introduced thanks to report Guido Bozzetto <reportbug@G-B.it>
# failJSON: { "time": "2004-11-11T23:33:27", "match": true , "host": "218.249.210.161" }
Nov 11 23:33:27 Server sshd[5174]: refused connect from _U2FsdGVkX19P3BCJmFBHhjLza8BcMH06WCUVwttMHpE=_@::ffff:218.249.210.161 (::ffff:218.249.210.161)
#7 added exclamation mark to BREAK-IN
# Now should be a negative since we decided not to catch those
# failJSON: { "match": false }
Oct 15 19:51:35 server sshd[7592]: Address 1.2.3.4 maps to 1234.bbbbbb.com, but this does not map back to the address - POSSIBLE BREAK-IN ATTEMPT
# failJSON: { "match": false }
Oct 15 19:51:35 server sshd[7592]: Address 1.2.3.4 maps to 1234.bbbbbb.com, but this does not map back to the address - POSSIBLE BREAK-IN ATTEMPT!
#8 DenyUsers https://github.com/fail2ban/fail2ban/issues/47
# failJSON: { "time": "2005-04-16T22:01:15", "match": true , "host": "46.45.128.3" }
Apr 16 22:01:15 al-ribat sshd[5154]: User root from 46.45.128.3 not allowed because listed in DenyUsers
#9 OpenSolaris patch - pull https://github.com/fail2ban/fail2ban/pull/182
# failJSON: { "time": "2005-03-29T05:59:23", "match": true , "host": "205.186.180.55" }
Mar 29 05:59:23 dusky sshd[20878]: [ID 800047 auth.info] Failed keyboard-interactive for <invalid username> from 205.186.180.55 port 42742 ssh2
# failJSON: { "time": "2005-03-29T05:20:09", "match": true , "host": "205.186.180.30" }
Mar 29 05:20:09 dusky sshd[19558]: [ID 800047 auth.info] Failed keyboard-interactive for james from 205.186.180.30 port 54520 ssh2
#10 OSX syslog error
# failJSON: { "time": "2005-04-29T17:16:20", "match": true , "host": "example.com" }
Apr 29 17:16:20 Jamess-iMac.local sshd[62312]: error: PAM: authentication error for james from example.com via 192.168.1.201
# failJSON: { "time": "2005-04-29T20:11:08", "match": true , "host": "205.186.180.35" }
Apr 29 20:11:08 Jamess-iMac.local sshd[63814]: [ID 800047 auth.info] Failed keyboard-interactive for <invalid username> from 205.186.180.35 port 42742 ssh2
# failJSON: { "time": "2005-04-29T20:12:08", "match": true , "host": "205.186.180.22" }
Apr 29 20:12:08 Jamess-iMac.local sshd[63814]: [ID 800047 auth.info] Failed keyboard-interactive for james from 205.186.180.22 port 54520 ssh2
# failJSON: { "time": "2005-04-29T20:13:08", "match": true , "host": "205.186.180.42" }
Apr 29 20:13:08 Jamess-iMac.local sshd[63814]: Failed keyboard-interactive for james from 205.186.180.42 port 54520 ssh2
# failJSON: { "time": "2005-04-29T20:14:08", "match": true , "host": "205.186.180.44" }
Apr 29 20:14:08 Jamess-iMac.local sshd[63814]: Failed keyboard-interactive for <invalid username> from 205.186.180.44 port 42742 ssh2
# failJSON: { "time": "2005-04-30T01:42:12", "match": true , "host": "205.186.180.77" }
Apr 30 01:42:12 Jamess-iMac.local sshd[2554]: Failed keyboard-interactive/pam for invalid user jamedds from 205.186.180.77 port 33723 ssh2
# failJSON: { "time": "2005-04-29T12:53:38", "match": true , "host": "205.186.180.88" }
Apr 29 12:53:38 Jamess-iMac.local sshd[47831]: error: PAM: authentication failure for james from 205.186.180.88 via 192.168.1.201
# failJSON: { "time": "2005-04-29T13:53:38", "match": true , "host": "205.186.180.99" }
Apr 29 13:53:38 Jamess-iMac.local sshd[47831]: error: PAM: Authentication failure for james from 205.186.180.99 via 192.168.1.201
# failJSON: { "time": "2005-04-29T15:53:38", "match": true , "host": "205.186.180.100" }
Apr 29 15:53:38 Jamess-iMac.local sshd[47831]: error: PAM: Authentication error for james from 205.186.180.100 via 192.168.1.201
# failJSON: { "time": "2005-04-29T16:53:38", "match": true , "host": "205.186.180.101" }
Apr 29 16:53:38 Jamess-iMac.local sshd[47831]: error: PAM: authentication error for james from 205.186.180.101 via 192.168.1.201
# failJSON: { "time": "2005-04-29T17:53:38", "match": true , "host": "205.186.180.102" }
Apr 29 17:53:38 Jamess-iMac.local sshd[47831]: error: PAM: authentication error for james from 205.186.180.102
# failJSON: { "time": "2005-04-29T18:53:38", "match": true , "host": "205.186.180.103" }
Apr 29 18:53:38 Jamess-iMac.local sshd[47831]: error: PAM: authentication error for james from 205.186.180.103
#11 https://github.com/fail2ban/fail2ban/issues/267 There might be no colon after [daemon]
# failJSON: { "time": "2005-06-25T23:53:34", "match": true , "host": "1.2.3.4" }
Jun 25 23:53:34 [sshd] User root from 1.2.3.4 not allowed because not listed in AllowUsers
#12

View File

@ -1,2 +1,3 @@
# http://forums.powervps.com/showthread.php?t=1667
# failJSON: { "time": "2005-06-07T01:10:56", "match": true , "host": "69.61.56.114" }
Jun 7 01:10:56 host sshd[5937]: Did not receive identification string from 69.61.56.114

View File

@ -1,7 +1,10 @@
#1 PAM based
# failJSON: { "time": "2004-10-11T01:06:47", "match": true , "host": "209.67.1.67" }
Oct 11 01:06:47 ServerJV vsftpd: (pam_unix) authentication failure; logname= uid=0 euid=0 tty= ruser= rhost=209.67.1.67
# failJSON: { "time": "2005-02-06T12:02:29", "match": true , "host": "64.168.103.1" }
Feb 6 12:02:29 server vsftpd(pam_unix)[15522]: authentication failure; logname= uid=0 euid=0 tty= ruser= rhost=64.168.103.1 user=user1
#2 Internal
# failJSON: { "time": "2005-01-19T12:20:33", "match": true , "host": "64.106.46.98" }
Fri Jan 19 12:20:33 2007 [pid 27202] [anonymous] FAIL LOGIN: Client "64.106.46.98"

View File

@ -1,7 +1,9 @@
#Webmin authentication failures from /var/log/auth.log
#1 User exists, bad password
# failJSON: { "time": "2004-12-13T08:15:18", "match": true , "host": "89.2.49.230" }
Dec 13 08:15:18 sb1 webmin[25875]: Invalid login as root from 89.2.49.230
#2 User does not exists
# failJSON: { "time": "2004-12-12T23:14:19", "match": true , "host": "188.40.105.142" }
Dec 12 23:14:19 sb1 webmin[22134]: Non-existent login as robert from 188.40.105.142

View File

@ -1,2 +1,3 @@
# This login line is from syslog
# failJSON: { "time": "2004-10-06T09:59:26", "match": true , "host": "202.108.145.173" }
Oct 6 09:59:26 myserver wu-ftpd[18760]: failed login from hj-145-173-a8.bta.net.cn [202.108.145.173]

View File

@ -47,6 +47,8 @@ TEST_FILES_DIR = os.path.join(os.path.dirname(__file__), "files")
# Useful helpers
#
from utils import mtimesleep
# yoh: per Steven Hiscocks's insight while troubleshooting
# https://github.com/fail2ban/fail2ban/issues/103#issuecomment-15542836
# adding a sufficiently large buffer might help to guarantee that
@ -79,18 +81,6 @@ def _killfile(f, name):
_killfile(None, name + '.bak')
def _sleep_4_poll():
"""PollFilter relies on file timestamps - so we might need to
sleep to guarantee that they differ
"""
if sys.version_info[:2] <= (2,4):
# on old Python st_mtime is int, so we should give
# at least 1 sec so polling filter could detect
# the change
time.sleep(1.)
else:
time.sleep(0.1)
def _assert_equal_entries(utest, found, output, count=None):
"""Little helper to unify comparisons with the target entries
@ -133,10 +123,9 @@ def _copy_lines_between_files(in_, fout, n=None, skip=0, mode='a', terminal_line
Returns open fout
"""
if sys.version_info[:2] <= (2,4): # pragma: no cover
# on old Python st_mtime is int, so we should give at least 1 sec so
# polling filter could detect the change
time.sleep(1)
# on old Python st_mtime is int, so we should give at least 1 sec so
# polling filter could detect the change
mtimesleep()
if isinstance(in_, str): # pragma: no branch - only used with str in test cases
fin = open(in_, 'r')
else:
@ -286,14 +275,14 @@ class LogFileMonitor(unittest.TestCase):
# but not any longer
self.assertTrue(self.notModified())
self.assertTrue(self.notModified())
_sleep_4_poll() # to guarantee freshier mtime
mtimesleep() # to guarantee freshier mtime
for i in range(4): # few changes
# unless we write into it
self.file.write("line%d\n" % i)
self.file.flush()
self.assertTrue(self.isModified())
self.assertTrue(self.notModified())
_sleep_4_poll() # to guarantee freshier mtime
mtimesleep() # to guarantee freshier mtime
os.rename(self.name, self.name + '.old')
# we are not signaling as modified whenever
# it gets away
@ -301,7 +290,7 @@ class LogFileMonitor(unittest.TestCase):
f = open(self.name, 'a')
self.assertTrue(self.isModified())
self.assertTrue(self.notModified())
_sleep_4_poll()
mtimesleep()
f.write("line%d\n" % i)
f.flush()
self.assertTrue(self.isModified())
@ -450,7 +439,7 @@ def get_monitor_failures_testcase(Filter_):
# actions might be happening too fast in the tests,
# sleep a bit to guarantee reliable time stamps
if isinstance(self.filter, FilterPoll):
_sleep_4_poll()
mtimesleep()
def isEmpty(self, delay=0.4):
# shorter wait time for not modified status
@ -511,7 +500,9 @@ def get_monitor_failures_testcase(Filter_):
self.file = _copy_lines_between_files(GetFailures.FILENAME_01, self.name,
n=14, mode='w')
# Poll might need more time
self.assertTrue(self.isEmpty(4 + int(isinstance(self.filter, FilterPoll))*2))
self.assertTrue(self.isEmpty(4 + int(isinstance(self.filter, FilterPoll))*2),
"Queue must be empty but it is not: %s."
% (', '.join([str(x) for x in self.jail.queue])))
self.assertRaises(FailManagerEmpty, self.filter.failManager.toBan)
self.assertEqual(self.filter.failManager.getFailTotal(), 2)

View File

@ -0,0 +1,148 @@
# emacs: -*- mode: python; py-indent-offset: 4; indent-tabs-mode: t -*-
# vi: set ft=python sts=4 ts=4 sw=4 noet :
# This file is part of Fail2Ban.
#
# Fail2Ban is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# Fail2Ban is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Fail2Ban; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
# Fail2Ban developers
__copyright__ = "Copyright (c) 2013 Steven Hiscocks"
__license__ = "GPL"
import unittest, sys, os, fileinput, re, datetime, inspect
if sys.version_info >= (2, 6):
import json
else:
import simplejson as json
next = lambda x: x.next()
from fail2ban.server.filter import Filter
from fail2ban.client.filterreader import FilterReader
from fail2ban.tests.utils import setUpMyTime, tearDownMyTime
TEST_FILES_DIR = os.path.join(os.path.dirname(__file__), "files")
if os.path.exists('config/fail2ban.conf'):
CONFIG_DIR = "config"
else:
CONFIG_DIR='/etc/fail2ban'
class FilterSamplesRegex(unittest.TestCase):
def setUp(self):
"""Call before every test case."""
self.filter = Filter(None)
self.filter.setActive(True)
setUpMyTime()
def tearDown(self):
"""Call after every test case."""
tearDownMyTime()
def testFiltersPresent(self):
"""Check to ensure some tests exist"""
self.assertTrue(
len([test for test in inspect.getmembers(self)
if test[0].startswith('testSampleRegexs')])
>= 10,
"Expected more FilterSampleRegexs tests")
def testSampleRegexsFactory(name):
def testFilter(self):
# Check filter exists
filterConf = FilterReader(name, "jail", {}, basedir=CONFIG_DIR)
filterConf.read()
filterConf.getOptions({})
for opt in filterConf.convert():
if opt[2] == "addfailregex":
self.filter.addFailRegex(opt[3])
if not self.filter.getFailRegex():
# No fail regexs set: likely just common file for includes.
return
# TODO: Remove exception handling once sample logs obtained for all
try:
self.assertTrue(
os.path.isfile(os.path.join(TEST_FILES_DIR, "logs", name)),
"No sample log file available for '%s' filter" % name)
except AssertionError:
print "I: No sample log file available for '%s' filter" % name
return
logFile = fileinput.FileInput(
os.path.join(TEST_FILES_DIR, "logs", name))
regexsUsed = set()
for line in logFile:
jsonREMatch = re.match("^# ?failJSON:(.+)$", line)
if jsonREMatch:
try:
faildata = json.loads(jsonREMatch.group(1))
except ValueError, e:
raise ValueError("%s: %s:%i" %
(e, logFile.filename(), logFile.filelineno()))
line = next(logFile)
elif line.startswith("#") or not line.strip():
continue
else:
faildata = {}
ret = self.filter.processLine(
line, returnRawHost=True, checkAllRegex=True)
if not ret:
# Check line is flagged as none match
self.assertFalse(faildata.get('match', True),
"Line not matched when should have: %s:%i %r" %
(logFile.filename(), logFile.filelineno(), line))
elif ret:
# Check line is flagged to match
self.assertTrue(faildata.get('match', False),
"Line matched when shouldn't have: %s:%i %r" %
(logFile.filename(), logFile.filelineno(), line))
self.assertEqual(len(ret), 1, "Multiple regexs matched")
# Verify timestamp and host as expected
failregex, host, time = ret[0]
self.assertEqual(host, faildata.get("host", None))
self.assertEqual(
datetime.datetime.fromtimestamp(time),
datetime.datetime.strptime(
faildata.get("time", None), "%Y-%m-%dT%H:%M:%S"))
regexsUsed.add(failregex)
# TODO: Remove exception handling once all regexs have samples
for failRegexIndex, failRegex in enumerate(self.filter.getFailRegex()):
try:
self.assertTrue(
failRegexIndex in regexsUsed,
"Regex for filter '%s' has no samples: %i: %r" %
(name, failRegexIndex, failRegex))
except AssertionError:
print "I: Regex for filter '%s' has no samples: %i: %r" % (
name, failRegexIndex, failRegex)
return testFilter
for filter_ in os.listdir(os.path.join(CONFIG_DIR, "filter.d")):
filterName = filter_.rpartition(".")[0]
setattr(
FilterSamplesRegex,
"testSampleRegexs%s" % filterName.upper(),
testSampleRegexsFactory(filterName))

View File

@ -354,9 +354,9 @@ class Transmitter(TransmitterBase):
"failed attempt from <HOST> again",
],
[
"user john at (?:::f{4,6}:)?(?P<host>[\w\-.^_]+)",
"Admin user login from (?:::f{4,6}:)?(?P<host>[\w\-.^_]+)",
"failed attempt from (?:::f{4,6}:)?(?P<host>[\w\-.^_]+) again",
"user john at (?:::f{4,6}:)?(?P<host>[\w\-.^_]*\\w)",
"Admin user login from (?:::f{4,6}:)?(?P<host>[\w\-.^_]*\\w)",
"failed attempt from (?:::f{4,6}:)?(?P<host>[\w\-.^_]*\\w) again",
],
self.jailName
)
@ -379,7 +379,7 @@ class Transmitter(TransmitterBase):
],
[
"user john",
"Admin user login from (?:::f{4,6}:)?(?P<host>[\w\-.^_]+)",
"Admin user login from (?:::f{4,6}:)?(?P<host>[\w\-.^_]*\\w)",
"Dont match me!",
],
self.jailName

View File

@ -22,9 +22,17 @@ __author__ = "Yaroslav Halchenko"
__copyright__ = "Copyright (c) 2013 Yaroslav Halchenko"
__license__ = "GPL"
import logging, os, re, traceback, time, unittest
import logging, os, re, traceback, time, unittest, sys
from os.path import basename, dirname
if sys.version_info >= (2, 6):
import json
else:
try:
import simplejson as json
except ImportError:
json = None
from fail2ban.server.mytime import MyTime
logSys = logging.getLogger(__name__)
@ -105,6 +113,11 @@ class FormatterWithTraceBack(logging.Formatter):
record.tbc = record.tb = self._tb()
return logging.Formatter.format(self, record)
def mtimesleep():
# no sleep now should be necessary since polling tracks now not only
# mtime but also ino and size
pass
old_TZ = os.environ.get('TZ', None)
def setUpMyTime():
# Set the time to a fixed, known value
@ -133,6 +146,8 @@ def gatherTests(regexps=None, no_network=False):
from fail2ban.tests import actiontestcase
from fail2ban.tests import sockettestcase
from fail2ban.tests import misctestcase
if json:
from fail2ban.tests import samplestestcase
if not regexps: # pragma: no cover
tests = unittest.TestSuite()
@ -182,6 +197,11 @@ def gatherTests(regexps=None, no_network=False):
# DateDetector
tests.addTest(unittest.makeSuite(datedetectortestcase.DateDetectorTest))
if json:
# Filter Regex tests with sample logs
tests.addTest(unittest.makeSuite(samplestestcase.FilterSamplesRegex))
else:
logSys.warning("I: Skipping filter samples testing. No simplejson/json module")
#
# Extensive use-tests of different available filters backends