diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md new file mode 100644 index 00000000..cb4b4bc6 --- /dev/null +++ b/.github/ISSUE_TEMPLATE.md @@ -0,0 +1,49 @@ +_We will be very grateful, if your problem was described as completely as possible, +enclosing excerpts from logs (if possible within DEBUG mode, if no errors evident +within INFO mode), and configuration in particular of effected relevant settings +(e.g., with ` fail2ban-client -d | grep 'affected-jail-name' ` for a particular +jail troubleshooting). +Thank you in advance for the details, because such issues like "It does not work" +alone could not help to resolve anything! +Thanks! (remove this paragraph and other comments upon reading)_ + +### Environment: + +_Fill out and check (`[x]`) the boxes which apply. If your Fail2Ban version is outdated, +and you can't verify that the issue persists in the recent release, better seek support +from the distribution you obtained Fail2Ban from_ + +- Fail2Ban version (including any possible distribution suffixes): +- OS, including release name/version: +- [ ] Fail2Ban installed via OS/distribution mechanisms +- [ ] You have not applied any additional foreign patches to the codebase +- [ ] Some customizations were done to the configuration (provide details below is so) + +### The issue: + +_Summary here_ + +#### Steps to reproduce + +#### Expected behavior + +#### Observed behavior + +#### Any additional information + +### Configuration, dump and another helpful excerpts + +#### Any customizations done to /etc/fail2ban/ configuration +``` +``` + +#### Relevant parts of /var/log/fail2ban.log file: +_preferably obtained while running fail2ban with `loglevel = 4`_ + +``` +``` + +#### Relevant lines from monitored log files in question: + +``` +``` \ No newline at end of file diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 00000000..a9fff350 --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,9 @@ +Before submitting your PR, please review the following checklist: + +- [ ] **CONSIDER adding a unit test** if your PR resolves an issue +- [ ] **LIST ISSUES** this PR resolves +- [ ] **MAKE SURE** this PR doesn't break existing tests +- [ ] **KEEP PR small** so it could be easily reviewed. +- [ ] **AVOID** making unnecessary stylistic changes in unrelated code +- [ ] **ACCOMPANY** each new `failregex` for filter `X` with sample log lines + within `fail2ban/tests/files/logs/X` file \ No newline at end of file diff --git a/.travis.yml b/.travis.yml index adb41e7d..50894a94 100644 --- a/.travis.yml +++ b/.travis.yml @@ -23,7 +23,7 @@ install: # coverage - travis_retry pip install coverage # coveralls - - travis_retry pip install coveralls + - travis_retry pip install coveralls codecov # 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 @@ -43,6 +43,7 @@ script: - sudo $VENV_BIN/pip install . after_success: - coveralls + - codecov matrix: fast_finish: true # Might be worth looking into diff --git a/ChangeLog b/ChangeLog index 883bbaf4..24001ea2 100644 --- a/ChangeLog +++ b/ChangeLog @@ -15,7 +15,7 @@ ver. 0.9.4 (2015/XX/XXX) - wanna-be-released * filter.d/apache-badbots.conf - Updated useragent string regex adding escape for `+` * filter.d/mysqld-auth.conf - - Updated "Access denied ..." regex for MySQL 5.6 and later (gh-1211) + - Updated "Access denied ..." regex for MySQL 5.6 and later (gh-1211, gh-1332) * filter.d/sshd.conf - Updated "Auth fail" regex for OpenSSH 5.9 and later * Treat failed and killed execution of commands identically (only @@ -28,6 +28,11 @@ ver. 0.9.4 (2015/XX/XXX) - wanna-be-released for python version < 3.x (gh-1248) * Use postfix_log logpath for postfix-rbl jail * filters.d/postfix.conf - add 'Sender address rejected: Domain not found' failregex + * use `fail2ban_agent` as user-agent in actions badips, blocklist_de, etc (gh-1271) + * Fix ignoring the sender option by action_mw, action_mwl and action_c_mwl + * Changed filter.d/asterisk regex for "Call from ..." (few vulnerable now) + * Removed compression and rotation count from logrotate (inherit them from + the global logrotate config) - New Features: * New interpolation feature for definition config readers - `` @@ -37,6 +42,9 @@ ver. 0.9.4 (2015/XX/XXX) - wanna-be-released filter.d/*.local file. As extension to interpolation `%(known/parameter)s`, that does not works for filter and action init parameters + * New actions: + - nftables-multiport and nftables-allports - filtering using nftables + framework. Note: it requires a pre-existing chain for the filtering rule. * New filters: - openhab - domotic software authentication failure with the rest api and web interface (gh-1223) @@ -44,10 +52,13 @@ ver. 0.9.4 (2015/XX/XXX) - wanna-be-released request processing rate (ngx_http_limit_req_module) - murmur - ban hosts that repeatedly attempt to connect to murmur/mumble-server with an invalid server password or certificate. + - haproxy-http-auth - filter to match failed HTTP Authentications against a + HAProxy server * New jails: - murmur - bans TCP and UDP from the bad host on the default murmur port. * sshd filter got new failregex to match "maximum authentication attempts exceeded" (introduced in openssh 6.8) + * Added filter for Mac OS screen sharing (VNC) daemon - Enhancements: * Do not rotate empty log files @@ -69,6 +80,15 @@ ver. 0.9.4 (2015/XX/XXX) - wanna-be-released * Performance improvements while monitoring large number of files (gh-1265). Use associative array (dict) for monitored log files to speed up lookup operations. Thanks @kshetragia + * Specified that fail2ban is PartOf iptables.service firewalld.service in + .service file -- would reload fail2ban if those services are restarted + * Provides new default `fail2ban_version` and interpolation variable + `fail2ban_agent` in jail.conf + * Enhance filter 'postfix' to ban incoming SMTP client with no fqdn hostname, + and to support multiple instances of postfix having varying suffix (gh-1331) + (Thanks Tom Hendrikx) + * files/gentoo-initd to use start-stop-daemon to robustify restarting the service + ver. 0.9.3 (2015/08/01) - lets-all-stay-friends ---------- diff --git a/README.md b/README.md index cbc075e2..a05b24c6 100644 --- a/README.md +++ b/README.md @@ -77,6 +77,8 @@ Code status: * [![Coverage Status](https://coveralls.io/repos/fail2ban/fail2ban/badge.png?branch=master)](https://coveralls.io/r/fail2ban/fail2ban) +* [![codecov.io](https://codecov.io/github/fail2ban/fail2ban/coverage.svg?branch=master)](https://codecov.io/github/fail2ban/fail2ban?branch=master) + Contact: -------- diff --git a/RELEASE b/RELEASE index ae6738a1..d4a4f971 100644 --- a/RELEASE +++ b/RELEASE @@ -116,7 +116,7 @@ Pre Release * http://packages.qa.debian.org/f/fail2ban.html - * FreeBSD: Christoph Theis theis@gmx.at>, Nick Hilliard + * FreeBSD: Christoph Theis theis@gmx.at> * http://svnweb.freebsd.org/ports/head/security/py-fail2ban/Makefile?view=markup * http://www.freebsd.org/cgi/query-pr-summary.cgi?text=fail2ban diff --git a/THANKS b/THANKS index 47156d82..0b45c019 100644 --- a/THANKS +++ b/THANKS @@ -115,6 +115,7 @@ Steven Hiscocks TESTOVIK Thomas Mayer Tom Pike +Tom Hendrikx Tomas Pihl Tony Lawrence Tomasz Ciolek diff --git a/config/action.d/badips.conf b/config/action.d/badips.conf index 4a5c0f97..70b46546 100644 --- a/config/action.d/badips.conf +++ b/config/action.d/badips.conf @@ -10,7 +10,7 @@ [Definition] -actionban = curl --fail --user-agent "fail2ban v0.8.12" http://www.badips.com/add// +actionban = curl --fail --user-agent "" http://www.badips.com/add// [Init] diff --git a/config/action.d/badips.py b/config/action.d/badips.py index 99e1866a..025289ca 100644 --- a/config/action.d/badips.py +++ b/config/action.d/badips.py @@ -21,7 +21,6 @@ import sys if sys.version_info < (2, 7): raise ImportError("badips.py action requires Python >= 2.7") import json -from functools import partial import threading import logging if sys.version_info >= (3, ): @@ -33,7 +32,6 @@ else: from urllib import urlencode from fail2ban.server.actions import ActionBase -from fail2ban.version import version as f2bVersion class BadIPsAction(ActionBase): @@ -72,6 +70,9 @@ class BadIPsAction(ActionBase): updateperiod : int, optional Time in seconds between updating bad IPs blacklist. Default 900 (15 minutes) + agent : str, optional + User agent transmitted to server. + Default `Fail2Ban/ver.` Raises ------ @@ -80,13 +81,14 @@ class BadIPsAction(ActionBase): """ _badips = "http://www.badips.com" - _Request = partial( - Request, headers={'User-Agent': "Fail2Ban %s" % f2bVersion}) + def _Request(self, url, **argv): + return Request(url, headers={'User-Agent': self.agent}, **argv) def __init__(self, jail, name, category, score=3, age="24h", key=None, - banaction=None, bancategory=None, bankey=None, updateperiod=900): + banaction=None, bancategory=None, bankey=None, updateperiod=900, agent="Fail2Ban"): super(BadIPsAction, self).__init__(jail, name) + self.agent = agent self.category = category self.score = score self.age = age diff --git a/config/action.d/blocklist_de.conf b/config/action.d/blocklist_de.conf index 6d520694..2f31d8b9 100644 --- a/config/action.d/blocklist_de.conf +++ b/config/action.d/blocklist_de.conf @@ -54,7 +54,7 @@ actioncheck = # 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" +actionban = curl --fail --data-urlencode 'server=' --data 'apikey=' --data 'service=' --data 'ip=' --data-urlencode 'logs=' --data 'format=text' --user-agent "" "https://www.blocklist.de/en/httpreports.html" # Option: actionunban # Notes.: command executed when unbanning an IP. Take care that the diff --git a/config/action.d/mynetwatchman.conf b/config/action.d/mynetwatchman.conf index 5245a4e3..8f3edf9e 100644 --- a/config/action.d/mynetwatchman.conf +++ b/config/action.d/mynetwatchman.conf @@ -111,13 +111,17 @@ myip = `ip -4 addr show dev eth0 | grep inet | head -n 1 | sed -r 's/.*inet ([0- # protocol = tcp +# Option: agent +# Default: Fail2ban +agent = Fail2ban + # Option: getcmd # Notes.: A command to fetch a URL. Should output page to STDOUT # Values: CMD Default: wget # -getcmd = wget --no-verbose --tries=3 --waitretry=10 --connect-timeout=10 --read-timeout=60 --retry-connrefused --output-document=- --user-agent=Fail2Ban +getcmd = wget --no-verbose --tries=3 --waitretry=10 --connect-timeout=10 --read-timeout=60 --retry-connrefused --output-document=- --user-agent= # Alternative value: -# getcmd = curl --silent --show-error --retry 3 --connect-timeout 10 --max-time 60 --user-agent Fail2Ban +# getcmd = curl --silent --show-error --retry 3 --connect-timeout 10 --max-time 60 --user-agent # Option: srcport # Notes.: The source port of the attack. You're unlikely to have this info, so diff --git a/config/action.d/nftables-allports.conf b/config/action.d/nftables-allports.conf new file mode 100644 index 00000000..afd0ca84 --- /dev/null +++ b/config/action.d/nftables-allports.conf @@ -0,0 +1,22 @@ +# Fail2Ban configuration file +# +# Author: Cyril Jaquier +# Modified: Yaroslav O. Halchenko +# made active on all ports from original iptables.conf +# Modified: Alexander Belykh +# adapted for nftables +# + +[INCLUDES] + +before = nftables-common.conf + +[Definition] + +# Option: nftables_mode +# Notes.: additional expressions for nftables filter rule +# Values: nftables expressions +# +nftables_mode = ip protocol + +[Init] diff --git a/config/action.d/nftables-common.conf b/config/action.d/nftables-common.conf new file mode 100644 index 00000000..80657c5c --- /dev/null +++ b/config/action.d/nftables-common.conf @@ -0,0 +1,119 @@ +# Fail2Ban configuration file +# +# Author: Daniel Black +# Author: Cyril Jaquier +# Modified: Yaroslav O. Halchenko +# made active on all ports from original iptables.conf +# Modified: Alexander Belykh +# adapted for nftables +# +# This is a included configuration file and includes the definitions for the nftables +# used in all nftables based actions by default. +# +# The user can override the defaults in nftables-common.local + +[INCLUDES] + +after = nftables-common.local + +[Definition] + +# Option: nftables_mode +# Notes.: additional expressions for nftables filter rule +# Values: nftables expressions +# +nftables_mode = dport \{ \} + +# Option: actionstart +# Notes.: command executed once at the start of Fail2Ban. +# Values: CMD +# +actionstart = add set f2b- \{ type \; \} + insert rule %(nftables_mode)s ip saddr @f2b- + +_nft_list = --handle --numeric list chain +_nft_get_handle_id = grep -m1 'ip saddr @f2b- # handle' | grep -oe ' handle [0-9]*' + +# Option: actionstop +# Notes.: command executed once at the end of Fail2Ban +# Values: CMD +# +actionstop = HANDLE_ID=$(%(_nft_list)s | %(_nft_get_handle_id)s) + delete rule $HANDLE_ID + delete set f2b- + +# Option: actioncheck +# Notes.: command executed once before each actionban command +# Values: CMD +# +actioncheck = list chain | grep -q '@f2b-[ \t]' + +# 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 = add element f2b- \{ \} + +# 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 = delete element f2b- \{ \} + +[Init] + +# Option: nftables_type +# Notes.: address type to work with +# Values: [ipv4_addr | ipv6_addr] Default: ipv4_addr +# +nftables_type = ipv4_addr + +# Option: nftables_family +# Notes.: address family to work in +# Values: [ip | ip6 | inet] Default: inet +# +nftables_family = inet + +# Option: nftables_table +# Notes.: table in the address family to work in +# Values: STRING Default: filter +# +nftables_table = filter + +# Option: chain +# Notes specifies the nftables chain to which the Fail2Ban rules should be +# added +# Values: STRING Default: input +chain = input + +# Default name of the filtering set +# +name = default + +# Option: port +# Notes.: specifies port to monitor +# Values: [ NUM | STRING ] Default: +# +port = ssh + +# Option: protocol +# Notes.: internally used by config reader for interpolations. +# Values: [ tcp | udp ] Default: tcp +# +protocol = tcp + +# Option: blocktype +# Note: This is what the action does with rules. This can be any jump target +# as per the nftables man page (section 8). Common values are drop +# reject, reject with icmp type host-unreachable +# Values: STRING +blocktype = reject + +# Option: nftables +# Notes.: Actual command to be executed, including common to all calls options +# Values: STRING +nftables = nft diff --git a/config/action.d/nftables-multiport.conf b/config/action.d/nftables-multiport.conf new file mode 100644 index 00000000..d1afafb3 --- /dev/null +++ b/config/action.d/nftables-multiport.conf @@ -0,0 +1,22 @@ +# Fail2Ban configuration file +# +# Author: Cyril Jaquier +# Modified: Yaroslav O. Halchenko +# made active on all ports from original iptables.conf +# Modified: Alexander Belykh +# adapted for nftables +# + +[INCLUDES] + +before = nftables-common.conf + +[Definition] + +# Option: nftables_mode +# Notes.: additional expressions for nftables filter rule +# Values: nftables expressions +# +nftables_mode = dport \{ \} + +[Init] diff --git a/config/filter.d/asterisk.conf b/config/filter.d/asterisk.conf index b446c44e..3975fb29 100644 --- a/config/filter.d/asterisk.conf +++ b/config/filter.d/asterisk.conf @@ -19,7 +19,7 @@ iso8601 = \d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d+[+-]\d{4} log_prefix= (?:NOTICE|SECURITY)%(__pid_re)s:?(?:\[C-[\da-f]*\])? \S+:\d*( in \w+:)? failregex = ^(%(__prefix_line)s|\[\]\s*)%(log_prefix)s Registration from '[^']*' failed for '(:\d+)?' - (Wrong password|Username/auth name mismatch|No matching peer found|Not a local domain|Device does not match ACL|Peer is not supposed to register|ACL error \(permit/deny\)|Not a local domain)$ - ^(%(__prefix_line)s|\[\]\s*)%(log_prefix)s Call from '[^']*' \(:\d+\) to extension '\d+' rejected because extension not found in context 'default'\.$ + ^(%(__prefix_line)s|\[\]\s*)%(log_prefix)s Call from '[^']*' \(:\d+\) to extension '[^']*' rejected because extension not found in context ^(%(__prefix_line)s|\[\]\s*)%(log_prefix)s Host failed to authenticate as '[^']*'$ ^(%(__prefix_line)s|\[\]\s*)%(log_prefix)s No registration for peer '[^']*' \(from \)$ ^(%(__prefix_line)s|\[\]\s*)%(log_prefix)s Host failed MD5 authentication for '[^']*' \([^)]+\)$ diff --git a/config/filter.d/botsearch-common.conf b/config/filter.d/botsearch-common.conf index 65f9da2f..a673a310 100644 --- a/config/filter.d/botsearch-common.conf +++ b/config/filter.d/botsearch-common.conf @@ -11,9 +11,9 @@ webmail = roundcube|(ext)?mail|horde|(v-?)?webmail phpmyadmin = (typo3/|xampp/|admin/|)(pma|(php)?[Mm]y[Aa]dmin) -wordpress = wp-(login|signup)\.php +wordpress = wp-(login|signup|admin)\.php # DEV Notes: # Taken from apache-botsearch filter # -# Author: Frantisek Sumsal \ No newline at end of file +# Author: Frantisek Sumsal diff --git a/config/filter.d/haproxy-http-auth.conf b/config/filter.d/haproxy-http-auth.conf new file mode 100644 index 00000000..298ca292 --- /dev/null +++ b/config/filter.d/haproxy-http-auth.conf @@ -0,0 +1,37 @@ +# Fail2Ban filter configuration file to match failed login attempts to +# HAProxy HTTP Authentication protected servers. +# +# PLEASE NOTE - When a user first hits the HTTP Auth a 401 is returned by the server +# which prompts their browser to ask for login details. +# This initial 401 is logged by HAProxy. +# In other words, even successful logins will have at least 1 fail regex match. +# Please keep this in mind when setting findtime and maxretry for jails. +# +# Author: Jordan Moeser +# + +[INCLUDES] + +# Read common prefixes. If any customizations available -- read them from +# common.local +before = common.conf + + +[Definition] + +_daemon = haproxy + +# Option: failregex +# Notes.: regex to match the password failures messages in the logfile. The +# host must be matched by a group named "host". The tag "" can +# be used for standard IP/hostname matching and is only an alias for +# (?:::f{4,6}:)?(?P[\w\-.^_]+) +# Values: TEXT +# +failregex = ^%(__prefix_line)s.* -1/-1/-1/-1/\+*\d* 401 + +# Option: ignoreregex +# Notes.: regex to ignore. If this regex matches, the line is ignored. +# Values: TEXT +# +ignoreregex = diff --git a/config/filter.d/mysqld-auth.conf b/config/filter.d/mysqld-auth.conf index f29beffc..3ad70cb7 100644 --- a/config/filter.d/mysqld-auth.conf +++ b/config/filter.d/mysqld-auth.conf @@ -17,7 +17,7 @@ before = common.conf _daemon = mysqld -failregex = ^%(__prefix_line)s(?:\d+ |\d{6} \s?\d{1,2}:\d{2}:\d{2} )?\[Warning\] Access denied for user '\w+'@'' (to database '[^']*'|\(using password: (YES|NO)\))*\s*$ +failregex = ^%(__prefix_line)s(?:\d+ |\d{6} \s?\d{1,2}:\d{2}:\d{2} )?\[\w+\] Access denied for user '[^']+'@'' (to database '[^']*'|\(using password: (YES|NO)\))*\s*$ ignoreregex = diff --git a/config/filter.d/postfix-rbl.conf b/config/filter.d/postfix-rbl.conf index 05a8bbc7..c3f8c332 100644 --- a/config/filter.d/postfix-rbl.conf +++ b/config/filter.d/postfix-rbl.conf @@ -10,7 +10,7 @@ before = common.conf [Definition] -_daemon = postfix/smtpd +_daemon = postfix(-\w+)?/smtpd failregex = ^%(__prefix_line)sNOQUEUE: reject: RCPT from \S+\[\]: 454 4\.7\.1 Service unavailable; Client host \[\S+\] blocked using .* from=<\S*> to=<\S+> proto=ESMTP helo=<\S*>$ diff --git a/config/filter.d/postfix-sasl.conf b/config/filter.d/postfix-sasl.conf index 199e29bf..7ff995c9 100644 --- a/config/filter.d/postfix-sasl.conf +++ b/config/filter.d/postfix-sasl.conf @@ -7,7 +7,7 @@ before = common.conf [Definition] -_daemon = postfix/(submission/)?smtp(d|s) +_daemon = postfix(-\w+)?/(submission/)?smtp(d|s) failregex = ^%(__prefix_line)swarning: [-._\w]+\[\]: SASL ((?i)LOGIN|PLAIN|(?:CRAM|DIGEST)-MD5) authentication failed(: [ A-Za-z0-9+/:]*={0,2})?\s*$ diff --git a/config/filter.d/postfix.conf b/config/filter.d/postfix.conf index f6a8578b..002b02b2 100644 --- a/config/filter.d/postfix.conf +++ b/config/filter.d/postfix.conf @@ -10,11 +10,12 @@ before = common.conf [Definition] -_daemon = postfix/(submission/)?smtp(d|s) +_daemon = postfix(-\w+)?/(submission/)?smtp(d|s) failregex = ^%(__prefix_line)sNOQUEUE: reject: RCPT from \S+\[\]: 554 5\.7\.1 .*$ ^%(__prefix_line)sNOQUEUE: reject: RCPT from \S+\[\]: 450 4\.7\.1 Client host rejected: cannot find your hostname, (\[\S*\]); from=<\S*> to=<\S+> proto=ESMTP helo=<\S*>$ ^%(__prefix_line)sNOQUEUE: reject: RCPT from \S+\[\]: 450 4\.7\.1 : Helo command rejected: Host not found; from=<> to=<> proto=ESMTP helo= *$ + ^%(__prefix_line)sNOQUEUE: reject: EHLO from \S+\[\]: 504 5\.5\.2 <\S+>: Helo command rejected: need fully-qualified hostname; ^%(__prefix_line)sNOQUEUE: reject: VRFY from \S+\[\]: 550 5\.1\.1 .*$ ^%(__prefix_line)sNOQUEUE: reject: RCPT from \S+\[\]: 450 4\.1\.8 <\S*>: Sender address rejected: Domain not found; from=<\S*> to=<\S+> proto=ESMTP helo=<\S*>$ ^%(__prefix_line)simproper command pipelining after \S+ from [^[]*\[\]:?$ diff --git a/config/filter.d/screensharingd.conf b/config/filter.d/screensharingd.conf new file mode 100644 index 00000000..4cd76465 --- /dev/null +++ b/config/filter.d/screensharingd.conf @@ -0,0 +1,31 @@ +# Fail2Ban configuration file +# +# Author: Simon Brown +# +# Filter for Mac OS X Screen Sharing service + +[INCLUDES] + +# Read common prefixes. If any customizations available -- read them from +# common.local +before = common.conf + + +[Definition] + +_daemon = screensharingd + +# Option: failregex +# Notes.: regex to match the password failures messages in the logfile. The +# host must be matched by a group named "host". The tag "" can +# be used for standard IP/hostname matching and is only an alias for +# (?:::f{4,6}:)?(?P[\w\-.^_]+) +# Values: TEXT +# +failregex = ^%(__prefix_line)sAuthentication: FAILED :: User Name: .+ :: Viewer Address: :: Type: DH$ + +# Option: ignoreregex +# Notes.: regex to ignore. If this regex matches, the line is ignored. +# Values: TEXT +# +ignoreregex = diff --git a/config/jail.conf b/config/jail.conf index 21b97798..b41ce24c 100644 --- a/config/jail.conf +++ b/config/jail.conf @@ -146,6 +146,9 @@ chain = INPUT # Usually should be overridden in a particular jail port = 0:65535 +# Format of user-agent https://tools.ietf.org/html/rfc7231#section-5.5.3 +fail2ban_agent = Fail2Ban/%(fail2ban_version)s + # # Action shortcuts. To be used to define action parameter @@ -161,12 +164,12 @@ action_ = %(banaction)s[name=%(__name__)s, bantime="%(bantime)s", port="%(port)s # ban & send an e-mail with whois report to the destemail. action_mw = %(banaction)s[name=%(__name__)s, bantime="%(bantime)s", port="%(port)s", protocol="%(protocol)s", chain="%(chain)s"] - %(mta)s-whois[name=%(__name__)s, dest="%(destemail)s", protocol="%(protocol)s", chain="%(chain)s"] + %(mta)s-whois[name=%(__name__)s, sender="%(sender)s", dest="%(destemail)s", protocol="%(protocol)s", chain="%(chain)s"] # ban & send an e-mail with whois report and relevant log lines # to the destemail. action_mwl = %(banaction)s[name=%(__name__)s, bantime="%(bantime)s", port="%(port)s", protocol="%(protocol)s", chain="%(chain)s"] - %(mta)s-whois-lines[name=%(__name__)s, dest="%(destemail)s", logpath=%(logpath)s, chain="%(chain)s"] + %(mta)s-whois-lines[name=%(__name__)s, sender="%(sender)s", dest="%(destemail)s", logpath=%(logpath)s, chain="%(chain)s"] # See the IMPORTANT note in action.d/xarf-login-attack for when to use this action # @@ -178,7 +181,7 @@ action_xarf = %(banaction)s[name=%(__name__)s, bantime="%(bantime)s", port="%(po # ban IP on CloudFlare & send an e-mail with whois report and relevant log lines # to the destemail. action_cf_mwl = cloudflare[cfuser="%(cfemail)s", cftoken="%(cfapikey)s"] - %(mta)s-whois-lines[name=%(__name__)s, dest="%(destemail)s", logpath=%(logpath)s, chain="%(chain)s"] + %(mta)s-whois-lines[name=%(__name__)s, sender="%(sender)s", dest="%(destemail)s", logpath=%(logpath)s, chain="%(chain)s"] # Report block via blocklist.de fail2ban reporting service API # @@ -187,7 +190,7 @@ action_cf_mwl = cloudflare[cfuser="%(cfemail)s", cftoken="%(cfapikey)s"] # [Init] # blocklist_de_apikey = {api key from registration] # -action_blocklist_de = blocklist_de[email="%(sender)s", service=%(filter)s, apikey="%(blocklist_de_apikey)s"] +action_blocklist_de = blocklist_de[email="%(sender)s", service=%(filter)s, apikey="%(blocklist_de_apikey)s", agent="%(fail2ban_agent)s"] # Report ban via badips.com, and use as blacklist # @@ -197,7 +200,11 @@ action_blocklist_de = blocklist_de[email="%(sender)s", service=%(filter)s, apik # NOTE: This action relies on banaction being present on start and therefore # should be last action defined for a jail. # -action_badips = badips.py[category="%(name)s", banaction="%(banaction)s"] +action_badips = badips.py[category="%(__name__)s", banaction="%(banaction)s", agent="%(fail2ban_agent)s"] +# +# Report ban via badips.com (uses action.d/badips.conf for reporting only) +# +action_badips_report = badips[category="%(__name__)s", agent="%(fail2ban_agent)s"] # Choose default action. To change, just override value of 'action' with the # interpolation to the chosen action shortcut (e.g. action_mw, action_mwl, etc) in jail.local @@ -240,7 +247,6 @@ backend = %(dropbear_backend)s port = ssh logpath = %(auditd_log)s -maxretry = 5 # @@ -266,7 +272,6 @@ maxretry = 1 port = http,https logpath = %(apache_error_log)s -maxretry = 6 [apache-overflows] @@ -304,18 +309,21 @@ port = http,https logpath = %(apache_error_log)s maxretry = 2 + [apache-shellshock] port = http,https logpath = %(apache_error_log)s maxretry = 1 + [openhab-auth] filter = openhab action = iptables-allports[name=NoAuthFailures] logpath = /opt/openhab/logs/request.log + [nginx-http-auth] port = http,https @@ -335,6 +343,7 @@ port = http,https logpath = %(nginx_error_log)s maxretry = 2 + # Ban attackers that try to use PHP's URL-fopen() functionality # through GET/POST variables. - Experimental, with more than a year # of usage in production environments. @@ -399,7 +408,6 @@ logpath = /var/log/sogo/sogo.log logpath = /var/log/tine20/tine20.log port = http,https -maxretry = 5 # @@ -420,7 +428,6 @@ logpath = /var/log/tomcat*/catalina.out [monit] #Ban clients brute-forcing the monit gui login -filter = monit port = 2812 logpath = /var/log/monit @@ -473,7 +480,6 @@ backend = %(proftpd_backend)s port = ftp,ftp-data,ftps,ftps-data logpath = %(pureftpd_log)s backend = %(pureftpd_backend)s -maxretry = 6 [gssftpd] @@ -481,7 +487,6 @@ maxretry = 6 port = ftp,ftp-data,ftps,ftps-data logpath = %(syslog_daemon)s backend = %(syslog_backend)s -maxretry = 6 [wuftpd] @@ -489,7 +494,6 @@ maxretry = 6 port = ftp,ftp-data,ftps,ftps-data logpath = %(wuftpd_log)s backend = %(wuftpd_backend)s -maxretry = 6 [vsftpd] @@ -724,7 +728,6 @@ maxretry = 10 port = 3306 logpath = %(mysql_log)s backend = %(mysql_backend)s -maxretry = 5 # Jail for more extended banning of persistent abusers @@ -740,7 +743,6 @@ logpath = /var/log/fail2ban.log banaction = %(banaction_allports)s bantime = 1w findtime = 1d -maxretry = 5 # Generic filter for PAM. Has to be used with action which bans all @@ -786,7 +788,6 @@ action = %(banaction)s[name=%(__name__)s-tcp, port="%(tcpport)s", protocol="tcp # nobody except your own Nagios server should ever probe nrpe [nagios] -enabled = false logpath = %(syslog_daemon)s ; nrpe.cfg may define a different log_facility backend = %(syslog_backend)s maxretry = 1 @@ -794,18 +795,14 @@ maxretry = 1 [oracleims] # see "oracleims" filter file for configuration requirement for Oracle IMS v6 and above -enabled = false logpath = /opt/sun/comms/messaging64/log/mail.log_current -maxretry = 6 banaction = %(banaction_allports)s [directadmin] -enabled = false logpath = /var/log/directadmin/login.log port = 2222 [portsentry] -enabled = false logpath = /var/lib/portsentry/portsentry.history maxretry = 1 @@ -826,7 +823,19 @@ findtime = 1 [murmur] # AKA mumble-server port = 64738 -filter = murmur action = %(banaction)s[name=%(__name__)s-tcp, port="%(port)s", protocol=tcp, chain="%(chain)s", actname=%(banaction)s-tcp] %(banaction)s[name=%(__name__)s-udp, port="%(port)s", protocol=udp, chain="%(chain)s", actname=%(banaction)s-udp] logpath = /var/log/mumble-server/mumble-server.log + + +[screensharingd] +# For Mac OS Screen Sharing Service (VNC) +logpath = /var/log/system.log +logencoding = utf-8 + +[haproxy-http-auth] +# HAProxy by default doesn't log to file you'll need to set it up to forward +# logs to a syslog server which would then write them to disk. +# See "haproxy-http-auth" filter for a brief cautionary note when setting +# maxretry and findtime. +logpath = /var/log/haproxy.log diff --git a/fail2ban/client/jailreader.py b/fail2ban/client/jailreader.py index 46f910e3..327ddf1b 100644 --- a/fail2ban/client/jailreader.py +++ b/fail2ban/client/jailreader.py @@ -32,6 +32,7 @@ import re from .configreader import ConfigReaderUnshared, ConfigReader from .filterreader import FilterReader from .actionreader import ActionReader +from ..version import version from ..helpers import getLogger from ..helpers import splitcommaspace @@ -108,6 +109,10 @@ class JailReader(ConfigReader): ["string", "filter", ""], ["string", "action", ""]] + # Before interpolation (substitution) add static options always available as default: + defsec = self._cfg.get_defaults() + defsec["fail2ban_version"] = version + # Read first options only needed for merge defaults ('known/...' from filter): self.__opts = ConfigReader.getOptions(self, self.__name, opts1st) if not self.__opts: diff --git a/fail2ban/server/datetemplate.py b/fail2ban/server/datetemplate.py index 746380ed..6a4db8ea 100644 --- a/fail2ban/server/datetemplate.py +++ b/fail2ban/server/datetemplate.py @@ -134,7 +134,7 @@ class DateEpoch(DateTemplate): def __init__(self): DateTemplate.__init__(self) - self.regex = "(?:^|(?P(?<=^\[))|(?P(?<=audit\()))\d{10}(?:\.\d{3,6})?(?(selinux)(?=:\d+\))(?(square)(?=\])))" + self.regex = r"(?:^|(?P(?<=^\[))|(?P(?<=audit\()))\d{10,11}\b(?:\.\d{3,6})?(?:(?(selinux)(?=:\d+\)))|(?(square)(?=\])))" def getDate(self, line, dateMatch=None): """Method to return the date for a log line. diff --git a/fail2ban/server/filter.py b/fail2ban/server/filter.py index b7de21c8..b0ccda84 100644 --- a/fail2ban/server/filter.py +++ b/fail2ban/server/filter.py @@ -696,7 +696,7 @@ class FileFilter(Filter): logSys.error("Error opening %s" % filename) logSys.exception(e) return False - except OSError, e: # pragma: no cover - Requires implemention error in FileContainer to generate + except Exception, e: # pragma: no cover - Requires implemention error in FileContainer to generate logSys.error("Internal error in FileContainer open method - please report as a bug to https://github.com/fail2ban/fail2ban/issues") logSys.exception(e) return False diff --git a/fail2ban/tests/clientreadertestcase.py b/fail2ban/tests/clientreadertestcase.py index 78c9a582..bd734c1b 100644 --- a/fail2ban/tests/clientreadertestcase.py +++ b/fail2ban/tests/clientreadertestcase.py @@ -28,13 +28,15 @@ import re import shutil import tempfile import unittest -from ..client.configreader import ConfigReaderUnshared +from ..client.configreader import ConfigReader, ConfigReaderUnshared from ..client import configparserinc from ..client.jailreader import JailReader from ..client.filterreader import FilterReader from ..client.jailsreader import JailsReader from ..client.actionreader import ActionReader from ..client.configurator import Configurator +from ..server.mytime import MyTime +from ..version import version from .utils import LogCaptureTestCase TEST_FILES_DIR = os.path.join(os.path.dirname(__file__), "files") @@ -253,6 +255,34 @@ class JailReaderTest(LogCaptureTestCase): result = JailReader.extractOptions(option) self.assertEqual(expected, result) + def testVersionAgent(self): + jail = JailReader('blocklisttest', force_enable=True, basedir=CONFIG_DIR) + # emulate jail.read(), because such jail not exists: + ConfigReader.read(jail, "jail"); + sections = jail._cfg.get_sections() + sections['blocklisttest'] = dict((('__name__', 'blocklisttest'), + ('filter', ''), ('failregex', '^test $'), + ('sender', 'f2b-test@example.com'), ('blocklist_de_apikey', 'test-key'), + ('action', + '%(action_blocklist_de)s\n' + '%(action_badips_report)s\n' + '%(action_badips)s\n' + 'mynetwatchman[port=1234,protocol=udp,agent="%(fail2ban_agent)s"]' + ), + )) + # get options: + self.assertTrue(jail.getOptions()) + # convert and get stream + stream = jail.convert() + # get action and retrieve agent from it, compare with agent saved in version: + act = [o for o in stream if len(o) > 4 and (o[4] == 'agent' or o[4].endswith('badips.py'))] + useragent = 'Fail2Ban/%s' % version + self.assertEqual(len(act), 4) + self.assertEqual(act[0], ['set', 'blocklisttest', 'action', 'blocklist_de', 'agent', useragent]) + self.assertEqual(act[1], ['set', 'blocklisttest', 'action', 'badips', 'agent', useragent]) + self.assertEqual(eval(act[2][5]).get('agent', ''), useragent) + self.assertEqual(act[3], ['set', 'blocklisttest', 'action', 'mynetwatchman', 'agent', useragent]) + def testGlob(self): d = tempfile.mkdtemp(prefix="f2b-temp") # Generate few files @@ -596,6 +626,12 @@ class JailsReaderTest(LogCaptureTestCase): # by default we have lots of jails ;) self.assertTrue(len(comm_commands)) + # some common sanity checks for commands + for command in comm_commands: + if len(command) >= 3 and [command[0], command[2]] == ['set', 'bantime']: + self.assertTrue(MyTime.str2seconds(command[3]) > 0) + + # and we know even some of them by heart for j in ['sshd', 'recidive']: # by default we have 'auto' backend ATM diff --git a/fail2ban/tests/datedetectortestcase.py b/fail2ban/tests/datedetectortestcase.py index dc01fd49..0c3c306d 100644 --- a/fail2ban/tests/datedetectortestcase.py +++ b/fail2ban/tests/datedetectortestcase.py @@ -55,13 +55,23 @@ class DateDetectorTest(LogCaptureTestCase): tearDownMyTime() def testGetEpochTime(self): - log = "1138049999 [sshd] error: PAM: Authentication failure" - #date = [2006, 1, 23, 21, 59, 59, 0, 23, 0] - dateUnix = 1138049999.0 - - ( datelog, matchlog ) = self.__datedetector.getTime(log) - self.assertEqual(datelog, dateUnix) - self.assertEqual(matchlog.group(), '1138049999') + # correct epoch time, using all variants: + for dateUnix in (1138049999, 32535244799): + for date in ("%s", "[%s]", "[%s.555]", "audit(%s.555:101)"): + date = date % dateUnix + log = date + " [sshd] error: PAM: Authentication failure" + datelog = self.__datedetector.getTime(log) + self.assertTrue(datelog, "Parse epoch time for %s failed" % (date,)) + ( datelog, matchlog ) = datelog + self.assertEqual(int(datelog), dateUnix) + self.assertIn(matchlog.group(), (str(dateUnix), str(dateUnix)+'.555')) + # wrong, no epoch time (< 10 digits, more as 11 digits, begin/end of word) : + for dateUnix in ('123456789', '9999999999999999', '1138049999A', 'A1138049999'): + for date in ("%s", "[%s]", "[%s.555]", "audit(%s.555:101)"): + date = date % dateUnix + log = date + " [sshd] error: PAM: Authentication failure" + datelog = self.__datedetector.getTime(log) + self.assertFalse(datelog) def testGetTime(self): log = "Jan 23 21:59:59 [sshd] error: PAM: Authentication failure" diff --git a/fail2ban/tests/files/logs/asterisk b/fail2ban/tests/files/logs/asterisk index ab018ba9..aa32a290 100644 --- a/fail2ban/tests/files/logs/asterisk +++ b/fail2ban/tests/files/logs/asterisk @@ -59,3 +59,11 @@ Nov 4 18:30:40 localhost asterisk[32229]: NOTICE[32257]: chan_sip.c:23417 in han # match UTF-8 in SessionID # failJSON: { "time": "2015-05-25T07:52:36", "match": true, "host": "10.250.251.252" } [2015-05-25 07:52:36] SECURITY[6988] res_security_log.c: SecurityEvent="InvalidAccountID",EventTV="2015-05-25T07:52:36.888+0300",Severity="Error",Service="PJSIP",EventVersion="1",AccountID="70000180",SessionID="Негодяй",LocalAddress="IPV4/UDP/1.2.3.4/5060",RemoteAddress="IPV4/UDP/10.250.251.252/5061" + +# match phone numbers with + symbol (and without number, or other context) +# failJSON: { "time": "2016-01-28T10:22:27", "match": true , "host": "1.2.3.4" } +[2016-01-28 10:22:27] NOTICE[3477][C-000003bb] chan_sip.c: Call from '' (1.2.3.4:10836) to extension '++441772285411' rejected because extension not found in context 'default'. +# failJSON: { "time": "2016-01-28T10:34:31", "match": true , "host": "1.2.3.4" } +[2016-01-28 10:34:31] NOTICE[3477][C-000003c3] chan_sip.c: Call from '' (1.2.3.4:10836) to extension '0+441772285407' rejected because extension not found in context 'default'. +# failJSON: { "time": "2016-01-28T10:34:33", "match": true , "host": "1.2.3.4" } +[2016-01-28 10:34:33] NOTICE[3477][C-000003c3] chan_sip.c: Call from '' (1.2.3.4:10836) to extension '' rejected because extension not found in context 'my-context'. diff --git a/fail2ban/tests/files/logs/haproxy-http-auth b/fail2ban/tests/files/logs/haproxy-http-auth new file mode 100644 index 00000000..298f1972 --- /dev/null +++ b/fail2ban/tests/files/logs/haproxy-http-auth @@ -0,0 +1,4 @@ +# failJSON: { "match": false } +Nov 14 22:45:27 test haproxy[760]: 192.168.33.1:58444 [14/Nov/2015:22:45:25.439] main app/app1 1939/0/1/0/1940 403 5168 - - ---- 3/3/0/0/0 0/0 "GET / HTTP/1.1" +# failJSON: { "time": "2004-11-14T22:45:11", "match": true , "host": "192.168.33.1" } +Nov 14 22:45:11 test haproxy[760]: 192.168.33.1:58430 [14/Nov/2015:22:45:11.608] main main/ -1/-1/-1/-1/0 401 248 - - PR-- 0/0/0/0/0 0/0 "GET / HTTP/1.1" diff --git a/fail2ban/tests/files/logs/mysqld-auth b/fail2ban/tests/files/logs/mysqld-auth index b75ecfc4..c77d214d 100644 --- a/fail2ban/tests/files/logs/mysqld-auth +++ b/fail2ban/tests/files/logs/mysqld-auth @@ -16,4 +16,9 @@ Sep 16 21:30:26 catinthehat mysqld: 130916 21:30:26 [Warning] Access denied for Sep 16 21:30:32 catinthehat mysqld: 130916 21:30:32 [Warning] Access denied for user 'hacker'@'74.207.241.159' (using password: NO) # failJSON: { "time": "2015-10-07T06:09:42", "match": true , "host": "127.0.0.1", "desc": "mysql 5.6 log format" } -2015-10-07 06:09:42 5907 [Warning] Access denied for user 'root'@'127.0.0.1' (using password: YES) \ No newline at end of file +2015-10-07 06:09:42 5907 [Warning] Access denied for user 'root'@'127.0.0.1' (using password: YES) +# failJSON: { "time": "2016-02-24T15:26:18", "match": true , "host": "localhost", "desc": "mysql 5.6 log format, Note instead of Warning" } +2016-02-24T15:26:18.237955 6 [Note] Access denied for user 'root'@'localhost' (using password: YES) + +# failJSON: { "time": "2016-02-24T15:26:18", "match": false , "host": "localhost", "desc": "A hypothetical example of injection having full log line first (for paranoid yoh)" } +2016-02-24T15:26:18.237955 6 [Note] Access denied for user 'root'@'localhost' (using password: YES) condition lead to a hypothetical failure diff --git a/fail2ban/tests/files/logs/postfix b/fail2ban/tests/files/logs/postfix index 4934a29e..3ec2886a 100644 --- a/fail2ban/tests/files/logs/postfix +++ b/fail2ban/tests/files/logs/postfix @@ -26,3 +26,9 @@ Dec 21 21:17:29 xxx postfix/smtpd[7150]: NOQUEUE: reject: RCPT from badserver.ex # failJSON: { "time": "2004-11-22T22:33:44", "match": true , "host": "1.2.3.4" } Nov 22 22:33:44 xxx postfix/smtpd[11111]: NOQUEUE: reject: RCPT from 1-2-3-4.example.com[1.2.3.4]: 450 4.1.8 : Sender address rejected: Domain not found; from= to= proto=ESMTP helo=<1-2-3-4.example.com> + +# failJSON: { "time": "2005-01-31T13:55:24", "match": true , "host": "78.107.251.238" } +Jan 31 13:55:24 xxx postfix/smtpd[3462]: NOQUEUE: reject: EHLO from s271272.static.corbina.ru[78.107.251.238]: 504 5.5.2 : Helo command rejected: need fully-qualified hostname; proto=SMTP helo= + +# failJSON: { "time": "2005-01-31T13:55:24", "match": true , "host": "78.107.251.238" } +Jan 31 13:55:24 xxx postfix-incoming/smtpd[3462]: NOQUEUE: reject: EHLO from s271272.static.corbina.ru[78.107.251.238]: 504 5.5.2 : Helo command rejected: need fully-qualified hostname; proto=SMTP helo= diff --git a/fail2ban/tests/files/logs/postfix-rbl b/fail2ban/tests/files/logs/postfix-rbl index fd420fa7..eff01bf9 100644 --- a/fail2ban/tests/files/logs/postfix-rbl +++ b/fail2ban/tests/files/logs/postfix-rbl @@ -1,2 +1,5 @@ # failJSON: { "time": "2004-12-30T18:19:15", "match": true , "host": "93.184.216.34" } Dec 30 18:19:15 xxx postfix/smtpd[1574]: NOQUEUE: reject: RCPT from badguy.example.com[93.184.216.34]: 454 4.7.1 Service unavailable; Client host [93.184.216.34] blocked using rbl.example.com; http://www.example.com/query?ip=93.184.216.34; from= to= proto=ESMTP helo= + +# failJSON: { "time": "2004-12-30T18:19:15", "match": true , "host": "93.184.216.34" } +Dec 30 18:19:15 xxx postfix-incoming/smtpd[1574]: NOQUEUE: reject: RCPT from badguy.example.com[93.184.216.34]: 454 4.7.1 Service unavailable; Client host [93.184.216.34] blocked using rbl.example.com; http://www.example.com/query?ip=93.184.216.34; from= to= proto=ESMTP helo= diff --git a/fail2ban/tests/files/logs/postfix-sasl b/fail2ban/tests/files/logs/postfix-sasl index beb8b11d..586f9584 100644 --- a/fail2ban/tests/files/logs/postfix-sasl +++ b/fail2ban/tests/files/logs/postfix-sasl @@ -21,3 +21,5 @@ Jan 29 08:11:45 mail postfix/smtpd[10752]: warning: unknown[1.1.1.1]: SASL LOGIN # failJSON: { "time": "2005-02-03T08:29:28", "match": false , "host": "1.1.1.1" } Feb 3 08:29:28 mail postfix/smtpd[21022]: warning: unknown[1.1.1.1]: SASL LOGIN authentication failed: Connection lost to authentication server +# failJSON: { "time": "2005-01-29T08:11:45", "match": true , "host": "1.1.1.1" } +Jan 29 08:11:45 mail postfix-incoming/smtpd[10752]: warning: unknown[1.1.1.1]: SASL LOGIN authentication failed: Password: diff --git a/fail2ban/tests/files/logs/screensharingd b/fail2ban/tests/files/logs/screensharingd new file mode 100644 index 00000000..0ec0ebd6 --- /dev/null +++ b/fail2ban/tests/files/logs/screensharingd @@ -0,0 +1,12 @@ +# NOTE: dates here include years -- this is not the typical configuration for the system.log +# file on Mac OS. However, without it the test routines will use 2004 as the year and matches will not pass. +# +# failJSON: { "match": false } +Oct 27 2015 09:24:46 test1.beezwax.net screensharingd[1170]: Authentication: SUCCEEDED :: User Name: simon :: Viewer Address: 192.168.5.247 :: Type: DH +# +# failJSON: { "time": "2015-10-27T12:35:40", "match": true , "host": "192.168.5.247" } +Oct 27 2015 12:35:40 test1.beezwax.net screensharingd[1170]: Authentication: FAILED :: User Name: sdfsdfs () mro :: Viewer Address: 192.168.5.247 :: Type: DH +# failJSON: { "time": "2015-10-27T12:35:50", "match": true , "host": "192.168.5.247" } +Oct 27 2015 12:35:50 test1.beezwax.net screensharingd[1170]: Authentication: FAILED :: User Name: brown_s :: :: Viewer Address: 192.168.5.247 :: Type: DH +# failJSON: { "time": "2015-10-27T12:26:01", "match": true , "host": "192.168.5.247" } +Oct 27 2015 12:26:01 test1.beezwax.net screensharingd[1170]: Authentication: FAILED :: User Name: brown @! s:: :: Viewer Address: 192.168.5.247 :: Type: DH diff --git a/fail2ban/tests/utils.py b/fail2ban/tests/utils.py index ce6d638a..7ce51138 100644 --- a/fail2ban/tests/utils.py +++ b/fail2ban/tests/utils.py @@ -279,6 +279,18 @@ def gatherTests(regexps=None, opts=None): return tests +# forwards compatibility of unittest.TestCase for some early python versions +if not hasattr(unittest.TestCase, 'assertIn'): + def __assertIn(self, a, b, msg=None): + if a not in b: # pragma: no cover + self.fail(msg or "%r was not found in %r" % (a, b)) + unittest.TestCase.assertIn = __assertIn + def __assertNotIn(self, a, b, msg=None): + if a in b: # pragma: no cover + self.fail(msg or "%r was found in %r" % (a, b)) + unittest.TestCase.assertNotIn = __assertNotIn + + class LogCaptureTestCase(unittest.TestCase): def setUp(self): diff --git a/files/fail2ban-logrotate b/files/fail2ban-logrotate index 8d94a8b3..13a94537 100644 --- a/files/fail2ban-logrotate +++ b/files/fail2ban-logrotate @@ -6,11 +6,9 @@ # https://github.com/fail2ban/fail2ban/blob/debian/debian/fail2ban.logrotate /var/log/fail2ban.log { - rotate 7 missingok notifempty - compress postrotate - /usr/bin/fail2ban-client flushlogs 1>/dev/null || true + /usr/bin/fail2ban-client flushlogs >/dev/null || true endscript } diff --git a/files/gentoo-initd b/files/gentoo-initd index 98c5edf9..b7e1067b 100755 --- a/files/gentoo-initd +++ b/files/gentoo-initd @@ -34,19 +34,21 @@ start() { # remove stalled sock file after system crash # bug 347477 rm -f /var/run/fail2ban/fail2ban.sock || return 1 - ${FAIL2BAN} start &> /dev/null + start-stop-daemon --start --exec ${FAIL2BAN} start \ + --pidfile /var/run/fail2ban/fail2ban.pid eend $? "Failed to start fail2ban" } stop() { ebegin "Stopping fail2ban" - ${FAIL2BAN} stop &> /dev/null + start-stop-daemon --stop --exec ${FAIL2BAN} stop \ + --pidfile /var/run/fail2ban/fail2ban.pid eend $? "Failed to stop fail2ban" } reload() { ebegin "Reloading fail2ban" - ${FAIL2BAN} reload > /dev/null + ${FAIL2BAN} reload eend $? "Failed to reload fail2ban" }