Merge branch 'master' into debian

debian
sebres 2024-08-11 11:56:56 +02:00
commit 9061536fb0
40 changed files with 212 additions and 120 deletions

View File

@ -9,4 +9,4 @@ check-hidden = true
ignore-regex = (\b([A-Z][A-Z][A-Z]+|gir\.st)\b)|\[[a-zA-Z]+\][a-z]+\b|[a-z]+://\S+|.*codespell-ignore.*
# some oddly named variables, some names, etc
# wee -- comes in regex etc for weeks
ignore-words-list = theis,timere,alls,wee,wight,ans,re-use
ignore-words-list = assertIn,theis,timere,alls,wee,wight,ans,re-use

3
.github/FUNDING.yml vendored
View File

@ -1,4 +1,5 @@
# These are supported funding model platforms
github: [sebres]
custom: [paypal.me/sebres]
custom: [https://paypal.me/sebres]
liberapay: sebres

View File

@ -22,7 +22,7 @@ jobs:
runs-on: ubuntu-20.04
strategy:
matrix:
python-version: [3.7, 3.8, 3.9, '3.10', '3.11', '3.12', '3.13.0-alpha.2', pypy3.10]
python-version: [3.7, 3.8, 3.9, '3.10', '3.11', '3.12', '3.13.0-beta.3', pypy3.10]
fail-fast: false
# Steps represent a sequence of tasks that will be executed as part of the job
steps:
@ -79,7 +79,7 @@ jobs:
cd "$GITHUB_WORKSPACE"
_debug() { echo -n "$1 "; err=$("${@:2}" 2>&1) && echo 'OK' || echo -e "FAIL\n$err"; }
# (debug) output current preferred encoding:
_debug 'Encodings:' python -c 'import locale, sys; from fail2ban.helpers import PREFER_ENC; print(PREFER_ENC, locale.getpreferredencoding(), (sys.stdout and sys.stdout.encoding))'
echo 'Encodings:' $(python -c 'import locale, sys; from fail2ban.helpers import PREFER_ENC; print(PREFER_ENC, locale.getpreferredencoding(), (sys.stdout and sys.stdout.encoding))')
# (debug) backend availabilities:
echo 'Backends:'
_debug '- systemd:' python -c 'from fail2ban.server.filtersystemd import FilterSystemd'

View File

@ -7,6 +7,33 @@
Fail2Ban: Changelog
===================
ver. 1.1.1-dev-1 (20??/??/??) - development nightly edition
-----------
### Fixes
* `jail.conf`:
- default banactions need to be specified in `paths-*.conf` (maintainer level) now
- since stock fail2ban includes `paths-debian.conf` by default, banactions are `nftables`
(can be overwritten in `jail.local` by user)
* `paths-debian.conf`:
- default banactions are `nftables`
- sshd backend switched to `systemd` (gh-3292)
* `action.d/firewallcmd-ipset.conf`:
- rename `ipsettype` to `ipsetbackend` (gh-2620), parameter `ipsettype` will be used now to the real set type (gh-3760)
* `filter.d/apache-overflows.conf` - consider AH10244: invalid URI path (gh-3778)
* `filter.d/postfix.conf` - consider CONNECT and other rejected commands as a valid `_pref` (gh-3800)
* `filter.d/recidive.conf` - restore possibility to set jail name in the filter, _jailname is positive now (gh-3769)
* `filter.d/roundcube-auth.conf` - improved RE better matching log format of roundcube version 1.4+ (gh-3816)
* `filter.d/sshd.conf` - adapted to conform possible new daemon name sshd-session, since OpenSSH 9.8
several log messages will be tagged with as originating from a process named "sshd-session" rather than "sshd" (gh-3782)
### New Features and Enhancements
* `action.d/*-ipset.conf`:
- parameter `ipsettype` to set type of ipset, e. g. hash:ip, hash:net, etc (gh-3760)
* `action.d/firewallcmd-rich-*.conf` - fixed incorrect quoting, disabling port variable expansion
by substitution of rich rule (gh-3815)
* `filter.d/proxmox.conf` - add support to Proxmox Web GUI (gh-2966)
ver. 1.1.0 (2024/04/25) - object-found--norad-59479-cospar-2024-069a--altitude-36267km
-----------

View File

@ -29,13 +29,13 @@ and the website: https://www.fail2ban.org
Installation:
-------------
Fail2Ban is likely already packaged for your Linux distribution and [can installed with a simple command](https://github.com/fail2ban/fail2ban/wiki/How-to-install-fail2ban-packages).
Fail2Ban is likely already packaged for your Linux distribution and [can be installed with a simple command](https://github.com/fail2ban/fail2ban/wiki/How-to-install-fail2ban-packages).
If your distribution is not listed, you can install from GitHub:
Required:
- [Python >= 3.5](https://www.python.org) or [PyPy3](https://pypy.org)
- python-setuptools, python-distutils (or python3-setuptools) for installation from source
- python-setuptools (or python3-setuptools) for installation from source
Optional:
- [pyinotify >= 0.8.3](https://github.com/seb-m/pyinotify), may require:
@ -52,7 +52,7 @@ To install:
cd fail2ban-master
sudo python setup.py install
Alternatively, you can clone the source from GitHub to a directory of Your choice, and do the install from there. Pick the correct branch, for example, master or 0.11
Alternatively, you can clone the source from GitHub to a directory of your choice, and do the install from there. Pick the correct branch, for example, master or 0.11
git clone https://github.com/fail2ban/fail2ban.git
cd fail2ban

View File

@ -80,7 +80,7 @@ actioncheck =
# use my (Shaun's) helper PHP script by commenting out the first #actionban
# line below, uncommenting the second one, and pointing the URL at
# wherever you install the helper script. For the PHP helper script, see
# <https://wiki.shaunc.com/wikka.php?wakka=ReportingToAbuseIPDBWithFail2Ban>
# <https://github.com/parseword/fail2ban-abuseipdb/>
#
# Tags: See jail.conf(5) man page
# Values: CMD

View File

@ -30,6 +30,9 @@
[Definition]
# bypass reporting of restored (already reported) tickets:
norestored = 1
# Option: actionstart
# Notes.: command executed on demand at the first ban (or at the start of Fail2Ban if actionstart_on_demand is set to false).
# Values: CMD

View File

@ -18,24 +18,24 @@ before = firewallcmd-common.conf
[Definition]
actionstart = <ipstype_<ipsettype>/actionstart>
actionstart = <ipsbackend_<ipsetbackend>/actionstart>
firewall-cmd --direct --add-rule <family> filter <chain> 0 <actiontype> -m set --match-set <ipmset> src -j <blocktype>
actionflush = <ipstype_<ipsettype>/actionflush>
actionflush = <ipsbackend_<ipsetbackend>/actionflush>
actionstop = firewall-cmd --direct --remove-rule <family> filter <chain> 0 <actiontype> -m set --match-set <ipmset> src -j <blocktype>
<actionflush>
<ipstype_<ipsettype>/actionstop>
<ipsbackend_<ipsetbackend>/actionstop>
actionban = <ipstype_<ipsettype>/actionban>
actionban = <ipsbackend_<ipsetbackend>/actionban>
# actionprolong = %(actionban)s
actionunban = <ipstype_<ipsettype>/actionunban>
actionunban = <ipsbackend_<ipsetbackend>/actionunban>
[ipstype_ipset]
[ipsbackend_ipset]
actionstart = ipset -exist create <ipmset> hash:ip timeout <default-ipsettime> maxelem <maxelem> <familyopt>
actionstart = ipset -exist create <ipmset> <ipsettype> timeout <default-ipsettime> maxelem <maxelem> <familyopt>
actionflush = ipset flush <ipmset>
@ -45,9 +45,9 @@ actionban = ipset -exist add <ipmset> <ip> timeout <ipsettime>
actionunban = ipset -exist del <ipmset> <ip>
[ipstype_firewalld]
[ipsbackend_firewalld]
actionstart = firewall-cmd --direct --new-ipset=<ipmset> --type=hash:ip --option=timeout=<default-ipsettime> --option=maxelem=<maxelem> <firewalld_familyopt>
actionstart = firewall-cmd --direct --new-ipset=<ipmset> --type=<ipsettype> --option=timeout=<default-ipsettime> --option=maxelem=<maxelem> <firewalld_familyopt>
# TODO: there doesn't seem to be an explicit way to invoke the ipset flush function using firewall-cmd
actionflush =
@ -60,6 +60,11 @@ actionunban = firewall-cmd --ipset=<ipmset> --remove-entry=<ip>
[Init]
# Option: ipsettype
# Notes: specifies type of set, see `man --pager='less -p "^SET TYPES"' ipset` for details
# Values: hash:ip, hash:net, etc... Default: hash:ip
ipsettype = hash:ip
# Option: chain
# Notes specifies the iptables chain to which the fail2ban rules should be
# added
@ -87,11 +92,11 @@ maxelem = 65536
# banaction = %(known/banaction)s[ipsettime='<timeout-bantime>']
timeout-bantime = $([ "<bantime>" -le 2147483 ] && echo "<bantime>" || echo 0)
# Option: ipsettype
# Notes.: defines type of ipset used for match-set (firewalld or ipset)
# Option: ipsetbackend
# Notes.: defines the backend of ipset used for match-set (firewalld or ipset)
# Values: firewalld or ipset
# Default: ipset
ipsettype = ipset
ipsetbackend = ipset
# Option: actiontype
# Notes.: defines additions to the blocking rule

View File

@ -35,7 +35,7 @@ actioncheck =
#
# Because rich rules can only handle single or a range of ports we must split ports and execute the command for each port. Ports can be single and ranges separated by a comma or space for an example: http, https, 22-60, 18 smtp
fwcmd_rich_rule = rule family='<family>' source address='<ip>' port port='$p' protocol='<protocol>' %(rich-suffix)s
fwcmd_rich_rule = rule family=\"<family>\" source address=\"<ip>\" port port=\"$p\" protocol=\"<protocol>\" %(rich-suffix)s
actionban = ports="<port>"; for p in $(echo $ports | tr ", " " "); do firewall-cmd --add-rich-rule="%(fwcmd_rich_rule)s"; done

View File

@ -24,7 +24,7 @@ before = iptables.conf
# Notes.: command executed on demand at the first ban (or at the start of Fail2Ban if actionstart_on_demand is set to false).
# Values: CMD
#
actionstart = ipset -exist create <ipmset> hash:ip timeout <default-ipsettime> maxelem <maxelem> <familyopt>
actionstart = ipset -exist create <ipmset> <ipsettype> timeout <default-ipsettime> maxelem <maxelem> <familyopt>
<_ipt_add_rules>
# Option: actionflush
@ -66,6 +66,11 @@ rule-jump = -m set --match-set <ipmset> src -j <blocktype>
[Init]
# Option: ipsettype
# Notes: specifies type of set, see `man --pager='less -p "^SET TYPES"' ipset` for details
# Values: hash:ip, hash:net, etc... Default: hash:ip
ipsettype = hash:ip
# Option: default-ipsettime
# Notes: specifies default timeout in seconds (handled default ipset timeout only)
# Values: [ NUM ] Default: 0 (no timeout, managed by fail2ban by unban)

View File

@ -51,7 +51,7 @@
# Values: CMD
#
actionstart = if ! ipset -quiet -name list f2b-<name> >/dev/null;
then ipset -quiet -exist create f2b-<name> hash:ip timeout <default-ipsettime> maxelem <maxelem>;
then ipset -quiet -exist create f2b-<name> <ipsettype> timeout <default-ipsettime> maxelem <maxelem>;
fi
# Option: actionstop
@ -94,6 +94,11 @@ timeout-bantime = $([ "<bantime>" -le 2147483 ] && echo "<bantime>" || echo 0)
[Init]
# Option: ipsettype
# Notes: specifies type of set, see `man --pager='less -p "^SET TYPES"' ipset` for details
# Values: hash:ip, hash:net, etc... Default: hash:ip
ipsettype = hash:ip
# Option: maxelem
# Notes: maximal number of elements which can be stored in the ipset
# You may want to increase this for long-duration/high-volume jails

View File

@ -8,7 +8,7 @@ before = apache-common.conf
[Definition]
failregex = ^%(_apache_error_client)s (?:(?:AH001[23][456]: )?Invalid (method|URI) in request\b|(?:AH00565: )?request failed: URI too long \(longer than \d+\)|request failed: erroneous characters after protocol string:|(?:AH00566: )?request failed: invalid characters in URI\b)
failregex = ^%(_apache_error_client)s (?:(?:AH(?:001[23][456]|10244): )?[Ii]nvalid (method|URI)\b|(?:AH00565: )?request failed: URI too long \(longer than \d+\)|request failed: erroneous characters after protocol string:|(?:AH00566: )?request failed: invalid characters in URI\b)
ignoreregex =

View File

@ -12,7 +12,7 @@ before = common.conf
_daemon = postfix(-\w+)?/[^/\[:\s]+(?:/smtp[ds])?
_port = (?::\d+)?
_pref = [A-Z]{4}
_pref = [A-Z]{4,}
prefregex = ^%(__prefix_line)s<mdpr-<mode>> <F-CONTENT>.+</F-CONTENT>$

View File

@ -0,0 +1,20 @@
# Fail2Ban filter for Proxmox Web GUI
#
# Jail example:
# [proxmox]
# enabled = true
# port = https,http,8006
# filter = proxmox
# logpath = /var/log/daemon.log
# maxretry = 3
# # 1 hour
# bantime = 3600
[Definition]
_daemon = pvedaemon
failregex = ^\s*\S+ %(_daemon)s\[\d+\]: authentication failure; rhost=<ADDR> user=<F-USER>\S+</F-USER>
ignoreregex =

View File

@ -24,14 +24,15 @@ before = common.conf
_daemon = (?:fail2ban(?:-server|\.actions)\s*)
# The name of the jail that this filter is used for. In jail.conf, name the jail using
# this filter 'recidive', or supply another name with `filter = recidive[_jailname="jail"]`
_jailname = recidive
# this filter 'recidive', or supply another name with `filter = recidive[_jailname="jail"]`,
# default all jails excepting recidive
_jailname = (?!recidive\])[^\]]*
failregex = ^%(__prefix_line)s(?:\s*fail2ban\.actions\s*%(__pid_re)s?:\s+)?NOTICE\s+\[(?!%(_jailname)s\])(?:.*)\]\s+Ban\s+<HOST>\s*$
failregex = ^%(__prefix_line)s(?:\s*fail2ban\.actions\s*%(__pid_re)s?:\s+)?NOTICE\s+\[<_jailname>\]\s+Ban\s+<HOST>
[lt_short]
_daemon = (?:fail2ban(?:-server|\.actions)?\s*)
failregex = ^%(__prefix_line)s(?:\s*fail2ban(?:\.actions)?\s*%(__pid_re)s?:\s+)?(?:NOTICE\s+)?\[(?!%(_jailname)s\])(?:.*)\]\s+Ban\s+<HOST>\s*$
failregex = ^%(__prefix_line)s(?:\s*fail2ban(?:\.actions)?\s*%(__pid_re)s?:\s+)?(?:NOTICE\s+)?\[<_jailname>\]\s+Ban\s+<HOST>
[lt_journal]
_daemon = <lt_short/_daemon>

View File

@ -13,10 +13,9 @@ before = common.conf
[Definition]
prefregex = ^\s*(\[\])?(%(__hostname)s\s*(?:roundcube(?:\[(\d*)\])?:)?\s*(<[\w]+>)? IMAP Error)?: <F-CONTENT>.+</F-CONTENT>$
prefregex = ^\s*(\[\])?(%(__hostname)s\s*(?:roundcube(?:\[(\d*)\])?:)?\s*(<[\w]+>)? IMAP Error)?: (?:<[\w]+> )?<F-CONTENT>.+</F-CONTENT>$
failregex = ^(?:FAILED login|Login failed) for <F-USER>.*</F-USER> from <HOST>(?:(?:\([^\)]*\))?\. (?:(?! from ).)*(?: user=(?P=user))? in \S+\.php on line \d+ \(\S+ \S+\))?$
^(?:<[\w]+> )?Failed login for <F-USER>.*</F-USER> from <HOST> in session \w+( \(error: \d\))?$
failregex = ^(?:Login failed|(?i:Failed) login) for <F-USER>(?:(?P<simple>\S+)|.*)</F-USER> (?:against \S+ )?from <ADDR>(?:(?:\([^\)]*\))?\.(?! from ) (?(simple)(?:\S+(?! from ) )*|(?:(?! from ).)*(?: user=(?P=user))? )in \S+\.php on line \d+| in session \w+)?(?: \([^\)]*\))?$
ignoreregex = Could not connect to .* Connection refused

View File

@ -16,7 +16,7 @@ before = common.conf
[DEFAULT]
_daemon = sshd
_daemon = sshd(?:-session)?
# optional prefix (logged from several ssh versions) like "error: ", "error: PAM: " or "fatal: "
__pref = (?:(?:error|fatal): (?:PAM: )?)?

View File

@ -990,3 +990,6 @@ logpath = /var/log/monitorix-httpd
port = 1080
logpath = %(syslog_daemon)s
[proxmox]
port = https,http,8006
logpath = /var/log/daemon.log

View File

@ -47,12 +47,9 @@ copyright = u'2014'
#
from fail2ban.version import version as fail2ban_version
from distutils.version import LooseVersion
fail2ban_loose_version = LooseVersion(fail2ban_version)
# The short X.Y version.
version = ".".join(str(_) for _ in fail2ban_loose_version.version[:2])
version = ".".join(str(_) for _ in fail2ban_version.split(".")[:2])
# The full version, including alpha/beta/rc tags.
release = fail2ban_version

View File

@ -21,8 +21,10 @@ __author__ = "Cyril Jaquier, Yaroslav Halchenko"
__copyright__ = "Copyright (c) 2004 Cyril Jaquier, 2013- Yaroslav Halchenko"
__license__ = "GPL"
import sys
from ..exceptions import UnknownJailException, DuplicateJailException
from ..helpers import getLogger, logging
from ..helpers import getLogger, logging, PREFER_ENC
# Gets the instance of the logger.
logSys = getLogger(__name__)
@ -36,6 +38,11 @@ logSys = getLogger(__name__)
class Beautifier:
stdoutEnc = PREFER_ENC
if sys.stdout and sys.stdout.encoding is not None:
stdoutEnc = sys.stdout.encoding
encUtf = 1 if stdoutEnc.lower() == 'utf-8' else 0
def __init__(self, cmd = None):
self.__inputCmd = cmd
@ -104,7 +111,11 @@ class Beautifier:
jail_stat(j, " " if i == len(jstat) else " | ")
msg = "\n".join(msg)
elif inC[0:1] == ['stats'] or inC[0:1] == ['statistics']:
def _statstable(response):
chrTable = [
['|', '-', '|', 'x', 'x', '-', '|', '-'], ## ascii
["\u2551", "\u2550", "\u255F", "\u256B", "\u256C", "\u2569", "\u2502", "\u2500"] ## utf-8
];
def _statstable(response, ct):
tophead = ["Jail", "Backend", "Filter", "Actions"]
headers = ["", "", "cur", "tot", "cur", "tot"]
minlens = [8, 8, 3, 3, 3, 3]
@ -120,29 +131,31 @@ class Beautifier:
f = "%%%ds" if ralign[i] else "%%-%ds"
rfmt.append(f % lens[i])
hfmt.append(f % lens[i])
rfmt = [rfmt[0], rfmt[1], "%s \u2502 %s" % (rfmt[2], rfmt[3]), "%s \u2502 %s" % (rfmt[4], rfmt[5])]
hfmt = [hfmt[0], hfmt[1], "%s \u2502 %s" % (hfmt[2], hfmt[3]), "%s \u2502 %s" % (hfmt[4], hfmt[5])]
rfmt = [rfmt[0], rfmt[1], "%s %s %s" % (rfmt[2], ct[6], rfmt[3]), "%s %s %s" % (rfmt[4], ct[6], rfmt[5])]
hfmt = [hfmt[0], hfmt[1], "%s %s %s" % (hfmt[2], ct[6], hfmt[3]), "%s %s %s" % (hfmt[4], ct[6], hfmt[5])]
tlens = [lens[0], lens[1], 3 + lens[2] + lens[3], 3 + lens[4] + lens[5]]
tfmt = [hfmt[0], hfmt[1], "%%-%ds" % (tlens[2],), "%%-%ds" % (tlens[3],)]
tsep = tfmt[0:2]
rfmt = " \u2551 ".join(rfmt)
hfmt = " \u2551 ".join(hfmt)
tfmt = " \u2551 ".join(tfmt)
tsep = " \u2551 ".join(tsep)
separator = ((tsep % tuple(tophead[0:2])) + " \u255F\u2500" +
("\u2500\u256B\u2500".join(['\u2500' * n for n in tlens[2:]])) + '\u2500')
rfmt = (" "+ct[0]+" ").join(rfmt)
hfmt = (" "+ct[0]+" ").join(hfmt)
tfmt = (" "+ct[0]+" ").join(tfmt)
tsep = (" "+ct[0]+" ").join(tsep)
separator = ((tsep % tuple(tophead[0:2])) + " "+ct[2]+ct[7] +
((ct[7]+ct[3]+ct[7]).join([ct[7] * n for n in tlens[2:]])) + ct[7])
ret = []
ret.append(tfmt % tuple(["", ""]+tophead[2:]))
ret.append(separator)
ret.append(hfmt % tuple(headers))
separator = "\u2550\u256C\u2550".join(['\u2550' * n for n in tlens]) + '\u2550'
ret.append(separator)
ret.append(" "+tfmt % tuple(["", ""]+tophead[2:]))
ret.append(" "+separator)
ret.append(" "+hfmt % tuple(headers))
separator = (ct[1]+ct[4]+ct[1]).join([ct[1] * n for n in tlens]) + ct[1]
ret.append(ct[1]+separator)
for row in rows:
ret.append(rfmt % tuple(row))
separator = "\u2550\u2569\u2550".join(['\u2550' * n for n in tlens]) + '\u2550'
ret.append(separator)
ret.append(" "+rfmt % tuple(row))
separator = (ct[1]+ct[5]+ct[1]).join([ct[1] * n for n in tlens]) + ct[1]
ret.append(ct[1]+separator)
return ret
msg = "\n".join(_statstable(response))
if not response:
return "No jails found."
msg = "\n".join(_statstable(response, chrTable[self.encUtf]))
elif len(inC) < 2:
pass # to few cmd args for below
elif inC[1] == "syslogsocket":

View File

@ -40,6 +40,14 @@ except:
_libcap = None
# some modules (like pyinotify, see #3487) may have dependency to asyncore, so ensure we've a path
# to compat folder, otherwise python 3.12+ could miss them:
def __extend_compat_path():
cp = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'compat')
if cp not in sys.path:
sys.path.append(cp)
__extend_compat_path()
PREFER_ENC = locale.getpreferredencoding()
# correct preferred encoding if lang not set in environment:
if PREFER_ENC.startswith('ANSI_'): # pragma: no cover

View File

@ -25,14 +25,6 @@ __copyright__ = "Copyright (c) 2004 Cyril Jaquier"
__license__ = "GPL"
from pickle import dumps, loads, HIGHEST_PROTOCOL
try:
import asynchat
except ImportError:
from ..compat import asynchat
try:
import asyncore
except ImportError:
from ..compat import asyncore
import errno
import fcntl
import os
@ -45,6 +37,13 @@ from .utils import Utils
from ..protocol import CSPROTO
from ..helpers import logging, getLogger, formatExceptionInfo
# load asyncore and asynchat after helper to ensure we've a path to compat folder:
import asynchat
if asynchat.asyncore:
asyncore = asynchat.asyncore
else: # pragma: no cover - normally unreachable
import asyncore
# Gets the instance of the logger.
logSys = getLogger(__name__)

View File

@ -24,22 +24,18 @@ __copyright__ = "Copyright (c) 2004 Cyril Jaquier, 2011-2012 Lee Clemens, 2012 Y
__license__ = "GPL"
import logging
from distutils.version import LooseVersion
import os
from os.path import dirname, sep as pathsep
import pyinotify
from .failmanager import FailManagerEmpty
from .filter import FileFilter
from .mytime import MyTime, time
from .utils import Utils
from ..helpers import getLogger
if not hasattr(pyinotify, '__version__') \
or LooseVersion(pyinotify.__version__) < '0.8.3': # pragma: no cover
raise ImportError("Fail2Ban requires pyinotify >= 0.8.3")
# pyinotify may have dependency to asyncore, so import it after helper to ensure
# we've a path to compat folder:
import pyinotify
# Verify that pyinotify is functional on this system
# Even though imports -- might be dysfunctional, e.g. as on kfreebsd

View File

@ -24,11 +24,8 @@ __license__ = "GPL"
import os
import time
from distutils.version import LooseVersion
from systemd import journal
if LooseVersion(getattr(journal, '__version__', "0")) < '204':
raise ImportError("Fail2Ban requires systemd >= 204")
from .failmanager import FailManagerEmpty
from .filter import JournalFilter, Filter

View File

@ -34,6 +34,7 @@ class BeautifierTest(unittest.TestCase):
""" Call before every test case """
super(BeautifierTest, self).setUp()
self.b = Beautifier()
self.b.encUtf = 0; ## we prefer ascii in test suite (see #3750)
def tearDown(self):
""" Call after every test case """
@ -170,22 +171,25 @@ class BeautifierTest(unittest.TestCase):
def testStatusStats(self):
self.b.setInputCmd(["stats"])
## no jails:
self.assertEqual(self.b.beautify({}), "No jails found.")
## 3 jails:
response = {
"ssh": ["systemd", (3, 6), (12, 24)],
"exim4": ["pyinotify", (6, 12), (20, 20)],
"jail-with-long-name": ["polling", (0, 0), (0, 0)]
}
output = (""
+ " ? ? Filter ? Actions \n"
+ "Jail ? Backend ????????????????????????\n"
+ " ? ? cur ? tot ? cur ? tot\n"
+ "????????????????????????????????????????????????????????\n"
+ "ssh ? systemd ? 3 ? 6 ? 12 ? 24\n"
+ "exim4 ? pyinotify ? 6 ? 12 ? 20 ? 20\n"
+ "jail-with-long-name ? polling ? 0 ? 0 ? 0 ? 0\n"
+ "????????????????????????????????????????????????????????"
+ " | | Filter | Actions \n"
+ " Jail | Backend |-----------x-----------\n"
+ " | | cur | tot | cur | tot\n"
+ "---------------------x-----------x-----------x-----------\n"
+ " ssh | systemd | 3 | 6 | 12 | 24\n"
+ " exim4 | pyinotify | 6 | 12 | 20 | 20\n"
+ " jail-with-long-name | polling | 0 | 0 | 0 | 0\n"
+ "---------------------------------------------------------"
)
response = self.b.beautify(response).encode('ascii', 'replace').decode('ascii')
response = self.b.beautify(response)
self.assertEqual(response, output)

View File

@ -9,7 +9,7 @@ before = ../../../../config/filter.d/common.conf
[DEFAULT]
_daemon = sshd
_daemon = sshd(?:-session)?
# optional prefix (logged from several ssh versions) like "error: ", "error: PAM: " or "fatal: "
__pref = (?:(?:error|fatal): (?:PAM: )?)?

View File

@ -25,3 +25,6 @@
# https://issues.apache.org/bugzilla/show_bug.cgi?id=46123
# failJSON: { "time": "2008-10-29T11:55:14", "match": true , "host": "127.0.0.1" }
[Wed Oct 29 11:55:14 2008] [error] [client 127.0.0.1] Invalid method in request \x16\x03\x01 - possible attempt to establish SSL connection when the server isn't expecting it
# failJSON: { "time": "2024-06-26T05:20:26", "match": true , "host": "192.0.2.39", "desc": "AH10244: invalid URI path, gh-3778" }
[Wed Jun 26 05:20:26.182799 2024] [core:error] [pid 2928] [client 192.0.2.39:37924] AH10244: invalid URI path (/cgi-bin/.%2e/.%2e/.%2e/.%2e/.%2e/.%2e/.%2e/.%2e/.%2e/.%2e/bin/sh)

View File

@ -70,6 +70,9 @@ Jun 12 08:58:35 xxx postfix/smtpd[13533]: improper command pipelining after AUTH
# failJSON: { "time": "2005-05-05T15:51:11", "match": true , "host": "216.245.194.173", "desc": "postfix postscreen / gh-1764" }
May 5 15:51:11 xxx postfix/postscreen[1148]: NOQUEUE: reject: RCPT from [216.245.194.173]:60591: 550 5.7.1 Service unavailable; client [216.245.194.173] blocked using rbl.example.com; from=<spammer@example.com>, to=<goodguy@example.com>, proto=ESMTP, helo=<badguy.example.com>
# failJSON: { "time": "2005-06-01T19:00:55", "match": true , "host": "192.0.2.114", "desc": "postfix client restriction / gh-3800" }
Jun 1 19:00:55 mail postfix/smtpd[7749]: NOQUEUE: reject: CONNECT from unknown[192.0.2.114]: 450 4.7.25 Client host rejected: cannot find your hostname, [178.215.236.114]; proto=SMTP
# failJSON: { "time": "2005-06-03T06:25:43", "match": true , "host": "192.0.2.11", "desc": "too many errors / gh-2439" }
Jun 3 06:25:43 srv postfix/smtpd[29306]: too many errors after RCPT from example.com[192.0.2.11]
@ -148,6 +151,9 @@ Jan 14 16:18:16 xxx postfix/smtpd[14933]: warning: host[192.0.2.5]: SASL CRAM-MD
# failJSON: { "time": "2005-01-14T16:18:16", "match": true , "host": "192.0.2.5", "desc": "aggressive only" }
Jan 14 16:18:16 xxx postfix/smtpd[14933]: warning: host[192.0.2.5]: SASL CRAM-MD5 authentication failed: Invalid authentication mechanism
# failJSON: { "time": "2004-11-04T09:11:01", "match": true , "host": "192.0.2.152", "desc": "reason unavailable" }
Nov 4 09:11:01 mail postfix/smtpd[1234]: warning: unknown[192.0.2.152]: SASL LOGIN authentication failed: (reason unavailable), sasl_username=admin
# ---------------------------------------
# Test-cases of postfix DDOS mode:
# ---------------------------------------

View File

@ -0,0 +1,5 @@
# failJSON: { "time": "2005-03-08T09:37:44", "match": true , "host": "192.0.2.123" }
Mar 8 09:37:44 HOSTNAME pvedaemon[12021]: authentication failure; rhost=192.0.2.123 user=root@pam msg=Authentication failure
# failJSON: { "time": "2005-03-09T03:32:27", "match": true , "host": "192.0.2.124" }
Mar 9 03:32:27 HOSTNAME pvedaemon[8961]: authentication failure; rhost=192.0.2.124 user=jose@pve msg=invalid credentials

View File

@ -54,3 +54,8 @@ Jul 11 03:06:37 myhostname roundcube: IMAP Error: Login failed for admin from 12
# failJSON: { "time": "2005-05-19T06:07:48", "match": true , "host": "192.0.2.1", "desc": "Roundcube logged to journald instead to a local file."}
May 19 06:07:48 server roundcube[21296]: <crk9n97i> IMAP Error: Login failed for test from 192.0.2.1. AUTHENTICATE PLAIN: Authentication failed. in /usr/share/php5/Roundcube/rcube_imap.php on line 193 (POST /mail/?_task=login&_action=login)
# Roundcube 1.5.0 (/var/log/roundcubemail/errors)
# failJSON: { "time": "2014-12-30T19:02:34", "match": true , "host": "1.2.3.4" }
[30-Dec-2014 13:02:34 -0500]: <3z506z6r> IMAP Error: Login failed for admin@example.com against localhost from 1.2.3.4. AUTHENTICATE PLAIN: Authentication failed. in /docroot/path/program/lib/Roundcube/rcube_imap.php on line 221 (POST /?_task=login?_task=login&_action=login)

View File

@ -20,6 +20,9 @@ Feb 25 14:34:10 belka sshd[31603]: Failed password for invalid user ROOT from aa
# failJSON: { "time": "2005-02-25T14:34:11", "match": true , "host": "aaaa:bbbb:cccc:1234::1:1" }
Feb 25 14:34:11 belka sshd[31603]: Failed password for invalid user ROOT from aaaa:bbbb:cccc:1234::1:1
# failJSON: { "time": "2005-07-03T14:59:17", "match": true , "host": "192.0.2.1", "desc": "new log with session in daemon prefix, gh-3782" }
Jul 3 14:59:17 host sshd-session[1571]: Failed password for root from 192.0.2.1 port 56502 ssh2
#3
# failJSON: { "time": "2005-01-05T01:31:41", "match": true , "host": "1.2.3.4" }
Jan 5 01:31:41 www sshd[1643]: ROOT LOGIN REFUSED FROM 1.2.3.4

View File

@ -120,7 +120,7 @@ class SetupTest(unittest.TestCase):
# suppress stdout (and stderr) if not heavydebug
supdbgout = ' >/dev/null' if unittest.F2B.log_level >= logging.DEBUG else '' # HEAVYDEBUG
try:
self.assertEqual(os.system("%s %s install --root=%s%s"
self.assertEqual(os.system("%s -W 'ignore:setup.py install is deprecated' %s install --root=%s%s"
% (sys.executable, self.setup, tmp, supdbgout)), 0)
def strippath(l):

View File

@ -2034,32 +2034,32 @@ class ServerConfigReaderTests(LogCaptureTestCase):
('j-fwcmd-rr', 'firewallcmd-rich-rules[port="22:24", protocol="tcp"]', {
'ip4': ("family='ipv4'", "icmp-port-unreachable",), 'ip6': ("family='ipv6'", 'icmp6-port-unreachable',),
'ip4-ban': (
"""`ports="22:24"; for p in $(echo $ports | tr ", " " "); do firewall-cmd --add-rich-rule="rule family='ipv4' source address='192.0.2.1' port port='$p' protocol='tcp' reject type='icmp-port-unreachable'"; done`""",
r"""`ports="22:24"; for p in $(echo $ports | tr ", " " "); do firewall-cmd --add-rich-rule="rule family=\"ipv4\" source address=\"192.0.2.1\" port port=\"$p\" protocol=\"tcp\" reject type='icmp-port-unreachable'"; done`""",
),
'ip4-unban': (
"""`ports="22:24"; for p in $(echo $ports | tr ", " " "); do firewall-cmd --remove-rich-rule="rule family='ipv4' source address='192.0.2.1' port port='$p' protocol='tcp' reject type='icmp-port-unreachable'"; done`""",
r"""`ports="22:24"; for p in $(echo $ports | tr ", " " "); do firewall-cmd --remove-rich-rule="rule family=\"ipv4\" source address=\"192.0.2.1\" port port=\"$p\" protocol=\"tcp\" reject type='icmp-port-unreachable'"; done`""",
),
'ip6-ban': (
""" `ports="22:24"; for p in $(echo $ports | tr ", " " "); do firewall-cmd --add-rich-rule="rule family='ipv6' source address='2001:db8::' port port='$p' protocol='tcp' reject type='icmp6-port-unreachable'"; done`""",
r""" `ports="22:24"; for p in $(echo $ports | tr ", " " "); do firewall-cmd --add-rich-rule="rule family=\"ipv6\" source address=\"2001:db8::\" port port=\"$p\" protocol=\"tcp\" reject type='icmp6-port-unreachable'"; done`""",
),
'ip6-unban': (
"""`ports="22:24"; for p in $(echo $ports | tr ", " " "); do firewall-cmd --remove-rich-rule="rule family='ipv6' source address='2001:db8::' port port='$p' protocol='tcp' reject type='icmp6-port-unreachable'"; done`""",
r"""`ports="22:24"; for p in $(echo $ports | tr ", " " "); do firewall-cmd --remove-rich-rule="rule family=\"ipv6\" source address=\"2001:db8::\" port port=\"$p\" protocol=\"tcp\" reject type='icmp6-port-unreachable'"; done`""",
),
}),
# firewallcmd-rich-logging --
('j-fwcmd-rl', 'firewallcmd-rich-logging[port="22:24", protocol="tcp"]', {
'ip4': ("family='ipv4'", "icmp-port-unreachable",), 'ip6': ("family='ipv6'", 'icmp6-port-unreachable',),
'ip4-ban': (
"""`ports="22:24"; for p in $(echo $ports | tr ", " " "); do firewall-cmd --add-rich-rule="rule family='ipv4' source address='192.0.2.1' port port='$p' protocol='tcp' log prefix='f2b-j-fwcmd-rl' level='info' limit value='1/m' reject type='icmp-port-unreachable'"; done`""",
r"""`ports="22:24"; for p in $(echo $ports | tr ", " " "); do firewall-cmd --add-rich-rule="rule family=\"ipv4\" source address=\"192.0.2.1\" port port=\"$p\" protocol=\"tcp\" log prefix='f2b-j-fwcmd-rl' level='info' limit value='1/m' reject type='icmp-port-unreachable'"; done`""",
),
'ip4-unban': (
"""`ports="22:24"; for p in $(echo $ports | tr ", " " "); do firewall-cmd --remove-rich-rule="rule family='ipv4' source address='192.0.2.1' port port='$p' protocol='tcp' log prefix='f2b-j-fwcmd-rl' level='info' limit value='1/m' reject type='icmp-port-unreachable'"; done`""",
r"""`ports="22:24"; for p in $(echo $ports | tr ", " " "); do firewall-cmd --remove-rich-rule="rule family=\"ipv4\" source address=\"192.0.2.1\" port port=\"$p\" protocol=\"tcp\" log prefix='f2b-j-fwcmd-rl' level='info' limit value='1/m' reject type='icmp-port-unreachable'"; done`""",
),
'ip6-ban': (
""" `ports="22:24"; for p in $(echo $ports | tr ", " " "); do firewall-cmd --add-rich-rule="rule family='ipv6' source address='2001:db8::' port port='$p' protocol='tcp' log prefix='f2b-j-fwcmd-rl' level='info' limit value='1/m' reject type='icmp6-port-unreachable'"; done`""",
r""" `ports="22:24"; for p in $(echo $ports | tr ", " " "); do firewall-cmd --add-rich-rule="rule family=\"ipv6\" source address=\"2001:db8::\" port port=\"$p\" protocol=\"tcp\" log prefix='f2b-j-fwcmd-rl' level='info' limit value='1/m' reject type='icmp6-port-unreachable'"; done`""",
),
'ip6-unban': (
"""`ports="22:24"; for p in $(echo $ports | tr ", " " "); do firewall-cmd --remove-rich-rule="rule family='ipv6' source address='2001:db8::' port port='$p' protocol='tcp' log prefix='f2b-j-fwcmd-rl' level='info' limit value='1/m' reject type='icmp6-port-unreachable'"; done`""",
r"""`ports="22:24"; for p in $(echo $ports | tr ", " " "); do firewall-cmd --remove-rich-rule="rule family=\"ipv6\" source address=\"2001:db8::\" port port=\"$p\" protocol=\"tcp\" log prefix='f2b-j-fwcmd-rl' level='info' limit value='1/m' reject type='icmp6-port-unreachable'"; done`""",
),
}),
)

View File

@ -24,7 +24,7 @@ __author__ = "Cyril Jaquier, Yaroslav Halchenko, Steven Hiscocks, Daniel Black"
__copyright__ = "Copyright (c) 2004 Cyril Jaquier, 2005-2016 Yaroslav Halchenko, 2013-2014 Steven Hiscocks, Daniel Black"
__license__ = "GPL-v2+"
version = "1.1.0"
version = "1.1.1.dev1"
def normVersion():
""" Returns fail2ban version in normalized machine-readable format"""

View File

@ -1,12 +1,12 @@
.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.49.3.
.TH FAIL2BAN-CLIENT "1" "April 2024" "Fail2Ban v1.1.0" "User Commands"
.TH FAIL2BAN-CLIENT "1" "April 2024" "Fail2Ban v1.1.1.dev1" "User Commands"
.SH NAME
fail2ban-client \- configure and control the server
.SH SYNOPSIS
.B fail2ban-client
[\fI\,OPTIONS\/\fR] \fI\,<COMMAND>\/\fR
.SH DESCRIPTION
Fail2Ban v1.1.0 reads log file that contains password failure report
Fail2Ban v1.1.1.dev1 reads log file that contains password failure report
and bans the corresponding IP addresses using firewall rules.
.SH OPTIONS
.TP

View File

@ -1,5 +1,5 @@
.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.49.3.
.TH FAIL2BAN-PYTHON "1" "April 2024" "fail2ban-python 1.1.0" "User Commands"
.TH FAIL2BAN-PYTHON "1" "April 2024" "fail2ban-python 1.1.1.1" "User Commands"
.SH NAME
fail2ban-python \- a helper for Fail2Ban to assure that the same Python is used
.SH DESCRIPTION

View File

@ -1,5 +1,5 @@
.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.49.3.
.TH FAIL2BAN-REGEX "1" "April 2024" "fail2ban-regex 1.1.0" "User Commands"
.TH FAIL2BAN-REGEX "1" "April 2024" "fail2ban-regex 1.1.1.dev1" "User Commands"
.SH NAME
fail2ban-regex \- test Fail2ban "failregex" option
.SH SYNOPSIS

View File

@ -1,12 +1,12 @@
.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.49.3.
.TH FAIL2BAN-SERVER "1" "April 2024" "Fail2Ban v1.1.0" "User Commands"
.TH FAIL2BAN-SERVER "1" "April 2024" "Fail2Ban v1.1.1.dev1" "User Commands"
.SH NAME
fail2ban-server \- start the server
.SH SYNOPSIS
.B fail2ban-server
[\fI\,OPTIONS\/\fR]
.SH DESCRIPTION
Fail2Ban v1.1.0 reads log file that contains password failure report
Fail2Ban v1.1.1.dev1 reads log file that contains password failure report
and bans the corresponding IP addresses using firewall rules.
.SH OPTIONS
.TP

View File

@ -1,5 +1,5 @@
.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.49.3.
.TH FAIL2BAN-TESTCASES "1" "April 2024" "fail2ban-testcases 1.1.0" "User Commands"
.TH FAIL2BAN-TESTCASES "1" "April 2024" "fail2ban-testcases 1.1.1.dev1" "User Commands"
.SH NAME
fail2ban-testcases \- run Fail2Ban unit-tests
.SH SYNOPSIS

View File

@ -24,23 +24,10 @@ __license__ = "GPL"
import platform
try:
import setuptools
from setuptools import setup
from setuptools.command.install import install
from setuptools.command.install_scripts import install_scripts
from setuptools.command.build_py import build_py
build_scripts = None
except ImportError:
setuptools = None
from distutils.core import setup
# older versions
if setuptools is None:
from distutils.command.build_py import build_py
from distutils.command.build_scripts import build_scripts
from distutils.command.install import install
from distutils.command.install_scripts import install_scripts
import setuptools
from setuptools import setup
from setuptools.command.install import install
from setuptools.command.install_scripts import install_scripts
import os
from os.path import isfile, join, isdir, realpath
@ -207,9 +194,9 @@ setup(
url = "http://www.fail2ban.org",
license = "GPL",
platforms = "Posix",
cmdclass = dict({'build_py': build_py, 'build_scripts': build_scripts} if build_scripts else {}, **{
cmdclass = {
'install_scripts': install_scripts_f2b, 'install': install_command_f2b
}),
},
scripts = [
'bin/fail2ban-client',
'bin/fail2ban-server',