mirror of https://github.com/fail2ban/fail2ban
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/wuftpdpull/300/head
commit
1eea0dcec8
34
ChangeLog
34
ChangeLog
|
@ -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
125
DEVELOP
|
@ -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
|
||||
--------------
|
||||
|
||||
|
|
|
@ -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
2
THANKS
|
@ -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
|
||||
|
|
|
@ -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")
|
||||
|
|
|
@ -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]
|
||||
|
|
|
@ -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]
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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+:)?
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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+\])?
|
||||
|
|
@ -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 =
|
|
@ -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*$
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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):
|
||||
|
|
|
@ -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.
|
||||
#
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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/~
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
@ -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
|
|
@ -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)
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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=
|
||||
|
|
|
@ -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
|
||||
|
||||
|
||||
|
|
|
@ -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]
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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"
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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]
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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))
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue