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.default b/config/fail2ban.conf.hostsdeny similarity index 71% rename from config/fail2ban.conf.default rename to config/fail2ban.conf.hostsdeny index 675c4202..03130f36 100644 --- a/config/fail2ban.conf.default +++ b/config/fail2ban.conf.hostsdeny @@ -1,6 +1,6 @@ # Fail2Ban configuration file # -# $Revision: 1.9 $ +# $Revision: 1.2 $ # # 2005.06.21 modified for readability Iain Lea iain@bricbrac.de @@ -11,12 +11,6 @@ # background = false -# Option: debug -# Notes.: enable debug mode. More verbose output and 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 @@ -48,7 +42,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 @@ -63,9 +58,9 @@ 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: 192.168.0.0/16 +# Values: IP Default: # -ignoreip = 192.168.0.0/16 +ignoreip = # Option: cmdstart # Notes.: command executed once at the start of Fail2Ban @@ -99,6 +94,44 @@ reinittime = 10 # 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 @@ -119,6 +152,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 @@ -182,53 +228,9 @@ enabled = false # logfile = /var/log/httpd/access_log -# Option: fwstart -# Notes.: command executed once at the start of Fail2Ban -# Values: CMD Default: -# -fwstart = iptables -N fail2ban-http - iptables -I INPUT -p tcp --dport http -j fail2ban-http - iptables -A fail2ban-http -j RETURN - -# Option: fwend -# Notes.: command executed once at the end of Fail2Ban -# Values: CMD Default: -# -fwend = iptables -D INPUT -p tcp --dport http -j fail2ban-http - iptables -F fail2ban-http - iptables -X fail2ban-http - -# Option: fwcheck -# Notes.: command executed once before each fwban command -# Values: CMD Default: -# -fwcheck = iptables -L INPUT | grep -q fail2ban-http - -# 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 = iptables -I fail2ban-http 1 -s -j 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 = iptables -D fail2ban-http -s -j DROP - # Option: timeregex -# Notes.: regex to match timestamp in Apache 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} # @@ -236,7 +238,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 @@ -248,6 +251,46 @@ timepattern = %%a %%b %%d %%H:%%M:%%S %%Y 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. @@ -261,53 +304,9 @@ enabled = true # logfile = /var/log/secure -# Option: fwstart -# Notes.: command executed once at the start of Fail2Ban -# Values: CMD Default: -# -fwstart = iptables -N fail2ban-ssh - iptables -I INPUT -p tcp --dport ssh -j fail2ban-ssh - iptables -A fail2ban-ssh -j RETURN - -# Option: fwend -# Notes.: command executed once at the end of Fail2Ban -# Values: CMD Default: -# -fwend = iptables -D INPUT -p tcp --dport ssh -j fail2ban-ssh - iptables -F fail2ban-ssh - iptables -X fail2ban-ssh - -# Option: fwcheck -# Notes.: command executed once before each fwban command -# Values: CMD Default: -# -fwcheck = iptables -L INPUT | grep -q fail2ban-ssh - -# Option: fwbanrule -# 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 = iptables -I fail2ban-ssh 1 -s -j DROP - -# Option: fwunbanrule -# 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 = iptables -D fail2ban-ssh -s -j DROP - # 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} # @@ -315,7 +314,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.iptables b/config/fail2ban.conf.iptables new file mode 100644 index 00000000..8ec591ec --- /dev/null +++ b/config/fail2ban.conf.iptables @@ -0,0 +1,361 @@ +# Fail2Ban configuration file +# +# $Revision: 1.2.2.1 $ +# +# 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: protocol +# Notes.: internally used by config reader for interpolations. +# Values: [ tcp | udp | icmp | all ] Default: tcp +# +protocol = tcp + +# Option: fwstart +# Notes.: command executed once at the start of Fail2Ban. +# Values: CMD Default: +# +fwstart = iptables -N fail2ban-%(__name__)s + iptables -A fail2ban-%(__name__)s -j RETURN + iptables -I INPUT -p %(protocol)s --dport %(port)s -j fail2ban-%(__name__)s + +# Option: fwend +# Notes.: command executed once at the end of Fail2Ban +# Values: CMD Default: +# +fwend = iptables -D INPUT -p %(protocol)s --dport %(port)s -j fail2ban-%(__name__)s + iptables -F fail2ban-%(__name__)s + iptables -X fail2ban-%(__name__)s + +# Option: fwcheck +# Notes.: command executed once before each fwban command +# Values: CMD Default: +# +fwcheck = iptables -L INPUT | grep -q fail2ban-%(__name__)s + +# 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 = iptables -I fail2ban-%(__name__)s 1 -s -j 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 = iptables -D fail2ban-%(__name__)s -s -j DROP + +[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: port +# Notes.: specifies port to monitor +# Values: [ NUM | STRING ] Default: +# +port = http + +# 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: port +# Notes.: specifies port to monitor +# Values: [ NUM | STRING ] Default: +# +port = ssh + +# 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.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/fail2ban b/fail2ban index f30dcfd9..86ed2ffc 100755 --- a/fail2ban +++ b/fail2ban @@ -18,18 +18,26 @@ # 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 -# Appends our own modules path. -sys.path.append("/usr/lib/fail2ban") +# 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 +sys.path.insert(1, "/usr/lib/fail2ban") # Now we can import our modules. import fail2ban @@ -41,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 971e0eca..ed8df793 100755 --- a/fail2ban.py +++ b/fail2ban.py @@ -17,11 +17,11 @@ # Author: Cyril Jaquier # Modified by: Yaroslav Halchenko (SYSLOG, findtime) # -# $Revision: 1.21 $ +# $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" @@ -56,7 +56,6 @@ def dispUsage(): print "and bans the corresponding IP addresses using firewall rules." print print " -b start in background" - print " -d start in debug mode" print " -c read configuration file FILE" print " -p create PID lock in FILE" print " -h display this help message" @@ -186,6 +185,7 @@ def main(): stdout.setFormatter(formatter) conf["kill"] = False + conf["debug"] = False conf["verbose"] = 0 conf["conffile"] = "/etc/fail2ban.conf" @@ -208,7 +208,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 @@ -216,7 +216,6 @@ def main(): ["str", "logtargets", "/var/log/fail2ban.log"], ["str", "syslog-target", "/dev/log"], ["int", "syslog-facility", 1], - ["bool", "debug", False], ["str", "pidlock", "/var/run/fail2ban.pid"], ["int", "maxfailures", 5], ["int", "bantime", 600], @@ -294,8 +293,8 @@ def main(): port = int(syslogtargets[3]) syslogtarget = (syslogtargets[1], port) hdlr = logging.handlers.SysLogHandler(syslogtarget, facility) - tformatter = logging.Formatter("fail2ban[%(process)d]: " + - formatterstring); + tformatter = logging.Formatter("%(asctime)s %(name)s " + + formatterstring, "%b %e %T"); else: # Target should be a file try: @@ -315,14 +314,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") @@ -358,6 +357,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"]) @@ -370,6 +371,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"]) @@ -420,7 +423,25 @@ def main(): else: logSys.warn(ip + " is not a valid IP address") - initializeFwRules() + # 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. + reinits = 0 + while True: + try: + initializeFwRules() + break + except ExternalError, e: + reinits += 1 + logSys.warn(e) + if conf["maxreinits"] < 0 or (reinits < conf["maxreinits"]): + logSys.warn("#%d attempt to initialize the firewalls" % reinits) + else: + logSys.error("Exiting: Too many attempts to initialize the " + + "firewall") + killApp() + time.sleep(conf["polltime"]) + # try to reinit once if it fails immediately lastReinitTime = time.time() - conf["reinittime"] - 1 reinits = 0 diff --git a/firewall/firewall.py b/firewall/firewall.py index 9c67f1c2..0fb764f2 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 9338fe8b..1aba772e 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" @@ -201,7 +201,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 01d638a6..200912e8 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"