mirror of https://github.com/fail2ban/fail2ban
Merge commit 'remotes/upstream-repo/FAIL2BAN-0_8' into upstream
* commit 'remotes/upstream-repo/FAIL2BAN-0_8': - Added actions to report abuse to ISP, DShield and myNetWatchman. Thanks to Russell Odom. - Added svn:keywords property. - Added apache-nohome.conf. Thanks to Yaroslav Halchenko. - Added new time format. No idea from where it comes... - Added new regex. Thanks to Tobias Offermann. - Try to match the regex even if the line does not contain a valid date/time. Described in Debian #491253. Thanks to Yaroslav Halchenko. - Removed "timeregex" and "timepattern" stuff that is not needed anymore. - Added date template for Day-Month-Year Hour:Minute:Second. - Added date pattern for Hour:Minute:Second. Thanks to Andreas Itzchak Rehberg. - Use current day and month instead of Jan 1st if both are not available in the log. Thanks to Andreas Itzchak Rehberg. - Improved pattern. Thanks to Yaroslav Halchenko. - Merged patches from Debian package. Thanks to Yaroslav Halchenko. - Changed to SVN version. Conflicts: MANIFESTdebian-upstream
commit
3ecce6a188
16
ChangeLog
16
ChangeLog
|
@ -4,9 +4,23 @@
|
||||||
|_| \__,_|_|_/___|_.__/\__,_|_||_|
|
|_| \__,_|_|_/___|_.__/\__,_|_||_|
|
||||||
|
|
||||||
=============================================================
|
=============================================================
|
||||||
Fail2Ban (version 0.8.3) 2008/07/17
|
Fail2Ban (version 0.8.4) 2008/??/??
|
||||||
=============================================================
|
=============================================================
|
||||||
|
|
||||||
|
ver. 0.8.4 (2008/??/??) - stable
|
||||||
|
----------
|
||||||
|
- Merged patches from Debian package. Thanks to Yaroslav
|
||||||
|
Halchenko.
|
||||||
|
- Use current day and month instead of Jan 1st if both are
|
||||||
|
not available in the log. Thanks to Andreas Itzchak
|
||||||
|
Rehberg.
|
||||||
|
- Try to match the regex even if the line does not contain a
|
||||||
|
valid date/time. Described in Debian #491253. Thanks to
|
||||||
|
Yaroslav Halchenko.
|
||||||
|
- Added/improved filters and date formats.
|
||||||
|
- Added actions to report abuse to ISP, DShield and
|
||||||
|
myNetWatchman. Thanks to Russell Odom.
|
||||||
|
|
||||||
ver. 0.8.3 (2008/07/17) - stable
|
ver. 0.8.3 (2008/07/17) - stable
|
||||||
----------
|
----------
|
||||||
- Process failtickets as long as failmanager is not empty.
|
- Process failtickets as long as failmanager is not empty.
|
||||||
|
|
9
README
9
README
|
@ -4,7 +4,7 @@
|
||||||
|_| \__,_|_|_/___|_.__/\__,_|_||_|
|
|_| \__,_|_|_/___|_.__/\__,_|_||_|
|
||||||
|
|
||||||
=============================================================
|
=============================================================
|
||||||
Fail2Ban (version 0.8.3) 2008/07/17
|
Fail2Ban (version 0.8.4) 2008/??/??
|
||||||
=============================================================
|
=============================================================
|
||||||
|
|
||||||
Fail2Ban scans log files like /var/log/pwdfail and bans IP
|
Fail2Ban scans log files like /var/log/pwdfail and bans IP
|
||||||
|
@ -28,8 +28,8 @@ Optional:
|
||||||
|
|
||||||
To install, just do:
|
To install, just do:
|
||||||
|
|
||||||
> tar xvfj fail2ban-0.8.3.tar.bz2
|
> tar xvfj fail2ban-0.8.4.tar.bz2
|
||||||
> cd fail2ban-0.8.3
|
> cd fail2ban-0.8.4
|
||||||
> python setup.py install
|
> python setup.py install
|
||||||
|
|
||||||
This will install Fail2Ban into /usr/share/fail2ban. The
|
This will install Fail2Ban into /usr/share/fail2ban. The
|
||||||
|
@ -76,7 +76,8 @@ René Berber, mEDI, Axel Thimm, Eric Gerbier, Christian Rauch,
|
||||||
Michael C. Haller, Jonathan Underwood, Hanno 'Rince' Wagner,
|
Michael C. Haller, Jonathan Underwood, Hanno 'Rince' Wagner,
|
||||||
Daniel B. Cid, David Nutter, Raphaël Marichez, Guillaume
|
Daniel B. Cid, David Nutter, Raphaël Marichez, Guillaume
|
||||||
Delvit, Vaclav Misek, Adrien Clerc, Michael Hanselmann,
|
Delvit, Vaclav Misek, Adrien Clerc, Michael Hanselmann,
|
||||||
Vincent Deffontaines, Bill Heaton and many others.
|
Vincent Deffontaines, Bill Heaton, Russell Odom and many
|
||||||
|
others.
|
||||||
|
|
||||||
License:
|
License:
|
||||||
--------
|
--------
|
||||||
|
|
|
@ -53,20 +53,14 @@ class FilterReader(ConfigReader):
|
||||||
return ConfigReader.read(self, "filter.d/" + self.__file)
|
return ConfigReader.read(self, "filter.d/" + self.__file)
|
||||||
|
|
||||||
def getOptions(self, pOpts):
|
def getOptions(self, pOpts):
|
||||||
opts = [["string", "timeregex", None],
|
opts = [["string", "ignoreregex", ""],
|
||||||
["string", "timepattern", None],
|
|
||||||
["string", "ignoreregex", ""],
|
|
||||||
["string", "failregex", ""]]
|
["string", "failregex", ""]]
|
||||||
self.__opts = ConfigReader.getOptions(self, "Definition", opts, pOpts)
|
self.__opts = ConfigReader.getOptions(self, "Definition", opts, pOpts)
|
||||||
|
|
||||||
def convert(self):
|
def convert(self):
|
||||||
stream = list()
|
stream = list()
|
||||||
for opt in self.__opts:
|
for opt in self.__opts:
|
||||||
if opt == "timeregex":
|
if opt == "failregex":
|
||||||
stream.append(["set", self.__name, "timeregex", self.__opts[opt]])
|
|
||||||
elif opt == "timepattern":
|
|
||||||
stream.append(["set", self.__name, "timepattern", self.__opts[opt]])
|
|
||||||
elif opt == "failregex":
|
|
||||||
for regex in self.__opts[opt].split('\n'):
|
for regex in self.__opts[opt].split('\n'):
|
||||||
# Do not send a command if the rule is empty.
|
# Do not send a command if the rule is empty.
|
||||||
if regex != '':
|
if regex != '':
|
||||||
|
|
|
@ -72,8 +72,6 @@ protocol = [
|
||||||
['', "JAIL INFORMATION", ""],
|
['', "JAIL INFORMATION", ""],
|
||||||
["get <JAIL> logpath", "gets the list of the monitored files for <JAIL>"],
|
["get <JAIL> logpath", "gets the list of the monitored files for <JAIL>"],
|
||||||
["get <JAIL> ignoreip", "gets the list of ignored IP addresses for <JAIL>"],
|
["get <JAIL> ignoreip", "gets the list of ignored IP addresses for <JAIL>"],
|
||||||
["get <JAIL> timeregex", "gets the regular expression used for the time detection for <JAIL>"],
|
|
||||||
["get <JAIL> timepattern", "gets the pattern used for the time detection for <JAIL>"],
|
|
||||||
["get <JAIL> failregex", "gets the list of regular expressions which matches the failures for <JAIL>"],
|
["get <JAIL> failregex", "gets the list of regular expressions which matches the failures for <JAIL>"],
|
||||||
["get <JAIL> ignoreregex", "gets the list of regular expressions which matches patterns to ignore for <JAIL>"],
|
["get <JAIL> ignoreregex", "gets the list of regular expressions which matches patterns to ignore for <JAIL>"],
|
||||||
["get <JAIL> findtime", "gets the time for which the filter will look back for failures for <JAIL>"],
|
["get <JAIL> findtime", "gets the time for which the filter will look back for failures for <JAIL>"],
|
||||||
|
|
|
@ -24,4 +24,4 @@ __date__ = "$Date: 2008-07-17 23:28:51 +0200 (Thu, 17 Jul 2008) $"
|
||||||
__copyright__ = "Copyright (c) 2004 Cyril Jaquier"
|
__copyright__ = "Copyright (c) 2004 Cyril Jaquier"
|
||||||
__license__ = "GPL"
|
__license__ = "GPL"
|
||||||
|
|
||||||
version = "0.8.3"
|
version = "0.8.3-SVN"
|
||||||
|
|
|
@ -0,0 +1,86 @@
|
||||||
|
# Fail2Ban configuration file
|
||||||
|
#
|
||||||
|
# Author: Russell Odom <russ@gloomytrousers.co.uk>
|
||||||
|
# Sends a complaint e-mail to addresses listed in the whois record for an
|
||||||
|
# offending IP address.
|
||||||
|
#
|
||||||
|
# You should provide the <logpath> in the jail config - lines from the log
|
||||||
|
# matching the given IP address will be provided in the complaint as evidence.
|
||||||
|
#
|
||||||
|
# Note that we will try to use e-mail addresses that are most likely to be abuse
|
||||||
|
# addresses (based on various keywords). If they aren't found we fall back on
|
||||||
|
# any other addresses found in the whois record, with a few exceptions.
|
||||||
|
# If no addresses are found, no e-mail is sent.
|
||||||
|
#
|
||||||
|
# $Revision$
|
||||||
|
#
|
||||||
|
|
||||||
|
[Definition]
|
||||||
|
|
||||||
|
# Option: actionstart
|
||||||
|
# Notes.: command executed once at the start of Fail2Ban.
|
||||||
|
# Values: CMD
|
||||||
|
#
|
||||||
|
actionstart =
|
||||||
|
|
||||||
|
# Option: actionstop
|
||||||
|
# Notes.: command executed once at the end of Fail2Ban
|
||||||
|
# Values: CMD
|
||||||
|
#
|
||||||
|
actionstop =
|
||||||
|
|
||||||
|
# Option: actioncheck
|
||||||
|
# Notes.: command executed once before each actionban command
|
||||||
|
# Values: CMD
|
||||||
|
#
|
||||||
|
actioncheck =
|
||||||
|
|
||||||
|
# Option: actionban
|
||||||
|
# Notes.: command executed when banning an IP. Take care that the
|
||||||
|
# command is executed with Fail2Ban user rights.
|
||||||
|
# Tags: <ip> IP address
|
||||||
|
# <failures> number of failures
|
||||||
|
# <failtime> unix timestamp of the last failure
|
||||||
|
# <bantime> unix timestamp of the ban time
|
||||||
|
# Values: CMD
|
||||||
|
#
|
||||||
|
actionban = ADDRESSES=`whois <ip> | perl -e 'while (<STDIN>) { next if /^changed|@(ripe|apnic)\.net/io; $m += (/abuse|trouble:|report|spam|security/io?3:0); if (/([a-z0-9_\-\.+]+@[a-z0-9\-]+(\.[[a-z0-9\-]+)+)/io) { while (s/([a-z0-9_\-\.+]+@[a-z0-9\-]+(\.[[a-z0-9\-]+)+)//io) { if ($m) { $a{lc($1)}=$m } else { $b{lc($1)}=$m } } $m=0 } else { $m && --$m } } if (%%a) {print join(",",keys(%%a))} else {print join(",",keys(%%b))}'`
|
||||||
|
IP=<ip>
|
||||||
|
if [ ! -z "$ADDRESSES" ]; then
|
||||||
|
(printf %%b "<message>\n"; date '+Note: Local timezone is %%z (%%Z)'; grep '<ip>' <logpath>) | <mailcmd> "Abuse from <ip>" $ADDRESSES <mailargs>
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Option: actionunban
|
||||||
|
# Notes.: command executed when unbanning an IP. Take care that the
|
||||||
|
# command is executed with Fail2Ban user rights.
|
||||||
|
# Tags: <ip> IP address
|
||||||
|
# <bantime> unix timestamp of the ban time
|
||||||
|
# <unbantime> unix timestamp of the unban time
|
||||||
|
# Values: CMD
|
||||||
|
#
|
||||||
|
actionunban =
|
||||||
|
|
||||||
|
[Init]
|
||||||
|
message = Dear Sir/Madam,\n\nWe have detected abuse from the IP address $IP, which according to a whois lookup is on your network. We would appreciate if you would investigate and take action as appropriate.\n\nLog lines are given below, but please ask if you require any further information.\n\n(If you are not the correct person to contact about this please accept our apologies - your e-mail address was extracted from the whois record by an automated process. This mail was generated by Fail2Ban.)\n
|
||||||
|
|
||||||
|
# Path to the log files which contain relevant lines for the abuser IP
|
||||||
|
#
|
||||||
|
logpath = /dev/null
|
||||||
|
|
||||||
|
# Option: mailcmd
|
||||||
|
# Notes.: Your system mail command. Is passed 2 args: subject and recipient
|
||||||
|
# Values: CMD Default: mail -s
|
||||||
|
#
|
||||||
|
mailcmd = mail -s
|
||||||
|
|
||||||
|
# Option: mailargs
|
||||||
|
# Notes.: Additional arguments to mail command. e.g. for standard Unix mail:
|
||||||
|
# CC reports to another address:
|
||||||
|
# -c me@example.com
|
||||||
|
# Appear to come from a different address - the '--' indicates
|
||||||
|
# arguments to be passed to Sendmail:
|
||||||
|
# -- -f me@example.com
|
||||||
|
# Values: [ STRING ] Default: (empty)
|
||||||
|
#
|
||||||
|
mailargs =
|
||||||
|
|
|
@ -0,0 +1,210 @@
|
||||||
|
# Fail2Ban configuration file
|
||||||
|
#
|
||||||
|
# Author: Russell Odom <russ@gloomytrousers.co.uk>
|
||||||
|
# Submits attack reports to DShield (http://www.dshield.org/)
|
||||||
|
#
|
||||||
|
# You MUST configure at least:
|
||||||
|
# <port> (the port that's being attacked - use number not name).
|
||||||
|
#
|
||||||
|
# You SHOULD also provide:
|
||||||
|
# <myip> (your public IP address, if it's not the address of eth0)
|
||||||
|
# <userid> (your DShield userID, if you have one - recommended, but reports will
|
||||||
|
# be used anonymously if not)
|
||||||
|
# <protocol> (the protocol in use - defaults to tcp)
|
||||||
|
#
|
||||||
|
# Best practice is to provide <port> and <protocol> in jail.conf like this:
|
||||||
|
# action = dshield[port=1234,protocol=tcp]
|
||||||
|
#
|
||||||
|
# ...and create "dshield.local" with contents something like this:
|
||||||
|
# [Init]
|
||||||
|
# myip = 10.0.0.1
|
||||||
|
# userid = 12345
|
||||||
|
#
|
||||||
|
# Other useful configuration values are <mailargs> (you can use for specifying
|
||||||
|
# a different sender address for the report e-mails, which should match what is
|
||||||
|
# configured at DShield), and <lines>/<minreportinterval>/<maxbufferage> (to
|
||||||
|
# configure how often the buffer is flushed).
|
||||||
|
#
|
||||||
|
# $Revision$
|
||||||
|
|
||||||
|
[Definition]
|
||||||
|
|
||||||
|
# Option: actionstart
|
||||||
|
# Notes.: command executed once at the start of Fail2Ban.
|
||||||
|
# Values: CMD
|
||||||
|
#
|
||||||
|
actionstart =
|
||||||
|
|
||||||
|
# Option: actionstop
|
||||||
|
# Notes.: command executed once at the end of Fail2Ban
|
||||||
|
# Values: CMD
|
||||||
|
#
|
||||||
|
actionstop = if [ -f <tmpfile>.buffer ]; then
|
||||||
|
cat <tmpfile>.buffer | <mailcmd> "FORMAT DSHIELD USERID <userid> TZ `date +%%z | sed 's/\([+-]..\)\(..\)/\1:\2/'` Fail2Ban" <dest> <mailargs>
|
||||||
|
date +%%s > <tmpfile>.lastsent
|
||||||
|
fi
|
||||||
|
rm -f <tmpfile>.buffer <tmpfile>.first
|
||||||
|
|
||||||
|
# Option: actioncheck
|
||||||
|
# Notes.: command executed once before each actionban command
|
||||||
|
# Values: CMD
|
||||||
|
#
|
||||||
|
actioncheck =
|
||||||
|
|
||||||
|
# Option: actionban
|
||||||
|
# Notes.: command executed when banning an IP. Take care that the
|
||||||
|
# command is executed with Fail2Ban user rights.
|
||||||
|
# Tags: <ip> IP address
|
||||||
|
# <failures> number of failures
|
||||||
|
# <time> unix timestamp of the ban time
|
||||||
|
# Values: CMD
|
||||||
|
#
|
||||||
|
# See http://www.dshield.org/specs.html for more on report format/notes
|
||||||
|
#
|
||||||
|
# Note: We are currently using <time> for the timestamp because no tag is
|
||||||
|
# available to indicate the timestamp of the log message(s) which triggered the
|
||||||
|
# ban. Therefore the timestamps we are using in the report, whilst often only a
|
||||||
|
# few seconds out, are incorrect. See
|
||||||
|
# http://sourceforge.net/tracker/index.php?func=detail&aid=2017795&group_id=121032&atid=689047
|
||||||
|
#
|
||||||
|
actionban = TZONE=`date +%%z | sed 's/\([+-]..\)\(..\)/\1:\2/'`
|
||||||
|
DATETIME="`perl -e '@t=localtime(<time>);printf "%%4d-%%02d-%%02d %%02d:%%02d:%%02d",1900+$t[5],$t[4]+1,$t[3],$t[2],$t[1],$t[0]'` $TZONE"
|
||||||
|
PROTOCOL=`awk '{IGNORECASE=1;if($1=="<protocol>"){print $2;exit}}' /etc/protocols`
|
||||||
|
if [ -z "$PROTOCOL" ]; then PROTOCOL=<protocol>; fi
|
||||||
|
printf %%b "$DATETIME\t<userid>\t<failures>\t<ip>\t<srcport>\t<myip>\t<port>\t$PROTOCOL\t<tcpflags>\n" >> <tmpfile>.buffer
|
||||||
|
NOW=`date +%%s`
|
||||||
|
if [ ! -f <tmpfile>.first ]; then
|
||||||
|
echo <time> | cut -d. -f1 > <tmpfile>.first
|
||||||
|
fi
|
||||||
|
if [ ! -f <tmpfile>.lastsent ]; then
|
||||||
|
echo 0 > <tmpfile>.lastsent
|
||||||
|
fi
|
||||||
|
LOGAGE=$(($NOW - `cat <tmpfile>.first`))
|
||||||
|
LASTREPORT=$(($NOW - `cat <tmpfile>.lastsent`))
|
||||||
|
LINES=$( wc -l <tmpfile>.buffer | awk '{ print $1 }' )
|
||||||
|
if [ $LINES -ge <lines> && $LASTREPORT -gt <minreportinterval> ] || [ $LOGAGE -gt <maxbufferage> ]; then
|
||||||
|
cat <tmpfile>.buffer | <mailcmd> "FORMAT DSHIELD USERID <userid> TZ $TZONE Fail2Ban" <dest> <mailargs>
|
||||||
|
rm -f <tmpfile>.buffer <tmpfile>.first
|
||||||
|
echo $NOW > <tmpfile>.lastsent
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Option: actionunban
|
||||||
|
# Notes.: command executed when unbanning an IP. Take care that the
|
||||||
|
# command is executed with Fail2Ban user rights.
|
||||||
|
# Tags: <ip> IP address
|
||||||
|
# <failures> number of failures
|
||||||
|
# <time> unix timestamp of the ban time
|
||||||
|
# Values: CMD
|
||||||
|
#
|
||||||
|
actionunban = if [ -f <tmpfile>.first ]; then
|
||||||
|
NOW=`date +%%s`
|
||||||
|
LOGAGE=$(($NOW - `cat <tmpfile>.first`))
|
||||||
|
if [ $LOGAGE -gt <maxbufferage> ]; then
|
||||||
|
cat <tmpfile>.buffer | <mailcmd> "FORMAT DSHIELD USERID <userid> TZ `date +%%z | sed 's/\([+-]..\)\(..\)/\1:\2/'` Fail2Ban" <dest> <mailargs>
|
||||||
|
rm -f <tmpfile>.buffer <tmpfile>.first
|
||||||
|
echo $NOW > <tmpfile>.lastsent
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
[Init]
|
||||||
|
# Option: port
|
||||||
|
# Notes.: The target port for the attack (numerical). MUST be provided in the
|
||||||
|
# jail config, as it cannot be detected here.
|
||||||
|
# Values: [ NUM ] Default: ???
|
||||||
|
#
|
||||||
|
port = ???
|
||||||
|
|
||||||
|
# Option: userid
|
||||||
|
# Notes.: Your DSheild user ID. Should be provided either in the jail config or
|
||||||
|
# in a .local file.
|
||||||
|
# Register at https://secure.dshield.org/register.html
|
||||||
|
# Values: [ NUM ] Default: 0
|
||||||
|
#
|
||||||
|
userid = 0
|
||||||
|
|
||||||
|
# Option: myip
|
||||||
|
# Notes.: TThe target IP for the attack (your public IP). Should be provided
|
||||||
|
# either in the jail config or in a .local file unless your PUBLIC IP
|
||||||
|
# is the first IP assigned to eth0
|
||||||
|
# Values: [ an IP address ] Default: Tries to find the IP address of eth0,
|
||||||
|
# which in most cases will be a private IP, and therefore incorrect
|
||||||
|
#
|
||||||
|
myip = `ip -4 addr show dev eth0 | grep inet | head -1 | sed -r 's/.*inet ([0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}).*/\1/'`
|
||||||
|
|
||||||
|
# Option: protocol
|
||||||
|
# Notes.: The protocol over which the attack is happening
|
||||||
|
# Values: [ tcp | udp | icmp | (any other protocol name from /etc/protocols) | NUM ] Default: tcp
|
||||||
|
#
|
||||||
|
protocol = tcp
|
||||||
|
|
||||||
|
# Option: lines
|
||||||
|
# Notes.: How many lines to buffer before making a report. Regardless of this,
|
||||||
|
# reports are sent a minimum of <minreportinterval> apart, or if the
|
||||||
|
# buffer contains an event over <maxbufferage> old, or on shutdown
|
||||||
|
# Values: [ NUM ] Default: 50
|
||||||
|
#
|
||||||
|
lines = 50
|
||||||
|
|
||||||
|
# Option: minreportinterval
|
||||||
|
# Notes.: Minimum period (in seconds) that must elapse before we submit another
|
||||||
|
# batch of reports. DShield request a minimum of 1 hour (3600 secs)
|
||||||
|
# between reports.
|
||||||
|
# Values: [ NUM ] Default: 3600
|
||||||
|
#
|
||||||
|
minreportinterval = 3600
|
||||||
|
|
||||||
|
# Option: maxbufferage
|
||||||
|
# Notes.: Maximum age (in seconds) of the oldest report in the buffer before we
|
||||||
|
# submit the batch, even if we haven't reached <lines> yet. Note that
|
||||||
|
# this is only checked on each ban/unban, and that we always send
|
||||||
|
# anything in the buffer on shutdown. Must be greater than
|
||||||
|
# <minreportinterval>.
|
||||||
|
# Values: [ NUM ] Default: 21600 (6 hours)
|
||||||
|
#
|
||||||
|
maxbufferage = 21600
|
||||||
|
|
||||||
|
# Option: srcport
|
||||||
|
# Notes.: The source port of the attack. You're unlikely to have this info, so
|
||||||
|
# you can leave the default
|
||||||
|
# Values: [ NUM ] Default: ???
|
||||||
|
#
|
||||||
|
srcport = ???
|
||||||
|
|
||||||
|
# Option: tcpflags
|
||||||
|
# Notes.: TCP flags on attack. You're unlikely to have this info, so you can
|
||||||
|
# leave empty
|
||||||
|
# Values: [ STRING ] Default: (empty)
|
||||||
|
#
|
||||||
|
tcpflags =
|
||||||
|
|
||||||
|
# Option: mailcmd
|
||||||
|
# Notes.: Your system mail command. Is passed 2 args: subject and recipient
|
||||||
|
# Values: CMD Default: mail -s
|
||||||
|
#
|
||||||
|
mailcmd = mail -s
|
||||||
|
|
||||||
|
# Option: mailargs
|
||||||
|
# Notes.: Additional arguments to mail command. e.g. for standard Unix mail:
|
||||||
|
# CC reports to another address:
|
||||||
|
# -c me@example.com
|
||||||
|
# Appear to come from a different address (the From address must match
|
||||||
|
# the one configured at DShield - the '--' indicates arguments to be
|
||||||
|
# passed to Sendmail):
|
||||||
|
# -- -f me@example.com
|
||||||
|
# Values: [ STRING ] Default: (empty)
|
||||||
|
#
|
||||||
|
mailargs =
|
||||||
|
|
||||||
|
# Option: dest
|
||||||
|
# Notes.: Destination e-mail address for reports
|
||||||
|
# Values: [ STRING ] Default: reports@dshield.org
|
||||||
|
#
|
||||||
|
dest = reports@dshield.org
|
||||||
|
|
||||||
|
# Option: tmpfile
|
||||||
|
# Notes.: Base name of temporary files used for buffering
|
||||||
|
# Values: [ STRING ] Default: /tmp/fail2ban-dshield
|
||||||
|
#
|
||||||
|
tmpfile = /tmp/fail2ban-dshield
|
||||||
|
|
|
@ -0,0 +1,144 @@
|
||||||
|
# Fail2Ban configuration file
|
||||||
|
#
|
||||||
|
# Author: Russell Odom <russ@gloomytrousers.co.uk>
|
||||||
|
# Submits attack reports to myNetWatchman (http://www.mynetwatchman.com/)
|
||||||
|
#
|
||||||
|
# You MUST configure at least:
|
||||||
|
# <port> (the port that's being attacked - use number not name).
|
||||||
|
# <mnwlogin> (your mNW login).
|
||||||
|
# <mnwpass> (your mNW password).
|
||||||
|
#
|
||||||
|
# You SHOULD also provide:
|
||||||
|
# <myip> (your public IP address, if it's not the address of eth0)
|
||||||
|
# <protocol> (the protocol in use - defaults to tcp)
|
||||||
|
#
|
||||||
|
# Best practice is to provide <port> and <protocol> in jail.conf like this:
|
||||||
|
# action = mynetwatchman[port=1234,protocol=udp]
|
||||||
|
#
|
||||||
|
# ...and create "mynetwatchman.local" with contents something like this:
|
||||||
|
# [Init]
|
||||||
|
# mnwlogin = me@example.com
|
||||||
|
# mnwpass = SECRET
|
||||||
|
# myip = 10.0.0.1
|
||||||
|
#
|
||||||
|
# Another useful configuration value is <getcmd>, if you don't have wget
|
||||||
|
# installed (an example config for curl is given below)
|
||||||
|
#
|
||||||
|
# $Revision$
|
||||||
|
|
||||||
|
[Definition]
|
||||||
|
|
||||||
|
# Option: actionstart
|
||||||
|
# Notes.: command executed once at the start of Fail2Ban.
|
||||||
|
# Values: CMD
|
||||||
|
#
|
||||||
|
actionstart =
|
||||||
|
|
||||||
|
# Option: actionstop
|
||||||
|
# Notes.: command executed once at the end of Fail2Ban
|
||||||
|
# Values: CMD
|
||||||
|
#
|
||||||
|
actionstop =
|
||||||
|
|
||||||
|
# Option: actioncheck
|
||||||
|
# Notes.: command executed once before each actionban command
|
||||||
|
# Values: CMD
|
||||||
|
#
|
||||||
|
actioncheck =
|
||||||
|
|
||||||
|
# Option: actionban
|
||||||
|
# Notes.: command executed when banning an IP. Take care that the
|
||||||
|
# command is executed with Fail2Ban user rights.
|
||||||
|
# Tags: <ip> IP address
|
||||||
|
# <failures> number of failures
|
||||||
|
# <time> unix timestamp of the ban time
|
||||||
|
# Values: CMD
|
||||||
|
#
|
||||||
|
#
|
||||||
|
# Note: We are currently using <time> for the timestamp because no tag is
|
||||||
|
# available to indicate the timestamp of the log message(s) which triggered the
|
||||||
|
# ban. Therefore the timestamps we are using in the report, whilst often only a
|
||||||
|
# few seconds out, are incorrect. See
|
||||||
|
# http://sourceforge.net/tracker/index.php?func=detail&aid=2017795&group_id=121032&atid=689047
|
||||||
|
#
|
||||||
|
actionban = MNWLOGIN=`perl -e '$s=shift;$s=~s/([\W])/"%%".uc(sprintf("%%2.2x",ord($1)))/eg;print $s' '<mnwlogin>'`
|
||||||
|
MNWPASS=`perl -e '$s=shift;$s=~s/([\W])/"%%".uc(sprintf("%%2.2x",ord($1)))/eg;print $s' '<mnwpass>'`
|
||||||
|
PROTOCOL=`awk '{IGNORECASE=1;if($1=="<protocol>"){print $2;exit}}' /etc/protocols`
|
||||||
|
if [ -z "$PROTOCOL" ]; then PROTOCOL=<protocol>; fi
|
||||||
|
DATETIME=`perl -e '@t=gmtime(<time>);printf "%%4d-%%02d-%%02d+%%02d:%%02d:%%02d",1900+$t[5],$t[4]+1,$t[3],$t[2],$t[1],$t[0]'`
|
||||||
|
<getcmd> "<mnwurl>?AT=2&AV=0&AgentEmail=$MNWLOGIN&AgentPassword=$MNWPASS&AttackerIP=<ip>&SrcPort=<srcport>&ProtocolID=$PROTOCOL&DestPort=<port>&AttackCount=<failures>&VictimIP=<myip>&AttackDateTime=$DATETIME" 2>&1 >> <tmpfile>.out && grep -q 'Attack Report Insert Successful' <tmpfile>.out && rm -f <tmpfile>.out
|
||||||
|
|
||||||
|
# Option: actionunban
|
||||||
|
# Notes.: command executed when unbanning an IP. Take care that the
|
||||||
|
# command is executed with Fail2Ban user rights.
|
||||||
|
# Tags: <ip> IP address
|
||||||
|
# <failures> number of failures
|
||||||
|
# <time> unix timestamp of the ban time
|
||||||
|
# Values: CMD
|
||||||
|
#
|
||||||
|
actionunban =
|
||||||
|
|
||||||
|
[Init]
|
||||||
|
# Option: port
|
||||||
|
# Notes.: The target port for the attack (numerical). MUST be provided in
|
||||||
|
# the jail config, as it cannot be detected here.
|
||||||
|
# Values: [ NUM ] Default: ???
|
||||||
|
#
|
||||||
|
port = 0
|
||||||
|
|
||||||
|
# Option: mnwlogin
|
||||||
|
# Notes.: Your mNW login e-mail address. MUST be provided either in the jail
|
||||||
|
# config or in a .local file.
|
||||||
|
# Register at http://www.mynetwatchman.com/reg.asp
|
||||||
|
# Values: [ STRING ] Default: (empty)
|
||||||
|
#
|
||||||
|
mnwlogin =
|
||||||
|
|
||||||
|
# Option: mnwpass
|
||||||
|
# Notes.: The password corresponding to your mNW login e-mail address. MUST be
|
||||||
|
# provided either in the jail config or in a .local file.
|
||||||
|
# Values: [ STRING ] Default: (empty)
|
||||||
|
#
|
||||||
|
mnwpass =
|
||||||
|
|
||||||
|
# Option: myip
|
||||||
|
# Notes.: TThe target IP for the attack (your public IP). Should be overridden
|
||||||
|
# either in the jail config or in a .local file unless your PUBLIC IP
|
||||||
|
# is the first IP assigned to eth0
|
||||||
|
# Values: [ an IP address ] Default: Tries to find the IP address of eth0,
|
||||||
|
# which in most cases will be a private IP, and therefore incorrect
|
||||||
|
#
|
||||||
|
myip = `ip -4 addr show dev eth0 | grep inet | head -1 | sed -r 's/.*inet ([0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}).*/\1/'`
|
||||||
|
|
||||||
|
# Option: protocol
|
||||||
|
# Notes.: The protocol over which the attack is happening
|
||||||
|
# Values: [ tcp | udp | icmp | (any other protocol name from /etc/protocols) | NUM ] Default: tcp
|
||||||
|
#
|
||||||
|
protocol = tcp
|
||||||
|
|
||||||
|
# Option: getcmd
|
||||||
|
# Notes.: A command to fetch a URL. Should output page to STDOUT
|
||||||
|
# Values: CMD Default: wget
|
||||||
|
#
|
||||||
|
getcmd = wget --no-verbose --tries=3 --waitretry=10 --connect-timeout=10 --read-timeout=60 --retry-connrefused --output-document=- --user-agent=Fail2Ban
|
||||||
|
# Alternative value:
|
||||||
|
# getcmd = curl --silent --show-error --retry 3 --connect-timeout 10 --max-time 60 --user-agent Fail2Ban
|
||||||
|
|
||||||
|
# Option: srcport
|
||||||
|
# Notes.: The source port of the attack. You're unlikely to have this info, so
|
||||||
|
# you can leave the default
|
||||||
|
# Values: [ NUM ] Default: 0
|
||||||
|
#
|
||||||
|
srcport = 0
|
||||||
|
|
||||||
|
# Option: mnwurl
|
||||||
|
# Notes.: The report service URL on the mNW site
|
||||||
|
# Values: STRING Default: http://mynetwatchman.com/insertwebreport.asp
|
||||||
|
#
|
||||||
|
mnwurl = http://mynetwatchman.com/insertwebreport.asp
|
||||||
|
|
||||||
|
# Option: tmpfile
|
||||||
|
# Notes.: Base name of temporary files
|
||||||
|
# Values: [ STRING ] Default: /tmp/fail2ban-mynetwatchman
|
||||||
|
#
|
||||||
|
tmpfile = /tmp/fail2ban-mynetwatchman
|
|
@ -0,0 +1,23 @@
|
||||||
|
# Fail2Ban configuration file
|
||||||
|
#
|
||||||
|
# Author: Yaroslav O. Halchenko <debian@onerussian.com>
|
||||||
|
#
|
||||||
|
# $Revision$
|
||||||
|
#
|
||||||
|
|
||||||
|
[Definition]
|
||||||
|
|
||||||
|
# Option: failregex
|
||||||
|
# Notes.: regex to match failures to find a home directory on a server, which
|
||||||
|
# became popular last days. Most often attacker just uses IP instead of
|
||||||
|
# domain name -- so expect to see them in generic error.log if you have
|
||||||
|
# per-domain log files.
|
||||||
|
# Values: TEXT
|
||||||
|
#
|
||||||
|
failregex = [[]client <HOST>[]] File does not exist: .*/~.*
|
||||||
|
|
||||||
|
# Option: ignoreregex
|
||||||
|
# Notes.: regex to ignore. If this regex matches, the line is ignored.
|
||||||
|
# Values: TEXT
|
||||||
|
#
|
||||||
|
ignoreregex =
|
|
@ -14,7 +14,8 @@
|
||||||
# (?:::f{4,6}:)?(?P<host>\S+)
|
# (?:::f{4,6}:)?(?P<host>\S+)
|
||||||
# Values: TEXT
|
# Values: TEXT
|
||||||
#
|
#
|
||||||
failregex = [[]client <HOST>[]] (File does not exist|script not found or unable to stat): .*(\.php|\.asp|\.exe|\.pl)
|
failregex = [[]client <HOST>[]] (File does not exist|script not found or unable to stat): /\S*(\.php|\.asp|\.exe|\.pl)
|
||||||
|
[[]client <HOST>[]] script '/\S*(\.php|\.asp|\.exe|\.pl)\S*' not found or unable to stat *$
|
||||||
|
|
||||||
# Option: ignoreregex
|
# Option: ignoreregex
|
||||||
# Notes.: regex to ignore. If this regex matches, the line is ignored.
|
# Notes.: regex to ignore. If this regex matches, the line is ignored.
|
||||||
|
|
|
@ -24,13 +24,15 @@ _daemon = sshd
|
||||||
# Values: TEXT
|
# Values: TEXT
|
||||||
#
|
#
|
||||||
failregex = ^%(__prefix_line)s(?:error: PAM: )?Authentication failure for .* from <HOST>\s*$
|
failregex = ^%(__prefix_line)s(?:error: PAM: )?Authentication failure for .* from <HOST>\s*$
|
||||||
^%(__prefix_line)sFailed [-/\w]+ for .* from <HOST>(?: port \d*)?(?: ssh\d*)?$
|
^%(__prefix_line)s(?:error: PAM: )?User not known to the underlying authentication module for .* from <HOST>\s*$
|
||||||
|
^%(__prefix_line)sFailed (?:password|publickey) for .* from <HOST>(?: port \d*)?(?: ssh\d*)?$
|
||||||
^%(__prefix_line)sROOT LOGIN REFUSED.* FROM <HOST>\s*$
|
^%(__prefix_line)sROOT LOGIN REFUSED.* FROM <HOST>\s*$
|
||||||
^%(__prefix_line)s[iI](?:llegal|nvalid) user .* from <HOST>\s*$
|
^%(__prefix_line)s[iI](?:llegal|nvalid) user .* from <HOST>\s*$
|
||||||
^%(__prefix_line)sUser \S+ from <HOST> not allowed because not listed in AllowUsers$
|
^%(__prefix_line)sUser \S+ from <HOST> not allowed because not listed in AllowUsers$
|
||||||
^%(__prefix_line)sauthentication failure; logname=\S* uid=\S* euid=\S* tty=\S* ruser=\S* rhost=<HOST>(?:\s+user=.*)?\s*$
|
^%(__prefix_line)sauthentication failure; logname=\S* uid=\S* euid=\S* tty=\S* ruser=\S* rhost=<HOST>(?:\s+user=.*)?\s*$
|
||||||
^%(__prefix_line)srefused connect from \S+ \(<HOST>\)\s*$
|
^%(__prefix_line)srefused connect from \S+ \(<HOST>\)\s*$
|
||||||
^%(__prefix_line)sAddress <HOST> .* POSSIBLE BREAK-IN ATTEMPT\s*$
|
^%(__prefix_line)sAddress <HOST> .* POSSIBLE BREAK-IN ATTEMPT\s*$
|
||||||
|
^%(__prefix_line)sUser \S+ from <HOST> not allowed because none of user's groups are listed in AllowGroups$
|
||||||
|
|
||||||
# Option: ignoreregex
|
# Option: ignoreregex
|
||||||
# Notes.: regex to ignore. If this regex matches, the line is ignored.
|
# Notes.: regex to ignore. If this regex matches, the line is ignored.
|
||||||
|
|
|
@ -43,19 +43,19 @@ class DateDetector:
|
||||||
try:
|
try:
|
||||||
# standard
|
# standard
|
||||||
template = DateStrptime()
|
template = DateStrptime()
|
||||||
template.setName("Month Day Hour:Minute:Second")
|
template.setName("MONTH Day Hour:Minute:Second")
|
||||||
template.setRegex("^\S{3}\s{1,2}\d{1,2} \d{2}:\d{2}:\d{2}")
|
template.setRegex("^\S{3}\s{1,2}\d{1,2} \d{2}:\d{2}:\d{2}")
|
||||||
template.setPattern("%b %d %H:%M:%S")
|
template.setPattern("%b %d %H:%M:%S")
|
||||||
self.__templates.append(template)
|
self.__templates.append(template)
|
||||||
# asctime
|
# asctime
|
||||||
template = DateStrptime()
|
template = DateStrptime()
|
||||||
template.setName("Weekday Month Day Hour:Minute:Second Year")
|
template.setName("WEEKDAY MONTH Day Hour:Minute:Second Year")
|
||||||
template.setRegex("\S{3} \S{3}\s{1,2}\d{1,2} \d{2}:\d{2}:\d{2} \d{4}")
|
template.setRegex("\S{3} \S{3}\s{1,2}\d{1,2} \d{2}:\d{2}:\d{2} \d{4}")
|
||||||
template.setPattern("%a %b %d %H:%M:%S %Y")
|
template.setPattern("%a %b %d %H:%M:%S %Y")
|
||||||
self.__templates.append(template)
|
self.__templates.append(template)
|
||||||
# asctime without year
|
# asctime without year
|
||||||
template = DateStrptime()
|
template = DateStrptime()
|
||||||
template.setName("Weekday Month Day Hour:Minute:Second")
|
template.setName("WEEKDAY MONTH Day Hour:Minute:Second")
|
||||||
template.setRegex("\S{3} \S{3}\s{1,2}\d{1,2} \d{2}:\d{2}:\d{2}")
|
template.setRegex("\S{3} \S{3}\s{1,2}\d{1,2} \d{2}:\d{2}:\d{2}")
|
||||||
template.setPattern("%a %b %d %H:%M:%S")
|
template.setPattern("%a %b %d %H:%M:%S")
|
||||||
self.__templates.append(template)
|
self.__templates.append(template)
|
||||||
|
@ -73,7 +73,7 @@ class DateDetector:
|
||||||
self.__templates.append(template)
|
self.__templates.append(template)
|
||||||
# Apache format [31/Oct/2006:09:22:55 -0000]
|
# Apache format [31/Oct/2006:09:22:55 -0000]
|
||||||
template = DateStrptime()
|
template = DateStrptime()
|
||||||
template.setName("Day/Month/Year:Hour:Minute:Second")
|
template.setName("Day/MONTH/Year:Hour:Minute:Second")
|
||||||
template.setRegex("\d{2}/\S{3}/\d{4}:\d{2}:\d{2}:\d{2}")
|
template.setRegex("\d{2}/\S{3}/\d{4}:\d{2}:\d{2}:\d{2}")
|
||||||
template.setPattern("%d/%b/%Y:%H:%M:%S")
|
template.setPattern("%d/%b/%Y:%H:%M:%S")
|
||||||
self.__templates.append(template)
|
self.__templates.append(template)
|
||||||
|
@ -85,10 +85,16 @@ class DateDetector:
|
||||||
self.__templates.append(template)
|
self.__templates.append(template)
|
||||||
# named 26-Jul-2007 15:20:52.252
|
# named 26-Jul-2007 15:20:52.252
|
||||||
template = DateStrptime()
|
template = DateStrptime()
|
||||||
template.setName("Day-Month-Year Hour:Minute:Second[.Millisecond]")
|
template.setName("Day-MONTH-Year Hour:Minute:Second[.Millisecond]")
|
||||||
template.setRegex("\d{2}-\S{3}-\d{4} \d{2}:\d{2}:\d{2}")
|
template.setRegex("\d{2}-\S{3}-\d{4} \d{2}:\d{2}:\d{2}")
|
||||||
template.setPattern("%d-%b-%Y %H:%M:%S")
|
template.setPattern("%d-%b-%Y %H:%M:%S")
|
||||||
self.__templates.append(template)
|
self.__templates.append(template)
|
||||||
|
# 17-07-2008 17:23:25
|
||||||
|
template = DateStrptime()
|
||||||
|
template.setName("Day-Month-Year Hour:Minute:Second")
|
||||||
|
template.setRegex("\d{2}-\d{2}-\d{4} \d{2}:\d{2}:\d{2}")
|
||||||
|
template.setPattern("%d-%m-%Y %H:%M:%S")
|
||||||
|
self.__templates.append(template)
|
||||||
# TAI64N
|
# TAI64N
|
||||||
template = DateTai64n()
|
template = DateTai64n()
|
||||||
template.setName("TAI64N")
|
template.setName("TAI64N")
|
||||||
|
@ -101,6 +107,18 @@ class DateDetector:
|
||||||
template = DateISO8601()
|
template = DateISO8601()
|
||||||
template.setName("ISO 8601")
|
template.setName("ISO 8601")
|
||||||
self.__templates.append(template)
|
self.__templates.append(template)
|
||||||
|
# Only time information in the log
|
||||||
|
template = DateStrptime()
|
||||||
|
template.setName("Hour:Minute:Second")
|
||||||
|
template.setRegex("^\d{2}:\d{2}:\d{2}")
|
||||||
|
template.setPattern("%H:%M:%S")
|
||||||
|
self.__templates.append(template)
|
||||||
|
# <09/16/08@05:03:30>
|
||||||
|
template = DateStrptime()
|
||||||
|
template.setName("<Month/Day/Year@Hour:Minute:Second>")
|
||||||
|
template.setRegex("^<\d{2}/\d{2}/\d{2}@\d{2}:\d{2}:\d{2}>")
|
||||||
|
template.setPattern("<%m/%d/%y@%H:%M:%S>")
|
||||||
|
self.__templates.append(template)
|
||||||
finally:
|
finally:
|
||||||
self.__lock.release()
|
self.__lock.release()
|
||||||
|
|
||||||
|
|
|
@ -146,6 +146,11 @@ class DateStrptime(DateTemplate):
|
||||||
# that the log is not from this year but from the year before
|
# that the log is not from this year but from the year before
|
||||||
if time.mktime(date) > MyTime.time():
|
if time.mktime(date) > MyTime.time():
|
||||||
date[0] -= 1
|
date[0] -= 1
|
||||||
|
elif date[1] == 1 and date[2] == 1:
|
||||||
|
# If it is Jan 1st, it is either really Jan 1st or there
|
||||||
|
# is neither month nor day in the log.
|
||||||
|
date[1] = MyTime.gmtime()[1]
|
||||||
|
date[2] = MyTime.gmtime()[2]
|
||||||
return date
|
return date
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -241,15 +241,16 @@ class Filter(JailThread):
|
||||||
except UnicodeDecodeError:
|
except UnicodeDecodeError:
|
||||||
l = line
|
l = line
|
||||||
timeMatch = self.dateDetector.matchTime(l)
|
timeMatch = self.dateDetector.matchTime(l)
|
||||||
if not timeMatch:
|
if timeMatch:
|
||||||
# There is no valid time in this line
|
# Lets split into time part and log part of the line
|
||||||
return []
|
timeLine = timeMatch.group()
|
||||||
# Lets split into time part and log part of the line
|
# Lets leave the beginning in as well, so if there is no
|
||||||
timeLine = timeMatch.group()
|
# anchore at the beginning of the time regexp, we don't
|
||||||
# Lets leave the beginning in as well, so if there is no
|
# at least allow injection. Should be harmless otherwise
|
||||||
# anchore at the beginning of the time regexp, we don't
|
logLine = l[:timeMatch.start()] + l[timeMatch.end():]
|
||||||
# at least allow injection. Should be harmless otherwise
|
else:
|
||||||
logLine = l[:timeMatch.start()] + l[timeMatch.end():]
|
timeLine = l
|
||||||
|
logLine = l
|
||||||
return self.findFailure(timeLine, logLine)
|
return self.findFailure(timeLine, logLine)
|
||||||
|
|
||||||
def processLineAndAdd(self, line):
|
def processLineAndAdd(self, line):
|
||||||
|
|
Loading…
Reference in New Issue