Merge remote-tracking branch 'remotes/gh-upstream/master' into f2b-perfom-prepare-716

pull/1346/head
sebres 2016-03-07 19:11:36 +01:00
commit d7e7b52013
38 changed files with 488 additions and 56 deletions

49
.github/ISSUE_TEMPLATE.md vendored Normal file
View File

@ -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:
```
```

9
.github/PULL_REQUEST_TEMPLATE.md vendored Normal file
View File

@ -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

View File

@ -23,7 +23,7 @@ install:
# coverage # coverage
- travis_retry pip install coverage - travis_retry pip install coverage
# coveralls # coveralls
- travis_retry pip install coveralls - travis_retry pip install coveralls codecov
# dnspython or dnspython3 # dnspython or dnspython3
- if [[ "$F2B_PY_2" ]]; then travis_retry pip install dnspython; fi - if [[ "$F2B_PY_2" ]]; then travis_retry pip install dnspython; fi
- if [[ "$F2B_PY_3" ]]; then travis_retry pip install dnspython3; fi - if [[ "$F2B_PY_3" ]]; then travis_retry pip install dnspython3; fi
@ -43,6 +43,7 @@ script:
- sudo $VENV_BIN/pip install . - sudo $VENV_BIN/pip install .
after_success: after_success:
- coveralls - coveralls
- codecov
matrix: matrix:
fast_finish: true fast_finish: true
# Might be worth looking into # Might be worth looking into

View File

@ -15,7 +15,7 @@ ver. 0.9.4 (2015/XX/XXX) - wanna-be-released
* filter.d/apache-badbots.conf * filter.d/apache-badbots.conf
- Updated useragent string regex adding escape for `+` - Updated useragent string regex adding escape for `+`
* filter.d/mysqld-auth.conf * 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 * filter.d/sshd.conf
- Updated "Auth fail" regex for OpenSSH 5.9 and later - Updated "Auth fail" regex for OpenSSH 5.9 and later
* Treat failed and killed execution of commands identically (only * 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) for python version < 3.x (gh-1248)
* Use postfix_log logpath for postfix-rbl jail * Use postfix_log logpath for postfix-rbl jail
* filters.d/postfix.conf - add 'Sender address rejected: Domain not found' failregex * 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 Features:
* New interpolation feature for definition config readers - `<known/parameter>` * New interpolation feature for definition config readers - `<known/parameter>`
@ -37,6 +42,9 @@ ver. 0.9.4 (2015/XX/XXX) - wanna-be-released
filter.d/*.local file. filter.d/*.local file.
As extension to interpolation `%(known/parameter)s`, that does not works for As extension to interpolation `%(known/parameter)s`, that does not works for
filter and action init parameters 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: * New filters:
- openhab - domotic software authentication failure with the - openhab - domotic software authentication failure with the
rest api and web interface (gh-1223) 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) request processing rate (ngx_http_limit_req_module)
- murmur - ban hosts that repeatedly attempt to connect to - murmur - ban hosts that repeatedly attempt to connect to
murmur/mumble-server with an invalid server password or certificate. 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: * New jails:
- murmur - bans TCP and UDP from the bad host on the default murmur port. - murmur - bans TCP and UDP from the bad host on the default murmur port.
* sshd filter got new failregex to match "maximum authentication * sshd filter got new failregex to match "maximum authentication
attempts exceeded" (introduced in openssh 6.8) attempts exceeded" (introduced in openssh 6.8)
* Added filter for Mac OS screen sharing (VNC) daemon
- Enhancements: - Enhancements:
* Do not rotate empty log files * 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). * Performance improvements while monitoring large number of files (gh-1265).
Use associative array (dict) for monitored log files to speed up lookup Use associative array (dict) for monitored log files to speed up lookup
operations. Thanks @kshetragia 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 ver. 0.9.3 (2015/08/01) - lets-all-stay-friends
---------- ----------

View File

@ -77,6 +77,8 @@ Code status:
* [![Coverage Status](https://coveralls.io/repos/fail2ban/fail2ban/badge.png?branch=master)](https://coveralls.io/r/fail2ban/fail2ban) * [![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: Contact:
-------- --------

View File

@ -116,7 +116,7 @@ Pre Release
* http://packages.qa.debian.org/f/fail2ban.html * http://packages.qa.debian.org/f/fail2ban.html
* FreeBSD: Christoph Theis theis@gmx.at>, Nick Hilliard <nick@foobar.org> * FreeBSD: Christoph Theis theis@gmx.at>
* http://svnweb.freebsd.org/ports/head/security/py-fail2ban/Makefile?view=markup * http://svnweb.freebsd.org/ports/head/security/py-fail2ban/Makefile?view=markup
* http://www.freebsd.org/cgi/query-pr-summary.cgi?text=fail2ban * http://www.freebsd.org/cgi/query-pr-summary.cgi?text=fail2ban

1
THANKS
View File

@ -115,6 +115,7 @@ Steven Hiscocks
TESTOVIK TESTOVIK
Thomas Mayer Thomas Mayer
Tom Pike Tom Pike
Tom Hendrikx
Tomas Pihl Tomas Pihl
Tony Lawrence Tony Lawrence
Tomasz Ciolek Tomasz Ciolek

View File

@ -10,7 +10,7 @@
[Definition] [Definition]
actionban = curl --fail --user-agent "fail2ban v0.8.12" http://www.badips.com/add/<category>/<ip> actionban = curl --fail --user-agent "<agent>" http://www.badips.com/add/<category>/<ip>
[Init] [Init]

View File

@ -21,7 +21,6 @@ import sys
if sys.version_info < (2, 7): if sys.version_info < (2, 7):
raise ImportError("badips.py action requires Python >= 2.7") raise ImportError("badips.py action requires Python >= 2.7")
import json import json
from functools import partial
import threading import threading
import logging import logging
if sys.version_info >= (3, ): if sys.version_info >= (3, ):
@ -33,7 +32,6 @@ else:
from urllib import urlencode from urllib import urlencode
from fail2ban.server.actions import ActionBase from fail2ban.server.actions import ActionBase
from fail2ban.version import version as f2bVersion
class BadIPsAction(ActionBase): class BadIPsAction(ActionBase):
@ -72,6 +70,9 @@ class BadIPsAction(ActionBase):
updateperiod : int, optional updateperiod : int, optional
Time in seconds between updating bad IPs blacklist. Time in seconds between updating bad IPs blacklist.
Default 900 (15 minutes) Default 900 (15 minutes)
agent : str, optional
User agent transmitted to server.
Default `Fail2Ban/ver.`
Raises Raises
------ ------
@ -80,13 +81,14 @@ class BadIPsAction(ActionBase):
""" """
_badips = "http://www.badips.com" _badips = "http://www.badips.com"
_Request = partial( def _Request(self, url, **argv):
Request, headers={'User-Agent': "Fail2Ban %s" % f2bVersion}) return Request(url, headers={'User-Agent': self.agent}, **argv)
def __init__(self, jail, name, category, score=3, age="24h", key=None, 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) super(BadIPsAction, self).__init__(jail, name)
self.agent = agent
self.category = category self.category = category
self.score = score self.score = score
self.age = age self.age = age

View File

@ -54,7 +54,7 @@ actioncheck =
# Tags: See jail.conf(5) man page # Tags: See jail.conf(5) man page
# Values: CMD # Values: CMD
# #
actionban = curl --fail --data-urlencode 'server=<email>' --data 'apikey=<apikey>' --data 'service=<service>' --data 'ip=<ip>' --data-urlencode 'logs=<matches>' --data 'format=text' --user-agent "fail2ban v0.8.12" "https://www.blocklist.de/en/httpreports.html" actionban = curl --fail --data-urlencode 'server=<email>' --data 'apikey=<apikey>' --data 'service=<service>' --data 'ip=<ip>' --data-urlencode 'logs=<matches>' --data 'format=text' --user-agent "<agent>" "https://www.blocklist.de/en/httpreports.html"
# Option: actionunban # Option: actionunban
# Notes.: command executed when unbanning an IP. Take care that the # Notes.: command executed when unbanning an IP. Take care that the

View File

@ -111,13 +111,17 @@ myip = `ip -4 addr show dev eth0 | grep inet | head -n 1 | sed -r 's/.*inet ([0-
# #
protocol = tcp protocol = tcp
# Option: agent
# Default: Fail2ban
agent = Fail2ban
# Option: getcmd # Option: getcmd
# Notes.: A command to fetch a URL. Should output page to STDOUT # Notes.: A command to fetch a URL. Should output page to STDOUT
# Values: CMD Default: wget # 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=<agent>
# Alternative value: # 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 <agent>
# Option: srcport # Option: srcport
# Notes.: The source port of the attack. You're unlikely to have this info, so # Notes.: The source port of the attack. You're unlikely to have this info, so

View File

@ -0,0 +1,22 @@
# Fail2Ban configuration file
#
# Author: Cyril Jaquier
# Modified: Yaroslav O. Halchenko <debian@onerussian.com>
# made active on all ports from original iptables.conf
# Modified: Alexander Belykh <albel727@ngs.ru>
# 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 <protocol>
[Init]

View File

@ -0,0 +1,119 @@
# Fail2Ban configuration file
#
# Author: Daniel Black
# Author: Cyril Jaquier
# Modified: Yaroslav O. Halchenko <debian@onerussian.com>
# made active on all ports from original iptables.conf
# Modified: Alexander Belykh <albel727@ngs.ru>
# 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 = <protocol> dport \{ <port> \}
# Option: actionstart
# Notes.: command executed once at the start of Fail2Ban.
# Values: CMD
#
actionstart = <nftables> add set <nftables_family> <nftables_table> f2b-<name> \{ type <nftables_type>\; \}
<nftables> insert rule <nftables_family> <nftables_table> <chain> %(nftables_mode)s ip saddr @f2b-<name> <blocktype>
_nft_list = <nftables> --handle --numeric list chain <nftables_family> <nftables_table> <chain>
_nft_get_handle_id = grep -m1 'ip saddr @f2b-<name> <blocktype> # 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)
<nftables> delete rule <nftables_family> <nftables_table> <chain> $HANDLE_ID
<nftables> delete set <nftables_family> <nftables_table> f2b-<name>
# Option: actioncheck
# Notes.: command executed once before each actionban command
# Values: CMD
#
actioncheck = <nftables> list chain <nftables_family> <nftables_table> <chain> | grep -q '@f2b-<name>[ \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 = <nftables> add element <nftables_family> <nftables_table> f2b-<name> \{ <ip> \}
# 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 = <nftables> delete element <nftables_family> <nftables_table> f2b-<name> \{ <ip> \}
[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

View File

@ -0,0 +1,22 @@
# Fail2Ban configuration file
#
# Author: Cyril Jaquier
# Modified: Yaroslav O. Halchenko <debian@onerussian.com>
# made active on all ports from original iptables.conf
# Modified: Alexander Belykh <albel727@ngs.ru>
# adapted for nftables
#
[INCLUDES]
before = nftables-common.conf
[Definition]
# Option: nftables_mode
# Notes.: additional expressions for nftables filter rule
# Values: nftables expressions
#
nftables_mode = <protocol> dport \{ <port> \}
[Init]

View File

@ -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+:)? 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 '<HOST>(:\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)$ failregex = ^(%(__prefix_line)s|\[\]\s*)%(log_prefix)s Registration from '[^']*' failed for '<HOST>(:\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 '[^']*' \(<HOST>:\d+\) to extension '\d+' rejected because extension not found in context 'default'\.$ ^(%(__prefix_line)s|\[\]\s*)%(log_prefix)s Call from '[^']*' \(<HOST>:\d+\) to extension '[^']*' rejected because extension not found in context
^(%(__prefix_line)s|\[\]\s*)%(log_prefix)s Host <HOST> failed to authenticate as '[^']*'$ ^(%(__prefix_line)s|\[\]\s*)%(log_prefix)s Host <HOST> failed to authenticate as '[^']*'$
^(%(__prefix_line)s|\[\]\s*)%(log_prefix)s No registration for peer '[^']*' \(from <HOST>\)$ ^(%(__prefix_line)s|\[\]\s*)%(log_prefix)s No registration for peer '[^']*' \(from <HOST>\)$
^(%(__prefix_line)s|\[\]\s*)%(log_prefix)s Host <HOST> failed MD5 authentication for '[^']*' \([^)]+\)$ ^(%(__prefix_line)s|\[\]\s*)%(log_prefix)s Host <HOST> failed MD5 authentication for '[^']*' \([^)]+\)$

View File

@ -11,7 +11,7 @@ webmail = roundcube|(ext)?mail|horde|(v-?)?webmail
phpmyadmin = (typo3/|xampp/|admin/|)(pma|(php)?[Mm]y[Aa]dmin) phpmyadmin = (typo3/|xampp/|admin/|)(pma|(php)?[Mm]y[Aa]dmin)
wordpress = wp-(login|signup)\.php wordpress = wp-(login|signup|admin)\.php
# DEV Notes: # DEV Notes:
# Taken from apache-botsearch filter # Taken from apache-botsearch filter

View File

@ -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 "<HOST>" can
# be used for standard IP/hostname matching and is only an alias for
# (?:::f{4,6}:)?(?P<host>[\w\-.^_]+)
# Values: TEXT
#
failregex = ^%(__prefix_line)s<HOST>.*<NOSRV> -1/-1/-1/-1/\+*\d* 401
# Option: ignoreregex
# Notes.: regex to ignore. If this regex matches, the line is ignored.
# Values: TEXT
#
ignoreregex =

View File

@ -17,7 +17,7 @@ before = common.conf
_daemon = mysqld _daemon = mysqld
failregex = ^%(__prefix_line)s(?:\d+ |\d{6} \s?\d{1,2}:\d{2}:\d{2} )?\[Warning\] Access denied for user '\w+'@'<HOST>' (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 '[^']+'@'<HOST>' (to database '[^']*'|\(using password: (YES|NO)\))*\s*$
ignoreregex = ignoreregex =

View File

@ -10,7 +10,7 @@ before = common.conf
[Definition] [Definition]
_daemon = postfix/smtpd _daemon = postfix(-\w+)?/smtpd
failregex = ^%(__prefix_line)sNOQUEUE: reject: RCPT from \S+\[<HOST>\]: 454 4\.7\.1 Service unavailable; Client host \[\S+\] blocked using .* from=<\S*> to=<\S+> proto=ESMTP helo=<\S*>$ failregex = ^%(__prefix_line)sNOQUEUE: reject: RCPT from \S+\[<HOST>\]: 454 4\.7\.1 Service unavailable; Client host \[\S+\] blocked using .* from=<\S*> to=<\S+> proto=ESMTP helo=<\S*>$

View File

@ -7,7 +7,7 @@ before = common.conf
[Definition] [Definition]
_daemon = postfix/(submission/)?smtp(d|s) _daemon = postfix(-\w+)?/(submission/)?smtp(d|s)
failregex = ^%(__prefix_line)swarning: [-._\w]+\[<HOST>\]: SASL ((?i)LOGIN|PLAIN|(?:CRAM|DIGEST)-MD5) authentication failed(: [ A-Za-z0-9+/:]*={0,2})?\s*$ failregex = ^%(__prefix_line)swarning: [-._\w]+\[<HOST>\]: SASL ((?i)LOGIN|PLAIN|(?:CRAM|DIGEST)-MD5) authentication failed(: [ A-Za-z0-9+/:]*={0,2})?\s*$

View File

@ -10,11 +10,12 @@ before = common.conf
[Definition] [Definition]
_daemon = postfix/(submission/)?smtp(d|s) _daemon = postfix(-\w+)?/(submission/)?smtp(d|s)
failregex = ^%(__prefix_line)sNOQUEUE: reject: RCPT from \S+\[<HOST>\]: 554 5\.7\.1 .*$ failregex = ^%(__prefix_line)sNOQUEUE: reject: RCPT from \S+\[<HOST>\]: 554 5\.7\.1 .*$
^%(__prefix_line)sNOQUEUE: reject: RCPT from \S+\[<HOST>\]: 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+\[<HOST>\]: 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+\[<HOST>\]: 450 4\.7\.1 : Helo command rejected: Host not found; from=<> to=<> proto=ESMTP helo= *$ ^%(__prefix_line)sNOQUEUE: reject: RCPT from \S+\[<HOST>\]: 450 4\.7\.1 : Helo command rejected: Host not found; from=<> to=<> proto=ESMTP helo= *$
^%(__prefix_line)sNOQUEUE: reject: EHLO from \S+\[<HOST>\]: 504 5\.5\.2 <\S+>: Helo command rejected: need fully-qualified hostname;
^%(__prefix_line)sNOQUEUE: reject: VRFY from \S+\[<HOST>\]: 550 5\.1\.1 .*$ ^%(__prefix_line)sNOQUEUE: reject: VRFY from \S+\[<HOST>\]: 550 5\.1\.1 .*$
^%(__prefix_line)sNOQUEUE: reject: RCPT from \S+\[<HOST>\]: 450 4\.1\.8 <\S*>: Sender address rejected: Domain not found; from=<\S*> to=<\S+> proto=ESMTP helo=<\S*>$ ^%(__prefix_line)sNOQUEUE: reject: RCPT from \S+\[<HOST>\]: 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 [^[]*\[<HOST>\]:?$ ^%(__prefix_line)simproper command pipelining after \S+ from [^[]*\[<HOST>\]:?$

View File

@ -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 "<HOST>" can
# be used for standard IP/hostname matching and is only an alias for
# (?:::f{4,6}:)?(?P<host>[\w\-.^_]+)
# Values: TEXT
#
failregex = ^%(__prefix_line)sAuthentication: FAILED :: User Name: .+ :: Viewer Address: <HOST> :: Type: DH$
# Option: ignoreregex
# Notes.: regex to ignore. If this regex matches, the line is ignored.
# Values: TEXT
#
ignoreregex =

View File

@ -146,6 +146,9 @@ chain = INPUT
# Usually should be overridden in a particular jail # Usually should be overridden in a particular jail
port = 0:65535 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 # 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. # 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"] 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 # ban & send an e-mail with whois report and relevant log lines
# to the destemail. # to the destemail.
action_mwl = %(banaction)s[name=%(__name__)s, bantime="%(bantime)s", port="%(port)s", protocol="%(protocol)s", chain="%(chain)s"] 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 # 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 # ban IP on CloudFlare & send an e-mail with whois report and relevant log lines
# to the destemail. # to the destemail.
action_cf_mwl = cloudflare[cfuser="%(cfemail)s", cftoken="%(cfapikey)s"] 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 # Report block via blocklist.de fail2ban reporting service API
# #
@ -187,7 +190,7 @@ action_cf_mwl = cloudflare[cfuser="%(cfemail)s", cftoken="%(cfapikey)s"]
# [Init] # [Init]
# blocklist_de_apikey = {api key from registration] # 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 # 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 # NOTE: This action relies on banaction being present on start and therefore
# should be last action defined for a jail. # 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 # 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 # 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 port = ssh
logpath = %(auditd_log)s logpath = %(auditd_log)s
maxretry = 5
# #
@ -266,7 +272,6 @@ maxretry = 1
port = http,https port = http,https
logpath = %(apache_error_log)s logpath = %(apache_error_log)s
maxretry = 6
[apache-overflows] [apache-overflows]
@ -304,18 +309,21 @@ port = http,https
logpath = %(apache_error_log)s logpath = %(apache_error_log)s
maxretry = 2 maxretry = 2
[apache-shellshock] [apache-shellshock]
port = http,https port = http,https
logpath = %(apache_error_log)s logpath = %(apache_error_log)s
maxretry = 1 maxretry = 1
[openhab-auth] [openhab-auth]
filter = openhab filter = openhab
action = iptables-allports[name=NoAuthFailures] action = iptables-allports[name=NoAuthFailures]
logpath = /opt/openhab/logs/request.log logpath = /opt/openhab/logs/request.log
[nginx-http-auth] [nginx-http-auth]
port = http,https port = http,https
@ -335,6 +343,7 @@ port = http,https
logpath = %(nginx_error_log)s logpath = %(nginx_error_log)s
maxretry = 2 maxretry = 2
# Ban attackers that try to use PHP's URL-fopen() functionality # Ban attackers that try to use PHP's URL-fopen() functionality
# through GET/POST variables. - Experimental, with more than a year # through GET/POST variables. - Experimental, with more than a year
# of usage in production environments. # of usage in production environments.
@ -399,7 +408,6 @@ logpath = /var/log/sogo/sogo.log
logpath = /var/log/tine20/tine20.log logpath = /var/log/tine20/tine20.log
port = http,https port = http,https
maxretry = 5
# #
@ -420,7 +428,6 @@ logpath = /var/log/tomcat*/catalina.out
[monit] [monit]
#Ban clients brute-forcing the monit gui login #Ban clients brute-forcing the monit gui login
filter = monit
port = 2812 port = 2812
logpath = /var/log/monit logpath = /var/log/monit
@ -473,7 +480,6 @@ backend = %(proftpd_backend)s
port = ftp,ftp-data,ftps,ftps-data port = ftp,ftp-data,ftps,ftps-data
logpath = %(pureftpd_log)s logpath = %(pureftpd_log)s
backend = %(pureftpd_backend)s backend = %(pureftpd_backend)s
maxretry = 6
[gssftpd] [gssftpd]
@ -481,7 +487,6 @@ maxretry = 6
port = ftp,ftp-data,ftps,ftps-data port = ftp,ftp-data,ftps,ftps-data
logpath = %(syslog_daemon)s logpath = %(syslog_daemon)s
backend = %(syslog_backend)s backend = %(syslog_backend)s
maxretry = 6
[wuftpd] [wuftpd]
@ -489,7 +494,6 @@ maxretry = 6
port = ftp,ftp-data,ftps,ftps-data port = ftp,ftp-data,ftps,ftps-data
logpath = %(wuftpd_log)s logpath = %(wuftpd_log)s
backend = %(wuftpd_backend)s backend = %(wuftpd_backend)s
maxretry = 6
[vsftpd] [vsftpd]
@ -724,7 +728,6 @@ maxretry = 10
port = 3306 port = 3306
logpath = %(mysql_log)s logpath = %(mysql_log)s
backend = %(mysql_backend)s backend = %(mysql_backend)s
maxretry = 5
# Jail for more extended banning of persistent abusers # Jail for more extended banning of persistent abusers
@ -740,7 +743,6 @@ logpath = /var/log/fail2ban.log
banaction = %(banaction_allports)s banaction = %(banaction_allports)s
bantime = 1w bantime = 1w
findtime = 1d findtime = 1d
maxretry = 5
# Generic filter for PAM. Has to be used with action which bans all # 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 # nobody except your own Nagios server should ever probe nrpe
[nagios] [nagios]
enabled = false
logpath = %(syslog_daemon)s ; nrpe.cfg may define a different log_facility logpath = %(syslog_daemon)s ; nrpe.cfg may define a different log_facility
backend = %(syslog_backend)s backend = %(syslog_backend)s
maxretry = 1 maxretry = 1
@ -794,18 +795,14 @@ maxretry = 1
[oracleims] [oracleims]
# see "oracleims" filter file for configuration requirement for Oracle IMS v6 and above # see "oracleims" filter file for configuration requirement for Oracle IMS v6 and above
enabled = false
logpath = /opt/sun/comms/messaging64/log/mail.log_current logpath = /opt/sun/comms/messaging64/log/mail.log_current
maxretry = 6
banaction = %(banaction_allports)s banaction = %(banaction_allports)s
[directadmin] [directadmin]
enabled = false
logpath = /var/log/directadmin/login.log logpath = /var/log/directadmin/login.log
port = 2222 port = 2222
[portsentry] [portsentry]
enabled = false
logpath = /var/lib/portsentry/portsentry.history logpath = /var/lib/portsentry/portsentry.history
maxretry = 1 maxretry = 1
@ -826,7 +823,19 @@ findtime = 1
[murmur] [murmur]
# AKA mumble-server # AKA mumble-server
port = 64738 port = 64738
filter = murmur
action = %(banaction)s[name=%(__name__)s-tcp, port="%(port)s", protocol=tcp, chain="%(chain)s", actname=%(banaction)s-tcp] 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] %(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 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

View File

@ -32,6 +32,7 @@ import re
from .configreader import ConfigReaderUnshared, ConfigReader from .configreader import ConfigReaderUnshared, ConfigReader
from .filterreader import FilterReader from .filterreader import FilterReader
from .actionreader import ActionReader from .actionreader import ActionReader
from ..version import version
from ..helpers import getLogger from ..helpers import getLogger
from ..helpers import splitcommaspace from ..helpers import splitcommaspace
@ -108,6 +109,10 @@ class JailReader(ConfigReader):
["string", "filter", ""], ["string", "filter", ""],
["string", "action", ""]] ["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): # Read first options only needed for merge defaults ('known/...' from filter):
self.__opts = ConfigReader.getOptions(self, self.__name, opts1st) self.__opts = ConfigReader.getOptions(self, self.__name, opts1st)
if not self.__opts: if not self.__opts:

View File

@ -134,7 +134,7 @@ class DateEpoch(DateTemplate):
def __init__(self): def __init__(self):
DateTemplate.__init__(self) DateTemplate.__init__(self)
self.regex = "(?:^|(?P<square>(?<=^\[))|(?P<selinux>(?<=audit\()))\d{10}(?:\.\d{3,6})?(?(selinux)(?=:\d+\))(?(square)(?=\])))" self.regex = r"(?:^|(?P<square>(?<=^\[))|(?P<selinux>(?<=audit\()))\d{10,11}\b(?:\.\d{3,6})?(?:(?(selinux)(?=:\d+\)))|(?(square)(?=\])))"
def getDate(self, line, dateMatch=None): def getDate(self, line, dateMatch=None):
"""Method to return the date for a log line. """Method to return the date for a log line.

View File

@ -696,7 +696,7 @@ class FileFilter(Filter):
logSys.error("Error opening %s" % filename) logSys.error("Error opening %s" % filename)
logSys.exception(e) logSys.exception(e)
return False 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.error("Internal error in FileContainer open method - please report as a bug to https://github.com/fail2ban/fail2ban/issues")
logSys.exception(e) logSys.exception(e)
return False return False

View File

@ -28,13 +28,15 @@ import re
import shutil import shutil
import tempfile import tempfile
import unittest import unittest
from ..client.configreader import ConfigReaderUnshared from ..client.configreader import ConfigReader, ConfigReaderUnshared
from ..client import configparserinc from ..client import configparserinc
from ..client.jailreader import JailReader from ..client.jailreader import JailReader
from ..client.filterreader import FilterReader from ..client.filterreader import FilterReader
from ..client.jailsreader import JailsReader from ..client.jailsreader import JailsReader
from ..client.actionreader import ActionReader from ..client.actionreader import ActionReader
from ..client.configurator import Configurator from ..client.configurator import Configurator
from ..server.mytime import MyTime
from ..version import version
from .utils import LogCaptureTestCase from .utils import LogCaptureTestCase
TEST_FILES_DIR = os.path.join(os.path.dirname(__file__), "files") TEST_FILES_DIR = os.path.join(os.path.dirname(__file__), "files")
@ -253,6 +255,34 @@ class JailReaderTest(LogCaptureTestCase):
result = JailReader.extractOptions(option) result = JailReader.extractOptions(option)
self.assertEqual(expected, result) 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 <HOST>$'),
('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', '<wrong>'), useragent)
self.assertEqual(act[3], ['set', 'blocklisttest', 'action', 'mynetwatchman', 'agent', useragent])
def testGlob(self): def testGlob(self):
d = tempfile.mkdtemp(prefix="f2b-temp") d = tempfile.mkdtemp(prefix="f2b-temp")
# Generate few files # Generate few files
@ -596,6 +626,12 @@ class JailsReaderTest(LogCaptureTestCase):
# by default we have lots of jails ;) # by default we have lots of jails ;)
self.assertTrue(len(comm_commands)) 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 # and we know even some of them by heart
for j in ['sshd', 'recidive']: for j in ['sshd', 'recidive']:
# by default we have 'auto' backend ATM # by default we have 'auto' backend ATM

View File

@ -55,13 +55,23 @@ class DateDetectorTest(LogCaptureTestCase):
tearDownMyTime() tearDownMyTime()
def testGetEpochTime(self): def testGetEpochTime(self):
log = "1138049999 [sshd] error: PAM: Authentication failure" # correct epoch time, using all variants:
#date = [2006, 1, 23, 21, 59, 59, 0, 23, 0] for dateUnix in (1138049999, 32535244799):
dateUnix = 1138049999.0 for date in ("%s", "[%s]", "[%s.555]", "audit(%s.555:101)"):
date = date % dateUnix
( datelog, matchlog ) = self.__datedetector.getTime(log) log = date + " [sshd] error: PAM: Authentication failure"
self.assertEqual(datelog, dateUnix) datelog = self.__datedetector.getTime(log)
self.assertEqual(matchlog.group(), '1138049999') 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): def testGetTime(self):
log = "Jan 23 21:59:59 [sshd] error: PAM: Authentication failure" log = "Jan 23 21:59:59 [sshd] error: PAM: Authentication failure"

View File

@ -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 # match UTF-8 in SessionID
# failJSON: { "time": "2015-05-25T07:52:36", "match": true, "host": "10.250.251.252" } # 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" [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'.

View File

@ -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/<NOSRV> -1/-1/-1/-1/0 401 248 - - PR-- 0/0/0/0/0 0/0 "GET / HTTP/1.1"

View File

@ -17,3 +17,8 @@ Sep 16 21:30:32 catinthehat mysqld: 130916 21:30:32 [Warning] Access denied for
# failJSON: { "time": "2015-10-07T06:09:42", "match": true , "host": "127.0.0.1", "desc": "mysql 5.6 log format" } # 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) 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

View File

@ -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" } # 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 <some@nonexistant.tld>: Sender address rejected: Domain not found; from=<some@nonexistant.tld> to=<goodguy@example.com> proto=ESMTP helo=<1-2-3-4.example.com> 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 <some@nonexistant.tld>: Sender address rejected: Domain not found; from=<some@nonexistant.tld> to=<goodguy@example.com> 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 <User>: Helo command rejected: need fully-qualified hostname; proto=SMTP helo=<User>
# 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 <User>: Helo command rejected: need fully-qualified hostname; proto=SMTP helo=<User>

View File

@ -1,2 +1,5 @@
# failJSON: { "time": "2004-12-30T18:19:15", "match": true , "host": "93.184.216.34" } # 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=<spammer@example.com> to=<goodguy@example.com> proto=ESMTP helo=<badguy.example.com> 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=<spammer@example.com> to=<goodguy@example.com> proto=ESMTP helo=<badguy.example.com>
# 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=<spammer@example.com> to=<goodguy@example.com> proto=ESMTP helo=<badguy.example.com>

View File

@ -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" } # 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 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:

View File

@ -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

View File

@ -279,6 +279,18 @@ def gatherTests(regexps=None, opts=None):
return tests 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): class LogCaptureTestCase(unittest.TestCase):
def setUp(self): def setUp(self):

View File

@ -6,11 +6,9 @@
# https://github.com/fail2ban/fail2ban/blob/debian/debian/fail2ban.logrotate # https://github.com/fail2ban/fail2ban/blob/debian/debian/fail2ban.logrotate
/var/log/fail2ban.log { /var/log/fail2ban.log {
rotate 7
missingok missingok
notifempty notifempty
compress
postrotate postrotate
/usr/bin/fail2ban-client flushlogs 1>/dev/null || true /usr/bin/fail2ban-client flushlogs >/dev/null || true
endscript endscript
} }

View File

@ -34,19 +34,21 @@ start() {
# remove stalled sock file after system crash # remove stalled sock file after system crash
# bug 347477 # bug 347477
rm -f /var/run/fail2ban/fail2ban.sock || return 1 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" eend $? "Failed to start fail2ban"
} }
stop() { stop() {
ebegin "Stopping fail2ban" 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" eend $? "Failed to stop fail2ban"
} }
reload() { reload() {
ebegin "Reloading fail2ban" ebegin "Reloading fail2ban"
${FAIL2BAN} reload > /dev/null ${FAIL2BAN} reload
eend $? "Failed to reload fail2ban" eend $? "Failed to reload fail2ban"
} }