diff --git a/.coveragerc b/.coveragerc index 3bffd79a..19bc3db4 100644 --- a/.coveragerc +++ b/.coveragerc @@ -1,4 +1,11 @@ [run] branch = True -omit = /usr* +source = + config + fail2ban + +[report] +exclude_lines = + pragma: no cover + pragma: systemd no cover diff --git a/.travis.yml b/.travis.yml index bd2d294c..f65e4896 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,24 +1,56 @@ # vim ft=yaml # travis-ci.org definition for Fail2Ban build +# https://travis-ci.org/fail2ban/fail2ban/ language: python python: - - "2.6" - - "2.7" - - "3.2" - - "3.3" - - "3.4" - - "pypy" + - 2.6 + - 2.7 + - pypy + - 3.2 + - 3.3 + - 3.4 + - pypy3 before_install: - - if [[ $TRAVIS_PYTHON_VERSION == 2.7 ]]; then sudo apt-get update -qq; fi + - if [[ $TRAVIS_PYTHON_VERSION == 2* || $TRAVIS_PYTHON_VERSION == 'pypy' ]]; then export F2B_PY_2=true && echo "Set F2B_PY_2"; fi + - if [[ $TRAVIS_PYTHON_VERSION == 3* || $TRAVIS_PYTHON_VERSION == 'pypy3' ]]; then export F2B_PY_3=true && echo "Set F2B_PY_3"; fi + - travis_retry sudo apt-get update -qq + # Set this so sudo executes the correct python binary + # Anything not using sudo will already have the correct environment + - export VENV_BIN="$VIRTUAL_ENV/bin" && echo "VENV_BIN set to $VENV_BIN" install: - - pip install pyinotify - - if [[ $TRAVIS_PYTHON_VERSION == 2.7 ]]; then sudo apt-get install -qq python-gamin; cp /usr/share/pyshared/gamin.py /usr/lib/pyshared/python2.7/_gamin.so $VIRTUAL_ENV/lib/python2.7/site-packages/; fi - - if [[ $TRAVIS_PYTHON_VERSION == 2.7 ]]; then cd ..; pip install -q coveralls; cd -; fi + # Install Python packages / dependencies + # coverage + - travis_retry pip install coverage + # coveralls + - travis_retry pip install coveralls + # dnspython or dnspython3 + - if [[ "$F2B_PY_2" ]]; then travis_retry pip install dnspython; fi + - if [[ "$F2B_PY_3" ]]; then travis_retry pip install dnspython3; fi + # gamin - install manually (not in PyPI) - travis-ci system Python is 2.7 + - if [[ $TRAVIS_PYTHON_VERSION == 2.7 ]]; then travis_retry sudo apt-get install -qq python-gamin && cp /usr/share/pyshared/gamin.py /usr/lib/pyshared/python2.7/_gamin.so $VIRTUAL_ENV/lib/python2.7/site-packages/; fi + # pyinotify + - travis_retry pip install pyinotify +before_script: + # Manually execute 2to3 for now + - if [[ "$F2B_PY_3" ]]; then ./fail2ban-2to3; fi script: - - if [[ $TRAVIS_PYTHON_VERSION == 2.7 ]]; then coverage run --rcfile=.travis_coveragerc setup.py test; else python setup.py test; fi -# test installation - - sudo python setup.py install + # Keep the legacy setup.py test approach of checking coverage for python2 + - if [[ "$F2B_PY_2" ]]; then coverage run setup.py test; fi + # Coverage doesn't pick up setup.py test with python3, so run it directly + - if [[ "$F2B_PY_3" ]]; then coverage run bin/fail2ban-testcases; fi + # Use $VENV_BIN (not python) or else sudo will always run the system's python (2.7) + - sudo $VENV_BIN/pip install . after_success: -# Coverage config file must be .coveragerc for coveralls - - if [[ $TRAVIS_PYTHON_VERSION == 2.7 ]]; then cp -v .travis_coveragerc .coveragerc; fi - - if [[ $TRAVIS_PYTHON_VERSION == 2.7 ]]; then coveralls; fi + - coveralls +matrix: + fast_finish: true +# Might be worth looking into +#notifications: +# email: true +# irc: +# channels: "irc.freenode.org#fail2ban" +# template: +# - "%{repository}@%{branch}: %{message} (%{build_url})" +# on_success: change +# on_failure: change +# skip_join: true diff --git a/.travis_coveragerc b/.travis_coveragerc deleted file mode 100644 index 49fc3134..00000000 --- a/.travis_coveragerc +++ /dev/null @@ -1,7 +0,0 @@ - -[run] -branch = True -omit = - /usr/* - /home/travis/virtualenv/* - fail2ban/server/filtersystemd.py diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index a668fa3d..b8783b01 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -15,3 +15,13 @@ join the [mailing list](https://lists.sourceforge.net/lists/listinfo/fail2ban-us ### You would like to contribute (new filters/actions/code/documentation)? send a [pull request](https://github.com/fail2ban/fail2ban/pulls) + +Pull requests guidelines +======================== + +- If there is an issue on github to be closed by the pull request, include + ```Closes #ISSUE``` (where ISSUE is issue's number) + +- Add a brief summary of the change to the ChangeLog file into a corresponding + section out of Fixes, New Features or Enhancements (improvements to existing + features) diff --git a/ChangeLog b/ChangeLog index d0589248..a1fc3baf 100644 --- a/ChangeLog +++ b/ChangeLog @@ -3,21 +3,67 @@ | _/ _` | | |/ /| '_ \/ _` | ' \ |_| \__,_|_|_/___|_.__/\__,_|_||_| -================================================================================ -Fail2Ban (version 0.9.2.dev) 2014/xx/xx -================================================================================ +Fail2Ban: Changelog +=================== -ver. 0.9.2 (2014/xx/xx) - increment ban time ----------- +ver. 0.9.3 (2015/XX/XXX) - increment ban time +----------- + +- IMPORTANT incompatible changes: + * filter.d/roundcube-auth.conf + - Changed logpath to 'errors' log (was 'userlogins') - Fixes: * purge database will be executed now (within observer). * database functionality extended with bad ips. * restoring currently banned ip after service restart fixed (now < timeofban + bantime), ignore old log failures (already banned) + * reload in interactive mode appends all the jails twice (gh-825) + * reload server/jail failed if database used (but was not changed) and + some jail active (gh-1072) + * filter.d/dovecot.conf - also match unknown user in passwd-file. + Thanks Anton Shestakov + * Fix fail2ban-regex not parsing journalmatch correctly from filter config + * filter.d/asterisk.conf - fix security log support for Asterisk 12+ + * filter.d/roundcube-auth.conf + - Updated regex to work with 'errors' log (1.0.5 and 1.1.1) + - Added regex to work with 'userlogins' log + * action.d/sendmail*.conf - use LC_ALL (superseeding LC_TIME) to override + locale on systems with customized LC_ALL + * performance fix: minimizes connection overhead, close socket only at + communication end (gh-1099) + * unbanip always deletes ip from database (independent of bantime, also if + currently not banned or persistent) + +- New Features: + * increment ban time (+ observer) functionality introduced. + Thanks Serg G. Brester (sebres) + * New filters: + - froxlor-auth Thanks Joern Muehlencord + +- Enhancements: + * action.d/cloudflare.conf - improved documentation on how to allow + multiple CF accounts, and jail.conf got new compound action + definition action_cf_mwl to submit cloudflare report. + * Check access to socket for more detailed logging on error (gh-595) + * fail2ban-testcases man page + * filter.d/apache-badbots.conf, filter.d/nginx-botsearch.conf - add + HEAD method verb + * Revamp of Travis and coverage automated testing + + +ver. 0.9.2 (2015/04/29) - better-quick-now-than-later +---------- + +- Fixes: + * Fix ufw action commands + * infinite busy loop on _escapedTags match in substituteRecursiveTags gh-907. + Thanks TonyThompson + * port[s] typo in jail.conf/nginx-http-auth gh-913. Thanks Frederik Wagner + (fnerdwq) * $ typo in jail.conf. Thanks Skibbi. Debian bug #767255 * grep'ing for IP in *mail-whois-lines.conf should now match also - at the begginning and EOL. Thanks Dean Lee + at the beginning and EOL. Thanks Dean Lee * jail.conf - php-url-fopen: separate logpath entries by newline * failregex declared direct in jail was joined to single line (specifying of @@ -26,23 +72,67 @@ ver. 0.9.2 (2014/xx/xx) - increment ban time details. Thanks bes.internal * filter.d/postfix-sasl.conf - failregex is now case insensitive * filters.d/postfix.conf - add 'Client host rejected error message' failregex + * fail2ban/__init__.py - add strptime thread safety hack-around + * recidive uses iptables-allports banaction by default now. + Avoids problems with iptables versions not understanding 'all' for + protocols and ports + * filter.d/dovecot.conf + - match pam_authenticate line from EL7 + - match unknown user line from EL7 + * Use use_poll=True for Python 2.7 and >=3.4 to overcome "Bad file + descriptor" msgs issue (gh-161) + * filter.d/postfix-sasl.conf - tweak failregex and add ignoreregex to ignore + system authentication issues + * fail2ban-regex reads filter file(s) completely, incl. '.local' file etc. + (gh-954) + * firewallcmd-* actions: split output into separate lines for grepping (gh-908) + * Guard unicode encode/decode issues while storing records in the database. + Fixes "binding parameter error (unsupported type)" (gh-973), thanks to kot + for reporting + * filter.d/sshd added regex for matching openSUSE ssh authentication failure + * filter.d/asterisk.conf: + - Dropped "Sending fake auth rejection" failregex since it incorrectly + targets the asterisk server itself + - match "hacking attempt detected" logs - New Features: - * increment ban time (+ observer) functionality introduced. - Thanks Serg G. Brester (sebres) - * New interpolation feature for config readers - `%(known/parameter)s`. + - New filters: + - postfix-rbl Thanks Lee Clemens + - apache-fakegooglebot.conf Thanks Lee Clemens + - nginx-botsearch Thanks Frantisek Sumsal + - drupal-auth Thanks Lee Clemens + - New recursive embedded substitution feature added: + - `<HOST>` becomes `` for PREF=`IPV4`; + - `<HOST>` becomes `1.2.3.4` for PREF=`IPV4` and IPV4HOST=`1.2.3.4`; + - New interpolation feature for config readers - `%(known/parameter)s`. (means last known option with name `parameter`). This interpolation makes possible to extend a stock filter or jail regexp in .local file (opposite to simply set failregex/ignoreregex that overwrites it), see gh-867. - - Monit config for fail2ban in /files/monit + - Monit config for fail2ban in files/monit/ - New actions: - action.d/firewallcmd-multiport and action.d/firewallcmd-allports Thanks Donald Yandt - + - action.d/sendmail-geoip-lines.conf + - action.d/nsupdate to update DNSBL. Thanks Andrew St. Jean + - New status argument for fail2ban-client -- flavor: + fail2ban-client status [flavor] + - empty or "basic" works as-is + - "cymru" additionally prints (ASN, Country RIR) per banned IP + (requires dnspython or dnspython3) + - Flush log at USR1 signal + - Enhancements: * Enable multiport for firewallcmd-new action. Closes gh-834 * files/debian-initd migrated from the debian branch and should be suitable for manual installations now (thanks Juan Karlo de Guzman) + * Define empty ignoreregex in filters which didn't have it to avoid + warnings (gh-934) + * action.d/{sendmail-*,xarf-login-attack}.conf - report local + timezone not UTC time/zone. Closes gh-911 + * Conditionally log Ignore IP with reason (dns, ip, command). Closes gh-916 + * Absorbed DNSUtils.cidr into addr2bin in filter.py, added unittests + * Added syslogsocket configuration to fail2ban.conf + * Note in the jail.conf for the recidive jail to increase dbpurgeage (gh-964) ver. 0.9.1 (2014/10/29) - better, faster, stronger ---------- diff --git a/DEVELOP b/DEVELOP index 1384a6ac..bb7de5c8 100644 --- a/DEVELOP +++ b/DEVELOP @@ -56,9 +56,12 @@ following (note: on Debian-based systems, the script is called `python-coverage`):: coverage run bin/fail2ban-testcases + coverage report + +Optionally: coverage html -Then look at htmlcov/index.html and see how much coverage your test cases +And then browse htmlcov/index.html and see how much coverage your test cases 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. @@ -88,7 +91,7 @@ Testing can now be done inside a vagrant VM. Vagrantfile provided in source code repository established two VMs: - VM "secure" which can be used for testing fail2ban code. -- VM "attacker" which hcan be used to perform attack against our "secure" VM. +- VM "attacker" which can be used to perform attack against our "secure" VM. Both VMs are sharing the 192.168.200/24 network. If you are using this network take a look into the Vagrantfile and change the IP. diff --git a/MANIFEST b/MANIFEST index c6de80fd..d6bdba10 100644 --- a/MANIFEST +++ b/MANIFEST @@ -9,14 +9,155 @@ RELEASE THANKS TODO Vagrantfile +bin/fail2ban-client +bin/fail2ban-regex +bin/fail2ban-server +bin/fail2ban-testcases +config/action.d/apf.conf +config/action.d/badips.conf +config/action.d/badips.py +config/action.d/blocklist_de.conf +config/action.d/bsd-ipfw.conf +config/action.d/cloudflare.conf +config/action.d/complain.conf +config/action.d/dshield.conf +config/action.d/dummy.conf +config/action.d/firewallcmd-allports.conf +config/action.d/firewallcmd-ipset.conf +config/action.d/firewallcmd-multiport.conf +config/action.d/firewallcmd-new.conf +config/action.d/hostsdeny.conf +config/action.d/ipfilter.conf +config/action.d/ipfw.conf +config/action.d/iptables-allports.conf +config/action.d/iptables-common.conf +config/action.d/iptables-ipset-proto4.conf +config/action.d/iptables-ipset-proto6-allports.conf +config/action.d/iptables-ipset-proto6.conf +config/action.d/iptables-multiport-log.conf +config/action.d/iptables-multiport.conf +config/action.d/iptables-new.conf +config/action.d/iptables-xt_recent-echo.conf +config/action.d/iptables.conf +config/action.d/mail-buffered.conf +config/action.d/mail-whois-lines.conf +config/action.d/mail-whois.conf +config/action.d/mail.conf +config/action.d/mynetwatchman.conf +config/action.d/nsupdate.conf +config/action.d/nsupdate.conf +config/action.d/osx-afctl.conf +config/action.d/osx-ipfw.conf +config/action.d/pf.conf +config/action.d/route.conf +config/action.d/sendmail-buffered.conf +config/action.d/sendmail-common.conf +config/action.d/sendmail-geoip-lines.conf +config/action.d/sendmail-whois-ipjailmatches.conf +config/action.d/sendmail-whois-ipmatches.conf +config/action.d/sendmail-whois-lines.conf +config/action.d/sendmail-whois-matches.conf +config/action.d/sendmail-whois.conf +config/action.d/sendmail.conf +config/action.d/shorewall.conf +config/action.d/smtp.py +config/action.d/symbiosis-blacklist-allports.conf +config/action.d/ufw.conf +config/action.d/xarf-login-attack.conf +config/fail2ban.conf +config/filter.d/3proxy.conf +config/filter.d/apache-auth.conf +config/filter.d/apache-badbots.conf +config/filter.d/apache-botsearch.conf +config/filter.d/apache-common.conf +config/filter.d/apache-fakegooglebot.conf +config/filter.d/apache-modsecurity.conf +config/filter.d/apache-nohome.conf +config/filter.d/apache-noscript.conf +config/filter.d/apache-overflows.conf +config/filter.d/apache-shellshock.conf +config/filter.d/assp.conf +config/filter.d/asterisk.conf +config/filter.d/botsearch-common.conf +config/filter.d/common.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/directadmin.conf +config/filter.d/dovecot.conf +config/filter.d/dropbear.conf +config/filter.d/ejabberd-auth.conf +config/filter.d/exim-common.conf +config/filter.d/exim-spam.conf +config/filter.d/exim.conf +config/filter.d/freeswitch.conf +config/filter.d/groupoffice.conf +config/filter.d/gssftpd.conf +config/filter.d/guacamole.conf +config/filter.d/horde.conf +config/filter.d/ignorecommands +config/filter.d/ignorecommands/apache-fakegooglebot +config/filter.d/kerio.conf +config/filter.d/lighttpd-auth.conf +config/filter.d/monit.conf +config/filter.d/mysqld-auth.conf +config/filter.d/nagios.conf +config/filter.d/named-refused.conf +config/filter.d/nginx-botsearch.conf +config/filter.d/nginx-http-auth.conf +config/filter.d/nsd.conf +config/filter.d/openwebmail.conf +config/filter.d/oracleims.conf +config/filter.d/pam-generic.conf +config/filter.d/pam-generic.conf +config/filter.d/pam-generic.conf +config/filter.d/perdition.conf +config/filter.d/php-url-fopen.conf +config/filter.d/php-url-fopen.conf +config/filter.d/php-url-fopen.conf +config/filter.d/portsentry.conf +config/filter.d/postfix-rbl.conf +config/filter.d/postfix-sasl.conf +config/filter.d/postfix-sasl.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/recidive.conf +config/filter.d/roundcube-auth.conf +config/filter.d/selinux-common.conf +config/filter.d/selinux-ssh.conf +config/filter.d/sendmail-auth.conf +config/filter.d/sendmail-reject.conf +config/filter.d/sendmail-spam.conf +config/filter.d/sieve.conf +config/filter.d/sogo-auth.conf +config/filter.d/solid-pop3d.conf +config/filter.d/squid.conf +config/filter.d/squirrelmail.conf +config/filter.d/sshd-ddos.conf +config/filter.d/sshd.conf +config/filter.d/stunnel.conf +config/filter.d/suhosin.conf +config/filter.d/tine20.conf +config/filter.d/uwimap-auth.conf +config/filter.d/vsftpd.conf +config/filter.d/webmin-auth.conf +config/filter.d/wuftpd.conf +config/filter.d/xinetd-fail.conf +config/jail.conf +config/paths-common.conf +config/paths-debian.conf +config/paths-fedora.conf +config/paths-freebsd.conf +config/paths-osx.conf +doc/run-rootless.txt 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/__init__.py fail2ban/client/__init__.py fail2ban/client/actionreader.py fail2ban/client/beautifier.py @@ -28,6 +169,9 @@ fail2ban/client/fail2banreader.py fail2ban/client/filterreader.py fail2ban/client/jailreader.py fail2ban/client/jailsreader.py +fail2ban/exceptions.py +fail2ban/helpers.py +fail2ban/protocol.py fail2ban/server/__init__.py fail2ban/server/action.py fail2ban/server/actions.py @@ -64,6 +208,8 @@ fail2ban/tests/clientreadertestcase.py fail2ban/tests/config/action.d/brokenaction.conf fail2ban/tests/config/fail2ban.conf fail2ban/tests/config/filter.d/simple.conf +fail2ban/tests/config/filter.d/test.conf +fail2ban/tests/config/filter.d/test.local fail2ban/tests/config/jail.conf fail2ban/tests/config/paths-common.conf fail2ban/tests/config/paths-debian.conf @@ -74,6 +220,7 @@ fail2ban/tests/datedetectortestcase.py fail2ban/tests/dummyjail.py fail2ban/tests/failmanagertestcase.py fail2ban/tests/files/action.d/action.py +fail2ban/tests/files/action.d/action_checkainfo.py fail2ban/tests/files/action.d/action_errors.py fail2ban/tests/files/action.d/action_modifyainfo.py fail2ban/tests/files/action.d/action_noAction.py @@ -104,6 +251,7 @@ fail2ban/tests/files/logs/apache-auth fail2ban/tests/files/logs/apache-badbots fail2ban/tests/files/logs/apache-botscripts fail2ban/tests/files/logs/apache-botsearch +fail2ban/tests/files/logs/apache-fakegooglebot fail2ban/tests/files/logs/apache-modsecurity fail2ban/tests/files/logs/apache-nohome fail2ban/tests/files/logs/apache-noscript @@ -135,6 +283,7 @@ fail2ban/tests/files/logs/monit fail2ban/tests/files/logs/mysqld-auth fail2ban/tests/files/logs/nagios fail2ban/tests/files/logs/named-refused +fail2ban/tests/files/logs/nginx-botsearch fail2ban/tests/files/logs/nginx-http-auth fail2ban/tests/files/logs/nsd fail2ban/tests/files/logs/openwebmail @@ -144,6 +293,7 @@ fail2ban/tests/files/logs/perdition fail2ban/tests/files/logs/php-url-fopen fail2ban/tests/files/logs/portsentry fail2ban/tests/files/logs/postfix +fail2ban/tests/files/logs/postfix-rbl fail2ban/tests/files/logs/postfix-sasl fail2ban/tests/files/logs/proftpd fail2ban/tests/files/logs/pure-ftpd @@ -182,170 +332,38 @@ fail2ban/tests/samplestestcase.py fail2ban/tests/servertestcase.py fail2ban/tests/sockettestcase.py fail2ban/tests/utils.py -setup.py -setup.cfg -fail2ban/__init__.py -fail2ban/exceptions.py -fail2ban/helpers.py fail2ban/version.py -fail2ban/protocol.py -kill-server -config/action.d/apf.conf -config/action.d/badips.conf -config/action.d/badips.py -config/action.d/blocklist_de.conf -config/action.d/bsd-ipfw.conf -config/action.d/cloudflare.conf -config/action.d/complain.conf -config/action.d/dshield.conf -config/action.d/dummy.conf -config/action.d/firewallcmd-ipset.conf -config/action.d/firewallcmd-new.conf -config/action.d/hostsdeny.conf -config/action.d/ipfilter.conf -config/action.d/ipfw.conf -config/action.d/iptables-allports.conf -config/action.d/iptables-common.conf -config/action.d/iptables-ipset-proto4.conf -config/action.d/iptables-ipset-proto6-allports.conf -config/action.d/iptables-ipset-proto6.conf -config/action.d/iptables-multiport-log.conf -config/action.d/iptables-multiport.conf -config/action.d/iptables-new.conf -config/action.d/iptables-xt_recent-echo.conf -config/action.d/iptables.conf -config/action.d/mail-buffered.conf -config/action.d/mail-whois-lines.conf -config/action.d/mail-whois.conf -config/action.d/mail.conf -config/action.d/mynetwatchman.conf -config/action.d/osx-afctl.conf -config/action.d/osx-ipfw.conf -config/action.d/pf.conf -config/action.d/route.conf -config/action.d/sendmail-buffered.conf -config/action.d/sendmail-common.conf -config/action.d/sendmail-whois-ipjailmatches.conf -config/action.d/sendmail-whois-ipmatches.conf -config/action.d/sendmail-whois-lines.conf -config/action.d/sendmail-whois-matches.conf -config/action.d/sendmail-whois.conf -config/action.d/sendmail.conf -config/action.d/shorewall.conf -config/action.d/smtp.py -config/action.d/symbiosis-blacklist-allports.conf -config/action.d/ufw.conf -config/action.d/xarf-login-attack.conf -config/fail2ban.conf -config/filter.d/3proxy.conf -config/filter.d/apache-auth.conf -config/filter.d/apache-badbots.conf -config/filter.d/apache-botsearch.conf -config/filter.d/apache-common.conf -config/filter.d/apache-modsecurity.conf -config/filter.d/apache-nohome.conf -config/filter.d/apache-noscript.conf -config/filter.d/apache-overflows.conf -config/filter.d/apache-shellshock.conf -config/filter.d/assp.conf -config/filter.d/asterisk.conf -config/filter.d/common.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/directadmin.conf -config/filter.d/dovecot.conf -config/filter.d/dropbear.conf -config/filter.d/ejabberd-auth.conf -config/filter.d/exim-common.conf -config/filter.d/exim-spam.conf -config/filter.d/exim.conf -config/filter.d/freeswitch.conf -config/filter.d/groupoffice.conf -config/filter.d/gssftpd.conf -config/filter.d/guacamole.conf -config/filter.d/horde.conf -config/filter.d/kerio.conf -config/filter.d/lighttpd-auth.conf -config/filter.d/monit.conf -config/filter.d/mysqld-auth.conf -config/filter.d/nagios.conf -config/filter.d/named-refused.conf -config/filter.d/nginx-http-auth.conf -config/filter.d/nsd.conf -config/filter.d/openwebmail.conf -config/filter.d/oracleims.conf -config/filter.d/pam-generic.conf -config/filter.d/pam-generic.conf -config/filter.d/pam-generic.conf -config/filter.d/perdition.conf -config/filter.d/php-url-fopen.conf -config/filter.d/php-url-fopen.conf -config/filter.d/php-url-fopen.conf -config/filter.d/portsentry.conf -config/filter.d/postfix-sasl.conf -config/filter.d/postfix-sasl.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/recidive.conf -config/filter.d/roundcube-auth.conf -config/filter.d/selinux-common.conf -config/filter.d/selinux-ssh.conf -config/filter.d/sendmail-auth.conf -config/filter.d/sendmail-reject.conf -config/filter.d/sendmail-spam.conf -config/filter.d/sieve.conf -config/filter.d/sogo-auth.conf -config/filter.d/solid-pop3d.conf -config/filter.d/squid.conf -config/filter.d/squirrelmail.conf -config/filter.d/sshd-ddos.conf -config/filter.d/sshd.conf -config/filter.d/stunnel.conf -config/filter.d/suhosin.conf -config/filter.d/tine20.conf -config/filter.d/uwimap-auth.conf -config/filter.d/vsftpd.conf -config/filter.d/webmin-auth.conf -config/filter.d/wuftpd.conf -config/filter.d/xinetd-fail.conf -config/jail.conf -config/paths-common.conf -config/paths-debian.conf -config/paths-fedora.conf -config/paths-freebsd.conf -config/paths-osx.conf -man/fail2ban-client.1 -man/fail2ban.1 -man/jail.conf.5 -man/fail2ban-client.h2m -man/fail2ban-server.1 -man/fail2ban-server.h2m -man/fail2ban-regex.1 -man/fail2ban-regex.h2m -man/generate-man +files/bash-completion +files/cacti/README +files/cacti/cacti_host_template_fail2ban.xml +files/cacti/fail2ban_stats.sh files/debian-initd -files/gentoo-initd +files/fail2ban-logrotate +files/fail2ban-tmpfiles.conf +files/fail2ban.service +files/fail2ban.upstart +files/gen_badbots files/gentoo-confd -files/redhat-initd +files/gentoo-initd +files/ipmasq-ZZZzzz_fail2ban.rul +files/logwatch/fail2ban files/macosx-initd +files/monit/fail2ban +files/nagios/README +files/nagios/check_fail2ban +files/redhat-initd files/solaris-fail2ban.xml files/solaris-svc-fail2ban files/suse-initd -files/fail2ban-logrotate -files/fail2ban.upstart -files/logwatch/fail2ban -files/cacti/fail2ban_stats.sh -files/cacti/cacti_host_template_fail2ban.xml -files/cacti/README -files/nagios/check_fail2ban -files/nagios/README -files/bash-completion -files/fail2ban-tmpfiles.conf -files/fail2ban.service -files/ipmasq-ZZZzzz_fail2ban.rul -files/gen_badbots +kill-server +man/fail2ban-client.1 +man/fail2ban-client.h2m +man/fail2ban-regex.1 +man/fail2ban-regex.h2m +man/fail2ban-server.1 +man/fail2ban-server.h2m +man/fail2ban.1 +man/generate-man +man/jail.conf.5 +setup.cfg +setup.py diff --git a/MANIFEST.in b/MANIFEST.in index 9473d3a6..22696a20 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -2,3 +2,4 @@ include ChangeLog COPYING DEVELOP FILTERS README.* THANKS TODO CONTRIBUTING* Vag graft doc graft files recursive-include config *.conf *.py +recursive-include config/filter.d/ignorecommands * diff --git a/README.md b/README.md index 8210837e..66f07034 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ / _|__ _(_) |_ ) |__ __ _ _ _ | _/ _` | | |/ /| '_ \/ _` | ' \ |_| \__,_|_|_/___|_.__/\__,_|_||_| - v0.9.1.dev 2014/??/?? + v0.9.2.dev0 2015/xx/xx ## Fail2Ban: ban hosts that cause multiple authentication errors @@ -33,11 +33,12 @@ Optional: - Linux >= 2.6.13 - [gamin >= 0.0.21](http://www.gnome.org/~veillard/gamin) - [systemd >= 204](http://www.freedesktop.org/wiki/Software/systemd) +- [dnspython](http://www.dnspython.org/) To install, just do: - tar xvfj fail2ban-0.9.1.tar.bz2 - cd fail2ban-0.9.1 + tar xvfj fail2ban-0.9.2.tar.bz2 + cd fail2ban-0.9.2 python setup.py install This will install Fail2Ban into the python library directory. The executable diff --git a/RELEASE b/RELEASE index db425a45..16880efb 100644 --- a/RELEASE +++ b/RELEASE @@ -61,24 +61,24 @@ Preparation * Which indicates that testcases/files/logs/mysqld.log has been moved or is a directory:: - tar -C /tmp -jxf dist/fail2ban-0.9.2.tar.bz2 + tar -C /tmp -jxf dist/fail2ban-0.9.3.tar.bz2 * clean up current direcory:: - diff -rul --exclude \*.pyc . /tmp/fail2ban-0.9.2/ + diff -rul --exclude \*.pyc . /tmp/fail2ban-0.9.3/ * Only differences should be files that you don't want distributed. * Ensure the tests work from the tarball:: - cd /tmp/fail2ban-0.9.2/ && export PYTHONPATH=`pwd` && bin/fail2ban-testcases + cd /tmp/fail2ban-0.9.3/ && bin/fail2ban-testcases * Add/finalize the corresponding entry in the ChangeLog * To generate a list of committers use e.g.:: - git shortlog -sn 0.9.2.. | sed -e 's,^[ 0-9\t]*,,g' | tr '\n' '\|' | sed -e 's:|:, :g' + git shortlog -sn 0.9.3.. | 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. * Ensure the top entry of the ChangeLog has the right version and current date. @@ -101,7 +101,7 @@ Preparation * Tag the release by using a signed (and annotated) tag. Cut/paste release ChangeLog entry as tag annotation:: - git tag -s 0.9.2 + git tag -s 0.9.3 Pre Release =========== @@ -197,5 +197,5 @@ Add the following to the top of the ChangeLog:: Alter the git shortlog command in the previous section to refer to the just released version. -and adjust fail2ban/version.py to carry .dev suffix to signal +and adjust fail2ban/version.py to carry .dev0 suffix to signal a version under development. diff --git a/THANKS b/THANKS index 67f4f894..73d1347b 100644 --- a/THANKS +++ b/THANKS @@ -6,6 +6,7 @@ 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 +Aaron Brice Adam Tkac Adrien Clerc ache @@ -13,6 +14,7 @@ ag4ve (Shawn) Alasdair D. Campbell Amir Caspi Amy +Andrew St. Jean Andrey G. Grozin Andy Fragen Arturo 'Buanzo' Busleiman @@ -39,6 +41,7 @@ Enrico Labedzki Eugene Hopkinson (SlowRiot) ftoppi François Boulogne +Frantisek Sumsal Frédéric Georgiy Mernov Guilhem Lettron @@ -83,6 +86,7 @@ Michael Hanselmann Mika (mkl) Nick Munger onorua +Orion Poplawski Paul Marrapese Paul Traina Noel Butler diff --git a/bin/fail2ban-client b/bin/fail2ban-client index 866a5287..7f3f5639 100755 --- a/bin/fail2ban-client +++ b/bin/fail2ban-client @@ -22,8 +22,17 @@ __author__ = "Cyril Jaquier" __copyright__ = "Copyright (c) 2004 Cyril Jaquier" __license__ = "GPL" -import sys, string, os, pickle, re, logging, signal -import getopt, time, shlex, socket +import getopt +import logging +import os +import pickle +import re +import shlex +import signal +import socket +import string +import sys +import time from fail2ban.version import version from fail2ban.protocol import printFormatted @@ -144,32 +153,58 @@ class Fail2banClient: return self.__processCmd([["ping"]], False) def __processCmd(self, cmd, showRet = True): - beautifier = Beautifier() - streamRet = True - for c in cmd: - beautifier.setInputCmd(c) - try: - client = CSocket(self.__conf["socket"]) - ret = client.send(c) - if ret[0] == 0: - logSys.debug("OK : " + `ret[1]`) + client = None + try: + beautifier = Beautifier() + streamRet = True + for c in cmd: + beautifier.setInputCmd(c) + try: + if not client: + client = CSocket(self.__conf["socket"]) + ret = client.send(c) + if ret[0] == 0: + logSys.debug("OK : " + `ret[1]`) + if showRet: + print beautifier.beautify(ret[1]) + else: + logSys.error("NOK: " + `ret[1].args`) + if showRet: + print beautifier.beautifyError(ret[1]) + streamRet = False + except socket.error: if showRet: - print beautifier.beautify(ret[1]) - else: - logSys.error("NOK: " + `ret[1].args`) + self.__logSocketError() + return False + except Exception, e: if showRet: - print beautifier.beautifyError(ret[1]) - streamRet = False - except socket.error: - if showRet: - logSys.error("Unable to contact server. Is it running?") - return False - except Exception, e: - if showRet: - logSys.error(e) - return False + logSys.error(e) + return False + finally: + if client: + client.close() return streamRet + def __logSocketError(self): + try: + if os.access(self.__conf["socket"], os.F_OK): + # This doesn't check if path is a socket, + # but socket.error should be raised + if os.access(self.__conf["socket"], os.W_OK): + # Permissions look good, but socket.error was raised + logSys.error("Unable to contact server. Is it running?") + else: + logSys.error("Permission denied to socket: %s," + " (you must be root)", self.__conf["socket"]) + else: + logSys.error("Failed to access socket path: %s." + " Is fail2ban running?", + self.__conf["socket"]) + except Exception as e: + logSys.error("Exception while checking socket access: %s", + self.__conf["socket"]) + logSys.error(e) + ## # Process a command line. # diff --git a/bin/fail2ban-regex b/bin/fail2ban-regex index 5644dd37..b7b0579f 100755 --- a/bin/fail2ban-regex +++ b/bin/fail2ban-regex @@ -29,7 +29,15 @@ __author__ = "Fail2Ban Developers" __copyright__ = "Copyright (c) 2004-2008 Cyril Jaquier, 2012-2014 Yaroslav Halchenko" __license__ = "GPL" -import getopt, sys, time, logging, os, locale, shlex, time, urllib +import getopt +import locale +import logging +import os +import shlex +import sys +import time +import time +import urllib from optparse import OptionParser, Option from ConfigParser import NoOptionError, NoSectionError, MissingSectionHeaderError @@ -220,6 +228,7 @@ class Fail2banRegex(object): self._datepattern_set = False self._journalmatch = None + self.share_config=dict() self._filter = Filter(None) self._ignoreregex = list() self._failregex = list() @@ -260,38 +269,47 @@ class Fail2banRegex(object): def readRegex(self, value, regextype): assert(regextype in ('fail', 'ignore')) regex = regextype + 'regex' - if os.path.isfile(value): - print "Use %11s file : %s" % (regex, value) - reader = FilterReader(value, 'fail2ban-regex-jail', {}) - reader.setBaseDir(None) - - 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) + if os.path.isfile(value) or os.path.isfile(value + '.conf'): + if os.path.basename(os.path.dirname(value)) == 'filter.d': + ## within filter.d folder - use standard loading algorithm to load filter completely (with .local etc.): + basedir = os.path.dirname(os.path.dirname(value)) + value = os.path.splitext(os.path.basename(value))[0] + print "Use %11s filter file : %s, basedir: %s" % (regex, value, basedir) + reader = FilterReader(value, 'fail2ban-regex-jail', {}, share_config=self.share_config, basedir=basedir) + if not reader.read(): + print "ERROR: failed to load filter %s" % value + return False else: - print "ERROR: failed to read %s" % value - return False + ## foreign file - readexplicit this file and includes if possible: + print "Use %11s file : %s" % (regex, value) + reader = FilterReader(value, 'fail2ban-regex-jail', {}, share_config=self.share_config) + reader.setBaseDir(None) + if not reader.readexplicit(): + print "ERROR: failed to read %s" % value + return False + 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(journalmatch) + elif command[2] == 'datepattern': + datepattern = command[3] + self.setDatePattern(datepattern) else: print "Use %11s line : %s" % (regex, shortstr(value)) regex_values = [RegexStat(value)] diff --git a/bin/fail2ban-server b/bin/fail2ban-server index ec0c0dbe..f522f418 100755 --- a/bin/fail2ban-server +++ b/bin/fail2ban-server @@ -22,7 +22,9 @@ __author__ = "Cyril Jaquier" __copyright__ = "Copyright (c) 2004 Cyril Jaquier" __license__ = "GPL" -import getopt, sys, os +import getopt +import os +import sys from fail2ban.version import version from fail2ban.server.server import Server diff --git a/bin/fail2ban-testcases b/bin/fail2ban-testcases index 475aa40b..dd6547a5 100755 --- a/bin/fail2ban-testcases +++ b/bin/fail2ban-testcases @@ -25,7 +25,10 @@ __copyright__ = "Copyright (c) 2004 Cyril Jaquier, 2012- Yaroslav Halchenko" __license__ = "GPL" import logging -import unittest, sys, time, os +import os +import sys +import time +import unittest # Check if local fail2ban module exists, and use if it exists by # modifying the path. This is such that tests can be used in dev diff --git a/config/action.d/badips.py b/config/action.d/badips.py index 250b1dc3..a1df00a3 100644 --- a/config/action.d/badips.py +++ b/config/action.d/badips.py @@ -35,6 +35,7 @@ else: from fail2ban.server.actions import ActionBase from fail2ban.version import version as f2bVersion + class BadIPsAction(ActionBase): """Fail2Ban action which reports bans to badips.com, and also blacklist bad IPs listed on badips.com by using another action's @@ -111,6 +112,8 @@ class BadIPsAction(ActionBase): ------ HTTPError Any issues with badips.com request. + ValueError + If badips.com response didn't contain necessary information """ try: response = urlopen( @@ -122,7 +125,13 @@ class BadIPsAction(ActionBase): messages['err']) raise else: - categories = json.loads(response.read().decode('utf-8'))['categories'] + response_json = json.loads(response.read().decode('utf-8')) + if not 'categories' in response_json: + err = "badips.com response lacked categories specification. Response was: %s" \ + % (response_json,) + self._logSys.error(err) + raise ValueError(err) + categories = response_json['categories'] categories_names = set( value['Name'] for value in categories) if incParents: diff --git a/config/action.d/bsd-ipfw.conf b/config/action.d/bsd-ipfw.conf index 1285361d..8b0a51aa 100644 --- a/config/action.d/bsd-ipfw.conf +++ b/config/action.d/bsd-ipfw.conf @@ -38,7 +38,7 @@ actioncheck = # Values: CMD # # requires an ipfw rule like "deny ip from table(1) to me" -actionban = ipfw table add +actionban = e=`ipfw table
add 2>&1`; x=$?; [ $x -eq 0 -o "$e" = 'ipfw: setsockopt(IP_FW_TABLE_XADD): File exists' ] || { echo "$e" 1>&2; exit $x; } # Option: actionunban @@ -47,7 +47,7 @@ actionban = ipfw table
add # Tags: See jail.conf(5) man page # Values: CMD # -actionunban = ipfw table
delete +actionunban = e=`ipfw table
delete 2>&1`; x=$?; [ $x -eq 0 -o "$e" = 'ipfw: setsockopt(IP_FW_TABLE_XDEL): No such process' ] || { echo "$e" 1>&2; exit $x; } [Init] # Option: table diff --git a/config/action.d/cloudflare.conf b/config/action.d/cloudflare.conf index 4d5e2dc8..4bc90c97 100644 --- a/config/action.d/cloudflare.conf +++ b/config/action.d/cloudflare.conf @@ -1,10 +1,14 @@ # # Author: Mike Rushton # -# Referenced from from http://www.normyee.net/blog/2012/02/02/adding-cloudflare-support-to-fail2ban by NORM YEE +# IMPORTANT # -# To get your Cloudflare API key: https://www.cloudflare.com/my-account +# Please set jail.local's permission to 640 because it contains your CF API key. # +# This action depends on curl. +# Referenced from http://www.normyee.net/blog/2012/02/02/adding-cloudflare-support-to-fail2ban by NORM YEE +# +# To get your CloudFlare API Key: https://www.cloudflare.com/a/account/my-account [Definition] @@ -34,7 +38,8 @@ actioncheck = #