From 4fa0eba064adb030485212da5549575b81adcf27 Mon Sep 17 00:00:00 2001 From: Yaroslav Halchenko Date: Sun, 19 Mar 2006 05:20:44 +0000 Subject: [PATCH] merged with upstream release 0.6.1 --- CHANGELOG | 34 +- PKG-INFO | 2 +- README | 27 +- TODO | 84 ++++- config/fail2ban.conf.hostsdeny | 327 ++++++++++++++++++ ...an.conf.default => fail2ban.conf.iptables} | 133 ++++--- config/fail2ban.conf.shorewall | 314 +++++++++++++++++ debian/TODO | 7 +- debian/changelog | 6 + fail2ban | 18 +- fail2ban.py | 54 +-- firewall/firewall.py | 18 +- logreader/logreader.py | 19 +- man/fail2ban.8 | 3 - setup.py | 8 +- utils/mail.py | 18 +- version.py | 8 +- 17 files changed, 965 insertions(+), 115 deletions(-) create mode 100644 config/fail2ban.conf.hostsdeny rename config/{fail2ban.conf.default => fail2ban.conf.iptables} (81%) create mode 100644 config/fail2ban.conf.shorewall diff --git a/CHANGELOG b/CHANGELOG index 99e4402e..fd74f7ce 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -4,9 +4,41 @@ |_| \__,_|_|_/___|_.__/\__,_|_||_| ============================================================= -Fail2Ban (version 0.6.0) 2005/11/20 +Fail2Ban (version 0.6.1) 2006/03/16 ============================================================= +ver. 0.6.1 (2006/03/16) - stable +---------- +- Added permanent banning. Set banTime to a negative value to + enable this feature (-1 is perfect). Thanks to Mannone +- Fixed locale bug. Thanks to Fernando JosĂ© +- Fixed crash when time format does not match data +- Propagated patch from Debian to fix fail2ban search path + addition to the path search list: now it is added first. + Thanks to Nick Craig-Wood +- Added SMTP authentification for mail notification. Thanks + to Markus Hoffmann +- Removed debug mode as it is confusing for people +- Added parsing of timestamp in TAI64N format (#1275325). + Thanks to Mark Edgington +- Added patch #1382936 (Default formatted syslog logging). + Thanks to Patrick Börjesson +- Removed 192.168.0.0/16 from ignoreip. Attacks could also + come from the local network. +- Robust startup: if iptables module does not get fully + initialized after startup of fail2ban, fail2ban will do + "maxreinit" attempts to initialize its own firewall. It + will sleep between attempts for "polltime" number of + seconds (closes Debian: #334272). Thanks to Yaroslav + Halchenko +- Added "interpolations" in fail2ban.conf. This is provided + by the ConfigParser module. Old configuration files still + work. Thanks to Yaroslav Halchenko +- Added initial support for hosts.deny and shorewall. Need + more testing. Please test. Thanks to kojiro from Gentoo + forum for hosts.deny support +- Added support for vsftpd. Thanks to zugeschmiert + ver. 0.6.0 (2005/11/20) - stable ---------- - Propagated patches introduced by Debian maintainer diff --git a/PKG-INFO b/PKG-INFO index fbc2f82b..57b716d8 100644 --- a/PKG-INFO +++ b/PKG-INFO @@ -1,6 +1,6 @@ Metadata-Version: 1.0 Name: fail2ban -Version: 0.6.0 +Version: 0.6.1 Summary: Ban IPs that make too many password failure Home-page: http://fail2ban.sourceforge.net Author: Cyril Jaquier diff --git a/README b/README index 915304bb..c7878a59 100644 --- a/README +++ b/README @@ -4,7 +4,7 @@ |_| \__,_|_|_/___|_.__/\__,_|_||_| ============================================================= -Fail2Ban (version 0.6.0) 2005/11/20 +Fail2Ban (version 0.6.1) 2006/03/16 ============================================================= Fail2Ban scans log files like /var/log/pwdfail and bans IP @@ -58,12 +58,12 @@ Require: python-2.4 (http://www.python.org) To install, just do: -> tar xvfj fail2ban-0.6.0.tar.bz2 -> cd fail2ban-0.6.0 +> tar xvfj fail2ban-0.6.1.tar.bz2 +> cd fail2ban-0.6.1 > python setup.py install -This will install Fail2Ban into /usr/lib/fail2ban. The fail2ban -executable is placed into /usr/bin. +This will install Fail2Ban into /usr/lib/fail2ban. The +fail2ban executable is placed into /usr/bin. Gentoo: ebuilds are available on the website. Debian: Fail2Ban is in Debian unstable. @@ -74,8 +74,17 @@ Fail2Ban should now be correctly installed. Just type: > fail2ban -h to see if everything is alright. You can configure fail2ban -with a config file. Copy config/fail2ban.conf.default to -/etc/fail2ban.conf. +with a config file. Different kind of configuration files are +available: + +iptables: copy config/fail2ban.conf.iptables to + /etc/fail2ban.conf +hosts.deny: copy config/fail2ban.conf.hostsdeny to + /etc/fail2ban.conf +shorewall: copy config/fail2ban.conf.shorewall to + /etc/fail2ban.conf + +Do not forget to edit fail2ban.conf to meet your needs. You can use the initd script available in config/. Copy -initd to /etc/init.d/fail2ban. Gentoo users must copy @@ -96,7 +105,6 @@ the value stored in fail2ban.conf. Here are the command line options: -b start in background - -d start in debug mode -c read configuration file FILE -p create PID lock in FILE -h display this help message @@ -124,7 +132,8 @@ Thanks: Kévin Drapel, Marvin Rouge, Sireyessire, Robert Edeker, Tom Pike, Iain Lea, Andrey G. Grozin, Yaroslav Halchenko, -Jonathan Kamens, Stephen Gildea +Jonathan Kamens, Stephen Gildea, Markus Hoffmann, Mark +Edgington, Patrick Börjesson, kojiro, zugeschmiert License: -------- diff --git a/TODO b/TODO index 4b93edfc..47ef6d93 100644 --- a/TODO +++ b/TODO @@ -4,20 +4,92 @@ |_| \__,_|_|_/___|_.__/\__,_|_||_| ============================================================= -ToDo $Revision: 1.5 $ +ToDo $Revision: 1.11 $ ============================================================= See Feature Request Tracking System at SourceForge.net - improve installation process (better prefix support) -- install Fail2ban into /usr/share + +- improve documentation and website for user + +- use Doxygen + +- use PyLint to check the code + - better configuration files + - add a check to see if the time of the log messages is correctly detected (valid regexp) -- split configuration files in /etc/fail2ban/services.d - Example: /etc/fail2ban/services.d/apache -- template for common services in /etc/fail2ban/scripts.d - Example: /etc/fail2ban/scripts.d/apache + +- use Gentoo Portage style for scripts. + - banning engines script in /etc/fail2ban/scripts.d + Example: /etc/fail2ban/scripts.d/iptables + Will be mostly bash scripting which is more "user + friendly". + - split configuration files in /etc/fail2ban/services.d + for log files + Example: /etc/fail2ban/services.d/apache + Mainly regular expressions. + - template for common regex in /etc/fail2ban/templates.d + Example: /etc/fail2ban/templates.d/date + Mainly regular expressions. + - remove debug mode (root check) + - better return values in function + - use more email.Utils in mail.py + +- add gettext support. Is this really needed for a server + utility? + +- send an email when fail2ban is running + +- add multithreading. Python threading is not really + efficient. However, fail2ban could benefit of it. We could + use threads like this: + - one thread which check for host to unban. + - one thread per file to watch. This will allow things like + different polling time for each file. + is read-only (we only read log files) thus no locks + are required. However, is read-write and must take + care of concurrency in case of multithreading. + +- add FAM/Gamin support. Should be quite efficient with + threading. Take care that handle_one_event() release the + Python lock. + +- add a test framework. We could use unittest which is in + Python since 2.1. It should be possible to run all tests + automatically. + +- add client/server using socket. Something similar to + gdesklets. DBUS seems to be designed for desktop use. + - fail2ban start -> start the daemon. + - fail2ban stop -> stop the daemon. + - fail2ban add -> add monitoring with + ban method (iptables, hosts.deny, etc). + - fail2ban del -> remove monitoring. + - fail2ban status -> query current fail2ban status. + Should return infos like a ban counter. Could be graph + with rrdtool. + - fail2ban pause -> suspend monitoring. + - fail2ban resume -> resume monitoring. + - fail2ban list -> list available services. + - fail2ban flush -> flush the ban list. + +- remove PID file. + +- remove most of the command lines options if possible. + +- add the possibility to specify wildcard in log files. + Example: logfile = /var/log/apache2/access-*.log + Should we start one thread per file or just one thread per + serivce? + +- autodetect date format in log file. Match the most popular + format and sort them using the hit ratio. Should avoid + user problem with regex and not have a big impact on perfs. + +- restart automatically the daemon if an exception occurs. diff --git a/config/fail2ban.conf.hostsdeny b/config/fail2ban.conf.hostsdeny new file mode 100644 index 00000000..03130f36 --- /dev/null +++ b/config/fail2ban.conf.hostsdeny @@ -0,0 +1,327 @@ +# Fail2Ban configuration file +# +# $Revision: 1.2 $ +# +# 2005.06.21 modified for readability Iain Lea iain@bricbrac.de + +[DEFAULT] +# Option: background +# Notes.: start fail2ban as a daemon. Output is redirect to logfile. +# Values: [true | false] Default: false +# +background = false + +# Option: logtargets +# Notes.: log targets. Space separated list of logging targets. +# Values: STDERR SYSLOG file Default: /var/log/fail2ban.log +# +logtargets = /var/log/fail2ban.log + +# Option: syslog-target +# Notes.: where to find syslog facility if logtarget SYSLOG. +# Values: SOCKET HOST HOST:PORT Default: /dev/log +# +syslog-target = /dev/log + +# Option: syslog-facility +# Notes.: which syslog facility to use if logtarget SYSLOG. +# Values: NUM Default: 1 +# +syslog-facility = 1 + +# Option: pidlock +# Notes.: path of the PID lock file (must be able to write to file). +# Values: FILE Default: /var/run/fail2ban.pid +# +pidlock = /var/run/fail2ban.pid + +# Option: maxfailures +# Notes.: number of failures before IP gets banned. +# Values: NUM Default: 5 +# +maxfailures = 5 + +# Option: bantime +# Notes.: number of seconds an IP will be banned. If set to a negative +# value, IP will never be unbanned (permanent banning). +# Values: NUM Default: 600 +# +bantime = 600 + +# Option: findtime +# Notes.: lifetime in seconds of a "failed" log entry. +# Values: NUM Default: 600 +# +findtime = 600 + +# Option: ignoreip +# Notes.: space separated list of IP's to be ignored by fail2ban. +# You can use CIDR mask in order to specify a range. +# Example: ignoreip = 192.168.0.1/24 123.45.235.65 +# Values: IP Default: +# +ignoreip = + +# Option: cmdstart +# Notes.: command executed once at the start of Fail2Ban +# Values: CMD Default: +# +cmdstart = + +# Option: cmdend +# Notes.: command executed once at the end of Fail2Ban. +# Values: CMD Default: +# +cmdend = + +# Option: polltime +# Notes.: number of seconds fail2ban sleeps between iterations. +# Values: NUM Default: 1 +# +polltime = 1 + +# Option: reinittime +# Notes.: minimal number of seconds between the re-initialization of +# firewalls due to external changes in their rules (see fwcheck) +# Values: NUM Default: 100 +# +reinittime = 10 + +# Option: maxreinits +# Notes.: maximal number of re-initialization of firewalls due to external +# changes. -1 stays for infinite, so only reinittime is of importance +# Values: NUM Default: -1 +# +maxreinits = -1 + +# NOTE: Interpolations +# +# fwstart, as well as fwend, fwcheck, fwban, fwunban, use interpolations +# so %(__name__)s will be substituted by a name of each section +# (unless the option is overriden in a section). +# If you are going to use interpolations in your setup, please make +# sure that you specified options port and protocol (which also has +# an option in DEFAULT). +# + +# Option: hostsdeny +# Notes.: hosts.deny file path. +# Values: STR Default: /etc/hosts.deny +# +hostsdeny = /etc/hosts.deny + +# Option: fwban +# Notes.: command executed when banning an IP. Take care that the +# command is executed with Fail2Ban user rights. +# Tags: IP address +# number of failures +# unix timestamp of the last failure +# unix timestamp of the ban time +# Values: CMD +# Default: iptables -I INPUT 1 -s -j DROP +# +fwban = IP= && echo "ALL: $IP" >> %(hostsdeny)s + +# Option: fwunban +# Notes.: command executed when unbanning an IP. Take care that the +# command is executed with Fail2Ban user rights. +# Tags: IP address +# unix timestamp of the ban time +# unix timestamp of the unban time +# Values: CMD +# Default: iptables -D INPUT -s -j DROP +# +fwunban = IP= && sed -i.old s/ALL:\ $IP// %(hostsdeny)s + +[MAIL] +# Option: enabled +# Notes.: enable mail notification when banning an IP address. +# Values: [true | false] Default: false +# +enabled = false + +# Option: host +# Notes.: host running the mail server. +# Values: STR Default: localhost +# +host = localhost + +# Option: port +# Notes.: port of the mail server. +# Values: INT Default: 25 +# +port = 25 + +# Option: user +# Notes.: the username for smtp-server if authentification is required. +# if user is empty, no authentification is done. +# Values: STR Default: +# +user = + +# Option: password +# Notes.: the smtp-user's password if authentification is required. +# Values: STR Default: +# +password = + +# Option: from +# Notes.: e-mail address of the sender. +# Values: MAIL Default: fail2ban +# +from = fail2ban + +# Option: to +# Notes.: e-mail addresses of the receiver. Addresses are space +# separated. +# Values: MAIL Default: root +# +to = root + +# Option: localtime +# Notes.: report local time (including timezone) or GMT +# Values: [true | false] Default: false +# +localtime = true + +# Option: subject +# Notes.: subject of the e-mail. +# Tags:
active section (eg ssh, apache, etc) +# IP address +# number of failures +# unix timestamp of the last failure +# Values: TEXT Default: [Fail2Ban]
: Banned +# +subject = [Fail2Ban]
: Banned + +# Option: message +# Notes.: message of the e-mail. +# Tags:
active section (eg ssh, apache, etc) +# IP address +# number of failures +# unix timestamp of the last failure +#
new line +# Values: TEXT Default: +# +message = Hi,
+ The IP has just been banned by Fail2Ban after + attempts against
.
+ Regards,
+ Fail2Ban + +# You can define a new section for each log file to check for +# password failure. Each section has to define the following +# options: logfile, fwban, fwunban, timeregex, timepattern, +# failregex. + + +[Apache] +# Option: enabled +# Notes.: enable monitoring for this section. +# Values: [true | false] Default: false +# +enabled = false + +# Option: logfile +# Notes.: logfile to monitor. +# Values: FILE Default: /var/log/httpd/access_log +# +logfile = /var/log/httpd/access_log + +# Option: timeregex +# Notes.: regex to match timestamp in Apache logfile. For TAI64N format, +# use timeregex = @[0-9a-f]{24} +# Values: [Wed Jan 05 15:08:01 2005] +# Default: \S{3} \S{3} \d{2} \d{2}:\d{2}:\d{2} \d{4} +# +timeregex = \S{3} \S{3} \d{2} \d{2}:\d{2}:\d{2} \d{4} + +# Option: timepattern +# Notes.: format used in "timeregex" fields definition. Note that '%' must be +# escaped with '%' (see http://rgruet.free.fr/PQR2.3.html#timeModule). +# For TAI64N format, use timepattern = tai64n +# Values: TEXT Default: %%a %%b %%d %%H:%%M:%%S %%Y +# +timepattern = %%a %%b %%d %%H:%%M:%%S %%Y + +# Option: failregex +# Notes.: regex to match the password failure messages in the logfile. +# Values: TEXT Default: authentication failure|user .* not found +# +failregex = authentication failure|user .* not found + + +[VSFTPD] +# Option: enabled +# Notes.: enable monitoring for this section. +# Values: [true | false] Default: false +# +enabled = false + +# Option: logfile +# Notes.: logfile to monitor. +# Values: FILE Default: /var/log/secure +# +logfile = /var/log/vsftpd.log + +# Option: port +# Notes.: specifies port to monitor +# Values: [ NUM | STRING ] Default: +# +port = ftp + +# Option: timeregex +# Notes.: regex to match timestamp in VSFTPD logfile. +# Values: [Mar 7 17:53:28] +# Default: \S{3}\s{1,2}\d{1,2} \d{2}:\d{2}:\d{2} +# +timeregex = \S{3}\s{1,2}\d{1,2} \d{2}:\d{2}:\d{2} + +# Option: timepattern +# Notes.: format used in "timeregex" fields definition. Note that '%' must be +# escaped with '%' (see http://rgruet.free.fr/PQR2.3.html#timeModule) +# Values: TEXT Default: %%b %%d %%H:%%M:%%S +# +timepattern = %%b %%d %%H:%%M:%%S + +# Option: failregex +# Notes.: regex to match the password failures messages in the logfile. +# Values: TEXT Default: Authentication failure|Failed password|Invalid user +# +failregex = FAIL LOGIN + + +[SSH] +# Option: enabled +# Notes.: enable monitoring for this section. +# Values: [true | false] Default: true +# +enabled = true + +# Option: logfile +# Notes.: logfile to monitor. +# Values: FILE Default: /var/log/secure +# +logfile = /var/log/secure + +# Option: timeregex +# Notes.: regex to match timestamp in SSH logfile. For TAI64N format, +# use timeregex = @[0-9a-f]{24} +# Values: [Mar 7 17:53:28] +# Default: \S{3}\s{1,2}\d{1,2} \d{2}:\d{2}:\d{2} +# +timeregex = \S{3}\s{1,2}\d{1,2} \d{2}:\d{2}:\d{2} + +# Option: timepattern +# Notes.: format used in "timeregex" fields definition. Note that '%' must be +# escaped with '%' (see http://rgruet.free.fr/PQR2.3.html#timeModule). +# For TAI64N format, use timepattern = tai64n +# Values: TEXT Default: %%b %%d %%H:%%M:%%S +# +timepattern = %%b %%d %%H:%%M:%%S + +# Option: failregex +# Notes.: regex to match the password failures messages in the logfile. +# Values: TEXT Default: Authentication failure|Failed password|Invalid user +# +failregex = Authentication failure|Failed password|Invalid user diff --git a/config/fail2ban.conf.default b/config/fail2ban.conf.iptables similarity index 81% rename from config/fail2ban.conf.default rename to config/fail2ban.conf.iptables index 71abe7ff..dcf9c215 100644 --- a/config/fail2ban.conf.default +++ b/config/fail2ban.conf.iptables @@ -21,13 +21,6 @@ background = true # verbose = 1 -# Option: debug -# Notes.: enable debug mode. No real commands gets executed but only -# reported, more verbose output, bypass root user test. -# Values: [true | false] Default: false -# -debug = false - # Option: logtargets # Notes.: log targets. Space separated list of logging targets. # Values: STDERR SYSLOG file Default: /var/log/fail2ban.log @@ -59,7 +52,8 @@ pidlock = /var/run/fail2ban.pid maxfailures = 5 # Option: bantime -# Notes.: number of seconds an IP will be banned. +# Notes.: number of seconds an IP will be banned. If set to a negative +# value, IP will never be unbanned (permanent banning). # Values: NUM Default: 600 # bantime = 600 @@ -74,22 +68,21 @@ findtime = 600 # Notes.: space separated list of IP's to be ignored by fail2ban. # You can use CIDR mask in order to specify a range. # Example: ignoreip = 192.168.0.1/24 123.45.235.65 -# Values: IP Default: +# Values: IP Default: # -ignoreip = - +ignoreip = # Option: cmdstart # Notes.: command executed once at the start of Fail2Ban # Values: CMD Default: # -cmdstart = +cmdstart = # Option: cmdend # Notes.: command executed once at the end of Fail2Ban. # Values: CMD Default: # -cmdend = +cmdend = # Option: polltime # Notes.: number of seconds fail2ban sleeps between iterations. @@ -111,15 +104,14 @@ reinittime = 10 # maxreinits = -1 -# # NOTE: Interpolations # -# fwstart, as well as fwend, fwcheck, fwban, fwunban, ise interpolations -# so %(__name__)s will be substituted by a name of each section -# (unless the option is overriden in a section). -# If you are going to use interpolations in your setup, please make -# sure that you specified options port and protocol (which also has -# an option in DEFAULT) +# fwstart, as well as fwend, fwcheck, fwban, fwunban, use interpolations +# so %(__name__)s will be substituted by a name of each section +# (unless the option is overriden in a section). +# If you are going to use interpolations in your setup, please make +# sure that you specified options port and protocol (which also has +# an option in DEFAULT). # # Option: protocol @@ -173,7 +165,6 @@ fwban = iptables -I fail2ban-%(__name__)s 1 -s -j DROP # fwunban = iptables -D fail2ban-%(__name__)s -s -j DROP - [MAIL] # Option: enabled # Notes.: enable mail notification when banning an IP address. @@ -193,6 +184,19 @@ host = localhost # port = 25 +# Option: user +# Notes.: the username for smtp-server if authentification is required. +# if user is empty, no authentification is done. +# Values: STR Default: +# +user = + +# Option: password +# Notes.: the smtp-user's password if authentification is required. +# Values: STR Default: +# +password = + # Option: from # Notes.: e-mail address of the sender. # Values: MAIL Default: fail2ban @@ -250,20 +254,21 @@ message = Hi,
# enabled = false -# Option: port -# Notes.: specifies port to monitor -# Values: [ NUM | STRING ] Default: -# -port = http - # Option: logfile # Notes.: logfile to monitor. # Values: FILE Default: /var/log/apache/error.log # logfile = /var/log/apache/error.log +# Option: port +# Notes.: specifies port to monitor +# Values: [ NUM | STRING ] Default: +# +port = http + # Option: timeregex -# Notes.: regex to match timestamp in Apache error logfile. +# Notes.: regex to match timestamp in Apache logfile. For TAI64N format, +# use timeregex = @[0-9a-f]{24} # Values: [Wed Jan 05 15:08:01 2005] # Default: \S{3} \S{3} \d{2} \d{2}:\d{2}:\d{2} \d{4} # @@ -271,7 +276,8 @@ timeregex = \S{3} \S{3} \d{2} \d{2}:\d{2}:\d{2} \d{4} # Option: timepattern # Notes.: format used in "timeregex" fields definition. Note that '%' must be -# escaped with '%' (see http://rgruet.free.fr/PQR2.3.html#timeModule) +# escaped with '%' (see http://rgruet.free.fr/PQR2.3.html#timeModule). +# For TAI64N format, use timepattern = tai64n # Values: TEXT Default: %%a %%b %%d %%H:%%M:%%S %%Y # timepattern = %%a %%b %%d %%H:%%M:%%S %%Y @@ -289,18 +295,18 @@ failregex = [[]client (?P\S*)[]] user .*(?:: authentication failure|not fo # enabled = false -# Option: port -# Notes.: specifies port to monitor -# Values: [ NUM | STRING ] Default: -# -port = http - # Option: logfile # Notes.: logfile to monitor. # Values: FILE Default: /var/log/apache/access.log # logfile = /var/log/apache/access.log +# Option: port +# Notes.: specifies port to monitor +# Values: [ NUM | STRING ] Default: +# +port = http + # Option: maxfailures # Notes.: number of failures before IP gets banned. # Values: NUM Default: 5 @@ -327,6 +333,45 @@ timepattern = %%d/%%b/%%Y:%%H:%%M:%%S # failregex = ^(?P\S*) -.*"GET .*(?:awstats\.pl\?configdir=|index2\.php\?_REQUEST\[option\].*)\|echo.* +[VSFTPD] +# Option: enabled +# Notes.: enable monitoring for this section. +# Values: [true | false] Default: false +# +enabled = false + +# Option: logfile +# Notes.: logfile to monitor. +# Values: FILE Default: /var/log/secure +# +logfile = /var/log/vsftpd.log + +# Option: port +# Notes.: specifies port to monitor +# Values: [ NUM | STRING ] Default: +# +port = ftp + +# Option: timeregex +# Notes.: regex to match timestamp in VSFTPD logfile. +# Values: [Mar 7 17:53:28] +# Default: \S{3}\s{1,2}\d{1,2} \d{2}:\d{2}:\d{2} +# +timeregex = \S{3}\s{1,2}\d{1,2} \d{2}:\d{2}:\d{2} + +# Option: timepattern +# Notes.: format used in "timeregex" fields definition. Note that '%' must be +# escaped with '%' (see http://rgruet.free.fr/PQR2.3.html#timeModule) +# Values: TEXT Default: %%b %%d %%H:%%M:%%S +# +timepattern = %%b %%d %%H:%%M:%%S + +# Option: failregex +# Notes.: regex to match the password failures messages in the logfile. +# Values: TEXT Default: Authentication failure|Failed password|Invalid user +# +failregex = FAIL LOGIN + [SSH] # Option: enabled # Notes.: enable monitoring for this section. @@ -334,20 +379,21 @@ failregex = ^(?P\S*) -.*"GET .*(?:awstats\.pl\?configdir=|index2\.php\?_RE # enabled = true -# Option: port -# Notes.: specifies port to monitor -# Values: [ NUM | STRING ] Default: -# -port = ssh - # Option: logfile # Notes.: logfile to monitor. # Values: FILE Default: /var/log/auth.log # logfile = /var/log/auth.log +# Option: port +# Notes.: specifies port to monitor +# Values: [ NUM | STRING ] Default: +# +port = ssh + # Option: timeregex -# Notes.: regex to match timestamp in SSH logfile. +# Notes.: regex to match timestamp in SSH logfile. For TAI64N format, +# use timeregex = @[0-9a-f]{24} # Values: [Mar 7 17:53:28] # Default: \S{3}\s{1,2}\d{1,2} \d{2}:\d{2}:\d{2} # @@ -355,7 +401,8 @@ timeregex = \S{3}\s{1,2}\d{1,2} \d{2}:\d{2}:\d{2} # Option: timepattern # Notes.: format used in "timeregex" fields definition. Note that '%' must be -# escaped with '%' (see http://rgruet.free.fr/PQR2.3.html#timeModule) +# escaped with '%' (see http://rgruet.free.fr/PQR2.3.html#timeModule). +# For TAI64N format, use timepattern = tai64n # Values: TEXT Default: %%b %%d %%H:%%M:%%S # timepattern = %%b %%d %%H:%%M:%%S diff --git a/config/fail2ban.conf.shorewall b/config/fail2ban.conf.shorewall new file mode 100644 index 00000000..28cab2ca --- /dev/null +++ b/config/fail2ban.conf.shorewall @@ -0,0 +1,314 @@ +# Fail2Ban configuration file +# +# $Revision: 1.2 $ +# +# 2005.06.21 modified for readability Iain Lea iain@bricbrac.de + +[DEFAULT] +# Option: background +# Notes.: start fail2ban as a daemon. Output is redirect to logfile. +# Values: [true | false] Default: false +# +background = false + +# Option: logtargets +# Notes.: log targets. Space separated list of logging targets. +# Values: STDERR SYSLOG file Default: /var/log/fail2ban.log +# +logtargets = /var/log/fail2ban.log + +# Option: syslog-target +# Notes.: where to find syslog facility if logtarget SYSLOG. +# Values: SOCKET HOST HOST:PORT Default: /dev/log +# +syslog-target = /dev/log + +# Option: syslog-facility +# Notes.: which syslog facility to use if logtarget SYSLOG. +# Values: NUM Default: 1 +# +syslog-facility = 1 + +# Option: pidlock +# Notes.: path of the PID lock file (must be able to write to file). +# Values: FILE Default: /var/run/fail2ban.pid +# +pidlock = /var/run/fail2ban.pid + +# Option: maxfailures +# Notes.: number of failures before IP gets banned. +# Values: NUM Default: 5 +# +maxfailures = 5 + +# Option: bantime +# Notes.: number of seconds an IP will be banned. If set to a negative +# value, IP will never be unbanned (permanent banning). +# Values: NUM Default: 600 +# +bantime = 600 + +# Option: findtime +# Notes.: lifetime in seconds of a "failed" log entry. +# Values: NUM Default: 600 +# +findtime = 600 + +# Option: ignoreip +# Notes.: space separated list of IP's to be ignored by fail2ban. +# You can use CIDR mask in order to specify a range. +# Example: ignoreip = 192.168.0.1/24 123.45.235.65 +# Values: IP Default: +# +ignoreip = + +# Option: cmdstart +# Notes.: command executed once at the start of Fail2Ban +# Values: CMD Default: +# +cmdstart = + +# Option: cmdend +# Notes.: command executed once at the end of Fail2Ban. +# Values: CMD Default: +# +cmdend = + +# Option: polltime +# Notes.: number of seconds fail2ban sleeps between iterations. +# Values: NUM Default: 1 +# +polltime = 1 + +# Option: reinittime +# Notes.: minimal number of seconds between the re-initialization of +# firewalls due to external changes in their rules (see fwcheck) +# Values: NUM Default: 100 +# +reinittime = 10 + +# Option: maxreinits +# Notes.: maximal number of re-initialization of firewalls due to external +# changes. -1 stays for infinite, so only reinittime is of importance +# Values: NUM Default: -1 +# +maxreinits = -1 + +# NOTE: Interpolations +# +# fwstart, as well as fwend, fwcheck, fwban, fwunban, use interpolations +# so %(__name__)s will be substituted by a name of each section +# (unless the option is overriden in a section). +# If you are going to use interpolations in your setup, please make +# sure that you specified options port and protocol (which also has +# an option in DEFAULT). +# + +# Option: fwban +# Notes.: command executed when banning an IP. Take care that the +# command is executed with Fail2Ban user rights. +# Tags: IP address +# number of failures +# unix timestamp of the last failure +# unix timestamp of the ban time +# Values: CMD +# Default: iptables -I INPUT 1 -s -j DROP +# +fwban = shorewall drop + +# Option: fwunban +# Notes.: command executed when unbanning an IP. Take care that the +# command is executed with Fail2Ban user rights. +# Tags: IP address +# unix timestamp of the ban time +# unix timestamp of the unban time +# Values: CMD +# Default: iptables -D INPUT -s -j DROP +# +fwunban = shorewall allow + +[MAIL] +# Option: enabled +# Notes.: enable mail notification when banning an IP address. +# Values: [true | false] Default: false +# +enabled = false + +# Option: host +# Notes.: host running the mail server. +# Values: STR Default: localhost +# +host = localhost + +# Option: port +# Notes.: port of the mail server. +# Values: INT Default: 25 +# +port = 25 + +# Option: user +# Notes.: the username for smtp-server if authentification is required. +# if user is empty, no authentification is done. +# Values: STR Default: +# +user = + +# Option: password +# Notes.: the smtp-user's password if authentification is required. +# Values: STR Default: +# +password = + +# Option: from +# Notes.: e-mail address of the sender. +# Values: MAIL Default: fail2ban +# +from = fail2ban + +# Option: to +# Notes.: e-mail addresses of the receiver. Addresses are space +# separated. +# Values: MAIL Default: root +# +to = root + +# Option: localtime +# Notes.: report local time (including timezone) or GMT +# Values: [true | false] Default: false +# +localtime = true + +# Option: subject +# Notes.: subject of the e-mail. +# Tags:
active section (eg ssh, apache, etc) +# IP address +# number of failures +# unix timestamp of the last failure +# Values: TEXT Default: [Fail2Ban]
: Banned +# +subject = [Fail2Ban]
: Banned + +# Option: message +# Notes.: message of the e-mail. +# Tags:
active section (eg ssh, apache, etc) +# IP address +# number of failures +# unix timestamp of the last failure +#
new line +# Values: TEXT Default: +# +message = Hi,
+ The IP has just been banned by Fail2Ban after + attempts against
.
+ Regards,
+ Fail2Ban + +# You can define a new section for each log file to check for +# password failure. Each section has to define the following +# options: logfile, fwban, fwunban, timeregex, timepattern, +# failregex. + + +[Apache] +# Option: enabled +# Notes.: enable monitoring for this section. +# Values: [true | false] Default: false +# +enabled = false + +# Option: logfile +# Notes.: logfile to monitor. +# Values: FILE Default: /var/log/httpd/access_log +# +logfile = /var/log/httpd/access_log + +# Option: timeregex +# Notes.: regex to match timestamp in Apache logfile. For TAI64N format, +# use timeregex = @[0-9a-f]{24} +# Values: [Wed Jan 05 15:08:01 2005] +# Default: \S{3} \S{3} \d{2} \d{2}:\d{2}:\d{2} \d{4} +# +timeregex = \S{3} \S{3} \d{2} \d{2}:\d{2}:\d{2} \d{4} + +# Option: timepattern +# Notes.: format used in "timeregex" fields definition. Note that '%' must be +# escaped with '%' (see http://rgruet.free.fr/PQR2.3.html#timeModule). +# For TAI64N format, use timepattern = tai64n +# Values: TEXT Default: %%a %%b %%d %%H:%%M:%%S %%Y +# +timepattern = %%a %%b %%d %%H:%%M:%%S %%Y + +# Option: failregex +# Notes.: regex to match the password failure messages in the logfile. +# Values: TEXT Default: authentication failure|user .* not found +# +failregex = authentication failure|user .* not found + +[VSFTPD] +# Option: enabled +# Notes.: enable monitoring for this section. +# Values: [true | false] Default: false +# +enabled = false + +# Option: logfile +# Notes.: logfile to monitor. +# Values: FILE Default: /var/log/secure +# +logfile = /var/log/vsftpd.log + +# Option: timeregex +# Notes.: regex to match timestamp in VSFTPD logfile. +# Values: [Mar 7 17:53:28] +# Default: \S{3}\s{1,2}\d{1,2} \d{2}:\d{2}:\d{2} +# +timeregex = \S{3}\s{1,2}\d{1,2} \d{2}:\d{2}:\d{2} + +# Option: timepattern +# Notes.: format used in "timeregex" fields definition. Note that '%' must be +# escaped with '%' (see http://rgruet.free.fr/PQR2.3.html#timeModule) +# Values: TEXT Default: %%b %%d %%H:%%M:%%S +# +timepattern = %%b %%d %%H:%%M:%%S + +# Option: failregex +# Notes.: regex to match the password failures messages in the logfile. +# Values: TEXT Default: Authentication failure|Failed password|Invalid user +# +failregex = FAIL LOGIN + + +[SSH] +# Option: enabled +# Notes.: enable monitoring for this section. +# Values: [true | false] Default: true +# +enabled = true + +# Option: logfile +# Notes.: logfile to monitor. +# Values: FILE Default: /var/log/secure +# +logfile = /var/log/secure + +# Option: timeregex +# Notes.: regex to match timestamp in SSH logfile. For TAI64N format, +# use timeregex = @[0-9a-f]{24} +# Values: [Mar 7 17:53:28] +# Default: \S{3}\s{1,2}\d{1,2} \d{2}:\d{2}:\d{2} +# +timeregex = \S{3}\s{1,2}\d{1,2} \d{2}:\d{2}:\d{2} + +# Option: timepattern +# Notes.: format used in "timeregex" fields definition. Note that '%' must be +# escaped with '%' (see http://rgruet.free.fr/PQR2.3.html#timeModule). +# For TAI64N format, use timepattern = tai64n +# Values: TEXT Default: %%b %%d %%H:%%M:%%S +# +timepattern = %%b %%d %%H:%%M:%%S + +# Option: failregex +# Notes.: regex to match the password failures messages in the logfile. +# Values: TEXT Default: Authentication failure|Failed password|Invalid user +# +failregex = Authentication failure|Failed password|Invalid user diff --git a/debian/TODO b/debian/TODO index 5a827939..cd9eff97 100644 --- a/debian/TODO +++ b/debian/TODO @@ -1,4 +1,7 @@ * Collect more sections for other log files -* Compose a filter for logwatch +* Compose a filter for logwatch (almost done -- testing, submission) +* In the next release split file configuration will be implemented, + that is why no split files is enabled for current release + (as of v0.6.1 Sun Mar 19 00:18:08 EST 2006) --- debian@onerussian.com + -- Yaroslav O. Halchenko , Sun Jan 15 15:18:13 2006 diff --git a/debian/changelog b/debian/changelog index ee3a12d5..95ee014d 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,9 @@ +fail2ban (0.6.1-0.1) unstable; urgency=low + + * New upstream release + + -- Yaroslav Halchenko Sat, 18 Mar 2006 23:11:53 -0500 + fail2ban (0.6.0-8) unstable; urgency=low * Minor adjustments to reduce the deviation from the upstream code diff --git a/fail2ban b/fail2ban index 23992080..53cd196f 100755 --- a/fail2ban +++ b/fail2ban @@ -18,15 +18,22 @@ # Author: Cyril Jaquier # -# $Revision: 1.5 $ +# $Revision: 1.7 $ __author__ = "Cyril Jaquier" -__version__ = "$Revision: 1.5 $" -__date__ = "$Date: 2005/11/20 17:07:47 $" +__version__ = "$Revision: 1.7 $" +__date__ = "$Date: 2005/12/27 15:09:50 $" __copyright__ = "Copyright (c) 2004 Cyril Jaquier" __license__ = "GPL" -import sys, traceback, logging +import sys, traceback, logging, locale + +# Set the locale with the user's default setting +try: + locale.setlocale(locale.LC_ALL, '') +except Exception: + print "Unable to set locale to " + `locale.getdefaultlocale()` + sys.exit(-1) # Inserts our own modules path first in the list # fix for bug #343821 @@ -42,8 +49,9 @@ logSys = logging.getLogger("fail2ban") # Get PID lock file instance pidLock = PIDLock() -# Start the application. Handle all the unhandled exceptions +# Handle all the unhandled exceptions try: + # Start the application fail2ban.main() except SystemExit: # We called sys.exit(). Nothing wrong so just pass diff --git a/fail2ban.py b/fail2ban.py index 52ae965a..1b311d04 100755 --- a/fail2ban.py +++ b/fail2ban.py @@ -15,13 +15,13 @@ # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # Author: Cyril Jaquier -# Modified by: Yaroslav Halchenko (SYSLOG, findtime) -# -# $Revision: 1.21 $ +# Modified by: Yaroslav Halchenko (SYSLOG, findtime, and oth) +# +# $Revision: 1.24 $ __author__ = "Cyril Jaquier" -__version__ = "$Revision: 1.21 $" -__date__ = "$Date: 2005/11/20 17:07:47 $" +__version__ = "$Revision: 1.24 $" +__date__ = "$Date: 2006/01/22 11:10:29 $" __copyright__ = "Copyright (c) 2004 Cyril Jaquier" __license__ = "GPL" @@ -206,13 +206,14 @@ def main(): stdout.setFormatter(formatter) conf["kill"] = False + conf["debug"] = False conf["verbose"] = 0 conf["conffile"] = "/etc/fail2ban.conf" # Reads the command line options. try: cmdOpts = 'hvVbdkc:t:f:i:r:p:e:' - cmdLongOpts = ['help', 'version'] + cmdLongOpts = ['help','version'] optList, args = getopt.getopt(sys.argv[1:], cmdOpts, cmdLongOpts) except getopt.GetoptError: dispUsage() @@ -228,7 +229,7 @@ def main(): # Reads the config file and create a LogReader instance for # each log file to check. - confReader = ConfigReader(conf["conffile"]); + confReader = ConfigReader(conf["conffile"]) confReader.openConf() # Options @@ -264,7 +265,7 @@ def main(): # PID lock pidLock.setPath(conf["pidlock"]) - + # Now we can kill properly a running instance if needed if conf["kill"]: pid = pidLock.exists() @@ -289,7 +290,7 @@ def main(): # Bug fix for #1234699 os.umask(0077) for target in conf["logtargets"].split(): - # target formatter + # target formatter # By default global formatter is taken. Is different for SYSLOG tformatter = formatter if target == "STDERR": @@ -335,9 +336,7 @@ def main(): # Set formatter and add handler to logger hdlr.setFormatter(tformatter) logSys.addHandler(hdlr) - - # Process some options - + # Verbose level if conf["verbose"]: logSys.warn("Verbose level is "+`conf["verbose"]`) @@ -345,14 +344,14 @@ def main(): logSys.setLevel(logging.INFO) elif conf["verbose"] > 1: logSys.setLevel(logging.DEBUG) - - # Set debug log level - if conf["debug"]: - logSys.setLevel(logging.DEBUG) - formatterstring = ('%(levelname)s: [%(filename)s (%(lineno)d)] ' + + if conf["verbose"] > 2: + formatterstring = ('%(levelname)s: [%(filename)s (%(lineno)d)] ' + '%(message)s') - formatter = logging.Formatter("%(asctime)s " + formatterstring) - stdout.setFormatter(formatter) + formatter = logging.Formatter("%(asctime)s " + formatterstring) + stdout.setFormatter(formatter) + + # Debug mode. Should only be used by developers + if conf["debug"]: logSys.warn("DEBUG MODE: FIREWALL COMMANDS ARE _NOT_ EXECUTED BUT " + "ONLY DISPLAYED IN THE LOG MESSAGES") @@ -365,7 +364,7 @@ def main(): logSys.error("You must be root") if not conf["debug"]: sys.exit(-1) - + # Checks that no instance of Fail2Ban is currently running. pid = pidLock.exists() if pid: @@ -388,6 +387,8 @@ def main(): ["int", "port", "25"], ["str", "from", "root"], ["str", "to", "root"], + ["str", "user", ''], + ["str", "password", ''], ["bool", "localtime", False], ["str", "subject", "[Fail2Ban] Banned "], ["str", "message", "Fail2Ban notification"]) @@ -400,6 +401,8 @@ def main(): logSys.debug("Mail enabled") mail = Mail(mailConf["host"], mailConf["port"]) mail.setFromAddr(mailConf["from"]) + mail.setUser(mailConf["user"]) + mail.setPassword(mailConf["password"]) mail.setToAddr(mailConf["to"]) mail.setLocalTimeFlag(mailConf["localtime"]) logSys.debug("to: " + mailConf["to"] + " from: " + mailConf["from"]) @@ -458,10 +461,10 @@ def main(): element[1].addIgnoreIP(ip) else: logSys.warn(ip + " is not a valid IP address") - + # Startup loop -- necessary to avoid crash if it takes time for iptables - # to startup - # To avoid introduction of new config options, reusing maxreinits and polltime + # to startup. To avoid introduction of new config options, reusing + # maxreinits and polltime. reinits = 0 while True: try: @@ -471,9 +474,10 @@ def main(): reinits += 1 logSys.warn(e) if conf["maxreinits"] < 0 or (reinits < conf["maxreinits"]): - logSys.warn("#%d attempt to initialize the firewalls"%reinits) + logSys.warn("#%d attempt to initialize the firewalls" % reinits) else: - logSys.error("Exiting: Too many attempts to initialize the firewall") + logSys.error("Exiting: Too many attempts to initialize the " + + "firewall") killApp() time.sleep(conf["polltime"]) diff --git a/firewall/firewall.py b/firewall/firewall.py index 52414fa0..66fba96b 100644 --- a/firewall/firewall.py +++ b/firewall/firewall.py @@ -16,11 +16,11 @@ # Author: Cyril Jaquier # -# $Revision: 1.9 $ +# $Revision: 1.10 $ __author__ = "Cyril Jaquier" -__version__ = "$Revision: 1.9 $" -__date__ = "$Date: 2005/11/20 17:07:47 $" +__version__ = "$Revision: 1.10 $" +__date__ = "$Date: 2005/12/16 23:48:52 $" __copyright__ = "Copyright (c) 2004 Cyril Jaquier" __license__ = "GPL" @@ -86,7 +86,11 @@ class Firewall: ip = aInfo["ip"] if not self.inBanList(ip): crtTime = time.time() - logSys.warn("%s: Ban "%self.section + ip) + if self.banTime < 0: + banMsg = "Ban (permanent)" + else: + banMsg = "Ban (%d s)"%self.banTime + logSys.warn("%s: %s "%(self.section, banMsg) + ip) self.banList[ip] = crtTime aInfo["bantime"] = crtTime self.runCheck(debug) @@ -138,8 +142,12 @@ class Firewall: return None def checkForUnBan(self, debug): - """ Check for IP to remove from ban list. + """ Check for IP to remove from ban list. If banTime is smaller than + zero, IP will be never removed. """ + if self.banTime < 0: + # Permanent banning + return banListTemp = self.banList.copy() for element in banListTemp.iteritems(): btime = element[1] diff --git a/logreader/logreader.py b/logreader/logreader.py index 77e86bad..b4fcdd19 100644 --- a/logreader/logreader.py +++ b/logreader/logreader.py @@ -16,11 +16,11 @@ # Author: Cyril Jaquier # -# $Revision: 1.14 $ +# $Revision: 1.16 $ __author__ = "Cyril Jaquier" -__version__ = "$Revision: 1.14 $" -__date__ = "$Date: 2005/11/20 17:07:47 $" +__version__ = "$Revision: 1.16 $" +__date__ = "$Date: 2006/01/03 15:13:04 $" __copyright__ = "Copyright (c) 2004 Cyril Jaquier" __license__ = "GPL" @@ -210,7 +210,18 @@ class LogReader: Pattern should describe the date construction of value. """ - date = list(time.strptime(value, self.timepattern)) + try: + # Check if the parsed value is in TAI64N format + if not self.timepattern.lower() == "tai64n": + date = list(time.strptime(value, self.timepattern)) + else: + # extract part of format which represents seconds since epoch + seconds_since_epoch = value[2:17] + date = list(time.gmtime(int(seconds_since_epoch, 16))) + except ValueError, e: + logSys.error(e) + logSys.error("Please check the format and your locale settings.") + return None if date[0] < 2000: # There is probably no year field in the logs date[0] = time.gmtime()[0] diff --git a/man/fail2ban.8 b/man/fail2ban.8 index c43b71ec..1c2e4f73 100644 --- a/man/fail2ban.8 +++ b/man/fail2ban.8 @@ -14,9 +14,6 @@ firewall rules to reject the IP address. \fB\-b\fR start in background .TP -\fB\-d\fR -start in debug mode. Commands are NOT executed but only displayed -.TP \fB\-c\fR \fIFILE\fR read configuration file \fIFILE\fR .TP diff --git a/setup.py b/setup.py index 21df697c..dc41eddd 100755 --- a/setup.py +++ b/setup.py @@ -18,11 +18,11 @@ # Author: Cyril Jaquier # -# $Revision: 1.5 $ +# $Revision: 1.6 $ __author__ = "Cyril Jaquier" -__version__ = "$Revision: 1.5 $" -__date__ = "$Date: 2005/11/20 17:07:47 $" +__version__ = "$Revision: 1.6 $" +__date__ = "$Date: 2006/01/22 11:08:42 $" __copyright__ = "Copyright (c) 2004 Cyril Jaquier" __license__ = "GPL" @@ -78,5 +78,5 @@ if obsoleteFiles: if argv[1] == "install": print print "Please do not forget to update your configuration file." - print "Use config/fail2ban.conf.default as example." + print "Use config/fail2ban.conf.* as example." print diff --git a/utils/mail.py b/utils/mail.py index 25473bf5..ec763a18 100644 --- a/utils/mail.py +++ b/utils/mail.py @@ -16,11 +16,11 @@ # Author: Cyril Jaquier # -# $Revision: 1.2 $ +# $Revision: 1.3 $ __author__ = "Cyril Jaquier" -__version__ = "$Revision: 1.2 $" -__date__ = "$Date: 2005/11/20 17:07:47 $" +__version__ = "$Revision: 1.3 $" +__date__ = "$Date: 2006/01/03 15:13:41 $" __copyright__ = "Copyright (c) 2004 Cyril Jaquier" __license__ = "GPL" @@ -44,6 +44,16 @@ class Mail: """ Set from: address """ self.fromAddr = fromAddr + + def setUser(self, user): + """ Set smtpuser + """ + self.user = user + + def setPassword(self, password): + """ Set smtppassword + """ + self.password = password def setToAddr(self, toAddr): """ Set to: address @@ -69,6 +79,8 @@ class Mail: try: server = smtplib.SMTP(self.host, self.port) #server.set_debuglevel(1) + if not self.user == '': + server.login(self.user, self.password) server.sendmail(self.fromAddr, self.toAddr, mail) logSys.debug("Email sent to " + `self.toAddr`) server.quit() diff --git a/version.py b/version.py index 28441547..9a7f95ae 100644 --- a/version.py +++ b/version.py @@ -16,12 +16,12 @@ # Author: Cyril Jaquier # -# $Revision: 1.13 $ +# $Revision: 1.15 $ __author__ = "Cyril Jaquier" -__version__ = "$Revision: 1.13 $" -__date__ = "$Date: 2005/11/20 17:07:47 $" +__version__ = "$Revision: 1.15 $" +__date__ = "$Date: 2006/03/15 23:07:12 $" __copyright__ = "Copyright (c) 2004 Cyril Jaquier" __license__ = "GPL" -version = "0.6.0" +version = "0.6.1"