diff --git a/.gitignore b/.gitignore index b697c3dc..76a33e60 100644 --- a/.gitignore +++ b/.gitignore @@ -7,3 +7,4 @@ htmlcov *.orig *.rej *.bak +__pycache__ diff --git a/.travis.yml b/.travis.yml index 4d312575..ea84432e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,11 +2,11 @@ # travis-ci.org definition for Fail2Ban build language: python python: - - "2.5" - "2.6" - "2.7" - "3.2" - "3.3" + - "pypy" before_install: - sudo apt-get update -qq install: diff --git a/ChangeLog b/ChangeLog index afb2b883..57b03e18 100644 --- a/ChangeLog +++ b/ChangeLog @@ -4,55 +4,167 @@ |_| \__,_|_|_/___|_.__/\__,_|_||_| ================================================================================ -Fail2Ban (version 0.9.0a1) 20??/??/?? +Fail2Ban (version 0.9.0a2) 2014/??/?? ================================================================================ -ver. 0.9.0 (2013/??/??) - alpha +ver. 0.9.0 (2014/??/??) - alpha ---------- -Carries all fixes in 0.8.9 and new features and enhancements. Nearly -all development is thanks to Steven Hiscocks (THANKS!) with only -code-review and minor additions from Yaroslav Halchenko. +Carries all fixes, features and enhancements from 0.8.12 with major changes. +Nearly all development is thanks to Steven Hiscocks (THANKS!), merging, +testcases and timezone support from Daniel Black, and code-review and minor +additions from Yaroslav Halchenko. + +The minimum supported python version is now 2.6. If you have python-2.4 or 2.5 +you can use the 0.8.12 version of fail2ban. + +Major changes have occured since version 0.8.12. Please test your +configuration before relying on it. - Refactoring (IMPORTANT -- Please review your setup and configuration): - Yaroslav Halchenko * [..bddbf1e] jail.conf was heavily refactored and now is similar to how it looked on Debian systems: - default action could be configured once for all jails - jails definitions only provide customizations (port, logpath) - no need to specify 'filter' if name matches jail name - Steven Hiscocks * [..5aef036] Core functionality moved into fail2ban/ module. Closes gh-26 + * Added fail2ban persistent database + - default location at /var/lib/fail2ban/fail2ban.sqlite3 + - allows active bans to be reinstated on restart + - log files read from last position after restart + * Added systemd journal backend + - Dependency on python-systemd + - New "journalmatch" option added to filter configs files + - New "systemd-journal" option added to fail2ban-regex + * Added python3 support + * Support %z (Timezone offset) and %f (sub-seconds) support for + datedetector. Enhanced existing date/time have been updated patterns to + support these. ISO8601 now defaults to localtime unless specified otherwise. + Some filters have been change as required to capture these elements in the + right timezone correctly. + - New features: - Steven Hiscocks * [..c7ae460] Multiline failregex. Close gh-54 * [8af32ed] Guacamole filter and support for Apache Tomcat date format - * [..4869186] Python3 support * [..b6059f4] 'timeout' option for actions Close gh-60 and Debian bug #410077. Also it would now capture and include stdout and stderr into logging messages in case of error or at DEBUG loglevel. + * Added action xarf-login-attack to report formatted attack messages + according to the XARF standard (v0.2). Close gh-105 + * Support PyPy + * Add filter for apache-botsearch + * Filter for stunnel + * Filter for Counter Strike 1.6. Thanks to onorua for logs. + Close gh-347 + - Enhancements - Steven Hiscocks + * Jail names increased to 26 characters and iptables prefix reduced + from fail2ban- to f2b- as suggested by buanzo in gh-462. + * Multiline filter for sendmail-spam. Close gh-418 + * Multiline regex for Disconnecting: Too many authentication failures for + root [preauth]\nConnection closed by 6X.XXX.XXX.XXX [preauth] * Replacing use of deprecated API (.warning, .assertEqual, etc) - * [..a648cc2] Filters can have options now too + * [..a648cc2] Filters can have options now too which are substituted into + failregex / ignoreregex * [..e019ab7] Multiple instances of the same action are allowed in the same jail -- use actname option to disambiguate. - Daniel Black - * Support %z (Timezone offset) and %f (sub-seconds) support for - datedetector. Enhanced existing date/time have been updated patterns to - support these. ISO8601 now defaults to localtime unless specified otherwise. - Some filters have been change as required to capture these elements in the - right timezone correctly. + * Add honeypot email address to exim-spam filter as argument -ver. 0.8.11 (2013/XX/XXX) - loves-unittests +ver. 0.8.12 (2013/12/XX) - things-can-only-get-better ----------- +- IMPORTANT incompatible changes: + - Fixes: + - Rename firewall-cmd-direct-new to firewall-cmd-new to fit within jail name + name length. As per gh-395 + - allow for ",milliseconds" in the custom date format of proftpd.log + - allow for ", referer ..." in apache-* filter for apache error logs. + - allow for spaces at the beginning of kernel messages. Closes gh-448 + - recidive jail to block all protocols. Closes gh-440. Thanks Ioan Indreias + - smtps not a IANA standard and has been removed from Arch. Replaced with + 465. Thanks Stefan. Closes gh-447 + - mysqld-syslog-iptables rule was too long. Part of gh-447. + - add 'flushlogs' command to allow logrotation without clobbering logtarget + settings. Closes gh-458, Debian bug #697333, Redhat bug #891798. + - complain action - ensure where not matching other IPs in log sample. + Closes gh-467 + - Fix firewall-cmd actioncheck - patch from Adam Tkac. Redhat Bug #979622 + - Fix apache-common for apache-2.4 log file format. Thanks Mark White. + Closes gh-516 + - Asynchat changed to use push method which verifys whether all data was + send. This ensures that all data is sent before closing the connection. + - Removed unnecessary reference to as yet undeclared $jail_name when checking + a specific jail in nagios script. + +- Enhancements: + - added firewallcmd-ipset action + - long names on jails documented based on iptables limit of 30 less + len("fail2ban-"). + - remove indentation of name and loglevel while logging to SYSLOG to + resolve syslog(-ng) parsing problems. Closes Debian bug #730202. + - added squid filter. Thanks Roman Gelfand. + - updated check_fail2ban to return performance data for all jails. + - filter apache-noscript now includes php cgi scripts. + Thanks dani. Closes gh-503 + - added ufw action. Thanks Guilhem Lettron. lp-#701522 + - exim-spam filter to match spamassassin log entry for option SAdevnull. + Thanks Ivo Truxa. Closes gh-533 + - filter.d/nsd.conf -- also amended Unix date template to match nsd format + - Added to sshd filter expression for "Received disconnect from : 3: + ...: Auth fail". Thanks Marcel Dopita. Closes gh-289 + - loglines now also report "[PID]" after the name portion + +- New Features: + + - filter.d/solid-pop3d -- added thanks to Jacques Lav!gnotte on mailinglist. + - Add filter for apache-modsecurity + - filter.d/nsd.conf -- also amended Unix date template to match nsd format + - Added openwebmail filter thanks Ivo Truxa. Closes gh-543 + - Added filter for freeswitch. Thanks Jim and editors and authors of + http://wiki.freeswitch.org/wiki/Fail2ban + - Added groupoffice filter thanks to logs from Merijn Schering. + Closes gh-566 + - Added filter for horde + +ver. 0.8.11 (2013/11/13) - loves-unittests-and-tight-DoS-free-filter-regexes + +In light of CVE-2013-2178 that triggered our last release we have put +a significant effort into tightening all of the regexs of our filters +to avoid another similar vulnerability. All filters have been updated +and some to catch more login/authentication failures and to support +for newer application versions. There are test cases for most log +cases of failures now. + +As usual, if you have other examples that demonstrate that a filter is +insufficient, or if we have inadvertently introduced a regression, +please provide us with example log lines on the github issue tracker +http://github.com/fail2ban/fail2ban/issues and NOT on a random blog in +some obscure corner of the Internet. + +Many thanks to our contributors for this release Daniel Black, Yaroslav +Halchenko, Steven Hiscocks, Mark McKinstry, Andy Fragen, Orion Poplawski, +Alexander Dietrich, JP Espinosa, Jamyn Shanley, Beau Raines, François +Boulogne and others who have helped on IRC and mailing list, logged issues +and bug requests. + +- IMPORTANT incompatible changes: + Filter name changes: + * 'lighttpd-fastcgi' filter has been renamed to 'suhosin' + * 'sasl' has been renamed to 'postfix-sasl' + * 'exim' spam catching failregexes was split out into 'exim-spam' + These changes will require changing jail.{conf,local} if any of + those filters were used. + +- Fixes: + Jonathan Lanning + * filter.d/asterisk -- identified another regex for blocking. Also channel + ID is hex not decimal as noted in sample logs provided. Daniel Black & Marcel Dopita - * filter.d/apache-auth -- fixed and apache auth samples provide. closes #286 + * filter.d/apache-auth -- fixed and apache auth samples provide. Closes gh-286 Yaroslav Halchenko * filter.d/common.conf -- make colon after [daemon] optional. Closes gh-267 * filter.d/apache-common.conf -- support apache 2.4 more detailed error @@ -66,52 +178,100 @@ ver. 0.8.11 (2013/XX/XXX) - loves-unittests - All backends, possible race condition: do not read from a file initially reported empty. Originally could have lead to accounting for detected log lines multiple times. + - Do not crash if executing a command in fail2ban-client interactive + mode has failed (e.g. due to incorrect syntax). Closes gh-353 Daniel Black & Мернов Георгий * filter.d/dovecot.conf -- Fix when no TLS enabled - line doesn't end in , - Daniel Black - * action.d/hostsdeny -- NOTE: new dependancy 'ed'. Switched to use 'ed' across - all platforms to ensure permissions are the same before and after a ban - - closes gh-266. hostsdeny supports daemon_list now too. - * filter.d/roundcube-auth - timezone offset can be positive or negative - * action.d/bsd-ipfw - action option unsed. Fixed to blocktype for - consistency. default to port unreach instead of deny - Rolf Fokkens - * action.d/dshield.conf and complain.conf -- reorder mailx arguments. - https://bugzilla.redhat.com/show_bug.cgi?id=998020 - John Doe (ache) - * action.d/bsd-ipfw.conf - invert actionstop logic to make exist status 0. - closes gh-343. - JP Espinosa (Reviewed by O.Poplawski) - * files/redhat-initd - rewritten to use stock init.d functions thus - avoiding problems with getpid. Also $network and iptables moved - to Should- rc init fields -- New Features: - Andy Fragen and Daniel Black - * filter.d/osx-ipfw.conf - ipfw action for OSX based on random rule - numbers. - Daniel Black & ykimon - * filter.d/3proxy.conf -- filter added - Daniel Black - * filter.d/exim-spam.conf -- a splitout of exim's spam regexes - with additions for greater control over filtering spam. - * add date expression for apache-2.4 - milliseconds - Christophe Carles & Daniel Black - * filter.d/perdition.conf -- filter added - -- Enhancements: - François Boulogne and Frédéric - * filter.d/lighttpd - auth regexs for lighttpd-1.4.31 - Daniel Black - * filter.d/{asterisk,assp,dovecot,proftpd}.conf -- regex hardening - and extra failure examples in sample logs - * filter.d/apache-auth - added expressions for mod_authz, mod_auth and - mod_auth_digest failures. Daniel Black & Georgiy Mernov & ftoppi & Мернов Георгий * filter.d/exim.conf -- regex hardening and extra failure examples in sample logs * filter.d/named-refused.conf - BIND 9.9.3 regex changes Daniel Black & Sebastian Arcus * filter.d/asterisk -- more regexes + Daniel Black + * action.d/hostsdeny -- NOTE: new dependancy 'ed'. Switched to use 'ed' across + all platforms to ensure permissions are the same before and after a ban. + Closes gh-266. hostsdeny supports daemon_list now too. + * action.d/bsd-ipfw - action option unsed. Change blocktype to port unreach + instead of deny for consistancy. + * filter.d/dovecot - added to support different dovecot failure + "..disallowed plaintext auth". Closes Debian bug #709324 + * filter.d/roundcube-auth - timezone offset can be positive or negative + * action.d/bsd-ipfw - action option unsed. Fixed to blocktype for + consistency. default to port unreach instead of deny + * filter.d/dropbear - fix regexs to match standard dropbear and the patched + http://www.unchartedbackwaters.co.uk/files/dropbear/dropbear-0.52.patch + and add PAM is it in dropbear-2013.60 source code. + * filter.d/{asterisk,assp,dovecot,proftpd}.conf -- regex hardening + and extra failure examples in sample logs + * filter.d/apache-auth - added expressions for mod_authz, mod_auth and + mod_auth_digest failures. + * filter.d/recidive -- support f2b syslog target and anchor regex at start + * filter.d/mysqld-auth.conf - mysql can use syslog + * filter.d/sshd - regex enhancements to support openssh-6.3. Closes Debian + bug #722970. Thanks Colin Watson for the regex analysis. + * filter.d/wuftpd - regex enhancements to support pam and wuftpd. Closes + Debian bug #665925 + Rolf Fokkens + * action.d/dshield.conf and complain.conf -- reorder mailx arguments. + https://bugzilla.redhat.com/show_bug.cgi?id=998020 + John Doe (ache) + * action.d/bsd-ipfw.conf - invert actionstop logic to make exist status 0. + Closes gh-343. + JP Espinosa (Reviewed by O.Poplawski) + * files/redhat-initd - rewritten to use stock init.d functions thus + avoiding problems with getpid. Also $network and iptables moved + to Should- rc init fields + Rick Mellor + * filter.d/vsftp - fix capture with tty=ftp + +- New Features: + Edgar Hoch + * action.d/firewall-cmd-direct-new.conf - action for firewalld + from https://bugzilla.redhat.com/show_bug.cgi?id=979622 + NOTE: requires firewalld-0.3.8+ + Andy Fragen and Daniel Black + * filter.d/osx-ipfw.conf - ipfw action for OSX based on random rule + numbers. + Anonymous: + * action.d/osx-afctl - an action based on afctl for osx + Daniel Black & ykimon + * filter.d/3proxy.conf -- filter added + * fail2ban-regex - now generates http://www.debuggex.com urls for debugging + regular expressions with the -D parameter. + Daniel Black + * filter.d/exim-spam.conf -- a splitout of exim's spam regexes + with additions for greater control over filtering spam. + * add date expression for apache-2.4 - milliseconds + * filter.d/nginx-http-auth -- filter added for http basic authentication + failures in nginx. Partially fulfills gh-405. + Christophe Carles & Daniel Black + * filter.d/perdition.conf -- filter added + Mark McKinstry + * action.d/apf.conf - add action for Advanced Policy Firewall (apf) + Amir Caspi and kjohnsonecl + * filter.d/uwimap-auth - filter for uwimap-auth IMAP/POP server + Steven Hiscocks and Daniel Black + * filter.d/selinux-{common,ssh} -- add SELinux date and ssh filter + +- Enhancements: + François Boulogne and Frédéric + * filter.d/lighttpd - auth regexs for lighttpd-1.4.31 + Daniel Black + * reorder parsing of jail.conf, jail.d/*.conf, jail.local, jail.d/*.local + and likewise for fail2ban.{conf|local|d/*.conf|d/*.local}. Closes gh-392 + * jail.conf now has asterisk jail - no need for asterisk-tcp and + asterisk-udp. Users should replace existing jails with asterisk to + reduce duplicate parsing of the asterisk log file. + * filter.d/{suhosin,pam-generic,gssftpd,sogo-auth,webmin}- regex anchor at + start + * filter.d/vsftpd - anchored regex at start. disable old pam format regex + * filter.d/pam-generic - added syslog prefix. Disabled support for + linux-pam before version 0.99.2.0 (2005) + * filter.d/postfix-sasl - renamed from sasl, anchor at start and base on + syslog + * filter.d/qmail - rewrote regex to anchor at start. Added regex for + another "in the wild" patch to rblsmtp. Yaroslav Halchenko * fail2ban-regex -- refactored to provide more details (missing and ignored lines, control over logging, etc) while maintaining look&feel @@ -122,6 +282,9 @@ ver. 0.8.11 (2013/XX/XXX) - loves-unittests * filter.d/roundcube-auth.conf -- anchored version * date matching - for standard asctime formats prefer more detailed first (thus use year if available) + * files/gen_badbots was added and filter.d/apache-badbots.conf was + regenerated to get updated (although now still an old) list of + "bad" bots Alexander Dietrich * action.d/sendmail-common.conf -- added common sendmail settings file and made the sender display name configurable @@ -132,10 +295,8 @@ ver. 0.8.11 (2013/XX/XXX) - loves-unittests * filter/named-refused - added refused on zone transfer * filter.d/{courier{login,smtp},proftpd,sieve,wuftpd,xinetd} - General regex impovements - * IMPORTANT: 'lighttpd-fastcgi' filter has been renamed to 'suhosin', which - will require changing in jail.{conf,local} if using this filter. Zurd - * filter.d/postfix - add filter for VRFY failures. closes gh-322. + * filter.d/postfix - add filter for VRFY failures. Closes gh-322. Orion Poplawski * fail2ban.d/ and jail.d/ directories are added to etc/fail2ban to facilitate their use diff --git a/DEVELOP b/DEVELOP index f9cac432..dc34340b 100644 --- a/DEVELOP +++ b/DEVELOP @@ -1,6 +1,6 @@ - __ _ _ ___ _ - / _|__ _(_) |_ ) |__ __ _ _ _ - | _/ _` | | |/ /| '_ \/ _` | ' \ + __ _ _ ___ _ + / _|__ _(_) |_ ) |__ __ _ _ _ + | _/ _` | | |/ /| '_ \/ _` | ' \ |_| \__,_|_|_/___|_.__/\__,_|_||_| ================================================================================ @@ -26,7 +26,7 @@ Pull Requests When submitting pull requests on GitHub we ask you to: * Clearly describe the problem you're solving; -* Don't introduce regressions that will make it hard for systems adminstrators +* Don't introduce regressions that will make it hard for systems administrators to update; * If adding a major feature rebase your changes on master and get to a single commit; * Include test cases (see below); @@ -34,128 +34,7 @@ When submitting pull requests on GitHub we ask you to: * Include a change to the relevant section of the ChangeLog; and * Include yourself in THANKS if not already there. -Filters -======= - -* Include sample logs with 1.2.3.4 used for IP addresses and - example.com/example.org used for DNS names -* Ensure sample log is provided in testcases/files/logs/ with same name as the - filter. Each log line should include match meta data for time & IP above - every line (see other sample log files for examples) -* Ensure regexs start with a ^ and are restrictive as possible. E.g. not .* if - \d+ is sufficient -* Use the functionality of regexs http://docs.python.org/2/library/re.html -* Take a look at the source code of the application. You may see optional or - extra log messages, or parts there of, that need to form part of your regex. - -If you only have a basic knowledge of regular repressions read -http://docs.python.org/2/library/re.html first. - -Filter Security ---------------- - -Poor filter regular expressions are suseptable to DoS attacks. - -When a remote user has the ability to introduce text that will match the -filter regex, such that the inserted text matches the part, they have the -ability to deny any host they choose. - -So the part must be anchored on text generated by the application, and not -the user, to a sufficient extent that the user cannot insert the entire text. - -Filters are matched against the log line with their date removed. - -Ideally filter regex should anchor to the beginning and end of the log line -however as more applications log at the beginning than the end, achoring the -beginning is more important. If the log file used by the application is shared -with other applications, like system logs, ensure the other application that -use that log file do not log user generated text at the beginning of the line, -or, if they do, ensure the regexs of the filter are sufficient to mitigate the -risk of insertion. - -When creating a regex that extends back to the begining remember the date part -has been removed within fail2ban so theres no need to match that. If the format -is like ' error 1.2.3.4 is evil' then you will need to match the < at -the start so here the regex would start like '^<> is evil$'. - -Some applications log spaces at the end. If you're not sure add \s*$ as the -end part of the regex. - -Examples of poor filters ------------------------- - -1. Too restrictive - -We find a log message: - - Apr-07-13 07:08:36 Invalid command fial2ban from 1.2.3.4 - -We make a failregex - - ^Invalid command \S+ from - -Now think evil. The user does the command 'blah from 1.2.3.44' - -The program diliently logs: - - Apr-07-13 07:08:36 Invalid command blah from 1.2.3.44 from 1.2.3.4 - -And fail2ban matches 1.2.3.44 as the IP that it ban. A DoS attack was successful. - -The fix here is that the command can be anything so .* is approprate. - - ^Invalid command .* from - -Here the .* will match until the end of the string. Then realise it has more to -match, i.e. "from " and go back until it find this. Then it will ban -1.2.3.4 correctly. Since the is always at the end, end the regex with a $. - - ^Invalid command .* from $ - -Note if we'd just had the expression: - - ^Invalid command \S+ from $ - -Then provided the user put a space in their command they would have never been -banned. - -2. Filter regex can match other user injected data - -From the apache vulnerability CVE-2013-2178 -( original ref: https://vndh.net/note:fail2ban-089-denial-service ). - -An example bad regex for apache: - - failregex = [[]client []] user .* not found - -Since the user can do a get request on: - - GET /[client%20192.168.0.1]%20user%20root%20not%20found HTTP/1.0 -Host: remote.site - -Now the log line will be: - - [Sat Jun 01 02:17:42 2013] [error] [client 192.168.33.1] File does not exist: /srv/http/site/[client 192.168.0.1] user root not found - -As this log line doesn't match other expressions hence it matches the above -regex and blocks 192.168.33.1 as a denial of service from the HTTP requester. - -3. Applicaiton generates two identical log messages with different meanings - -If the application generates the following two messages under different -circmstances: - - client : authentication failed - client : authentication failed - - -Then it's obvious that a regex of "^client : authentication -failed$" will still cause problems if the user can trigger the second -log message with a of 123.1.1.1. - -Here there's nothing to do except request/change the application so it logs -messages differently. - +If you are developing filters see the FILTERS file for documentation. Code Testing ============ @@ -179,7 +58,7 @@ coverage run bin/fail2ban-testcases coverage html Then look at htmlcov/index.html and see how much coverage your test cases -exert over the codebase. Full coverage is a good thing however it may not be +exert over the code base. Full coverage is a good thing however it may not be complete. Try to ensure tests cover as many independent paths through the code. @@ -270,7 +149,7 @@ Design Fail2Ban was initially developed with Python 2.3 (IIRC). It should still be compatible with Python 2.4 and such compatibility assurance makes code ... old-fashioned in many places (RF-Note). In 0.7 the -design went through major refactoring into client/server, +design went through major re-factoring into client/server, a-thread-per-jail design which made it a bit difficult to follow. Below you can find a sketchy description of the main components of the system to orient yourself better. @@ -381,7 +260,7 @@ one way or another provide except FailManagerEmpty: self.failManager.cleanup(MyTime.time()) -thus channeling "ban tickets" from their failManager to the +thus channelling "ban tickets" from their failManager to the corresponding jail. action.py @@ -406,35 +285,54 @@ Releasing * https://github.com/fail2ban/fail2ban/issues?sort=updated&state=open * http://bugs.debian.org/cgi-bin/pkgreport.cgi?dist=unstable;package=fail2ban + * https://bugs.launchpad.net/ubuntu/+source/fail2ban * http://bugs.sabayon.org/buglist.cgi?quicksearch=net-analyzer%2Ffail2ban + * https://bugs.archlinux.org/?project=5&cat%5B%5D=33&string=fail2ban * https://bugs.gentoo.org/buglist.cgi?query_format=advanced&short_desc=fail2ban&bug_status=UNCONFIRMED&bug_status=CONFIRMED&bug_status=IN_PROGRESS&short_desc_type=allwords * https://bugzilla.redhat.com/buglist.cgi?query_format=advanced&bug_status=NEW&bug_status=ASSIGNED&component=fail2ban&classification=Red%20Hat&classification=Fedora * http://www.freebsd.org/cgi/query-pr-summary.cgi?text=fail2ban + * https://bugs.mageia.org/buglist.cgi?quicksearch=fail2ban + * https://build.opensuse.org/package/requests/openSUSE:Factory/fail2ban -# Provide a release sample to distributors +# Make sure the tests pass - * Debian: Yaroslav Halchenko - http://packages.qa.debian.org/f/fail2ban.html - * FreeBSD: Christoph Theis theis@gmx.at>, Nick Hilliard - http://svnweb.freebsd.org/ports/head/security/py-fail2ban/Makefile?view=markup - * Fedora: Axel Thimm - https://apps.fedoraproject.org/packages/fail2ban - * Gentoo: netmon@gentoo.org - http://sources.gentoo.org/cgi-bin/viewvc.cgi/gentoo-x86/net-analyzer/fail2ban/metadata.xml?view=markup - * openSUSE: Stephan Kulow - https://build.opensuse.org/package/users?package=fail2ban&project=openSUSE%3AFactory - * Mac Ports: @Malbrouck on github (gh-49) - https://trac.macports.org/browser/trunk/dports/security/fail2ban/Portfile + ./fail2ban-testcases-all -# Wait for feedback from distributors +# Ensure the version is correct -# Ensure the version is correct in ./common/version.py + in: + * ./common/version.py + * top of ChangeLog + * README.md + +# Ensure the MANIFEST is complete + +Run: + + python setup.py sdist + +Look for errors like: + 'testcases/files/logs/mysqld.log' not a regular file -- skipping + +Which indicates that testcases/files/logs/mysqld.log has been moved or is a directory + + tar -C /tmp -jxf dist/fail2ban-0.9.0.tar.bz2 + +# clean up current direcory + + diff -rul --exclude \*.pyc . /tmp/fail2ban-0.9.0/ + + # Only differences should be files that you don't want distributed. + +# Ensure the tests work from the tarball + + cd /tmp/fail2ban-0.9.0/ && ./fail2ban-testcases-all # Add/finalize the corresponding entry in the ChangeLog To generate a list of committers use e.g. - git shortlog -sn 0.8.8.. | sed -e 's,^[ 0-9\t]*,,g' | tr '\n' '\|' | sed -e 's:|:, :g' + git shortlog -sn 0.8.11.. | sed -e 's,^[ 0-9\t]*,,g' | tr '\n' '\|' | sed -e 's:|:, :g' Ensure the top of the ChangeLog has the right version and current date. @@ -443,23 +341,66 @@ Releasing # Update man pages (cd man ; ./generate-man ) - git commit -m 'update man pages for release' man/* + git commit -m 'DOC/ENH: update man pages for release' man/* -# Make sure the tests pass +# Prepare source and rpm binary distributions - ./fail2ban-testcases-all - -# Prepare/upload source and rpm binary distributions - - python setup.py check python setup.py sdist python setup.py bdist_rpm python setup.py upload -# Run the following and update the wiki with output: +# Provide a release sample to distributors + * Arch Linux: + https://www.archlinux.org/packages/community/any/fail2ban/ + * Debian: Yaroslav Halchenko + http://packages.qa.debian.org/f/fail2ban.html + * FreeBSD: Christoph Theis theis@gmx.at>, Nick Hilliard + http://svnweb.freebsd.org/ports/head/security/py-fail2ban/Makefile?view=markup + http://www.freebsd.org/cgi/query-pr-summary.cgi?text=fail2ban + * Fedora: Axel Thimm + https://apps.fedoraproject.org/packages/fail2ban + http://pkgs.fedoraproject.org/cgit/fail2ban.git + https://admin.fedoraproject.org/pkgdb/acls/bugs/fail2ban + * Gentoo: netmon@gentoo.org + http://sources.gentoo.org/cgi-bin/viewvc.cgi/gentoo-x86/net-analyzer/fail2ban/metadata.xml?view=markup + https://bugs.gentoo.org/buglist.cgi?quicksearch=fail2ban + * openSUSE: Stephan Kulow + https://build.opensuse.org/package/show/openSUSE:Factory/fail2ban + * Mac Ports: @Malbrouck on github (gh-49) + https://trac.macports.org/browser/trunk/dports/security/fail2ban/Portfile + * Mageia: + https://bugs.mageia.org/buglist.cgi?quicksearch=fail2ban + An potentially to the fail2ban-users directory. + +# Wait for feedback from distributors + +# Prepare a release notice https://github.com/fail2ban/fail2ban/releases/new + + Upload the source/binaries from the dist directory and tag the release using the URL + +# Upload source/binaries to sourceforge http://sourceforge.net/projects/fail2ban/ + +# Run the following and update the wiki with output: python -c 'import fail2ban.protocol; fail2ban.protocol.printWiki()' + page: http://www.fail2ban.org/wiki/index.php/Commands + +* Update: + http://www.fail2ban.org/wiki/index.php?title=Template:Fail2ban_Versions&action=edit + + http://www.fail2ban.org/wiki/index.php?title=Template:Fail2ban_News&action=edit + move old bits to: + http://www.fail2ban.org/wiki/index.php?title=Template:Fail2ban_OldNews&action=edit + + http://www.fail2ban.org/wiki/index.php?title=Template:Fail2ban_Versions&action=edit + http://www.fail2ban.org/wiki/index.php/ChangeLog + http://www.fail2ban.org/wiki/index.php/Requirements (Check requirement) + http://www.fail2ban.org/wiki/index.php/Features + +* See if any filters are upgraded: + http://www.fail2ban.org/wiki/index.php/Special:AllPages + # Email users and development list of release # notify distributors @@ -469,15 +410,17 @@ Post Release Add the following to the top of the ChangeLog -ver. 0.8.12 (2013/XX/XXX) - wanna-be-released +ver. 0.9.1 (2014/XX/XXX) - wanna-be-released ----------- - Fixes: - + - New Features: - + - Enhancements: - + +Alter the git shortlog command in the previous section to refer to the just +released version. and adjust common/version.py to carry .dev suffix to signal a version under development. diff --git a/FILTERS b/FILTERS new file mode 100644 index 00000000..fd441e58 --- /dev/null +++ b/FILTERS @@ -0,0 +1,469 @@ + __ _ _ ___ _ + / _|__ _(_) |_ ) |__ __ _ _ _ + | _/ _` | | |/ /| '_ \/ _` | ' \ + |_| \__,_|_|_/___|_.__/\__,_|_||_| + +================================================================================ +Developing Filters +================================================================================ + +Filters +======= + +Filters are tricky. They need to: +* work with a variety of the versions of the software that generates the logs; +* work with the range of logging configuration options available in the + software; +* work with multiple operating systems; +* not make assumptions about the log format in excess of the software + (e.g. do not assume a username doesn't contain spaces and use \S+ unless + you've checked the source code); +* account for how future versions of the software will log messages + (e.g. guess what would happen to the log message if different authentication + types are added); +* not be susceptible to DoS vulnerabilities (see Filter Security below); and +* match intended log lines only. + +Please follow the steps from Filter Test Cases to Developing Filter Regular +Expressions and submit a GitHub pull request (PR) afterwards. If you get stuck, +you can push your unfinished changes and still submit a PR -- describe +what you have done, what is the hurdle, and we'll attempt to help (PR +will be automagically updated with future commits you would push to +complete it). + +Filter test cases +----------------- + +Purpose: + +Start by finding the log messages that the application generates related to +some form of authentication failure. If you are adding to an existing filter +think about whether the log messages are of a similar importance and purpose +to the existing filter. If you were a user of Fail2Ban, and did a package +update of Fail2Ban that started matching new log messages, would anything +unexpected happen? Would the bantime/findtime for the jail be appropriate for +the new log messages? If it doesn't, perhaps it needs to be in a separate +filter definition, for example like exim filter aims at authentication failures +and exim-spam at log messages related to spam. + +Even if it is a new filter you may consider separating the log messages into +different filters based on purpose. + +Cause: + +Are some of the log lines a result of the same action? For example, is a PAM +failure log message, followed by an application specific failure message the +result of the same user/script action? If you add regular expressions for +both you would end up with two failures for a single action. +Therefore, select the most appropriate log message and document the other log +message) with a test case not to match it and a description as to why you chose +one over another. + +With the selected log lines consider what action has caused those log +messages and whether they could have been generated by accident? Could +the log message be occurring due to the first step towards the application +asking for authentication? Could the log messages occur often? If some of +these are true make a note of this in the jail.conf example that you provide. + +Samples: + +It is important to include log file samples so any future change in the regular +expression will still work with the log lines you have identified. + +The sample log messages are provided in a file under testcases/files/logs/ +named identically as the corresponding filter (but without .conf extension). +Each log line should be preceded by a line with failJSON metadata (so the logs +lines are tested in the test suite) directly above the log line. If there is +any specific information about the log message, such as version or an +application configuration option that is needed for the message to occur, +include this in a comment (line beginning with #) above the failJSON metadata. + +Log samples should include only one, definitely not more than 3, examples of +log messages of the same form. If log messages are different in different +versions of the application log messages that show this are encouraged. + +Also attempt to inject an IP into the application (e.g. by specifying +it as a username) so that Fail2Ban possibly detects the IP +from user input rather than the true origin. See the Filter Security section +and the top example in testcases/files/logs/apache-auth as to how to do this. +One you have discovered that this is possible, correct the regex so it doesn't +match and provide this as a test case with "match": false (see failJSON below). + +If the mechanism to create the log message isn't obvious provide a +configuration and/or sample scripts testcases/files/config/{filtername} and +reference these in the comments above the log line. + +FailJSON metadata: + +A failJSON metadata is a comment immediately above the log message. It will +look like: + +# failJSON: { "time": "2013-06-10T10:10:59", "match": true , "host": "93.184.216.119" } + +Time should match the time of the log message. It is in a specific format of +Year-Month-Day'T'Hour:minute:Second. If your log message does not include a +year, like the example below, the year should be listed as 2005, if before Sun +Aug 14 10am UTC, and 2004 if afterwards. Here is an example failJSON +line preceding a sample log line: + +# failJSON: { "time": "2005-03-24T15:25:51", "match": true , "host": "198.51.100.87" } +Mar 24 15:25:51 buffalo1 dropbear[4092]: bad password attempt for 'root' from 198.51.100.87:5543 + +The "host" in failJSON should contain the IP or domain that should be blocked. + +For long lines that you do not want to be matched (e.g. from log injection +attacks) and any log lines to be excluded (see "Cause" section above), set +"match": false in the failJSON and describe the reason in the comment above. + +After developing regexes, the following command will test all failJSON metadata +against the log lines in all sample log files + +./fail2ban-testcases testSampleRegex + +Developing Filter Regular Expressions +------------------------------------- + +Date/Time: + +At the moment, Fail2Ban depends on log lines to have time stamps. That is why +before starting to develop failregex, check if your log line format known to +Fail2Ban. Copy the time component from the log line and append an IP address to +test with following command: + +./fail2ban-regex "2013-09-19 02:46:12 1.2.3.4" "" + +Output of such command should contain something like: + +Date template hits: +|- [# of hits] date format +| [1] Year-Month-Day Hour:Minute:Second + +Ensure that the template description matches time/date elements in your log line +time stamp. If there is no matched format then date template needs to be added +to server/datedetector.py. Ensure that a new template is added in the order +that more specific matches occur first and that there is no confusion between a +Day and a Month. + +Filter file: + +The filter is specified in a config/filter.d/{filtername}.conf file. Filter file +can have sections INCLUDES (optional) and Definition as follows: + +[INCLUDES] + +before = common.conf + +after = filtername.local + +[Definition] + +failregex = .... + +ignoreregex = .... + +This is also documented in the man page jail.conf (section 5). Other definitions +can be added to make failregex's more readable and maintainable to be used +through string Interpolations (see http://docs.python.org/2.7/library/configparser.html) + + +General rules: + +Use "before" if you need to include a common set of rules, like syslog or if +there is a common set of regexes for multiple filters. + +Use "after" if you wish to allow the user to overwrite a set of customisations +of the current filter. This file doesn't need to exist. + +Try to avoid using ignoreregex mainly for performance reasons. The case when you +would use it is if in trying to avoid using it, you end up with an unreadable +failregex. + +Syslog: + +If your application logs to syslog you can take advantage of log line prefix +definitions present in common.conf. So as a base use: + +[INCLUDES] + +before = common.conf + +[Definition] + +_daemon = app + +failregex = ^%(__prefix_line)s + +In this example common.conf defines __prefix_line which also contains the +_daemon name (in syslog terms the service) you have just specified. _daemon +can also be a regex. + +For example, to capture following line _daemon should be set to "dovecot" + +Dec 12 11:19:11 dunnart dovecot: pop3-login: Aborted login (tried to use disabled plaintext auth): rip=190.210.136.21, lip=113.212.99.193 + +and then ^%(__prefix_line)s would match "Dec 12 11:19:11 dunnart dovecot: +". Note it matches the trailing space(s) as well. + +Substitutions (AKA string interpolations): + +We have used string interpolations in above examples. They are useful for +making the regexes more readable, reuse generic patterns in multiple failregex +lines, and also to refer definition of regex parts to specific filters or even +to the user. General principle is that value of a _name variable replaces +occurrences of %(_name)s within the same section or anywhere in the config file +if defined in [DEFAULT] section. + +Regular Expressions: + +Regular expressions (failregex, ignoreregex) assume that the date/time has been +removed from the log line (this is just how fail2ban works internally ATM). + +If the format is like ' error 1.2.3.4 is evil' then you need to match +the < at the start so regex should be similar to '^<> is evil$' using + where the IP/domain name appears in the log line. + +The following general rules apply to regular expressions: + +* ensure regexes start with a ^ and are as restrictive as possible. E.g. do not + use .* if \d+ is sufficient; +* use functionality of Python regexes defined in the standard Python re library + http://docs.python.org/2/library/re.html; +* make regular expressions readable (as much as possible). E.g. + (?:...) represents a non-capturing regex but (...) is more readable, thus + preferred. + +If you have only a basic knowledge of regular repressions we advise to read +http://docs.python.org/2/library/re.html first. It doesn't take long and would +remind you e.g. which characters you need to escape and which you don't. + +Developing/testing a regex: + +You can develop a regex in a file or using command line depending on your +preference. You can also use samples you have already created in the test cases +or test them one at a time. + +The general tool for testing Fail2Ban regexes is fail2ban-regex. To see how to +use it run: + +./fail2ban-regex --help + +Take note of -l heavydebug / -l debug and -v as they might be very useful. + +TIP: Take a look at the source code of the application you are developing + failregex for. You may see optional or extra log messages, or parts there + of, that need to form part of your regex. It may also reveal how some + parts are constrained and different formats depending on configuration or + less common usages. + +TIP: For looking through source code - http://sourcecodebrowser.com/ . It has + call graphs and can browse different versions. + +TIP: Some applications log spaces at the end. If you are not sure add \s*$ as + the end part of the regex. + +If your regex is not matching, http://www.debuggex.com/?flavor=python can help +to tune it. fail2ban-regex -D ... will present Debuggex URLs for the regexs +and sample log files that you pass into it. + +In general use when using regex debuggers for generating fail2ban filters: +* use regex from the ./fail2ban-regex output (to ensure all substitutions are +done) +* replace with (?&.ipv4) +* make sure that regex type set to Python +* for the test data put your log output with the date/time removed + +When you have fixed the regex put it back into your filter file. + +Please spread the good word about Debuggex - Serge Toarca is kindly continuing +its free availability to Open Source developers. + +Finishing up: + +If you've added a new filter, add a new entry in config/jail.conf. The theory +here is that a user will create a jail.local with [filtername]\nenable=true to +enable your jail. + +So more specifically in the [filter] section in jail.conf: +* ensure that you have "enabled = false" (users will enable as needed); +* use "filter =" set to your filter name; +* use a typical action to disable ports associated with the application; +* set "logpath" to the usual location of application log file; +* if the default findtime or bantime isn't appropriate to the filter, specify + more appropriate choices (possibly with a brief comment line). + +Submit github pull request (See "Pull Requests" above) for +github.com/fail2ban/fail2ban containing your great work. + +Filter Security +--------------- + +Poor filter regular expressions are susceptible to DoS attacks. + +When a remote user has the ability to introduce text that would match filter's +failregex, while matching inserted text to the part, they have the +ability to deny any host they choose. + +So the part must be anchored on text generated by the application, and +not the user, to an extent sufficient to prevent user inserting the entire text +matching this or any other failregex. + +Ideally filter regex should anchor at the beginning and at the end of log line. +However as more applications log at the beginning than the end, anchoring the +beginning is more important. If the log file used by the application is shared +with other applications, like system logs, ensure the other application that use +that log file do not log user generated text at the beginning of the line, or, +if they do, ensure the regexes of the filter are sufficient to mitigate the risk +of insertion. + + +Examples of poor filters +------------------------ + +1. Too restrictive + +We find a log message: + + Apr-07-13 07:08:36 Invalid command fial2ban from 1.2.3.4 + +We make a failregex + + ^Invalid command \S+ from + +Now think evil. The user does the command 'blah from 1.2.3.44' + +The program diligently logs: + + Apr-07-13 07:08:36 Invalid command blah from 1.2.3.44 from 1.2.3.4 + +And fail2ban matches 1.2.3.44 as the IP that it ban. A DoS attack was successful. + +The fix here is that the command can be anything so .* is appropriate. + + ^Invalid command .* from + +Here the .* will match until the end of the string. Then realise it has more to +match, i.e. "from " and go back until it find this. Then it will ban +1.2.3.4 correctly. Since the is always at the end, end the regex with a $. + + ^Invalid command .* from $ + +Note if we'd just had the expression: + + ^Invalid command \S+ from $ + +Then provided the user put a space in their command they would have never been +banned. + +2. Unanchored regex can match other user injected data + +From the Apache vulnerability CVE-2013-2178 +( original ref: https://vndh.net/note:fail2ban-089-denial-service ). + +An example bad regex for Apache: + + failregex = [[]client []] user .* not found + +Since the user can do a get request on: + + GET /[client%20192.168.0.1]%20user%20root%20not%20found HTTP/1.0 +Host: remote.site + +Now the log line will be: + + [Sat Jun 01 02:17:42 2013] [error] [client 192.168.33.1] File does not exist: /srv/http/site/[client 192.168.0.1] user root not found + +As this log line doesn't match other expressions hence it matches the above +regex and blocks 192.168.33.1 as a denial of service from the HTTP requester. + +3. Over greedy pattern matching + +From: https://github.com/fail2ban/fail2ban/pull/426 + +An example ssh log (simplified) + + Sep 29 17:15:02 spaceman sshd[12946]: Failed password for user from 127.0.0.1 port 20000 ssh1: ruser remoteuser + +As we assume username can include anything including spaces its prudent to put +.* here. The remote user can also exist as anything so lets not make assumptions again. + + failregex = ^%(__prefix_line)sFailed \S+ for .* from ( port \d*)?( ssh\d+)?(: ruser .*)?$ + +So this works. The problem is if the .* after remote user is injected by the +user to be 'from 1.2.3.4'. The resultant log line is. + + Sep 29 17:15:02 spaceman sshd[12946]: Failed password for user from 127.0.0.1 port 20000 ssh1: ruser from 1.2.3.4 + +Testing with: + + fail2ban-regex -v 'Sep 29 17:15:02 Failed password for user from 127.0.0.1 port 20000 ssh1: ruser from 1.2.3.4' '^ Failed \S+ for .* from ( port \d*)?( ssh\d+)?(: ruser .*)?$' + +TIP: I've removed the bit that matches __prefix_line from the regex and log. + +Shows: + + 1) [1] ^ Failed \S+ for .* from ( port \d*)?( ssh\d+)?(: ruser .*)?$ + 1.2.3.4 Sun Sep 29 17:15:02 2013 + +It should of matched 127.0.0.1. So the first greedy part of the greedy regex +matched until the end of the string. The was no "from " so the regex +engine worked backwards from the end of the string until this was matched. + +The result was that 1.2.3.4 was matched, injected by the user, and the wrong IP +was banned. + +The solution here is to make the first .* non-greedy with .*?. Here it matches +as little as required and the fail2ban-regex tool shows the output: + + fail2ban-regex -v 'Sep 29 17:15:02 Failed password for user from 127.0.0.1 port 20000 ssh1: ruser from 1.2.3.4' '^ Failed \S+ for .*? from ( port \d*)?( ssh\d+)?(: ruser .*)?$' + + 1) [1] ^ Failed \S+ for .*? from ( port \d*)?( ssh\d+)?(: ruser .*)?$ + 127.0.0.1 Sun Sep 29 17:15:02 2013 + +So the general case here is a log line that contains: + + (fixed_data_1)(fixed_data_2)(user_injectable_data) + +Where the regex that matches fixed_data_1 is gready and matches the entire +string, before moving backwards and user_injectable_data can match the entire +string. + +Another case: + +ref: https://www.debuggex.com/r/CtAbeKMa2sDBEfA2/0 + +A webserver logs the following without URL escaping: + + [error] 2865#0: *66647 user "xyz" was not found in "/file", client: 1.2.3.1, server: www.host.com, request: "GET ", client: 3.2.1.1, server: fake.com, request: "GET exploited HTTP/3.3", host: "injected.host", host: "www.myhost.com" + +regex: + + failregex = ^ \[error\] \d+#\d+: \*\d+ user "\S+":? (?:password mismatch|was not found in ".*"), client: , server: \S+, request: "\S+ .+ HTTP/\d+\.\d+", host: "\S+" + +The .* matches to the end of the string. Finds that it can't continue to match +", client ... so it moves from the back and find that the user injected web URL: + + ", client: 3.2.1.1, server: fake.com, request: "GET exploited HTTP/3.3", host: "injected.host + +In this case there is a fixed host: "www.myhost.com" at the end so the solution +is to anchor the regex at the end with a $. + +If this wasn't the case then first .* needed to be made so it didn't capture +beyond . + +4. Application generates two identical log messages with different meanings + +If the application generates the following two messages under different +circumstances: + + client : authentication failed + client : authentication failed + + +Then it's obvious that a regex of "^client : authentication +failed$" will still cause problems if the user can trigger the second +log message with a of 123.1.1.1. + +Here there's nothing to do except request/change the application so it logs +messages differently. + + diff --git a/MANIFEST b/MANIFEST index 1c2b5779..675cd662 100644 --- a/MANIFEST +++ b/MANIFEST @@ -5,12 +5,15 @@ TODO THANKS COPYING DEVELOP -doc/run-rootless.txt +FILTERS fail2ban-2to3 +fail2ban-testcases-all +fail2ban-testcases-all-python3 bin/fail2ban-client bin/fail2ban-server bin/fail2ban-testcases bin/fail2ban-regex +doc/run-rootless.txt fail2ban/client/configreader.py fail2ban/client/configparserinc.py fail2ban/client/jailreader.py @@ -23,6 +26,7 @@ fail2ban/client/__init__.py fail2ban/client/configurator.py fail2ban/client/csocket.py fail2ban/server/asyncserver.py +fail2ban/server/database.py fail2ban/server/filter.py fail2ban/server/filterpyinotify.py fail2ban/server/filtergamin.py @@ -45,45 +49,113 @@ fail2ban/server/banmanager.py fail2ban/server/datetemplate.py fail2ban/server/mytime.py fail2ban/server/failregex.py +fail2ban/server/database.py fail2ban/tests/banmanagertestcase.py fail2ban/tests/failmanagertestcase.py fail2ban/tests/clientreadertestcase.py fail2ban/tests/filtertestcase.py fail2ban/tests/__init__.py +fail2ban/tests/dummyjail.py +fail2ban/tests/samplestestcase.py fail2ban/tests/datedetectortestcase.py fail2ban/tests/actiontestcase.py fail2ban/tests/servertestcase.py fail2ban/tests/sockettestcase.py fail2ban/tests/utils.py fail2ban/tests/misctestcase.py +fail2ban/tests/databasetestcase.py +fail2ban/tests/config/jail.conf +fail2ban/tests/config/fail2ban.conf +fail2ban/tests/config/filter.d/simple.conf +fail2ban/tests/config/action.d/brokenaction.conf +fail2ban/tests/files/config/apache-auth/digest/.htaccess +fail2ban/tests/files/config/apache-auth/digest/.htpasswd +fail2ban/tests/files/config/apache-auth/digest_time/.htaccess +fail2ban/tests/files/config/apache-auth/digest_time/.htpasswd +fail2ban/tests/files/config/apache-auth/basic/authz_owner/.htaccess +fail2ban/tests/files/config/apache-auth/basic/authz_owner/cant_get_me.html +fail2ban/tests/files/config/apache-auth/basic/authz_owner/.htpasswd +fail2ban/tests/files/config/apache-auth/basic/file/.htaccess +fail2ban/tests/files/config/apache-auth/basic/file/.htpasswd +fail2ban/tests/files/config/apache-auth/digest.py +fail2ban/tests/files/config/apache-auth/digest_wrongrelm/.htaccess +fail2ban/tests/files/config/apache-auth/digest_wrongrelm/.htpasswd +fail2ban/tests/files/config/apache-auth/digest_anon/.htaccess +fail2ban/tests/files/config/apache-auth/digest_anon/.htpasswd +fail2ban/tests/files/config/apache-auth/README +fail2ban/tests/files/config/apache-auth/noentry/.htaccess +fail2ban/tests/files/database_v1.db +fail2ban/tests/files/ignorecommand.py +fail2ban/tests/files/filter.d/substition.conf +fail2ban/tests/files/filter.d/testcase-common.conf +fail2ban/tests/files/filter.d/testcase01.conf fail2ban/tests/files/testcase01.log fail2ban/tests/files/testcase02.log fail2ban/tests/files/testcase03.log fail2ban/tests/files/testcase04.log fail2ban/tests/files/testcase-usedns.log +fail2ban/tests/files/testcase-journal.log +fail2ban/tests/files/testcase-multiline.log fail2ban/tests/files/logs/bsd/syslog-plain.txt fail2ban/tests/files/logs/bsd/syslog-v.txt fail2ban/tests/files/logs/bsd/syslog-vv.txt +fail2ban/tests/files/logs/3proxy +fail2ban/tests/files/logs/apache-auth +fail2ban/tests/files/logs/apache-badbots +fail2ban/tests/files/logs/apache-botscripts +fail2ban/tests/files/logs/apache-modsecurity +fail2ban/tests/files/logs/apache-nohome +fail2ban/tests/files/logs/apache-noscript fail2ban/tests/files/logs/apache-overflows fail2ban/tests/files/logs/assp fail2ban/tests/files/logs/asterisk +fail2ban/tests/files/logs/counter-strike +fail2ban/tests/files/logs/courier-auth +fail2ban/tests/files/logs/courier-smtp +fail2ban/tests/files/logs/cyrus-imap fail2ban/tests/files/logs/dovecot +fail2ban/tests/files/logs/dropbear +fail2ban/tests/files/logs/ejabberd-auth fail2ban/tests/files/logs/exim -fail2ban/tests/files/logs/lighttpd -fail2ban/tests/files/logs/mysqld.log +fail2ban/tests/files/logs/exim-spam +fail2ban/tests/files/logs/freeswitch +fail2ban/tests/files/logs/groupoffice +fail2ban/tests/files/logs/gssftpd +fail2ban/tests/files/logs/guacamole +fail2ban/tests/files/logs/lighttpd-auth +fail2ban/tests/files/logs/mysqld-auth +fail2ban/tests/files/logs/nsd +fail2ban/tests/files/logs/perdition +fail2ban/tests/files/logs/php-url-fopen +fail2ban/tests/files/logs/postfix-sasl fail2ban/tests/files/logs/named-refused +fail2ban/tests/files/logs/nginx-http-auth fail2ban/tests/files/logs/pam-generic fail2ban/tests/files/logs/postfix fail2ban/tests/files/logs/proftpd fail2ban/tests/files/logs/pure-ftpd +fail2ban/tests/files/logs/qmail +fail2ban/tests/files/logs/recidive fail2ban/tests/files/logs/roundcube-auth -fail2ban/tests/files/logs/sasl +fail2ban/tests/files/logs/selinux-ssh +fail2ban/tests/files/logs/sendmail-spam +fail2ban/tests/files/logs/sieve +fail2ban/tests/files/logs/squid +fail2ban/tests/files/logs/stunnel +fail2ban/tests/files/logs/suhosin fail2ban/tests/files/logs/sogo-auth +fail2ban/tests/files/logs/solid-pop3d fail2ban/tests/files/logs/sshd fail2ban/tests/files/logs/sshd-ddos fail2ban/tests/files/logs/vsftpd fail2ban/tests/files/logs/webmin-auth -fail2ban/tests/files/logs/wu-ftpd +fail2ban/tests/files/logs/wuftpd +fail2ban/tests/files/logs/uwimap-auth +fail2ban/tests/files/logs/xinetd-fail +fail2ban/tests/config/jail.conf +fail2ban/tests/config/fail2ban.conf +fail2ban/tests/config/filter.d/simple.conf +fail2ban/tests/config/action.d/brokenaction.conf setup.py setup.cfg fail2ban/__init__.py @@ -91,30 +163,43 @@ fail2ban/exceptions.py fail2ban/helpers.py fail2ban/version.py fail2ban/protocol.py +setup.py +setup.cfg +kill-server config/jail.conf +config/fail2ban.conf config/filter.d/common.conf config/filter.d/apache-auth.conf config/filter.d/apache-badbots.conf +config/filter.d/apache-botsearch.conf config/filter.d/apache-nohome.conf config/filter.d/apache-noscript.conf config/filter.d/apache-overflows.conf -config/filter.d/courierlogin.conf -config/filter.d/couriersmtp.conf +config/filter.d/nginx-http-auth.conf +config/filter.d/counter-strike.conf +config/filter.d/courier-auth.conf +config/filter.d/courier-smtp.conf config/filter.d/cyrus-imap.conf config/filter.d/exim.conf config/filter.d/gssftpd.conf config/filter.d/suhosin.conf config/filter.d/named-refused.conf +config/filter.d/openwebmail.conf +config/filter.d/pam-generic.conf +config/filter.d/php-url-fopen.conf +config/filter.d/postfix-sasl.conf +config/filter.d/pam-generic.conf +config/filter.d/php-url-fopen.conf +config/filter.d/postfix-sasl.conf config/filter.d/postfix.conf config/filter.d/proftpd.conf config/filter.d/pure-ftpd.conf config/filter.d/qmail.conf -config/filter.d/pam-generic.conf -config/filter.d/php-url-fopen.conf -config/filter.d/sasl.conf config/filter.d/sieve.conf +config/filter.d/solid-pop3d.conf config/filter.d/sshd.conf config/filter.d/sshd-ddos.conf +config/filter.d/stunnel.conf config/filter.d/vsftpd.conf config/filter.d/webmin-auth.conf config/filter.d/wuftpd.conf @@ -126,10 +211,32 @@ config/filter.d/lighttpd-auth.conf config/filter.d/recidive.conf config/filter.d/roundcube-auth.conf config/filter.d/assp.conf -config/filter.d/mysqld-auth.conf config/filter.d/sogo-auth.conf +config/filter.d/mysqld-auth.conf +config/filter.d/selinux-common.conf +config/filter.d/selinux-ssh.conf +config/filter.d/3proxy.conf +config/filter.d/apache-common.conf +config/filter.d/exim-common.conf +config/filter.d/exim-spam.conf +config/filter.d/freeswitch.conf +config/filter.d/groupoffice.conf +config/filter.d/perdition.conf +config/filter.d/uwimap-auth.conf +config/filter.d/courier-auth.conf +config/filter.d/courier-smtp.conf +config/filter.d/ejabberd-auth.conf +config/filter.d/guacamole.conf +config/filter.d/sendmail-spam.conf +config/action.d/apf.conf +config/action.d/osx-afctl.conf +config/action.d/osx-ipfw.conf +config/action.d/sendmail-common.conf config/action.d/bsd-ipfw.conf config/action.d/dummy.conf +config/action.d/firewallcmd-new.conf +config/action.d/firewallcmd-ipset.conf +config/action.d/iptables-ipset-proto6-allports.conf config/action.d/iptables-blocktype.conf config/action.d/iptables-ipset-proto4.conf config/action.d/iptables-ipset-proto6.conf @@ -153,10 +260,13 @@ config/action.d/mynetwatchman.conf config/action.d/pf.conf config/action.d/sendmail.conf config/action.d/sendmail-buffered.conf +config/action.d/sendmail-whois-ipmatches.conf config/action.d/sendmail-whois.conf config/action.d/sendmail-whois-lines.conf config/action.d/shorewall.conf -config/fail2ban.conf +config/action.d/xarf-login-attack.conf +config/action.d/ufw.conf +doc/run-rootless.txt man/fail2ban-client.1 man/fail2ban.1 man/jail.conf.5 @@ -178,9 +288,9 @@ files/cacti/fail2ban_stats.sh files/cacti/cacti_host_template_fail2ban.xml files/cacti/README files/nagios/check_fail2ban -files/nagios/f2ban.txt +files/nagios/README files/bash-completion files/fail2ban-tmpfiles.conf files/fail2ban.service files/ipmasq-ZZZzzz_fail2ban.rul -files/nagios/README +files/gen_badbots diff --git a/README.md b/README.md index 1b7cf718..2482856f 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ / _|__ _(_) |_ ) |__ __ _ _ _ | _/ _` | | |/ /| '_ \/ _` | ' \ |_| \__,_|_|_/___|_.__/\__,_|_||_| - v0.9.0a0 2013/??/?? + v0.9.0a2 2014/??/?? ## Fail2Ban: ban hosts that cause multiple authentication errors @@ -21,7 +21,7 @@ Installation: this case, you should use it instead.** Required: -- [Python2 >= 2.4 or Python3 >= 3.2](http://www.python.org) +- [Python2 >= 2.6 or Python3 >= 3.2](http://www.python.org) or [PyPy](http://pypy.org) Optional: - [pyinotify >= 0.8.3](https://github.com/seb-m/pyinotify) @@ -31,8 +31,8 @@ Optional: To install, just do: - tar xvfj fail2ban-0.8.10.tar.bz2 - cd fail2ban-0.8.10 + tar xvfj fail2ban-0.9.0.tar.bz2 + cd fail2ban-0.9.0 python setup.py install This will install Fail2Ban into /usr/share/fail2ban. The executable scripts are diff --git a/THANKS b/THANKS index 2da6614f..7b2d12b8 100644 --- a/THANKS +++ b/THANKS @@ -1,22 +1,32 @@ -Fail2Ban is an open source project with many contributions from its -users community. Below is an alphabetically sorted partial list of the -contributors to the project. If you have been left off, please let us -know (preferably send a pull request on github with the "fix") and you -will be added +Fail2Ban is an open source project which was conceived and originally +developed by Cyril Jaquier until 2010. Since then Fail2Ban grew into +a community-driven project with many contributions from its users. +Below is an alphabetically sorted partial list of the contributors to +the project. If you have been left off, please let us know +(preferably send a pull request on github with the "fix") and you will +be added +Adam Tkac Adrien Clerc ache +ag4ve (Shawn) +Alasdair D. Campbell +Amir Caspi Andrey G. Grozin Andy Fragen Arturo 'Buanzo' Busleiman Axel Thimm +Bas van den Dikkenberg +Beau Raines Bill Heaton Carlos Alberto Lopez Perez Christian Rauch Christophe Carles Christoph Haas Christos Psonis +Cyril Jaquier Daniel B. Cid +Daniel B. Daniel Black David Nutter Eric Gerbier @@ -25,41 +35,59 @@ ftoppi François Boulogne Frédéric Georgiy Mernov +Guilhem Lettron Guillaume Delvit Hanno 'Rince' Wagner Iain Lea +Ivo Truxa +John Thoe +Jacques Lav!gnotte +Ioan Indreias Jonathan Kamens +Jonathan Lanning Jonathan Underwood Joël Bertrand JP Espinosa Justin Shore Kévin Drapel +kjohnsonecl kojiro +Lee Clemens +Manuel Arostegui Ramirez Marcel Dopita Mark Edgington +Mark McKinstry +Mark White Markus Hoffmann Marvin Rouge mEDI Мернов Георгий +Merijn Schering Michael C. Haller Michael Hanselmann -NickMunger +Nick Munger +onorua Patrick Börjesson Raphaël Marichez +RealRancor René Berber Robert Edeker Rolf Fokkens +Roman Gelfand Russell Odom Sebastian Arcus Sireyessire silviogarbes +Stefan Tatschner Stephen Gildea Steven Hiscocks +TESTOVIK Tom Pike Tyler Vaclav Misek Vincent Deffontaines Yaroslav Halchenko +Winston Smith ykimon Yehuda Katz zugeschmiert diff --git a/bin/fail2ban-client b/bin/fail2ban-client index 0f84a15c..6275d420 100755 --- a/bin/fail2ban-client +++ b/bin/fail2ban-client @@ -147,8 +147,9 @@ class Fail2banClient: if showRet: print beautifier.beautify(ret[1]) else: - logSys.debug("NOK: " + `ret[1].args`) - print beautifier.beautifyError(ret[1]) + logSys.error("NOK: " + `ret[1].args`) + if showRet: + print beautifier.beautifyError(ret[1]) return False except socket.error: if showRet: @@ -375,7 +376,10 @@ class Fail2banClient: if cmd == "help": self.dispUsage() elif not cmd == "": - self.__processCommand(shlex.split(cmd)) + try: + self.__processCommand(shlex.split(cmd)) + except Exception, e: + logSys.error(e) except (EOFError, KeyboardInterrupt): print return True diff --git a/bin/fail2ban-regex b/bin/fail2ban-regex index e54659f7..cfaa4a89 100755 --- a/bin/fail2ban-regex +++ b/bin/fail2ban-regex @@ -23,15 +23,13 @@ and bans the corresponding IP addresses using firewall rules. This tools can test regular expressions for "fail2ban". -Report bugs to https://github.com/fail2ban/fail2ban/issues """ __author__ = "Cyril Jaquier, Yaroslav Halchenko" __copyright__ = "Copyright (c) 2004-2008 Cyril Jaquier, 2012-2013 Yaroslav Halchenko" __license__ = "GPL" -import getopt, sys, time, logging, os, locale, shlex - +import getopt, sys, time, logging, os, locale, shlex, urllib from optparse import OptionParser, Option from ConfigParser import NoOptionError, NoSectionError, MissingSectionHeaderError @@ -43,7 +41,7 @@ except ImportError: journal = None from fail2ban.version import version -from fail2ban.client.configparserinc import SafeConfigParserWithIncludes +from fail2ban.client.filterreader import FilterReader from fail2ban.server.filter import Filter from fail2ban.server.failregex import RegexException @@ -51,6 +49,12 @@ from fail2ban.tests.utils import FormatterWithTraceBack # Gets the instance of the logger. logSys = logging.getLogger("fail2ban") +def debuggexURL(sample, regex): + q = urllib.urlencode({ 're': regex.replace('', '(?&.ipv4)'), + 'str': sample, + 'flavor': 'python' }) + return 'http://www.debuggex.com/?' + q + def shortstr(s, l=53): """Return shortened string """ @@ -94,7 +98,7 @@ def get_opt_parser(): LOG: string a string representing a log line filename path to a log file (/var/log/auth.log) - "systemd-journal" search systemd journal (systemd-python required) + "systemd-journal" search systemd journal (systemd-python required) REGEX: string a string representing a 'failregex' @@ -103,6 +107,15 @@ REGEX: IGNOREREGEX: string a string representing an 'ignoreregex' filename path to a filter file (filter.d/sshd.conf) + +Copyright (c) 2004-2008 Cyril Jaquier, 2008- Fail2Ban Contributors +Copyright of modifications held by their respective authors. +Licensed under the GNU General Public License v2 (GPL). + +Written by Cyril Jaquier . +Many contributions by Yaroslav O. Halchenko and Steven Hiscocks. + +Report bugs to https://github.com/fail2ban/fail2ban/issues """, version="%prog " + version) @@ -116,14 +129,15 @@ IGNOREREGEX: Option("-m", "--journalmatch", help="journalctl style matches overriding filter file. " "\"systemd-journal\" only"), - Option("-v", "--verbose", action='store_true', - help="Be verbose in output"), - Option('-l', "--log-level", type="choice", dest="log_level", choices=('heavydebug', 'debug', 'info', 'warning', 'error', 'fatal'), default=None, help="Log level for the Fail2Ban logger to use"), + Option("-v", "--verbose", action='store_true', + help="Be verbose in output"), + Option("-D", "--debuggex", action='store_true', + help="Produce debuggex.com urls for debugging there"), Option("--print-all-missed", action='store_true', help="Either to print all missed lines"), Option("--print-all-ignored", action='store_true', @@ -132,7 +146,6 @@ IGNOREREGEX: help="Enrich log-messages with compressed tracebacks"), Option("--full-traceback", action='store_true', help="Either to make the tracebacks full, not compressed (as by default)"), - ]) return p @@ -171,7 +184,9 @@ class LineStats(object): def __init__(self): self.tested = self.matched = 0 self.missed_lines = [] + self.missed_lines_timeextracted = [] self.ignored_lines = [] + self.ignored_lines_timeextracted = [] def __str__(self): return "%(tested)d lines, %(ignored)d ignored, %(matched)d matched, %(missed)d missed" % self @@ -191,10 +206,9 @@ class LineStats(object): class Fail2banRegex(object): - CONFIG_DEFAULTS = {'configpath' : "/etc/fail2ban/"} - def __init__(self, opts): self._verbose = opts.verbose + self._debuggex = opts.debuggex self._print_all_missed = opts.print_all_missed self._print_all_ignored = opts.print_all_ignored self._maxlines_set = False # so we allow to override maxlines in cmdline @@ -223,7 +237,9 @@ class Fail2banRegex(object): if not self._datepattern_set: self._filter.setDatePattern(pattern) self._datepattern_set = True - print "Use datepattern : %s" % self._filter.getDatePattern()[1] + if pattern is not None: + print "Use datepattern : %s" % ( + self._filter.getDatePattern()[1], ) def setMaxLines(self, v): if not self._maxlines_set: @@ -239,46 +255,37 @@ class Fail2banRegex(object): assert(regextype in ('fail', 'ignore')) regex = regextype + 'regex' if os.path.isfile(value): - reader = SafeConfigParserWithIncludes(defaults=self.CONFIG_DEFAULTS) - try: - reader.read(value) - print "Use %11s file : %s" % (regex, value) - # TODO: reuse functionality in client - regex_values = [ - RegexStat(m) - for m in reader.get("Definition", regex).split('\n') - if m != ""] - except NoSectionError: - print "No [Definition] section in %s" % value - return False - except NoOptionError: - print "No %s option in %s" % (regex, value) - return False - except MissingSectionHeaderError: - print "No section headers in %s" % value - return False + print "Use %11s file : %s" % (regex, value) + reader = FilterReader(value, 'fail2ban-regex-jail', {}) + reader.setBaseDir(None) - # Read out and set possible value of maxlines - try: - maxlines = reader.get("Init", "maxlines") - except (NoSectionError, NoOptionError): - # No [Init].maxlines found. - pass + if reader.readexplicit(): + reader.getOptions(None) + readercommands = reader.convert() + regex_values = [ + RegexStat(m[3]) + for m in filter( + lambda x: x[0] == 'set' and x[2] == "add%sregex" % regextype, + readercommands)] + # Read out and set possible value of maxlines + for command in readercommands: + if command[2] == "maxlines": + maxlines = int(command[3]) + try: + self.setMaxLines(maxlines) + except ValueError: + print "ERROR: Invalid value for maxlines (%(maxlines)r) " \ + "read from %(value)s" % locals() + return False + elif command[2] == 'addjournalmatch': + journalmatch = command[3] + self.setJournalMatch(shlex.split(journalmatch)) + elif command[2] == 'datepattern': + datepattern = command[3] + self.setDatePattern(datepattern) else: - try: - self.setMaxLines(maxlines) - except ValueError: - print "ERROR: Invalid value for maxlines (%(maxlines)r) " \ - "read from %(value)s" % locals() - return False - # Read out and set possible value for journalmatch - try: - journalmatch = reader.get("Init", "journalmatch") - except (NoSectionError, NoOptionError): - # No [Init].journalmatch found. - pass - else: - self.setJournalMatch(shlex.split(journalmatch)) + print "ERROR: failed to read %s" % value + return False else: print "Use %11s line : %s" % (regex, shortstr(value)) regex_values = [RegexStat(value)] @@ -293,7 +300,7 @@ class Fail2banRegex(object): def testIgnoreRegex(self, line): found = False try: - ret = self._filter.ignoreLine(line) + ret = self._filter.ignoreLine([(line, "", "")]) if ret is not None: found = True regex = self._ignoreregex[ret].inc() @@ -302,11 +309,11 @@ class Fail2banRegex(object): return False return found - def testRegex(self, line): + def testRegex(self, line, date=None): orgLineBuffer = self._filter._Filter__lineBuffer fullBuffer = len(orgLineBuffer) >= self._filter.getMaxLines() try: - ret = self._filter.processLine(line, checkAllRegex=True) + line, ret = self._filter.processLine(line, date, checkAllRegex=True) for match in ret: # Append True/False flag depending if line was matched by # more than one regex @@ -318,59 +325,78 @@ class Fail2banRegex(object): print e return False except IndexError: - print "Sorry, but no found in regex" + print "Sorry, but no found in regex" return False for bufLine in orgLineBuffer[int(fullBuffer):]: if bufLine not in self._filter._Filter__lineBuffer: - if self.removeMissedLine(bufLine): + try: + self._line_stats.missed_lines.pop( + self._line_stats.missed_lines.index("".join(bufLine))) + self._line_stats.missed_lines_timeextracted.pop( + self._line_stats.missed_lines_timeextracted.index( + "".join(bufLine[::2]))) + except ValueError: + pass + else: self._line_stats.matched += 1 - return len(ret) > 0 - - def removeMissedLine(self, line): - """Remove `line` from missed lines, by comparing without time match""" - for n, missed_line in \ - enumerate(reversed(self._line_stats.missed_lines)): - timeMatch = self._filter.dateDetector.matchTime( - missed_line, incHits=False) - if timeMatch: - logLine = (missed_line[:timeMatch.start()] + - missed_line[timeMatch.end():]) - else: - logLine = missed_line - if logLine.rstrip("\r\n") == line: - self._line_stats.missed_lines.pop( - len(self._line_stats.missed_lines) - n - 1) - return True - return False + return line, ret def process(self, test_lines): for line_no, line in enumerate(test_lines): - if line.startswith('#') or not line.strip(): - # skip comment and empty lines - continue - is_ignored = fail2banRegex.testIgnoreRegex(line) + if isinstance(line, tuple): + line_datetimestripped, ret = fail2banRegex.testRegex( + line[0], line[1]) + line = "".join(line[0]) + else: + line = line.rstrip('\r\n') + if line.startswith('#') or not line: + # skip comment and empty lines + continue + line_datetimestripped, ret = fail2banRegex.testRegex(line) + is_ignored = fail2banRegex.testIgnoreRegex(line_datetimestripped) + if is_ignored: self._line_stats.ignored_lines.append(line) + self._line_stats.ignored_lines_timeextracted.append(line_datetimestripped) - if fail2banRegex.testRegex(line): + if len(ret) > 0: assert(not is_ignored) self._line_stats.matched += 1 else: if not is_ignored: self._line_stats.missed_lines.append(line) + self._line_stats.missed_lines_timeextracted.append(line_datetimestripped) self._line_stats.tested += 1 - if line_no % 10 == 0: + if line_no % 10 == 0 and self._filter.dateDetector is not None: self._filter.dateDetector.sortTemplate() + + def printLines(self, ltype): lstats = self._line_stats assert(len(lstats.missed_lines) == lstats.tested - (lstats.matched + lstats.ignored)) l = lstats[ltype + '_lines'] if len(l): header = "%s line(s):" % (ltype.capitalize(),) - if len(l) < 20 or getattr(self, '_print_all_' + ltype): + if self._debuggex: + if ltype == 'missed': + regexlist = self._failregex + else: + regexlist = self._ignoreregex + l = lstats[ltype + '_lines_timeextracted'] + lines = len(l)*len(regexlist) + if lines < 20 or getattr(self, '_print_all_' + ltype): + ans = [[]] + for arg in [l, regexlist]: + ans = [ x + [y] for x in ans for y in arg ] + b = map(lambda a: a[0] + ' | ' + a[1].getFailRegex() + ' | ' + debuggexURL(a[0], a[1].getFailRegex()), ans) + pprint_list([x.rstrip() for x in b], header) + else: + print "%s: too many to print. Use --print-all-%s " \ + "to print all %d lines" % (header, ltype, lines) + elif len(l) < 20 or getattr(self, '_print_all_' + ltype): pprint_list([x.rstrip() for x in l], header) else: print "%s: too many to print. Use --print-all-%s " \ @@ -398,7 +424,7 @@ class Fail2banRegex(object): " %s %s%s" % ( ip[1], timeString, - ip[3] and " (multiple regex matched)" or "")) + ip[-1] and " (multiple regex matched)" or "")) print "\n%s: %d total" % (title, total) pprint_list(out, " #) [# of hits] regular expression") @@ -409,12 +435,14 @@ class Fail2banRegex(object): _ = print_failregexes("Ignoreregex", self._ignoreregex) - print "\nDate template hits:" - out = [] - for template in self._filter.dateDetector.getTemplates(): - if self._verbose or template.getHits(): - out.append("[%d] %s" % (template.getHits(), template.getName())) - pprint_list(out, "[# of hits] date format") + if self._filter.dateDetector is not None: + print "\nDate template hits:" + out = [] + for template in self._filter.dateDetector.getTemplates(): + if self._verbose or template.getHits(): + out.append("[%d] %s" % ( + template.getHits(), template.getName())) + pprint_list(out, "[# of hits] date format") print "\nLines: %s" % self._line_stats @@ -493,7 +521,7 @@ if __name__ == "__main__": sys.exit(-1) myjournal = journal.Reader(converters={'__CURSOR': lambda x: x}) journalmatch = fail2banRegex._journalmatch - fail2banRegex.setDatePattern("ISO8601") + fail2banRegex.setDatePattern(None) if journalmatch: try: for element in journalmatch: diff --git a/bin/fail2ban-testcases b/bin/fail2ban-testcases index bc1cb79a..578763d9 100755 --- a/bin/fail2ban-testcases +++ b/bin/fail2ban-testcases @@ -48,7 +48,7 @@ def get_opt_parser(): p.add_options([ Option('-l', "--log-level", type="choice", dest="log_level", - choices=('heavydebug', 'debug', 'info', 'warn', 'error', 'fatal'), + choices=('heavydebug', 'debug', 'info', 'warning', 'error', 'fatal'), default=None, help="Log level for the logger to use during running tests"), Option('-n', "--no-network", action="store_true", @@ -72,7 +72,7 @@ parser = get_opt_parser() logSys = logging.getLogger("fail2ban") # Numerical level of verbosity corresponding to a log "level" -verbosity = {'heavydebug': 3, +verbosity = {'heavydebug': 4, 'debug': 3, 'info': 2, 'warning': 1, diff --git a/config/action.d/apf.conf b/config/action.d/apf.conf new file mode 100644 index 00000000..5c4a2614 --- /dev/null +++ b/config/action.d/apf.conf @@ -0,0 +1,25 @@ +# Fail2Ban configuration file +# https://www.rfxn.com/projects/advanced-policy-firewall/ +# +# Note: APF doesn't play nicely with other actions. It has been observed to +# remove bans created by other iptables based actions. If you are going to use +# this action, use it for all of your jails. +# +# DON'T MIX APF and other IPTABLES based actions +[Definition] + +actionstart = +actionstop = +actioncheck = +actionban = apf --deny "banned by Fail2Ban " +actionunban = apf --remove + +[Init] + +# Name used in APF configuration +# +name = default + +# DEV NOTES: +# +# Author: Mark McKinstry diff --git a/config/action.d/blocklist_de.conf b/config/action.d/blocklist_de.conf new file mode 100644 index 00000000..d4170cab --- /dev/null +++ b/config/action.d/blocklist_de.conf @@ -0,0 +1,86 @@ +# Fail2Ban configuration file +# +# Author: Steven Hiscocks +# +# + +# Action to report IP address to blocklist.de +# Blocklist.de must be signed up to at www.blocklist.de +# Once registered, one or more servers can be added. +# This action requires the server 'email address' and the assoicate apikey. +# +# From blocklist.de: +# www.blocklist.de is a free and voluntary service provided by a +# Fraud/Abuse-specialist, whose servers are often attacked on SSH-, +# Mail-Login-, FTP-, Webserver- and other services. +# The mission is to report all attacks to the abuse deparments of the +# infected PCs/servers to ensure that the responsible provider can inform +# the customer about the infection and disable them +# +# IMPORTANT: +# +# Reporting an IP of abuse is a serious complaint. Make sure that it is +# serious. Fail2ban developers and network owners recommend you only use this +# action for: +# * The recidive where the IP has been banned multiple times +# * Where maxretry has been set quite high, beyond the normal user typing +# password incorrectly. +# * For filters that have a low likelyhood of receiving human errors +# + +[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: See jail.conf(5) man page +# Values: CMD +# +actionban = curl --fail --data-urlencode 'server=' --data 'apikey=' --data 'service=' --data 'ip=' --data-urlencode 'logs=' --data 'format=text' --user-agent "fail2ban v0.8.12" "https://www.blocklist.de/en/httpreports.html" + +# Option: actionunban +# Notes.: command executed when unbanning an IP. Take care that the +# command is executed with Fail2Ban user rights. +# Tags: See jail.conf(5) man page +# Values: CMD +# +actionunban = + +[Init] + +# Option: email +# Notes server email address, as per blocklise.de account +# Values: STRING Default: None +# +#email = + +# Option: apikey +# Notes your user blocklist.de user account apikey +# Values: STRING Default: None +# +#apikey = + +# Option: service +# Notes service name you are reporting on, typically aligns with filter name +# see http://www.blocklist.de/en/httpreports.html for full list +# Values: STRING Default: None +# +#service = diff --git a/config/action.d/complain.conf b/config/action.d/complain.conf index 57f19135..62331f19 100644 --- a/config/action.d/complain.conf +++ b/config/action.d/complain.conf @@ -58,7 +58,7 @@ actioncheck = actionban = ADDRESSES=`whois | perl -e 'while () { 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= if [ ! -z "$ADDRESSES" ]; then - (printf %%b "\n"; date '+Note: Local timezone is %%z (%%Z)'; grep '' ) | "Abuse from " $ADDRESSES + (printf %%b "\n"; date '+Note: Local timezone is %%z (%%Z)'; grep -E '(^|[^0-9])([^0-9]|$)' ) | "Abuse from " $ADDRESSES fi # Option: actionunban @@ -78,7 +78,7 @@ logpath = /dev/null # Option: mailcmd # Notes.: Your system mail command. Is passed 2 args: subject and recipient -# Values: CMD Default: mail -s +# Values: CMD # mailcmd = mail -s @@ -89,7 +89,7 @@ mailcmd = mail -s # Appear to come from a different address - the '--' indicates # arguments to be passed to Sendmail: # -- -f me@example.com -# Values: [ STRING ] Default: (empty) +# Values: [ STRING ] # mailargs = diff --git a/config/action.d/dshield.conf b/config/action.d/dshield.conf index 29ed3043..a0041986 100644 --- a/config/action.d/dshield.conf +++ b/config/action.d/dshield.conf @@ -106,7 +106,7 @@ actionunban = if [ -f .first ]; then # 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: ??? +# Values: [ NUM ] # port = ??? @@ -114,7 +114,7 @@ port = ??? # Notes.: Your DShield 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 +# Values: [ NUM ] # userid = 0 @@ -137,7 +137,7 @@ protocol = tcp # Notes.: How many lines to buffer before making a report. Regardless of this, # reports are sent a minimum of apart, or if the # buffer contains an event over old, or on shutdown -# Values: [ NUM ] Default: 50 +# Values: [ NUM ] # lines = 50 @@ -145,7 +145,7 @@ lines = 50 # 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 +# Values: [ NUM ] # minreportinterval = 3600 @@ -154,27 +154,27 @@ minreportinterval = 3600 # submit the batch, even if we haven't reached 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 -# Values: [ NUM ] Default: 21600 (6 hours) +# Values: [ NUM ] # 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: ??? +# Values: [ NUM ] # srcport = ??? # Option: tcpflags # Notes.: TCP flags on attack. You're unlikely to have this info, so you can # leave empty -# Values: [ STRING ] Default: (empty) +# Values: [ STRING ] # tcpflags = # Option: mailcmd # Notes.: Your system mail command. Is passed 2 args: subject and recipient -# Values: CMD Default: mail -s +# Values: CMD # mailcmd = mail -s @@ -186,19 +186,19 @@ mailcmd = mail -s # the one configured at DShield - the '--' indicates arguments to be # passed to Sendmail): # -- -f me@example.com -# Values: [ STRING ] Default: (empty) +# Values: [ STRING ] # mailargs = # Option: dest # Notes.: Destination e-mail address for reports -# Values: [ STRING ] Default: reports@dshield.org +# Values: [ STRING ] # dest = reports@dshield.org # Option: tmpfile # Notes.: Base name of temporary files used for buffering -# Values: [ STRING ] Default: /var/run/fail2ban/tmp-dshield +# Values: [ STRING ] # tmpfile = /var/run/fail2ban/tmp-dshield diff --git a/config/action.d/firewallcmd-ipset.conf b/config/action.d/firewallcmd-ipset.conf new file mode 100644 index 00000000..2c4a36f1 --- /dev/null +++ b/config/action.d/firewallcmd-ipset.conf @@ -0,0 +1,69 @@ +# Fail2Ban action file for firewall-cmd/ipset +# +# This requires: +# ipset (package: ipset) +# firewall-cmd (package: firewalld) +# +# This is for ipset protocol 6 (and hopefully later) (ipset v6.14). +# Use ipset -V to see the protocol and version. +# +# IPset was a feature introduced in the linux kernel 2.6.39 and 3.0.0 kernels. +# +# If you are running on an older kernel you make need to patch in external +# modules. + +[INCLUDES] + +before = iptables-blocktype.conf + +[Definition] + +actionstart = ipset create fail2ban- hash:ip timeout + firewall-cmd --direct --add-rule ipv4 filter 0 -p -m multiport --dports -m set --match-set fail2ban- src -j + +actionstop = firewall-cmd --direct --remove-rule ipv4 filter 0 -p -m multiport --dports -m set --match-set fail2ban- src -j + ipset flush fail2ban- + ipset destroy fail2ban- + +actioncheck = firewall-cmd --direct --get-chains ipv4 filter | grep -q '^fail2ban-$' + +actionban = ipset add fail2ban- timeout -exist + +actionunban = ipset del fail2ban- -exist + +[Init] + +# Default name of the chain +# +name = default + +# Option: port +# Notes.: specifies port to monitor +# Values: [ NUM | STRING ] +# +port = ssh + +# Option: protocol +# Notes.: internally used by config reader for interpolations. +# Values: [ tcp | udp | icmp | all ] +# +protocol = tcp + +# Option: chain +# Notes specifies the iptables chain to which the fail2ban rules should be +# added +# Values: [ STRING ] +# +chain = INPUT_direct + +# Option: bantime +# Notes: specifies the bantime in seconds (handled internally rather than by fail2ban) +# Values: [ NUM ] Default: 600 + +bantime = 600 + + +# DEV NOTES: +# +# Author: Edgar Hoch and Daniel Black +# firewallcmd-new / iptables-ipset-proto6 combined for maximium goodness diff --git a/config/action.d/firewallcmd-new.conf b/config/action.d/firewallcmd-new.conf new file mode 100644 index 00000000..62887967 --- /dev/null +++ b/config/action.d/firewallcmd-new.conf @@ -0,0 +1,72 @@ +# Fail2Ban configuration file +# +# Because of the --remove-rules in stop this action requires firewalld-0.3.8+ + +[INCLUDES] + +before = iptables-blocktype.conf + +[Definition] + +actionstart = firewall-cmd --direct --add-chain ipv4 filter f2b- + firewall-cmd --direct --add-rule ipv4 filter f2b- 1000 -j RETURN + firewall-cmd --direct --add-rule ipv4 filter 0 -m state --state NEW -p --dport -j f2b- + +actionstop = firewall-cmd --direct --remove-rule ipv4 filter 0 -m state --state NEW -p --dport -j f2b- + firewall-cmd --direct --remove-rules ipv4 filter f2b- + firewall-cmd --direct --remove-chain ipv4 filter f2b- + +actioncheck = firewall-cmd --direct --get-chains ipv4 filter | grep -q 'f2b-$' + +actionban = firewall-cmd --direct --add-rule ipv4 filter f2b- 0 -s -j + +actionunban = firewall-cmd --direct --remove-rule ipv4 filter f2b- 0 -s -j + +[Init] + +# Default name of the chain +# +name = default + +# Option: port +# Notes.: specifies port to monitor +# Values: [ NUM | STRING ] +# +port = ssh + +# Option: protocol +# Notes.: internally used by config reader for interpolations. +# Values: [ tcp | udp | icmp | all ] +# +protocol = tcp + +# Option: chain +# Notes specifies the iptables chain to which the fail2ban rules should be +# added +# Values: [ STRING ] +# +chain = INPUT_direct + +# DEV NOTES: +# +# Author: Edgar Hoch +# Copied from iptables-new.conf and modified for use with firewalld by Edgar Hoch. +# It uses "firewall-cmd" instead of "iptables". +# +# Output: +# +# $ firewall-cmd --direct --add-chain ipv4 filter fail2ban-name +# success +# $ firewall-cmd --direct --add-rule ipv4 filter fail2ban-name 1000 -j RETURN +# success +# $ sudo firewall-cmd --direct --add-rule ipv4 filter INPUT_direct 0 -m state --state NEW -p tcp --dport 22 -j fail2ban-name +# success +# $ firewall-cmd --direct --get-chains ipv4 filter +# fail2ban-name +# $ firewall-cmd --direct --get-chains ipv4 filter | od -h +# 0000000 6166 6c69 6232 6e61 6e2d 6d61 0a65 +# $ firewall-cmd --direct --get-chains ipv4 filter | grep -Eq 'fail2ban-name( |$)' ; echo $? +# 0 +# $ firewall-cmd -V +# 0.3.8 + diff --git a/config/action.d/ipfw.conf b/config/action.d/ipfw.conf index 09045815..37625209 100644 --- a/config/action.d/ipfw.conf +++ b/config/action.d/ipfw.conf @@ -43,7 +43,7 @@ actionban = ipfw add tcp from to # Tags: See jail.conf(5) man page # Values: CMD # -actionunban = ipfw delete `ipfw list | grep -i | awk '{print $1;}'` +actionunban = ipfw delete `ipfw list | grep -i "[^0-9][^0-9]" | awk '{print $1;}'` [Init] diff --git a/config/action.d/iptables-allports.conf b/config/action.d/iptables-allports.conf index 91d40711..480badc7 100644 --- a/config/action.d/iptables-allports.conf +++ b/config/action.d/iptables-allports.conf @@ -17,23 +17,23 @@ before = iptables-blocktype.conf # Notes.: command executed once at the start of Fail2Ban. # Values: CMD # -actionstart = iptables -N fail2ban- - iptables -A fail2ban- -j RETURN - iptables -I -p -j fail2ban- +actionstart = iptables -N f2b- + iptables -A f2b- -j RETURN + iptables -I -p -j f2b- # Option: actionstop # Notes.: command executed once at the end of Fail2Ban # Values: CMD # -actionstop = iptables -D -p -j fail2ban- - iptables -F fail2ban- - iptables -X fail2ban- +actionstop = iptables -D -p -j f2b- + iptables -F f2b- + iptables -X f2b- # Option: actioncheck # Notes.: command executed once before each actionban command # Values: CMD # -actioncheck = iptables -n -L | grep -q 'fail2ban-[ \t]' +actioncheck = iptables -n -L | grep -q 'f2b-[ \t]' # Option: actionban # Notes.: command executed when banning an IP. Take care that the @@ -41,7 +41,7 @@ actioncheck = iptables -n -L | grep -q 'fail2ban-[ \t]' # Tags: See jail.conf(5) man page # Values: CMD # -actionban = iptables -I fail2ban- 1 -s -j +actionban = iptables -I f2b- 1 -s -j # Option: actionunban # Notes.: command executed when unbanning an IP. Take care that the @@ -49,7 +49,7 @@ actionban = iptables -I fail2ban- 1 -s -j # Tags: See jail.conf(5) man page # Values: CMD # -actionunban = iptables -D fail2ban- -s -j +actionunban = iptables -D f2b- -s -j [Init] diff --git a/config/action.d/iptables-ipset-proto4.conf b/config/action.d/iptables-ipset-proto4.conf index 3ed778f9..fc03c68c 100644 --- a/config/action.d/iptables-ipset-proto4.conf +++ b/config/action.d/iptables-ipset-proto4.conf @@ -11,12 +11,11 @@ # IPset was a feature introduced in the linux kernel 2.6.39 and 3.0.0 kernels. # # If you are running on an older kernel you make need to patch in external -# modules. +# modules. Debian squeeze can do this with: +# apt-get install xtables-addons-source +# module-assistant auto-install xtables-addons # -# On Debian machines this can be done with: -# -# apt-get install ipset xtables-addons-source -# module-assistant auto-install xtables-addons +# Debian wheezy and above uses protocol 6 [INCLUDES] @@ -28,16 +27,16 @@ before = iptables-blocktype.conf # Notes.: command executed once at the start of Fail2Ban. # Values: CMD # -actionstart = ipset --create fail2ban- iphash - iptables -I INPUT -p -m multiport --dports -m set --match-set fail2ban- src -j +actionstart = ipset --create f2b- iphash + iptables -I INPUT -p -m multiport --dports -m set --match-set f2b- src -j # Option: actionstop # Notes.: command executed once at the end of Fail2Ban # Values: CMD # -actionstop = iptables -D INPUT -p -m multiport --dports -m set --match-set fail2ban- src -j - ipset --flush fail2ban- - ipset --destroy fail2ban- +actionstop = iptables -D INPUT -p -m multiport --dports -m set --match-set f2b- src -j + ipset --flush f2b- + ipset --destroy f2b- # Option: actionban # Notes.: command executed when banning an IP. Take care that the @@ -45,7 +44,7 @@ actionstop = iptables -D INPUT -p -m multiport --dports -m set # Tags: See jail.conf(5) man page # Values: CMD # -actionban = ipset --test fail2ban- || ipset --add fail2ban- +actionban = ipset --test f2b- || ipset --add f2b- # Option: actionunban # Notes.: command executed when unbanning an IP. Take care that the @@ -53,7 +52,7 @@ actionban = ipset --test fail2ban- || ipset --add fail2ban- && ipset --del fail2ban- +actionunban = ipset --test f2b- && ipset --del f2b- [Init] diff --git a/config/action.d/iptables-ipset-proto6-allports.conf b/config/action.d/iptables-ipset-proto6-allports.conf new file mode 100644 index 00000000..72fba9cd --- /dev/null +++ b/config/action.d/iptables-ipset-proto6-allports.conf @@ -0,0 +1,64 @@ +# Fail2Ban configuration file +# +# Author: Daniel Black +# +# This is for ipset protocol 6 (and hopefully later) (ipset v6.14). +# Use ipset -V to see the protocol and version. Version 4 should use +# iptables-ipset-proto4.conf. +# +# This requires the program ipset which is normally in package called ipset. +# +# IPset was a feature introduced in the linux kernel 2.6.39 and 3.0.0 kernels. +# +# If you are running on an older kernel you make need to patch in external +# modules which probably won't be protocol version 6. + +[INCLUDES] + +before = iptables-blocktype.conf + + +[Definition] + +# Option: actionstart +# Notes.: command executed once at the start of Fail2Ban. +# Values: CMD +# +actionstart = ipset create f2b- hash:ip timeout + iptables -I INPUT -m set --match-set f2b- src -j + +# Option: actionstop +# Notes.: command executed once at the end of Fail2Ban +# Values: CMD +# +actionstop = iptables -D INPUT -m set --match-set f2b- src -j + ipset flush f2b- + ipset destroy f2b- + +# Option: actionban +# Notes.: command executed when banning an IP. Take care that the +# command is executed with Fail2Ban user rights. +# Tags: See jail.conf(5) man page +# Values: CMD +# +actionban = ipset add f2b- timeout -exist + +# Option: actionunban +# Notes.: command executed when unbanning an IP. Take care that the +# command is executed with Fail2Ban user rights. +# Tags: See jail.conf(5) man page +# Values: CMD +# +actionunban = ipset del f2b- -exist + +[Init] + +# Default name of the ipset +# +name = default + +# Option: bantime +# Notes: specifies the bantime in seconds (handled internally rather than by fail2ban) +# Values: [ NUM ] Default: 600 + +bantime = 600 diff --git a/config/action.d/iptables-ipset-proto6.conf b/config/action.d/iptables-ipset-proto6.conf index 3cf9b140..5d848110 100644 --- a/config/action.d/iptables-ipset-proto6.conf +++ b/config/action.d/iptables-ipset-proto6.conf @@ -12,11 +12,6 @@ # # If you are running on an older kernel you make need to patch in external # modules. -# -# On Debian machines this can be done with: -# -# apt-get install ipset xtables-addons-source -# module-assistant auto-install xtables-addons [INCLUDES] @@ -29,16 +24,16 @@ before = iptables-blocktype.conf # Notes.: command executed once at the start of Fail2Ban. # Values: CMD # -actionstart = ipset create fail2ban- hash:ip timeout - iptables -I INPUT -p -m multiport --dports -m set --match-set fail2ban- src -j DROP +actionstart = ipset create f2b- hash:ip timeout + iptables -I INPUT -p -m multiport --dports -m set --match-set f2b- src -j # Option: actionstop # Notes.: command executed once at the end of Fail2Ban # Values: CMD # -actionstop = iptables -D INPUT -p -m multiport --dports -m set --match-set fail2ban- src -j DROP - ipset flush fail2ban- - ipset destroy fail2ban- +actionstop = iptables -D INPUT -p -m multiport --dports -m set --match-set f2b- src -j + ipset flush f2b- + ipset destroy f2b- # Option: actionban # Notes.: command executed when banning an IP. Take care that the @@ -46,7 +41,7 @@ actionstop = iptables -D INPUT -p -m multiport --dports -m set # Tags: See jail.conf(5) man page # Values: CMD # -actionban = ipset add fail2ban- timeout -exist +actionban = ipset add f2b- timeout -exist # Option: actionunban # Notes.: command executed when unbanning an IP. Take care that the @@ -54,7 +49,7 @@ actionban = ipset add fail2ban- timeout -exist # Tags: See jail.conf(5) man page # Values: CMD # -actionunban = ipset del fail2ban- -exist +actionunban = ipset del f2b- -exist [Init] diff --git a/config/action.d/iptables-multiport-log.conf b/config/action.d/iptables-multiport-log.conf index 6084cb6c..5a611033 100644 --- a/config/action.d/iptables-multiport-log.conf +++ b/config/action.d/iptables-multiport-log.conf @@ -3,9 +3,9 @@ # Author: Guido Bozzetto # Modified: Cyril Jaquier # -# make "fail2ban-" chain to match drop IP -# make "fail2ban--log" chain to log and drop -# insert a jump to fail2ban- from -I if proto/port match +# make "f2b-" chain to match drop IP +# make "f2b--log" chain to log and drop +# insert a jump to f2b- from -I if proto/port match # # @@ -19,28 +19,28 @@ before = iptables-blocktype.conf # Notes.: command executed once at the start of Fail2Ban. # Values: CMD # -actionstart = iptables -N fail2ban- - iptables -A fail2ban- -j RETURN - iptables -I 1 -p -m multiport --dports -j fail2ban- - iptables -N fail2ban--log - iptables -I fail2ban--log -j LOG --log-prefix "$(expr fail2ban- : '\(.\{1,23\}\)'):DROP " --log-level warning -m limit --limit 6/m --limit-burst 2 - iptables -A fail2ban--log -j +actionstart = iptables -N f2b- + iptables -A f2b- -j RETURN + iptables -I 1 -p -m multiport --dports -j f2b- + iptables -N f2b--log + iptables -I f2b--log -j LOG --log-prefix "$(expr f2b- : '\(.\{1,23\}\)'):DROP " --log-level warning -m limit --limit 6/m --limit-burst 2 + iptables -A f2b--log -j # Option: actionstop # Notes.: command executed once at the end of Fail2Ban # Values: CMD # -actionstop = iptables -D -p -m multiport --dports -j fail2ban- - iptables -F fail2ban- - iptables -F fail2ban--log - iptables -X fail2ban- - iptables -X fail2ban--log +actionstop = iptables -D -p -m multiport --dports -j f2b- + iptables -F f2b- + iptables -F f2b--log + iptables -X f2b- + iptables -X f2b--log # Option: actioncheck # Notes.: command executed once before each actionban command # Values: CMD # -actioncheck = iptables -n -L fail2ban--log >/dev/null +actioncheck = iptables -n -L f2b--log >/dev/null # Option: actionban # Notes.: command executed when banning an IP. Take care that the @@ -48,7 +48,7 @@ actioncheck = iptables -n -L fail2ban--log >/dev/null # Tags: See jail.conf(5) man page # Values: CMD # -actionban = iptables -I fail2ban- 1 -s -j fail2ban--log +actionban = iptables -I f2b- 1 -s -j f2b--log # Option: actionunban # Notes.: command executed when unbanning an IP. Take care that the @@ -56,7 +56,7 @@ actionban = iptables -I fail2ban- 1 -s -j fail2ban--log # Tags: See jail.conf(5) man page # Values: CMD # -actionunban = iptables -D fail2ban- -s -j fail2ban--log +actionunban = iptables -D f2b- -s -j f2b--log [Init] diff --git a/config/action.d/iptables-multiport.conf b/config/action.d/iptables-multiport.conf index daa31148..ab3225bc 100644 --- a/config/action.d/iptables-multiport.conf +++ b/config/action.d/iptables-multiport.conf @@ -14,23 +14,23 @@ before = iptables-blocktype.conf # Notes.: command executed once at the start of Fail2Ban. # Values: CMD # -actionstart = iptables -N fail2ban- - iptables -A fail2ban- -j RETURN - iptables -I -p -m multiport --dports -j fail2ban- +actionstart = iptables -N f2b- + iptables -A f2b- -j RETURN + iptables -I -p -m multiport --dports -j f2b- # Option: actionstop # Notes.: command executed once at the end of Fail2Ban # Values: CMD # -actionstop = iptables -D -p -m multiport --dports -j fail2ban- - iptables -F fail2ban- - iptables -X fail2ban- +actionstop = iptables -D -p -m multiport --dports -j f2b- + iptables -F f2b- + iptables -X f2b- # Option: actioncheck # Notes.: command executed once before each actionban command # Values: CMD # -actioncheck = iptables -n -L | grep -q 'fail2ban-[ \t]' +actioncheck = iptables -n -L | grep -q 'f2b-[ \t]' # Option: actionban # Notes.: command executed when banning an IP. Take care that the @@ -38,7 +38,7 @@ actioncheck = iptables -n -L | grep -q 'fail2ban-[ \t]' # Tags: See jail.conf(5) man page # Values: CMD # -actionban = iptables -I fail2ban- 1 -s -j +actionban = iptables -I f2b- 1 -s -j # Option: actionunban # Notes.: command executed when unbanning an IP. Take care that the @@ -46,7 +46,7 @@ actionban = iptables -I fail2ban- 1 -s -j # Tags: See jail.conf(5) man page # Values: CMD # -actionunban = iptables -D fail2ban- -s -j +actionunban = iptables -D f2b- -s -j [Init] diff --git a/config/action.d/iptables-new.conf b/config/action.d/iptables-new.conf index 38927442..75411ad1 100644 --- a/config/action.d/iptables-new.conf +++ b/config/action.d/iptables-new.conf @@ -17,23 +17,23 @@ before = iptables-blocktype.conf # Notes.: command executed once at the start of Fail2Ban. # Values: CMD # -actionstart = iptables -N fail2ban- - iptables -A fail2ban- -j RETURN - iptables -I -m state --state NEW -p --dport -j fail2ban- +actionstart = iptables -N f2b- + iptables -A f2b- -j RETURN + iptables -I -m state --state NEW -p --dport -j f2b- # Option: actionstop # Notes.: command executed once at the end of Fail2Ban # Values: CMD # -actionstop = iptables -D -m state --state NEW -p --dport -j fail2ban- - iptables -F fail2ban- - iptables -X fail2ban- +actionstop = iptables -D -m state --state NEW -p --dport -j f2b- + iptables -F f2b- + iptables -X f2b- # Option: actioncheck # Notes.: command executed once before each actionban command # Values: CMD # -actioncheck = iptables -n -L | grep -q 'fail2ban-[ \t]' +actioncheck = iptables -n -L | grep -q 'f2b-[ \t]' # Option: actionban # Notes.: command executed when banning an IP. Take care that the @@ -41,7 +41,7 @@ actioncheck = iptables -n -L | grep -q 'fail2ban-[ \t]' # Tags: See jail.conf(5) man page # Values: CMD # -actionban = iptables -I fail2ban- 1 -s -j +actionban = iptables -I f2b- 1 -s -j # Option: actionunban # Notes.: command executed when unbanning an IP. Take care that the @@ -49,7 +49,7 @@ actionban = iptables -I fail2ban- 1 -s -j # Tags: See jail.conf(5) man page # Values: CMD # -actionunban = iptables -D fail2ban- -s -j +actionunban = iptables -D f2b- -s -j [Init] diff --git a/config/action.d/iptables-xt_recent-echo.conf b/config/action.d/iptables-xt_recent-echo.conf index 829d4c06..4be97c44 100644 --- a/config/action.d/iptables-xt_recent-echo.conf +++ b/config/action.d/iptables-xt_recent-echo.conf @@ -23,29 +23,29 @@ before = iptables-blocktype.conf # iptables-persistent package). # # Explanation of the rule below: -# Check if any packets coming from an IP on the fail2ban- +# Check if any packets coming from an IP on the f2b- # list have been seen in the last 3600 seconds. If yes, update the # timestamp for this IP and drop the packet. If not, let the packet # through. # -# Fail2ban inserts blacklisted hosts into the fail2ban- list +# Fail2ban inserts blacklisted hosts into the f2b- list # and removes them from the list after some time, according to its # own rules. The 3600 second timeout is independent and acts as a # safeguard in case the fail2ban process dies unexpectedly. The # shorter of the two timeouts actually matters. -actionstart = iptables -I INPUT -m recent --update --seconds 3600 --name fail2ban- -j +actionstart = iptables -I INPUT -m recent --update --seconds 3600 --name f2b- -j # Option: actionstop # Notes.: command executed once at the end of Fail2Ban # Values: CMD # -actionstop = echo / > /proc/net/xt_recent/fail2ban- +actionstop = echo / > /proc/net/xt_recent/f2b- # Option: actioncheck # Notes.: command executed once before each actionban command # Values: CMD # -actioncheck = test -e /proc/net/xt_recent/fail2ban- +actioncheck = test -e /proc/net/xt_recent/f2b- # Option: actionban # Notes.: command executed when banning an IP. Take care that the @@ -53,7 +53,7 @@ actioncheck = test -e /proc/net/xt_recent/fail2ban- # Tags: See jail.conf(5) man page # Values: CMD # -actionban = echo + > /proc/net/xt_recent/fail2ban- +actionban = echo + > /proc/net/xt_recent/f2b- # Option: actionunban # Notes.: command executed when unbanning an IP. Take care that the @@ -61,7 +61,7 @@ actionban = echo + > /proc/net/xt_recent/fail2ban- # Tags: See jail.conf(5) man page # Values: CMD # -actionunban = echo - > /proc/net/xt_recent/fail2ban- +actionunban = echo - > /proc/net/xt_recent/f2b- [Init] diff --git a/config/action.d/iptables.conf b/config/action.d/iptables.conf index 370e4731..5afe4bf1 100644 --- a/config/action.d/iptables.conf +++ b/config/action.d/iptables.conf @@ -14,23 +14,23 @@ before = iptables-blocktype.conf # Notes.: command executed once at the start of Fail2Ban. # Values: CMD # -actionstart = iptables -N fail2ban- - iptables -A fail2ban- -j RETURN - iptables -I -p --dport -j fail2ban- +actionstart = iptables -N f2b- + iptables -A f2b- -j RETURN + iptables -I -p --dport -j f2b- # Option: actionstop # Notes.: command executed once at the end of Fail2Ban # Values: CMD # -actionstop = iptables -D -p --dport -j fail2ban- - iptables -F fail2ban- - iptables -X fail2ban- +actionstop = iptables -D -p --dport -j f2b- + iptables -F f2b- + iptables -X f2b- # Option: actioncheck # Notes.: command executed once before each actionban command # Values: CMD # -actioncheck = iptables -n -L | grep -q 'fail2ban-[ \t]' +actioncheck = iptables -n -L | grep -q 'f2b-[ \t]' # Option: actionban # Notes.: command executed when banning an IP. Take care that the @@ -38,7 +38,7 @@ actioncheck = iptables -n -L | grep -q 'fail2ban-[ \t]' # Tags: See jail.conf(5) man page # Values: CMD # -actionban = iptables -I fail2ban- 1 -s -j +actionban = iptables -I f2b- 1 -s -j # Option: actionunban # Notes.: command executed when unbanning an IP. Take care that the @@ -46,7 +46,7 @@ actionban = iptables -I fail2ban- 1 -s -j # Tags: See jail.conf(5) man page # Values: CMD # -actionunban = iptables -D fail2ban- -s -j +actionunban = iptables -D f2b- -s -j [Init] diff --git a/config/action.d/mail-buffered.conf b/config/action.d/mail-buffered.conf index 7ff17cf2..914d4a5a 100644 --- a/config/action.d/mail-buffered.conf +++ b/config/action.d/mail-buffered.conf @@ -14,7 +14,7 @@ actionstart = printf %%b "Hi,\n The jail has been started successfully.\n Output will be buffered until lines are available.\n Regards,\n - Fail2Ban"|mail -s "[Fail2Ban] : started" + Fail2Ban"|mail -s "[Fail2Ban] : started on `uname -n`" # Option: actionstop # Notes.: command executed once at the end of Fail2Ban @@ -25,13 +25,13 @@ actionstop = if [ -f ]; then These hosts have been banned by Fail2Ban.\n `cat ` Regards,\n - Fail2Ban"|mail -s "[Fail2Ban] : Summary" + Fail2Ban"|mail -s "[Fail2Ban] : Summary from `uname -n`" rm fi printf %%b "Hi,\n The jail has been stopped.\n Regards,\n - Fail2Ban"|mail -s "[Fail2Ban] : stopped" + Fail2Ban"|mail -s "[Fail2Ban] : stopped on `uname -n`" # Option: actioncheck # Notes.: command executed once before each actionban command diff --git a/config/action.d/mail-whois-lines.conf b/config/action.d/mail-whois-lines.conf index d30e266d..aa7d0950 100644 --- a/config/action.d/mail-whois-lines.conf +++ b/config/action.d/mail-whois-lines.conf @@ -13,7 +13,7 @@ actionstart = printf %%b "Hi,\n The jail has been started successfully.\n Regards,\n - Fail2Ban"|mail -s "[Fail2Ban] : started" + Fail2Ban"|mail -s "[Fail2Ban] : started on `uname -n`" # Option: actionstop # Notes.: command executed once at the end of Fail2Ban @@ -22,7 +22,7 @@ actionstart = printf %%b "Hi,\n actionstop = printf %%b "Hi,\n The jail has been stopped.\n Regards,\n - Fail2Ban"|mail -s "[Fail2Ban] : stopped" + Fail2Ban"|mail -s "[Fail2Ban] : stopped on `uname -n`" # Option: actioncheck # Notes.: command executed once before each actionban command @@ -39,12 +39,12 @@ actioncheck = actionban = printf %%b "Hi,\n The IP has just been banned by Fail2Ban after attempts against .\n\n - Here are more information about :\n - `whois `\n\n + Here is more information about :\n + `whois || echo missing whois program`\n\n Lines containing IP: in \n - `grep '\<\>' `\n\n + `grep '[^0-9][^0-9]' `\n\n Regards,\n - Fail2Ban"|mail -s "[Fail2Ban] : banned " + Fail2Ban"|mail -s "[Fail2Ban] : banned from `uname -n`" # Option: actionunban # Notes.: command executed when unbanning an IP. Take care that the diff --git a/config/action.d/mail-whois.conf b/config/action.d/mail-whois.conf index f58ae535..e4c8450e 100644 --- a/config/action.d/mail-whois.conf +++ b/config/action.d/mail-whois.conf @@ -13,7 +13,7 @@ actionstart = printf %%b "Hi,\n The jail has been started successfully.\n Regards,\n - Fail2Ban"|mail -s "[Fail2Ban] : started" + Fail2Ban"|mail -s "[Fail2Ban] : started on `uname -n`" # Option: actionstop # Notes.: command executed once at the end of Fail2Ban @@ -22,7 +22,7 @@ actionstart = printf %%b "Hi,\n actionstop = printf %%b "Hi,\n The jail has been stopped.\n Regards,\n - Fail2Ban"|mail -s "[Fail2Ban] : stopped" + Fail2Ban"|mail -s "[Fail2Ban] : stopped on `uname -n`" # Option: actioncheck # Notes.: command executed once before each actionban command @@ -39,10 +39,10 @@ actioncheck = actionban = printf %%b "Hi,\n The IP has just been banned by Fail2Ban after attempts against .\n\n - Here are more information about :\n - `whois `\n + Here is more information about :\n + `whois || echo missing whois program`\n Regards,\n - Fail2Ban"|mail -s "[Fail2Ban] : banned " + Fail2Ban"|mail -s "[Fail2Ban] : banned from `uname -n`" # Option: actionunban # Notes.: command executed when unbanning an IP. Take care that the diff --git a/config/action.d/mail.conf b/config/action.d/mail.conf index f9a54979..7bf51a1d 100644 --- a/config/action.d/mail.conf +++ b/config/action.d/mail.conf @@ -13,7 +13,7 @@ actionstart = printf %%b "Hi,\n The jail has been started successfully.\n Regards,\n - Fail2Ban"|mail -s "[Fail2Ban] : started" + Fail2Ban"|mail -s "[Fail2Ban] : started on `uname -n`" # Option: actionstop # Notes.: command executed once at the end of Fail2Ban @@ -22,7 +22,7 @@ actionstart = printf %%b "Hi,\n actionstop = printf %%b "Hi,\n The jail has been stopped.\n Regards,\n - Fail2Ban"|mail -s "[Fail2Ban] : stopped" + Fail2Ban"|mail -s "[Fail2Ban] : stopped on `uname -n`" # Option: actioncheck # Notes.: command executed once before each actionban command @@ -40,7 +40,7 @@ actionban = printf %%b "Hi,\n The IP has just been banned by Fail2Ban after attempts against .\n Regards,\n - Fail2Ban"|mail -s "[Fail2Ban] : banned " + Fail2Ban"|mail -s "[Fail2Ban] : banned from `uname -n`" # Option: actionunban # Notes.: command executed when unbanning an IP. Take care that the diff --git a/config/action.d/osx-afctl.conf b/config/action.d/osx-afctl.conf new file mode 100644 index 00000000..a319fc6b --- /dev/null +++ b/config/action.d/osx-afctl.conf @@ -0,0 +1,16 @@ +# Fail2Ban configuration file for using afctl on Mac OS X Server 10.5 +# +# Anonymous author +# http://www.fail2ban.org/wiki/index.php?title=HOWTO_Mac_OS_X_Server_(10.5)&diff=prev&oldid=4081 +# +# Ref: https://developer.apple.com/library/mac/documentation/Darwin/Reference/ManPages/man8/afctl.8.html + +[Definition] +actionstart = +actionstop = +actioncheck = +actionban = /usr/libexec/afctl -a -t +actionunban = /usr/libexec/afctl -r + +[Init] +bantime = 2880 diff --git a/config/action.d/pf.conf b/config/action.d/pf.conf index d82cbb12..edcaa175 100644 --- a/config/action.d/pf.conf +++ b/config/action.d/pf.conf @@ -56,7 +56,7 @@ actionunban = /sbin/pfctl -t -T delete /32 [Init] # Option: tablename # Notes.: The pf table name. -# Values: [ STRING ] Default: fail2ban +# Values: [ STRING ] # tablename = fail2ban diff --git a/config/action.d/sendmail-buffered.conf b/config/action.d/sendmail-buffered.conf index f5ca6c10..80eb20a3 100644 --- a/config/action.d/sendmail-buffered.conf +++ b/config/action.d/sendmail-buffered.conf @@ -14,7 +14,7 @@ before = sendmail-common.conf # Notes.: command executed once at the start of Fail2Ban. # Values: CMD # -actionstart = printf %%b "Subject: [Fail2Ban] : started +actionstart = printf %%b "Subject: [Fail2Ban] : started on `uname -n` From: <> To: \n Hi,\n @@ -28,7 +28,7 @@ actionstart = printf %%b "Subject: [Fail2Ban] : started # Values: CMD # actionstop = if [ -f ]; then - printf %%b "Subject: [Fail2Ban] : summary + printf %%b "Subject: [Fail2Ban] : summary from `uname -n` From: <> To: \n Hi,\n @@ -38,7 +38,7 @@ actionstop = if [ -f ]; then Fail2Ban" | /usr/sbin/sendmail -f rm fi - printf %%b "Subject: [Fail2Ban] : stopped + printf %%b "Subject: [Fail2Ban] : stopped on `uname -n` From: Fail2Ban <> To: \n Hi,\n @@ -61,7 +61,7 @@ actioncheck = actionban = printf %%b "`date`: ( failures)\n" >> LINE=$( wc -l | awk '{ print $1 }' ) if [ $LINE -ge ]; then - printf %%b "Subject: [Fail2Ban] : summary + printf %%b "Subject: [Fail2Ban] : summary from `uname -n` From: <> To: \n Hi,\n diff --git a/config/action.d/sendmail-common.conf b/config/action.d/sendmail-common.conf index e2820470..26dcb4c8 100644 --- a/config/action.d/sendmail-common.conf +++ b/config/action.d/sendmail-common.conf @@ -8,6 +8,56 @@ after = sendmail-common.local +[Definition] + +# Option: actionstart +# Notes.: command executed once at the start of Fail2Ban. +# Values: CMD +# +actionstart = printf %%b "Subject: [Fail2Ban] : started on `uname -n` + Date: `LC_TIME=C date -u +"%%a, %%d %%h %%Y %%T +0000"` + From: <> + To: \n + Hi,\n + The jail has been started successfully.\n + Regards,\n + Fail2Ban" | /usr/sbin/sendmail -f + +# Option: actionstop +# Notes.: command executed once at the end of Fail2Ban +# Values: CMD +# +actionstop = printf %%b "Subject: [Fail2Ban] : stopped on `uname -n` + Date: `LC_TIME=C date -u +"%%a, %%d %%h %%Y %%T +0000"` + From: <> + To: \n + Hi,\n + The jail has been stopped.\n + Regards,\n + Fail2Ban" | /usr/sbin/sendmail -f + +# 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: See jail.conf(5) man page +# Values: CMD +# +actionban = + +# Option: actionunban +# Notes.: command executed when unbanning an IP. Take care that the +# command is executed with Fail2Ban user rights. +# Tags: See jail.conf(5) man page +# Values: CMD +# +actionunban = + [Init] # Recipient mail address diff --git a/config/action.d/sendmail-whois-ipjailmatches.conf b/config/action.d/sendmail-whois-ipjailmatches.conf new file mode 100644 index 00000000..45b1f312 --- /dev/null +++ b/config/action.d/sendmail-whois-ipjailmatches.conf @@ -0,0 +1,37 @@ +# Fail2Ban configuration file +# +# Author: Cyril Jaquier +# +# + +[INCLUDES] + +before = sendmail-common.conf + +[Definition] + +# Option: actionban +# Notes.: command executed when banning an IP. Take care that the +# command is executed with Fail2Ban user rights. +# Tags: See jail.conf(5) man page +# Values: CMD +# +actionban = printf %%b "Subject: [Fail2Ban] : banned from `uname -n` + Date: `LC_TIME=C date -u +"%%a, %%d %%h %%Y %%T +0000"` + From: <> + To: \n + Hi,\n + The IP has just been banned by Fail2Ban after + attempts against .\n\n + Here are more information about :\n + `/usr/bin/whois `\n\n + Matches for with failures IP:\n + \n\n + Regards,\n + Fail2Ban" | /usr/sbin/sendmail -f + +[Init] + +# Default name of the chain +# +name = default diff --git a/config/action.d/sendmail-whois-ipmatches.conf b/config/action.d/sendmail-whois-ipmatches.conf new file mode 100644 index 00000000..8193fb04 --- /dev/null +++ b/config/action.d/sendmail-whois-ipmatches.conf @@ -0,0 +1,37 @@ +# Fail2Ban configuration file +# +# Author: Cyril Jaquier +# +# + +[INCLUDES] + +before = sendmail-common.conf + +[Definition] + +# Option: actionban +# Notes.: command executed when banning an IP. Take care that the +# command is executed with Fail2Ban user rights. +# Tags: See jail.conf(5) man page +# Values: CMD +# +actionban = printf %%b "Subject: [Fail2Ban] : banned from `uname -n` + Date: `LC_TIME=C date -u +"%%a, %%d %%h %%Y %%T +0000"` + From: <> + To: \n + Hi,\n + The IP has just been banned by Fail2Ban after + attempts against .\n\n + Here are more information about :\n + `/usr/bin/whois `\n\n + Matches with failures IP:\n + \n\n + Regards,\n + Fail2Ban" | /usr/sbin/sendmail -f + +[Init] + +# Default name of the chain +# +name = default diff --git a/config/action.d/sendmail-whois-lines.conf b/config/action.d/sendmail-whois-lines.conf index 2cb27bd2..270373e7 100644 --- a/config/action.d/sendmail-whois-lines.conf +++ b/config/action.d/sendmail-whois-lines.conf @@ -10,66 +10,26 @@ before = sendmail-common.conf [Definition] -# Option: actionstart -# Notes.: command executed once at the start of Fail2Ban. -# Values: CMD -# -actionstart = printf %%b "Subject: [Fail2Ban] : started - Date: `LC_TIME=C date -u +"%%a, %%d %%h %%Y %%T +0000"` - From: <> - To: \n - Hi,\n - The jail has been started successfully.\n - Regards,\n - Fail2Ban" | /usr/sbin/sendmail -f - -# Option: actionstop -# Notes.: command executed once at the end of Fail2Ban -# Values: CMD -# -actionstop = printf %%b "Subject: [Fail2Ban] : stopped - Date: `LC_TIME=C date -u +"%%a, %%d %%h %%Y %%T +0000"` - From: <> - To: \n - Hi,\n - The jail has been stopped.\n - Regards,\n - Fail2Ban" | /usr/sbin/sendmail -f - -# 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: See jail.conf(5) man page # Values: CMD # -actionban = printf %%b "Subject: [Fail2Ban] : banned +actionban = printf %%b "Subject: [Fail2Ban] : banned from `uname -n` Date: `LC_TIME=C date -u +"%%a, %%d %%h %%Y %%T +0000"` From: <> To: \n Hi,\n The IP has just been banned by Fail2Ban after attempts against .\n\n - Here are more information about :\n - `/usr/bin/whois `\n\n + Here is more information about :\n + `/usr/bin/whois || echo missing whois program`\n\n Lines containing IP: in \n - `grep '\<\>' `\n\n + `grep '[^0-9][^0-9]' `\n\n Regards,\n Fail2Ban" | /usr/sbin/sendmail -f -# Option: actionunban -# Notes.: command executed when unbanning an IP. Take care that the -# command is executed with Fail2Ban user rights. -# Tags: See jail.conf(5) man page -# Values: CMD -# -actionunban = - [Init] # Default name of the chain diff --git a/config/action.d/sendmail-whois-matches.conf b/config/action.d/sendmail-whois-matches.conf new file mode 100644 index 00000000..ed664766 --- /dev/null +++ b/config/action.d/sendmail-whois-matches.conf @@ -0,0 +1,37 @@ +# Fail2Ban configuration file +# +# Author: Cyril Jaquier +# +# + +[INCLUDES] + +before = sendmail-common.conf + +[Definition] + +# Option: actionban +# Notes.: command executed when banning an IP. Take care that the +# command is executed with Fail2Ban user rights. +# Tags: See jail.conf(5) man page +# Values: CMD +# +actionban = printf %%b "Subject: [Fail2Ban] : banned from `uname -n` + Date: `LC_TIME=C date -u +"%%a, %%d %%h %%Y %%T +0000"` + From: <> + To: \n + Hi,\n + The IP has just been banned by Fail2Ban after + attempts against .\n\n + Here are more information about :\n + `/usr/bin/whois `\n\n + Matches:\n + \n\n + Regards,\n + Fail2Ban" | /usr/sbin/sendmail -f + +[Init] + +# Default name of the chain +# +name = default diff --git a/config/action.d/sendmail-whois.conf b/config/action.d/sendmail-whois.conf index b111e19f..fc601277 100644 --- a/config/action.d/sendmail-whois.conf +++ b/config/action.d/sendmail-whois.conf @@ -10,64 +10,24 @@ before = sendmail-common.conf [Definition] -# Option: actionstart -# Notes.: command executed once at the start of Fail2Ban. -# Values: CMD -# -actionstart = printf %%b "Subject: [Fail2Ban] : started - Date: `LC_TIME=C date -u +"%%a, %%d %%h %%Y %%T +0000"` - From: <> - To: \n - Hi,\n - The jail has been started successfully.\n - Regards,\n - Fail2Ban" | /usr/sbin/sendmail -f - -# Option: actionstop -# Notes.: command executed once at the end of Fail2Ban -# Values: CMD -# -actionstop = printf %%b "Subject: [Fail2Ban] : stopped - Date: `LC_TIME=C date -u +"%%a, %%d %%h %%Y %%T +0000"` - From: <> - To: \n - Hi,\n - The jail has been stopped.\n - Regards,\n - Fail2Ban" | /usr/sbin/sendmail -f - -# 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: See jail.conf(5) man page # Values: CMD # -actionban = printf %%b "Subject: [Fail2Ban] : banned +actionban = printf %%b "Subject: [Fail2Ban] : banned from `uname -n` Date: `LC_TIME=C date -u +"%%a, %%d %%h %%Y %%T +0000"` From: <> To: \n Hi,\n The IP has just been banned by Fail2Ban after attempts against .\n\n - Here are more information about :\n - `/usr/bin/whois `\n + Here is more information about :\n + `/usr/bin/whois || echo missing whois program`\n Regards,\n Fail2Ban" | /usr/sbin/sendmail -f -# Option: actionunban -# Notes.: command executed when unbanning an IP. Take care that the -# command is executed with Fail2Ban user rights. -# Tags: See jail.conf(5) man page -# Values: CMD -# -actionunban = - [Init] # Default name of the chain diff --git a/config/action.d/sendmail.conf b/config/action.d/sendmail.conf index 55d388fc..46050e11 100644 --- a/config/action.d/sendmail.conf +++ b/config/action.d/sendmail.conf @@ -10,45 +10,13 @@ before = sendmail-common.conf [Definition] -# Option: actionstart -# Notes.: command executed once at the start of Fail2Ban. -# Values: CMD -# -actionstart = printf %%b "Subject: [Fail2Ban] : started - Date: `LC_TIME=C date -u +"%%a, %%d %%h %%Y %%T +0000"` - From: <> - To: \n - Hi,\n - The jail has been started successfully.\n - Regards,\n - Fail2Ban" | /usr/sbin/sendmail -f - -# Option: actionstop -# Notes.: command executed once at the end of Fail2Ban -# Values: CMD -# -actionstop = printf %%b "Subject: [Fail2Ban] : stopped - Date: `LC_TIME=C date -u +"%%a, %%d %%h %%Y %%T +0000"` - From: <> - To: \n - Hi,\n - The jail has been stopped.\n - Regards,\n - Fail2Ban" | /usr/sbin/sendmail -f - -# 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: See jail.conf(5) man page # Values: CMD # -actionban = printf %%b "Subject: [Fail2Ban] : banned +actionban = printf %%b "Subject: [Fail2Ban] : banned from `uname -n` Date: `LC_TIME=C date -u +"%%a, %%d %%h %%Y %%T +0000"` From: <> To: \n @@ -58,14 +26,6 @@ actionban = printf %%b "Subject: [Fail2Ban] : banned Regards,\n Fail2Ban" | /usr/sbin/sendmail -f -# Option: actionunban -# Notes.: command executed when unbanning an IP. Take care that the -# command is executed with Fail2Ban user rights. -# Tags: See jail.conf(5) man page -# Values: CMD -# -actionunban = - [Init] # Default name of the chain diff --git a/config/action.d/smtp.py b/config/action.d/smtp.py new file mode 100644 index 00000000..065a0bba --- /dev/null +++ b/config/action.d/smtp.py @@ -0,0 +1,225 @@ +# emacs: -*- mode: python; py-indent-offset: 4; indent-tabs-mode: t -*- +# vi: set ft=python sts=4 ts=4 sw=4 noet : + +# This file is part of Fail2Ban. +# +# Fail2Ban is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# Fail2Ban is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Fail2Ban; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +import sys +import socket +import smtplib +from email.mime.text import MIMEText +from email.utils import formatdate, formataddr + +from fail2ban.server.actions import ActionBase, CallingMap + +messages = {} +messages['start'] = \ +"""Hi, + +The jail %(jailname)s has been started successfully. + +Regards, +Fail2Ban""" + +messages['stop'] = \ +"""Hi, + +The jail %(jailname)s has been stopped. + +Regards, +Fail2Ban""" + +messages['ban'] = {} +messages['ban']['head'] = \ +"""Hi, + +The IP %(ip)s has just been banned for %(bantime)s seconds +by Fail2Ban after %(failures)i attempts against %(jailname)s. +""" +messages['ban']['tail'] = \ +""" +Regards, +Fail2Ban""" +messages['ban']['matches'] = \ +""" +Matches for this ban: +%(matches)s +""" +messages['ban']['ipmatches'] = \ +""" +Matches for %(ip)s: +%(ipmatches)s +""" +messages['ban']['ipjailmatches'] = \ +""" +Matches for %(ip)s for jail %(jailname)s: +%(ipjailmatches)s +""" + +class SMTPAction(ActionBase): + """Fail2Ban action which sends emails to inform on jail starting, + stopping and bans. + """ + + def __init__( + self, jail, name, host="localhost", user=None, password=None, + sendername="Fail2Ban", sender="fail2ban", dest="root", matches=None): + """Initialise action. + + Parameters + ---------- + jail : Jail + The jail which the action belongs to. + name : str + Named assigned to the action. + host : str, optional + SMTP host, of host:port format. Default host "localhost" and + port "25" + user : str, optional + Username used for authentication with SMTP server. + password : str, optional + Password used for authentication with SMTP server. + sendername : str, optional + Name to use for from address in email. Default "Fail2Ban". + sender : str, optional + Email address to use for from address in email. + Default "fail2ban". + dest : str, optional + Email addresses of intended recipient(s) in comma delimited + format. Default "root". + matches : str, optional + Type of matches to be included from ban in email. Can be one + of "matches", "ipmatches" or "ipjailmatches". Default None + (see man jail.conf.5). + """ + + super(SMTPAction, self).__init__(jail, name) + + self.host = host + #TODO: self.ssl = ssl + + self.user = user + self.password =password + + self.fromname = sendername + self.fromaddr = sender + self.toaddr = dest + + self.matches = matches + + self.message_values = CallingMap( + jailname = self._jail.getName(), # Doesn't change + hostname = socket.gethostname, + bantime = self._jail.actions.getBanTime, + ) + + def _sendMessage(self, subject, text): + """Sends message based on arguments and instance's properties. + + Parameters + ---------- + subject : str + Subject of the email. + text : str + Body of the email. + + Raises + ------ + SMTPConnectionError + Error on connecting to host. + SMTPAuthenticationError + Error authenticating with SMTP server. + SMTPException + See Python `smtplib` for full list of other possible + exceptions. + """ + msg = MIMEText(text) + msg['Subject'] = subject + msg['From'] = formataddr((self.fromname, self.fromaddr)) + msg['To'] = self.toaddr + msg['Date'] = formatdate() + + smtp = smtplib.SMTP() + try: + self._logSys.debug("Connected to SMTP '%s', response: %i: %s", + self.host, *smtp.connect(self.host)) + if self.user and self.password: + smtp.login(self.user, self.password) + failed_recipients = smtp.sendmail( + self.fromaddr, self.toaddr, msg.as_string()) + except smtplib.SMTPConnectError: + self._logSys.error("Error connecting to host '%s'", self.host) + raise + except smtplib.SMTPAuthenticationError: + self._logSys.error( + "Failed to authenticate with host '%s' user '%s'", + self.host, self.user) + raise + except smtplib.SMTPException: + self._logSys.error( + "Error sending mail to host '%s' from '%s' to '%s'", + self.host, self.fromaddr, self.toaddr) + raise + else: + if failed_recipients: + self._logSys.warning( + "Email to '%s' failed to following recipients: %r", + self.toaddr, failed_recipients) + self._logSys.debug("Email '%s' successfully sent", subject) + finally: + try: + self._logSys.debug("Disconnected from '%s', response %i: %s", + self.host, *smtp.quit()) + except smtplib.SMTPServerDisconnected: + pass # Not connected + + def start(self): + """Sends email to recipients informing that the jail has started. + """ + self._sendMessage( + "[Fail2Ban] %(jailname)s: started on %(hostname)s" % + self.message_values, + messages['start'] % self.message_values) + + def stop(self): + """Sends email to recipients informing that the jail has stopped. + """ + self._sendMessage( + "[Fail2Ban] %(jailname)s: stopped on %(hostname)s" % + self.message_values, + messages['stop'] % self.message_values) + + def ban(self, aInfo): + """Sends email to recipients informing that ban has occurred. + + Parameters + ---------- + aInfo : dict + Dictionary which includes information in relation to + the ban. + """ + aInfo.update(self.message_values) + message = "".join([ + messages['ban']['head'], + messages['ban'].get(self.matches, ""), + messages['ban']['tail'] + ]) + self._sendMessage( + "[Fail2Ban] %(jailname)s: banned %(ip)s from %(hostname)s" % + aInfo, + message % aInfo) + +Action = SMTPAction diff --git a/config/action.d/ufw.conf b/config/action.d/ufw.conf new file mode 100644 index 00000000..c826729d --- /dev/null +++ b/config/action.d/ufw.conf @@ -0,0 +1,40 @@ +# Fail2Ban action configuration file for ufw +# +# You are required to run "ufw enable" before this will have an effect. +# +# The insert position should be approprate to block the required traffic. +# A number after an allow rule to the application won't be much use. + +[Definition] + +actionstart = + +actionstop = + +actioncheck = + +actionban = [ -n "" ] && app="app " ; ufw insert from to $app + +actionunban = [ -n "" ] && app="app " ; ufw delete from to $app + +[Init] +# Option: insertpos +# Notes.: The postition number in the firewall list to insert the block rule +insertpos = 1 + +# Option: blocktype +# Notes.: reject or deny +blocktype = reject + +# Option: destination +# Notes.: The destination address to block in the ufw rule +destination = any + +# Option: application +# Notes.: application from sudo ufw app list +application = + +# DEV NOTES: +# +# Author: Guilhem Lettron +# Enhancements: Daniel Black diff --git a/config/action.d/xarf-login-attack.conf b/config/action.d/xarf-login-attack.conf new file mode 100644 index 00000000..c5ac5110 --- /dev/null +++ b/config/action.d/xarf-login-attack.conf @@ -0,0 +1,125 @@ +# Fail2Ban action for sending xarf Login-Attack messages to IP owner +# +# IMPORTANT: +# +# Emailing a IP owner of abuse is a serious complain. Make sure that it is +# serious. Fail2ban developers and network owners recommend you only use this +# action for: +# * The recidive where the IP has been banned multiple times +# * Where maxretry has been set quite high, beyond the normal user typing +# password incorrectly. +# * For filters that have a low likelyhood of receiving human errors +# +# DEPENDANCIES: +# +# This requires the dig command from bind-utils +# +# This uses the https://abusix.com/contactdb.html to lookup abuse contacts. +# +# XARF is a specification for sending a formatted response +# for non-messaging based abuse including: +# +# Login-Attack, Malware-Attack, Fraud (Phishing, etc.), Info DNSBL +# +# For details see: +# https://github.com/abusix/xarf-specification +# http://www.x-arf.org/schemata.html +# +# Author: Daniel Black +# Based on complain written by Russell Odom +# +# + +[Definition] + +actionstart = + +actionstop = + +actioncheck = + +actionban = oifs=${IFS}; IFS=.;SEP_IP=( ); set -- ${SEP_IP} ;ADDRESSES=$(dig +short -t txt -q $4.$3.$2.$1.abuse-contacts.abusix.org); IFS=${oifs} + IP= + FROM= + SERVICE= + FAILURES= + MATCHES='' + REPORTID=