mirror of
https://github.com/fail2ban/fail2ban.git
synced 2026-05-13 14:36:43 +00:00
Compare commits
108 commits
1.1.1.beta
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
557e7eecf9 | ||
|
|
adfffe5267 | ||
|
|
8d3f5048ef | ||
|
|
507d0468cd | ||
|
|
732dc86ef3 | ||
|
|
0a8356dd31 | ||
|
|
8be17b0981 | ||
|
|
c03a6204c1 | ||
|
|
eb7ed973ef | ||
|
|
3b8033b337 | ||
|
|
243876e60a | ||
|
|
3bead7c011 | ||
|
|
05f6ad4fcc | ||
|
|
81b906303c | ||
|
|
025adbf485 | ||
|
|
f457cf8131 | ||
|
|
1a802bee93 | ||
|
|
36e28359ed | ||
|
|
8a8afefd70 | ||
|
|
8afd0c8956 | ||
|
|
6cdb5738ec | ||
|
|
9887ee4412 | ||
|
|
8506e4a41d | ||
|
|
481be8790a | ||
|
|
948e923589 | ||
|
|
247667c9c2 | ||
|
|
7528fce11b | ||
|
|
edaf8ef19f | ||
|
|
74981e4c13 | ||
|
|
45453826a3 | ||
|
|
2f0e05a0d7 | ||
|
|
ef65652671 | ||
|
|
bfafd12c59 | ||
|
|
7c2bda4977 | ||
|
|
3f78f1520b | ||
|
|
7bac839603 | ||
|
|
d0b94c147e | ||
|
|
070d49e09c | ||
|
|
dda4aa7d2d | ||
|
|
ad9aba5871 | ||
|
|
13563fd09b | ||
|
|
a9401233dd | ||
|
|
1379a262f6 | ||
|
|
abdd0d4b25 | ||
|
|
897b21a4c5 | ||
|
|
65668b8ed8 | ||
|
|
2856092709 | ||
|
|
2ac7e1284f | ||
|
|
0fee8dbe92 | ||
|
|
6c47bf6461 | ||
|
|
9534bdac37 | ||
|
|
a8875c36b8 | ||
|
|
9f26da3cf8 | ||
|
|
5beee494a3 | ||
|
|
3fd3454146 | ||
|
|
ce8cc5d261 | ||
|
|
4539e6719c | ||
|
|
85cfb81782 | ||
|
|
3d23a44bb1 | ||
|
|
77efe3b40c | ||
|
|
26b91862fc | ||
|
|
10b12e8c57 | ||
|
|
13876e93ad | ||
|
|
70d7fd0fdd | ||
|
|
9e72e78f34 | ||
|
|
912e3c81a2 | ||
|
|
c54d505dea | ||
|
|
6ac181f559 | ||
|
|
52399e6ef1 | ||
|
|
c9e1a1b087 | ||
|
|
a055568500 | ||
|
|
0265df854e | ||
|
|
a3d181c973 | ||
|
|
002719dca4 | ||
|
|
c26fda9dbb | ||
|
|
bdb5d99906 | ||
|
|
4e22c20559 | ||
|
|
3ce6f344e3 | ||
|
|
bf4903538d | ||
|
|
77ba28bae1 | ||
|
|
dc3268ce5d | ||
|
|
eb80b895d1 | ||
|
|
6120a731d9 | ||
|
|
e16e982a45 | ||
|
|
dd58d440bc | ||
|
|
e6516fd2b3 | ||
|
|
0a91bf69a5 | ||
|
|
d86a7aecca | ||
|
|
ff3eca1d61 | ||
|
|
0b255a8723 | ||
|
|
793d0c6555 | ||
|
|
7bb86822d0 | ||
|
|
6d3bfa8781 | ||
|
|
b309cf6b3c | ||
|
|
e97df4672a | ||
|
|
1c2ace2958 | ||
|
|
b710d5b6c7 | ||
|
|
dc899e438f | ||
|
|
7d6b1a4c3b | ||
|
|
05575de1f1 | ||
|
|
5a0224ff0e | ||
|
|
64983ecc29 | ||
|
|
6a2d2aa97a | ||
|
|
11768a97e9 | ||
|
|
2224b3db4a | ||
|
|
f376da4bec | ||
|
|
60b136333e | ||
|
|
3359845242 |
51 changed files with 602 additions and 153 deletions
2
.github/workflows/main.yml
vendored
2
.github/workflows/main.yml
vendored
|
|
@ -22,7 +22,7 @@ jobs:
|
|||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
matrix:
|
||||
python-version: [3.8, 3.9, '3.10', '3.11', '3.12', '3.13', '3.14.0-alpha.6', pypy3.11]
|
||||
python-version: [3.8, 3.9, '3.10', '3.11', '3.12', '3.13', '3.14', '3.15.0-alpha.5', pypy3.11]
|
||||
fail-fast: false
|
||||
# Steps represent a sequence of tasks that will be executed as part of the job
|
||||
steps:
|
||||
|
|
|
|||
40
ChangeLog
40
ChangeLog
|
|
@ -24,6 +24,10 @@ ver. 1.1.1-dev-1 (20??/??/??) - development nightly edition
|
|||
in systemd module (see https://github.com/systemd/python-systemd/issues/143)
|
||||
* fixes `systemd` causing "too many open files" error for a lot of journal files and large amount of systemd jails
|
||||
(see new parameter `rotated` below, gh-3391);
|
||||
* passing of arguments from jails to action or filter will affect conditional section too (gh-4069),
|
||||
e. g. setting `blocktype="DROP"` via jail for action would now apply for IPv4 and IPv6 chains,
|
||||
to submit different `blocktype` for IPv4 and IPv6 from jail, one can pass them like in this example:
|
||||
`banaction = iptables-ipset[blocktype="...", blocktype?family=inet6="..."]`
|
||||
* `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`
|
||||
|
|
@ -33,10 +37,20 @@ ver. 1.1.1-dev-1 (20??/??/??) - development nightly edition
|
|||
* `paths-debian.conf`:
|
||||
- default banactions are `nftables`
|
||||
- sshd backend switched to `systemd` (gh-3292)
|
||||
- postfix backend switched to `systemd` (gh-3527)
|
||||
* `action.d/firewallcmd-ipset.conf`:
|
||||
- rename `ipsettype` to `ipsetbackend` (gh-2620), parameter `ipsettype` will be used now to the real set type (gh-3760)
|
||||
* `action.d/nftables.conf`:
|
||||
- action fixed for SELinux without execmem permission, rewrite capturing with `grep -P` using `grep -E` or `sed`
|
||||
(PCRE-JIT by `grep -P` may cause SELinux denial for execmem, see gh-4137)
|
||||
* `action.d/xarf-login-attack.conf` - ignore errors or warnings in output of `dig` provided as comment (gh-4068)
|
||||
* `filter.d/apache-badbots.conf`, `filter.d/apache-fakegooglebot.conf`:
|
||||
- regexs rewritten more strict (removed catch-alls, etc);
|
||||
- regexs fixed to match lines with vhost in accesslog (gh-1594)
|
||||
* `filter.d/apache-noscript.conf` - consider new log-format with "AH02811: stderr from /..." (gh-3900)
|
||||
* `filter.d/apache-overflows.conf` - consider AH10244: invalid URI path (gh-3778, gh-3900)
|
||||
* `filter.d/asterisk.conf` - fixed RE for "no matching endpoint" with retry info (like `after X tries in Y ms`) at end,
|
||||
loosening of end anchor (ignore any simple text tokens at end if no single quote found), gh-4037
|
||||
* `filter.d/exim.conf`:
|
||||
- several rules of mode `normal` moved to new mode `more`, because of too risky handling (gh-3940),
|
||||
thereby mode `aggressive` is not affected, because it fully includes mode `more` now;
|
||||
|
|
@ -45,18 +59,28 @@ ver. 1.1.1-dev-1 (20??/??/??) - development nightly edition
|
|||
FreeSWITCH log line prefix has changed in newer versions (gh-3143)
|
||||
* `filter.d/lighttpd-auth.conf` - fixed regex (if failures generated by systemd-journal), bypass several prefixes now (gh-3955)
|
||||
* `filter.d/postfix.conf`:
|
||||
- extended `prefregex` to capture username in postfix SASL failures (gh-4165)
|
||||
- consider CONNECT and other rejected commands as a valid `_pref` (gh-3800)
|
||||
- default `_daemon` in prefix-line is loosened - can match everything starting with word postfix, like `postfix-example.com/smtpd` (gh-3297)
|
||||
- add optional `NOQUEUE:` prefix to ddos regex (gh-4072)
|
||||
- internal parameter `_pref` is renamed to `_cmd`, `_pref` matches now optional prefix like `NOQUEUE: ` etc
|
||||
- modes `ddos` and `aggressive` extended to match `rate limit exceeded` for connection or message delivery request rates (gh-3265, gh-4073)
|
||||
* `filter.d/dropbear.conf`:
|
||||
- recognizes extra pid/timestamp if logged into stdout/journal, added `journalmatch` (gh-3597)
|
||||
- failregex extended to match different format of "Exit before auth" message (gh-3791)
|
||||
* `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/sendmail-reject.conf`: (gh-4020)
|
||||
- support `<F-MLFID>` for BSD-style logfiles
|
||||
- add match for `User unknown` to default
|
||||
- the relay field may not always have a hostname before the ip address
|
||||
- mode `aggressive` enables match for `lost input channel` and `Cannot resolve PTR record`
|
||||
* `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)
|
||||
- `ddos` and `aggressive` modes: regex extended for timeout before authentication (optional connection from part, gh-3907)
|
||||
* `filter.d/vsftpd.conf` - fixed regex (if failures generated by systemd-journal, gh-3954)
|
||||
* `filter.d/froxlor-auth.conf` - updated the regex to the new logging situation for froxlor and changed logpath in jail.conf (gh-4075).
|
||||
|
||||
### New Features and Enhancements
|
||||
* backend `systemd` extended with new parameter `rotated` (default `false`, as prevention against "too many open files"),
|
||||
|
|
@ -75,16 +99,30 @@ ver. 1.1.1-dev-1 (20??/??/??) - development nightly edition
|
|||
by first ban (and automatically reloaded by update after small latency to avoid expensive stats check on every compare);
|
||||
the entries inside the file can be separated by comma, space or new line with optional comments (text following chars
|
||||
`#` or `;` after space or newline would be ignored up to next newline)
|
||||
* `action.d/apprise.conf` - updated to support tagging and other command line args (gh-4141)
|
||||
* `action.d/*-ipset.conf`:
|
||||
- parameter `ipsettype` to set type of ipset, e. g. hash:ip, hash:net, etc (gh-3760)
|
||||
* `action.d/iptables.conf` - action and few derivatives of it extended to handle multiple chains,
|
||||
e. g. would also accept `chain = INPUT,FORWARD` (gh-3909)
|
||||
* `action.d/nftables.conf` (gh-3291):
|
||||
- new parameter `addr_options` for addr-set (default `flags interval\;`, allows to store CIDR or address ranges);
|
||||
can be set to empty value to create simple addresses set (restore previous behavior).
|
||||
* `action.d/firewallcmd-rich-*.conf` - fixed incorrect quoting, disabling port variable expansion
|
||||
by substitution of rich rule (gh-3815)
|
||||
* `filter.d/dovecot.conf` - add support for latest Dovecot 2.4 release (gh-4016)
|
||||
* `filter.d/dovecot.conf`:
|
||||
- add support for latest Dovecot 2.4 release (gh-4016)
|
||||
- mode `aggressive` covered new variant for `no auth attempts in X secs` with `Login aborted` and `(no_auth_attempts)`
|
||||
- mode `aggressive` extended to match `disconnected during TLS handshake` with `no application protocol` and `no shared cipher`
|
||||
* `filter.d/nginx-http-auth.conf`:
|
||||
- extended with `prefregex` to capture content of error only (bypass common prefix and suffix, like server, request, host, referrer);
|
||||
- extended to match PAM authentication failures (gh-4071)
|
||||
- modes `fallback` and `aggressive` extended to match more SSL failures by SSL_do_handshake or SSL_read (gh-4142, gh-2881)
|
||||
* `filter.d/nginx-limit-req.conf` - extended to ban hosts failed by limit connection in ngx_http_limit_conn_module (gh-3674, gh-4047)
|
||||
* `filter.d/proxmox.conf` - add support to Proxmox Web GUI (gh-2966)
|
||||
* `filter.d/openvpn.conf` - new filter and jail for openvpn recognizing failed TLS handshakes (gh-2702)
|
||||
* `filter.d/sendmail-reject.conf` - also recognize "Domain of sender address ... does not resolve" (gh-4035)
|
||||
* `filter.d/vaultwarden.conf` - new filter and jail for Vaultwarden (gh-3979)
|
||||
* `filter.d/xrdp.conf` - new filter for XRDP, an open source RDP server (gh-3254)
|
||||
* `fail2ban-regex` extended with new option `-i` or `--invert` to output not-matched lines by `-o` or `--out` (gh-4001)
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ attempts, it cannot eliminate the risk presented by weak authentication.
|
|||
Set up services to use only two factor, or public/private authentication
|
||||
mechanisms if you really want to protect services.
|
||||
|
||||
<img src="http://www.worldipv6launch.org/wp-content/themes/ipv6/downloads/World_IPv6_launch_logo.svg" height="52pt"/> | Since v0.10 fail2ban supports the matching of IPv6 addresses.
|
||||
<img src="http://www.worldipv6launch.org/wp-content/themes/ipv6/downloads/World_IPv6_launch_logo.svg" style="height:52pt;"/> | Since v0.10 fail2ban supports the matching of IPv6 addresses.
|
||||
------|------
|
||||
|
||||
This README is a quick introduction to Fail2Ban. More documentation, FAQ, and HOWTOs
|
||||
|
|
|
|||
|
|
@ -2,7 +2,61 @@
|
|||
#
|
||||
# Author: Chris Caron <lead2gold@gmail.com>
|
||||
#
|
||||
# ban & send a notification to one or more of the 120+ services supported by
|
||||
# Apprise.
|
||||
# - See https://appriseit.com/services/ for details on what is supported.
|
||||
# - See https://appriseit.com/getting-started/configuration/ for information
|
||||
# on how to prepare an Apprise configuration file.
|
||||
#
|
||||
# This plugin requires that Apprise is installed on your system:
|
||||
#
|
||||
# pip install apprise
|
||||
#
|
||||
# Breakdown:
|
||||
# config provide a path to an Apprise Config file
|
||||
# The default is /etc/fail2ban/apprise.conf if not provided.
|
||||
# Both YAML and TEXT formats are supported.
|
||||
# You can even point your configuration to an Apprise API
|
||||
# endpoint.
|
||||
#
|
||||
# args Provide additional arguments to support the Apprise CLI.
|
||||
# See https://appriseit.com/cli/usage/ for additional options.
|
||||
# the --tag (-g) is incredibly useful for integrating with
|
||||
# fail2ban as you can exclusively have it target specific
|
||||
# notifications this way.
|
||||
#
|
||||
# Config Example #1: Simple
|
||||
# 1. Create a /etc/fail2ban/apprise.conf
|
||||
# ```
|
||||
# # /etc/fail2ban/apprise.conf
|
||||
# fail2ban=mailto://user:pass@example.com
|
||||
# ```
|
||||
# 2 In jail:
|
||||
# ```
|
||||
# action = %(action_)s
|
||||
# apprise[args='--tag fail2ban']
|
||||
# ```
|
||||
#
|
||||
# Config Example #2: YAML an Custom path
|
||||
# 1. Create a /etc/fail2ban/apprise.conf
|
||||
# ```
|
||||
# # /etc/fail2ban/apprise.yaml
|
||||
# urls:
|
||||
# - mailto://user:pass@example.com:
|
||||
# tags: f2b
|
||||
# ```
|
||||
# 2. In jail:
|
||||
# ```
|
||||
# action = %(action_)s
|
||||
# apprise[config='/etc/fail2ban/apprise.yaml',args='--tag f2b']
|
||||
# ```
|
||||
#
|
||||
# Config Example #3: Apprise API
|
||||
# 1. In jail:
|
||||
# ```
|
||||
# action = %(action_)s
|
||||
# apprise[config='http://apprise.example.ca/get/mykey',args='-g f2b']
|
||||
# ```
|
||||
|
||||
[Definition]
|
||||
|
||||
|
|
@ -45,5 +99,9 @@ actionunban =
|
|||
# Define location of the default apprise configuration file to use
|
||||
#
|
||||
config = /etc/fail2ban/apprise.conf
|
||||
|
||||
# Support passing in arguments for example: "-g fail2ban"
|
||||
#
|
||||
apprise = apprise -c "<config>"
|
||||
args =
|
||||
#
|
||||
apprise = apprise -c "<config>" <args>
|
||||
|
|
|
|||
|
|
@ -53,9 +53,9 @@ _nft_for_proto-multiport-iter = for proto in $(echo '<protocol>' | sed 's/,/ /g'
|
|||
_nft_for_proto-multiport-done = done
|
||||
|
||||
_nft_list = <nftables> -a list chain <table_family> <table> <chain>
|
||||
_nft_get_handle_id = grep -oP '@<addr_set>\s+.*\s+\Khandle\s+(\d+)$'
|
||||
_nft_get_handle_id = sed -nE 's/.*@<addr_set>\s+.*\s+\#\s*(handle\s+[0-9]+)$/\1/p'
|
||||
|
||||
_nft_add_set = <nftables> add set <table_family> <table> <addr_set> \{ type <addr_type>\; \}
|
||||
_nft_add_set = <nftables> add set <table_family> <table> <addr_set> \{ type <addr_type>\;<addr_options> \}
|
||||
<_nft_for_proto-<type>-iter>
|
||||
<nftables> add rule <table_family> <table> <chain> %(rule_stat)s
|
||||
<_nft_for_proto-<type>-done>
|
||||
|
|
@ -67,7 +67,7 @@ _nft_del_set = { %(_nft_list)s | %(_nft_get_handle_id)s; } | while read -r hdl;
|
|||
# Notes.: command executed after the stop in order to delete table (it checks that no sets are available):
|
||||
# Values: CMD
|
||||
#
|
||||
_nft_shutdown_table = { <nftables> list table <table_family> <table> | grep -qP '^\s+set\s+'; } || {
|
||||
_nft_shutdown_table = { <nftables> list table <table_family> <table> | grep -qE '^\s+set\s+'; } || {
|
||||
<nftables> delete table <table_family> <table>
|
||||
}
|
||||
|
||||
|
|
@ -197,6 +197,11 @@ addr_set = addr-set-<name>
|
|||
# Values: [ ip | ip6 ]
|
||||
addr_family = ip
|
||||
|
||||
# Option: addr_options
|
||||
# Notes: Additional options for the addr-set, by default allows to store CIDR or address ranges.
|
||||
# Can be set to empty value to create simple addresses set.
|
||||
addr_options = <sp>flags interval\;
|
||||
|
||||
[Init?family=inet6]
|
||||
addr_family = ip6
|
||||
addr_type = ipv6_addr
|
||||
|
|
|
|||
|
|
@ -44,7 +44,13 @@ actioncheck =
|
|||
actionban = oifs=${IFS};
|
||||
RESOLVER_ADDR="%(addr_resolver)s"
|
||||
if [ "<debug>" -gt 0 ]; then echo "try to resolve $RESOLVER_ADDR"; fi
|
||||
ADDRESSES=$(dig +short -t txt -q $RESOLVER_ADDR | tr -d '"')
|
||||
ADDRESSES=$(dig +short -t txt -q $RESOLVER_ADDR | grep -v ';;' | tr -d '"')
|
||||
if [ "<debug>" -gt 0 ]; then echo "returned address $ADDRESSES"; fi
|
||||
if [ -z "$ADDRESSES" ]; then
|
||||
echo "address for $RESOLVER_ADDR cannot be found or timeout from dig";
|
||||
if [ "<debug>" -gt 0 ]; then exit 1; fi
|
||||
exit 0
|
||||
fi
|
||||
IFS=,; ADDRESSES=$(echo $ADDRESSES)
|
||||
IFS=${oifs}
|
||||
IP=<ip>
|
||||
|
|
@ -55,13 +61,11 @@ actionban = oifs=${IFS};
|
|||
TLP=<tlp>
|
||||
PORT=<port>
|
||||
DATE=`LC_ALL=C date --date=@<time> +"%%a, %%d %%h %%Y %%T %%z"`
|
||||
if [ ! -z "$ADDRESSES" ]; then
|
||||
oifs=${IFS}; IFS=,; ADDRESSES=$(echo $ADDRESSES)
|
||||
IFS=${oifs}
|
||||
(printf -- %%b "<header>\n<message>\n<report>\n\n";
|
||||
date '+Note: Local timezone is %%z (%%Z)';
|
||||
printf -- %%b "\n<ipmatches>\n\n<footer>") | <mailcmd> <mailargs> $ADDRESSES
|
||||
fi
|
||||
oifs=${IFS}; IFS=,; ADDRESSES=$(echo $ADDRESSES)
|
||||
IFS=${oifs}
|
||||
(printf -- %%b "<header>\n<message>\n<report>\n\n";
|
||||
date '+Note: Local timezone is %%z (%%Z)';
|
||||
printf -- %%b "\n<ipmatches>\n\n<footer>") | <mailcmd> <mailargs> $ADDRESSES
|
||||
|
||||
actionunban =
|
||||
|
||||
|
|
|
|||
|
|
@ -10,7 +10,8 @@
|
|||
badbotscustom = EmailCollector|WebEMailExtrac|TrackBack/1\.02|sogou music spider|(?:Mozilla/\d+\.\d+ )?Jorgee
|
||||
badbots = Atomic_Email_Hunter/4\.0|atSpider/1\.0|autoemailspider|bwh3_user_agent|China Local Browse 2\.6|ContactBot/0\.2|ContentSmartz|DataCha0s/2\.0|DBrowse 1\.4b|DBrowse 1\.4d|Demo Bot DOT 16b|Demo Bot Z 16b|DSurf15a 01|DSurf15a 71|DSurf15a 81|DSurf15a VA|EBrowse 1\.4b|Educate Search VxB|EmailSiphon|EmailSpider|EmailWolf 1\.00|ESurf15a 15|ExtractorPro|Franklin Locator 1\.8|FSurf15a 01|Full Web Bot 0416B|Full Web Bot 0516B|Full Web Bot 2816B|Guestbook Auto Submitter|Industry Program 1\.0\.x|ISC Systems iRc Search 2\.1|IUPUI Research Bot v 1\.9a|LARBIN-EXPERIMENTAL \(efp@gmx\.net\)|LetsCrawl\.com/1\.0 \+http\://letscrawl\.com/|Lincoln State Web Browser|LMQueueBot/0\.2|LWP\:\:Simple/5\.803|Mac Finder 1\.0\.xx|MFC Foundation Class Library 4\.0|Microsoft URL Control - 6\.00\.8xxx|Missauga Locate 1\.0\.0|Missigua Locator 1\.9|Missouri College Browse|Mizzu Labs 2\.2|Mo College 1\.9|MVAClient|Mozilla/2\.0 \(compatible; NEWT ActiveX; Win32\)|Mozilla/3\.0 \(compatible; Indy Library\)|Mozilla/3\.0 \(compatible; scan4mail \(advanced version\) http\://www\.peterspages\.net/?scan4mail\)|Mozilla/4\.0 \(compatible; Advanced Email Extractor v2\.xx\)|Mozilla/4\.0 \(compatible; Iplexx Spider/1\.0 http\://www\.iplexx\.at\)|Mozilla/4\.0 \(compatible; MSIE 5\.0; Windows NT; DigExt; DTS Agent|Mozilla/4\.0 efp@gmx\.net|Mozilla/5\.0 \(Version\: xxxx Type\:xx\)|NameOfAgent \(CMS Spider\)|NASA Search 1\.0|Nsauditor/1\.x|PBrowse 1\.4b|PEval 1\.4b|Poirot|Port Huron Labs|Production Bot 0116B|Production Bot 2016B|Production Bot DOT 3016B|Program Shareware 1\.0\.2|PSurf15a 11|PSurf15a 51|PSurf15a VA|psycheclone|RSurf15a 41|RSurf15a 51|RSurf15a 81|searchbot admin@google\.com|ShablastBot 1\.0|snap\.com beta crawler v0|Snapbot/1\.0|Snapbot/1\.0 \(Snap Shots, \+http\://www\.snap\.com\)|sogou develop spider|Sogou Orion spider/3\.0\(\+http\://www\.sogou\.com/docs/help/webmasters\.htm#07\)|sogou spider|Sogou web spider/3\.0\(\+http\://www\.sogou\.com/docs/help/webmasters\.htm#07\)|sohu agent|SSurf15a 11 |TSurf15a 11|Under the Rainbow 2\.2|User-Agent\: Mozilla/4\.0 \(compatible; MSIE 6\.0; Windows NT 5\.1\)|VadixBot|WebVulnCrawl\.unknown/1\.0 libwww-perl/5\.803|Wells Search II|WEP Search 00
|
||||
|
||||
failregex = ^<HOST> -.*"(GET|POST|HEAD).*HTTP.*"(?:%(badbots)s|%(badbotscustom)s)"$
|
||||
vhostpref = (?:[\w]+[\w\-\.]*\s+)?
|
||||
failregex = ^\s*%(vhostpref)s<ADDR> [^"]*"[A-Z]{3,10} [^"]+" \d+ \d+ "[^"]+" "[^"]*(?:%(badbots)s|%(badbotscustom)s)"$
|
||||
|
||||
ignoreregex =
|
||||
|
||||
|
|
|
|||
|
|
@ -2,7 +2,8 @@
|
|||
|
||||
[Definition]
|
||||
|
||||
failregex = ^\s*<HOST> \S+ \S+(?: \S+)?\s+\S+ "[A-Z]+ /\S* [^"]*" \d+ \d+ \"[^"]*\" "[^"]*\bGooglebot/[^"]*"
|
||||
vhostpref = (?:[\w]+[\w\-\.]*\s+)?
|
||||
failregex = ^\s*%(vhostpref)s<ADDR> [^"]*"[A-Z]{3,10} /\S* [^"]*" \d+ \d+ "[^"]*" "[^"]*\bGooglebot/[^"]*"
|
||||
|
||||
ignoreregex =
|
||||
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ failregex = ^Registration from '[^']*' failed for '<HOST>(:\d+)?' - (?:Wrong pas
|
|||
^hacking attempt detected '<HOST>'$
|
||||
^SecurityEvent="(?:FailedACL|InvalidAccountID|ChallengeResponseFailed|InvalidPassword)"(?:(?:,(?!RemoteAddress=)\w+="[^"]*")*|.*?),RemoteAddress="IPV[46]/[^/"]+/<HOST>/\d+"(?:,(?!RemoteAddress=)\w+="[^"]*")*$
|
||||
^"Rejecting unknown SIP connection from <HOST>(?::\d+)?"$
|
||||
^Request (?:'[^']*' )?from '(?:[^']*|.*?)' failed for '<HOST>(?::\d+)?'\s\(callid: [^\)]*\) - (?:No matching endpoint found|Not match Endpoint(?: Contact)? ACL|(?:Failed|Error) to authenticate)\s*$
|
||||
^Request (?:'[^']*' )?from '(?:[^']*|.*?)' failed for '<HOST>(?::\d+)?'\s\(callid: [^\)]*\) - (?:No matching endpoint found|Not match Endpoint(?: Contact)? ACL|(?:Failed|Error) to authenticate)\b[^']*$
|
||||
|
||||
# FreePBX (todo: make optional in v.0.10):
|
||||
# ^(%(__prefix_line)s|\[\]\s*WARNING%(__pid_re)s:?(?:\[C-[\da-f]*\])? )[^:]+: Friendly Scanner from <HOST>$
|
||||
|
|
|
|||
|
|
@ -16,12 +16,12 @@ _bypass_reject_reason = (?:: (?:\w+\([^\):]*\) \w+|[^\(]+))*
|
|||
prefregex = ^%(__prefix_line)s(?:%(_auth_worker)s(?:\([^\)]+\))?: )?(?:%(__pam_auth)s(?:\(dovecot:auth\))?: |(?:pop3|imap|managesieve|submission)-login: )?(?:Info: )?%(_auth_worker_info)s<F-CONTENT>.+</F-CONTENT>$
|
||||
|
||||
failregex = ^authentication failure; logname=<F-ALT_USER1>\S*</F-ALT_USER1> uid=\S* euid=\S* tty=dovecot ruser=<F-USER>\S*</F-USER> rhost=<HOST>(?:\s+user=<F-ALT_USER>\S*</F-ALT_USER>)?\s*$
|
||||
^(?:Login aborted|Aborted login|Disconnected|Remote closed connection|Client has quit the connection)%(_bypass_reject_reason)s \((?:auth failed, \d+ attempts(?: in \d+ secs)?|tried to use (?:disabled|disallowed) \S+ auth|proxy dest auth failed)\)(?: \(auth_failed\))?:(?: user=<<F-USER>[^>]*</F-USER>>,)?(?: method=\S+,)? rip=<HOST>(?:[^>]*(?:, session=<\S+>)?)\s*$
|
||||
^(?:Login aborted|Aborted login|Disconnected|Remote closed connection|Client has quit the connection)%(_bypass_reject_reason)s \((?:auth failed, \d+ attempts(?: in \d+ secs)?|tried to use (?:disabled|disallowed) \S+ auth|proxy dest auth failed)\)[^:]*:(?: user=<<F-USER>[^>]*</F-USER>>,)?(?: method=\S+,)? rip=<HOST>(?:[^>]*(?:, session=<\S+>)?)\s*$
|
||||
^pam\(\S+,<HOST>(?:,\S*)?\): pam_authenticate\(\) failed: (?:User not known to the underlying authentication module: \d+ Time\(s\)|Authentication failure \([Pp]assword mismatch\?\)|Permission denied)\s*$
|
||||
^[a-z\-]{3,15}\(\S*,<HOST>(?:,\S*)?\): (?:[Uu]nknown user|[Ii]nvalid credentials|[Pp]assword mismatch)
|
||||
<mdre-<mode>>
|
||||
|
||||
mdre-aggressive = ^(?:Aborted login|Disconnected|Remote closed connection|Client has quit the connection)%(_bypass_reject_reason)s \((?:no auth attempts|disconnected before auth was ready,|client didn't finish \S+ auth,)(?: (?:in|waited) \d+ secs)?\):(?: user=<[^>]*>,)?(?: method=\S+,)? rip=<HOST>(?:[^>]*(?:, session=<\S+>)?)\s*$
|
||||
mdre-aggressive = ^(?:Login aborted|Aborted login|Disconnected|Remote closed connection|Client has quit the connection)%(_bypass_reject_reason)s \((?:no auth attempts|disconnected before auth was ready,|client didn't finish \S+ auth,|disconnected during TLS handshake)(?: (?:in|waited) \d+ secs)?\)[^:]*:(?: user=<[^>]*>,)?(?: method=\S+,)? rip=<HOST>(?:[^>]*(?:, session=<\S+>)?)\s*$
|
||||
|
||||
mdre-normal =
|
||||
|
||||
|
|
|
|||
|
|
@ -1,11 +1,15 @@
|
|||
# Fail2Ban configuration file to block repeated failed login attempts to Frolor installation(s)
|
||||
#
|
||||
# Froxlor needs to log to Syslog User (e.g. /var/log/user.log) with one of the following messages
|
||||
# <syslog prefix> Froxlor: [Login Action <HOST>] Unknown user '<USER>' tried to login.
|
||||
# <syslog prefix> Froxlor: [Login Action <HOST>] User '<USER>' tried to login with wrong password.
|
||||
# - for type=2
|
||||
# <syslog prefix> froxlor[1-6]: froxlor.WARNING: Unknown user tried to login. {"source":"login","action":"50","user":"<ADDR>"} []
|
||||
# <syslog prefix> froxlor[1-6]: froxlor.WARNING: User tried to login with wrong password. {"source":"login","action":"50","user":"<ADDR>"} []
|
||||
# - for type=1:
|
||||
# <syslog prefix> Froxlor: [Login Action <ADDR>] Unknown user '<USER>' tried to login.
|
||||
# <syslog prefix> Froxlor: [Login Action <ADDR>] User '<USER>' tried to login with wrong password.
|
||||
#
|
||||
# Author: Joern Muehlencord
|
||||
#
|
||||
# Modified: Para-do-x™️ - Andreas Duennwald
|
||||
|
||||
[INCLUDES]
|
||||
|
||||
|
|
@ -13,28 +17,18 @@
|
|||
# common.local
|
||||
before = common.conf
|
||||
|
||||
[DEFAULT]
|
||||
_daemon = [Ff]roxlor
|
||||
|
||||
_re = (?:Unknown )?[uU]ser(?: '<F-USER>(?:\S*|[^']*)</F-USER>')? tried to login(?: with wrong password)?\.
|
||||
|
||||
[type1]
|
||||
failregex = ^%(__prefix_line)s\[Login Action <ADDR>\] %(_re)s$
|
||||
|
||||
[type2]
|
||||
failregex = ^%(__prefix_line)sfroxlor\.WARNING: %(_re)s \{(?:"[^"]+":"[^"]*",\s*){,5}"user":"<ADDR>"\} \[\]$
|
||||
|
||||
[Definition]
|
||||
|
||||
_daemon = Froxlor
|
||||
|
||||
# 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
|
||||
#
|
||||
|
||||
prefregex = ^%(__prefix_line)s\[Login Action <HOST>\] <F-CONTENT>.+</F-CONTENT>$
|
||||
|
||||
failregex = ^Unknown user \S* tried to login.$
|
||||
^User \S* tried to login with wrong password.$
|
||||
|
||||
|
||||
# Option: ignoreregex
|
||||
# Notes.: regex to ignore. If this regex matches, the line is ignored.
|
||||
# Values: TEXT
|
||||
#
|
||||
type = 2
|
||||
failregex = <type<type>/failregex>
|
||||
ignoreregex =
|
||||
|
||||
|
|
|
|||
|
|
@ -8,16 +8,18 @@ before = nginx-error-common.conf
|
|||
|
||||
mode = normal
|
||||
|
||||
__err_type = <_ertp-<mode>>
|
||||
__err_type = (?:error|crit)
|
||||
|
||||
_ertp-auth = error
|
||||
mdre-auth = ^%(__prefix_line)suser "(?:[^"]+|.*?)":? (?:password mismatch|was not found in "[^\"]*"), client: <HOST>, server: \S*, request: "\S+ \S+ HTTP/\d+\.\d+", host: "\S+"(?:, referrer: "\S+")?\s*$
|
||||
_ertp-fallback = crit
|
||||
mdre-fallback = ^%(__prefix_line)sSSL_do_handshake\(\) failed \(SSL: error:\S+(?: \S+){1,3} too (?:long|short)\)[^,]*, client: <HOST>
|
||||
__suffix_line = , client: <ADDR>(?:, (?:server|request|host|referrer): (?:"[^"]*"|\S*)){0,4}
|
||||
|
||||
prefregex = ^%(__prefix_line)s<F-CONTENT>.*</F-CONTENT>%(__suffix_line)s\s*$
|
||||
|
||||
mdre-auth = ^user "<F-USER>(?:[^"]+|.*?)</F-USER>":? (?:password mismatch|was not found in "[^\"]*")$
|
||||
^(?:PAM: )?user '<F-USER>(?:[^']+|.*?)</F-USER>' - not authenticated: Authentication failure$
|
||||
mdre-fallback = ^SSL_(?:do_handshake|read)\(\) failed \(SSL: error:\S+(?: \S+){1,3}[^\)]*\)[^,]*
|
||||
|
||||
_ertp-normal = %(_ertp-auth)s
|
||||
mdre-normal = %(mdre-auth)s
|
||||
_ertp-aggressive = (?:%(_ertp-auth)s|%(_ertp-fallback)s)
|
||||
|
||||
mdre-aggressive = %(mdre-auth)s
|
||||
%(mdre-fallback)s
|
||||
|
||||
|
|
|
|||
|
|
@ -46,7 +46,7 @@ __err_type = [a-z]+
|
|||
# failregex = ^%(__prefix_line)slimiting requests, excess: [\d\.]+ by zone "(?:%(ngx_limit_req_zones)s)", client: <HOST>, server: \S*, request: "\S+ \S+ HTTP/\d+\.\d+", host: "\S+"(, referrer: "\S+")?\s*$
|
||||
|
||||
# Shortly, much faster and stable version of regexp:
|
||||
failregex = ^%(__prefix_line)slimiting requests, excess: [\d\.]+ by zone "(?:%(ngx_limit_req_zones)s)", client: <HOST>,
|
||||
failregex = ^%(__prefix_line)s(?:limiting|delaying) (?:request|connection)s?(?:, excess: [\d\.]+,?)? by zone "(?:%(ngx_limit_req_zones)s)", client: <ADDR>,
|
||||
|
||||
ignoreregex =
|
||||
|
||||
|
|
|
|||
|
|
@ -11,49 +11,62 @@ before = common.conf
|
|||
[Definition]
|
||||
|
||||
_daemon = postfix\b([^\[\s]+)?
|
||||
# optional port:
|
||||
_port = (?::\d+)?
|
||||
_pref = [A-Z]{4,}
|
||||
# optional prefix like `NOQUEUE: ` or `00ADB3C0899: ` etc...
|
||||
_pref = (?:\w+: )?
|
||||
# SMTP commands like RCPT etc
|
||||
_cmd = [A-Z]{4,}
|
||||
|
||||
prefregex = ^%(__prefix_line)s<mdpr-<mode>> <F-CONTENT>.+</F-CONTENT>$
|
||||
prefregex = ^%(__prefix_line)s%(_pref)s<mdpr-<mode>> <F-CONTENT>.+?</F-CONTENT>(?:, sasl_username=<F-USER>\S+</F-USER>)?\s*$
|
||||
|
||||
# Extended RE for normal mode to match reject by unknown users or undeliverable address, can be set to empty to avoid this:
|
||||
exre-user = |[Uu](?:ser unknown|ndeliverable address) ; pragma: codespell-ignore
|
||||
|
||||
mdpr-normal = (?:\w+: (?:milter-)?reject:|(?:improper command pipelining|too many errors) after \S+)
|
||||
mdre-normal=^%(_pref)s from [^[]*\[<HOST>\]%(_port)s: [45][50][04] [45]\.\d\.\d+ (?:(?:<[^>]*>)?: )?(?:(?:Helo command|(?:Sender|Recipient) address) rejected: )?(?:Service unavailable|Access denied|(?:Client host|Command|Data command) rejected|Relay access denied|Malformed DNS server reply|(?:Host|Domain) not found|need fully-qualified hostname|match%(exre-user)s)\b
|
||||
mdpr-normal = (?:(?:milter-)?reject:|(?:improper command pipelining|too many errors) after \S+)
|
||||
mdre-normal=^%(_cmd)s from [^[]*\[<HOST>\]%(_port)s: [45][50][04] [45]\.\d\.\d+ (?:(?:<[^>]*>)?: )?(?:(?:Helo command|(?:Sender|Recipient) address) rejected: )?(?:Service unavailable|Access denied|(?:Client host|Command|Data command) rejected|Relay access denied|Malformed DNS server reply|(?:Host|Domain) not found|need fully-qualified hostname|match%(exre-user)s)\b
|
||||
^from [^[]*\[<HOST>\]%(_port)s:?
|
||||
mdad-normal =
|
||||
|
||||
mdpr-auth = warning:
|
||||
mdre-auth = ^[^[]*\[<HOST>\]%(_port)s: SASL ((?i)LOGIN|PLAIN|(?:CRAM|DIGEST)-MD5) authentication failed:(?! Connection lost to authentication server| Invalid authentication mechanism)
|
||||
mdre-auth2= ^[^[]*\[<HOST>\]%(_port)s: SASL ((?i)LOGIN|PLAIN|(?:CRAM|DIGEST)-MD5) authentication failed:(?! Connection lost to authentication server)
|
||||
# todo: check/remove "Invalid authentication mechanism" from ignore list, if gh-1243 will get finished (see gh-1297).
|
||||
mdad-auth =
|
||||
mdad-auth2 =
|
||||
|
||||
# Mode "rbl" currently included in mode "normal", but if needed for jail "postfix-rbl" only:
|
||||
mdpr-rbl = %(mdpr-normal)s
|
||||
mdre-rbl = ^%(_pref)s from [^[]*\[<HOST>\]%(_port)s: [45]54 [45]\.7\.1 Service unavailable; Client host \[\S+\] blocked\b
|
||||
mdre-rbl = ^%(_cmd)s from [^[]*\[<HOST>\]%(_port)s: [45]54 [45]\.7\.1 Service unavailable; Client host \[\S+\] blocked\b
|
||||
mdad-rbl =
|
||||
|
||||
# Mode "rbl" currently included in mode "normal" (within 1st rule)
|
||||
mdpr-more = %(mdpr-normal)s
|
||||
mdre-more = %(mdre-normal)s
|
||||
mdad-more =
|
||||
|
||||
# Includes some of the log messages described in
|
||||
# <http://www.postfix.org/POSTSCREEN_README.html>.
|
||||
mdpr-ddos = (?:lost connection after (?!(?:DATA|AUTH)\b)[A-Z]+|disconnect(?= from \S+(?: \S+=\d+)* auth=0/(?:[1-9]|\d\d+))|(?:PREGREET \d+|HANGUP) after \S+|COMMAND (?:TIME|COUNT|LENGTH) LIMIT)
|
||||
mdpr-ddos = (?:lost connection after (?!(?:DATA|AUTH)\b)[A-Z]+|disconnect(?= from \S+(?: \S+=\d+)* auth=0/(?:[1-9]|\d\d+))|(?:PREGREET \d+|HANGUP) after \S+|COMMAND (?:TIME|COUNT|LENGTH) LIMIT|warning:)
|
||||
mdre-ddos = ^from [^[]*\[<HOST>\]%(_port)s:?
|
||||
mdad-ddos = ^(?:Message delivery request|Connection) rate limit exceeded: \d+ from [^[]*\[<ADDR>\]
|
||||
|
||||
mdpr-extra = (?:%(mdpr-auth)s|%(mdpr-normal)s)
|
||||
mdre-extra = %(mdre-auth)s
|
||||
%(mdre-normal)s
|
||||
mdad-extra =
|
||||
|
||||
mdpr-aggressive = (?:%(mdpr-auth)s|%(mdpr-normal)s|%(mdpr-ddos)s)
|
||||
mdre-aggressive = %(mdre-auth2)s
|
||||
%(mdre-normal)s
|
||||
mdad-aggressive = %(mdad-ddos)s
|
||||
|
||||
mdpr-errors = too many errors after \S+
|
||||
mdre-errors = ^from [^[]*\[<HOST>\]%(_port)s$
|
||||
|
||||
mdad-errors =
|
||||
|
||||
failregex = <mdre-<mode>>
|
||||
<mdad-<mode>>
|
||||
|
||||
# Parameter "mode": more (default combines normal and rbl), auth, normal, rbl, ddos, extra or aggressive (combines all)
|
||||
# Usage example (for jail.local):
|
||||
|
|
|
|||
|
|
@ -22,21 +22,28 @@ before = common.conf
|
|||
_daemon = (?:(sm-(mta|acceptingconnections)|sendmail))
|
||||
__prefix_line = %(known/__prefix_line)s(?:\w{14,20}: )?
|
||||
addr = (?:(?:IPv6:)?<IP6>|<IP4>)
|
||||
# mta_dname -- matches name of MTA daemon (typically specified in DAEMON_OPTIONS),
|
||||
# normally something without spaces like MTA-v4 or Deamon0, etc. If it'd contain spaces, one can
|
||||
# rewrite it in jail using `filter = %(known/filter)s[mta_dname="[^,]+"]` or in .local overwrite
|
||||
# of the filter. (we would not use catch-alls here to satisfy obscure artificial case).
|
||||
mta_dname = \S+
|
||||
|
||||
prefregex = ^<F-MLFID>%(__prefix_line)s</F-MLFID><F-CONTENT>.+</F-CONTENT>$
|
||||
prefregex = ^\s*(?:<mail\.[^\>]+> )?<F-MLFID>%(__prefix_line)s</F-MLFID><F-CONTENT>.+</F-CONTENT>$
|
||||
|
||||
cmnfailre = ^ruleset=check_rcpt, arg1=(?P<email><\S+@\S+>), relay=(\S+ )?\[%(addr)s\](?: \(may be forged\))?, reject=(?:550 5\.7\.1(?: (?P=email)\.\.\.)?(?: Relaying denied\.)? (?:IP name possibly forged \[(\d+\.){3}\d+\]|Proper authentication required\.|IP name lookup failed \[(\d+\.){3}\d+\]|Fix reverse DNS for \S+)|553 5\.1\.8(?: (?P=email)\.\.\.)? Domain of sender address \S+ does not exist|550 5\.[71]\.1 (?P=email)\.\.\. (Rejected: .*|User unknown))$
|
||||
cmnfailre = ^ruleset=check_rcpt, arg1=(?P<email><\S+@\S+>), relay=(\S+ )?\[%(addr)s\](?: \(may be forged\))?, reject=(?:550 5\.7\.1(?: (?P=email)\.\.\.)?(?: Relaying denied\.)? (?:IP name possibly forged \[(\d+\.){3}\d+\]|Proper authentication required\.|IP name lookup failed \[(\d+\.){3}\d+\]|Fix reverse DNS for \S+)|[45]5[13] [45]\.1\.8(?: (?P=email)\.\.\.)? Domain of sender address \S+ does not (?:exist|resolve)|550 5\.[71]\.1 (?P=email)\.\.\. (Rejected: .*|User unknown))$
|
||||
^ruleset=check_relay(?:, arg\d+=\S*)*, relay=(\S+ )?\[%(addr)s\](?: \(may be forged\))?, reject=421 4\.3\.2 (Connection rate limit exceeded\.|Too many open connections\.)$
|
||||
^rejecting commands from (\S* )?\[%(addr)s\] due to pre-greeting traffic after \d+ seconds$
|
||||
^(?:\S+ )?\[%(addr)s\]: (?:(?i)expn|vrfy) \S+ \[rejected\]$
|
||||
^<[^@]+@[^>]+>\.\.\. No such user here$
|
||||
^<F-NOFAIL>from=<[^@]+@[^>]+></F-NOFAIL>, size=\d+, class=\d+, nrcpts=\d+, bodytype=\w+, proto=E?SMTP, daemon=MTA, relay=\S+ \[%(addr)s\]$
|
||||
^<[^@]+@[^>]+>\.\.\. (?:No such user here|User unknown)$
|
||||
^<F-NOFAIL>from=<[^@]+@[^>]+></F-NOFAIL>, size=\d+, class=\d+, nrcpts=\d+,(?: bodytype=\w+,)? proto=E?SMTP, daemon=%(mta_dname)s, relay=(?:\S+ )?\[%(addr)s\]$
|
||||
|
||||
mdre-normal =
|
||||
|
||||
mdre-extra = ^(?:\S+ )?\[%(addr)s\](?: \(may be forged\))? did not issue \S+ during connection
|
||||
|
||||
mdre-aggressive = %(mdre-extra)s
|
||||
^lost input channel from (?:\S+ )?\[%(addr)s\] to %(mta_dname)s after rcpt$
|
||||
^ruleset=check_rcpt, arg1=(?P<email><\S+@\S+>), relay=(?:\S+ )?\[%(addr)s\](?: \(may be forged\))?, reject=(?:450 4\.4\.0(?: (?P=email)\.\.\.)?(?: Relaying temporarily denied\.)?(?: Cannot resolve PTR record for (\d+\.){3}\d+))$
|
||||
|
||||
failregex = %(cmnfailre)s
|
||||
<mdre-<mode>>
|
||||
|
|
@ -63,6 +70,8 @@ journalmatch = SYSLOG_IDENTIFIER=sm-mta + _SYSTEMD_UNIT=sendmail.service
|
|||
# Note the capture <F-MLFID>, includes both the __prefix_lines (which includes
|
||||
# the sendmail PID), but also the `\w{14}` which the the sendmail assigned
|
||||
# mail ID (todo: check this is necessary, possible obsolete).
|
||||
# Avoid moving <F-MLFID> into the entire prefregex because the grouped messages we
|
||||
# need have different syslog levels (info vs notice) that break the group if BSD verbose format is set
|
||||
#
|
||||
# Author: Daniel Black, Fabian Wenk and Sergey Brester aka sebres.
|
||||
# Rewritten using prefregex by Serg G. Brester.
|
||||
|
|
|
|||
|
|
@ -4,5 +4,5 @@
|
|||
|
||||
[Definition]
|
||||
|
||||
failregex = ^\s*(?:\[\]\s*)?\[vaultwarden::api::(identity||admin||core::two_factor::authenticator)\]\[ERROR\] (Invalid admin token||Invalid TOTP code||Username or password is incorrect)[\.!](?:\s+(?!IP:)\S+)* IP: <ADDR>(?:\. Username: <F-USER>\S+</F-USER>)?
|
||||
failregex = ^\s*(?:\[\]\s*)?\[vaultwarden::api::(?:identity|admin|core::two_factor::authenticator)?\]\[ERROR\] (?:Invalid admin token|Invalid TOTP code|Username or password is incorrect)[\.!](?:\s+(?!IP:)\S+)* IP: <ADDR>(?:\. Username: <F-USER>\S+</F-USER>)?
|
||||
ignoreregex =
|
||||
|
|
|
|||
35
config/filter.d/xrdp.conf
Normal file
35
config/filter.d/xrdp.conf
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
#
|
||||
# Fail2Ban filter for XRDP
|
||||
#
|
||||
# Detects login attempts with invalid credentials
|
||||
#
|
||||
# Requirements:
|
||||
# - xrdp >= 0.9.19
|
||||
# - The log level in sesman.ini should be set to `INFO` or higher
|
||||
# to emit the log messages needed for this filter.
|
||||
#
|
||||
# Author: Evan Linde
|
||||
#
|
||||
|
||||
[INCLUDES]
|
||||
|
||||
# Read common prefixes. If any customizations available -- read them from
|
||||
# common.local
|
||||
before = common.conf
|
||||
|
||||
|
||||
[DEFAULT]
|
||||
|
||||
_daemon = xrdp-sesman
|
||||
|
||||
|
||||
[Definition]
|
||||
|
||||
authfail_re = \[INFO \] AUTHFAIL: user=<F-USER>(?:\S+|.+)</F-USER> ip=<ADDR> time=\d+
|
||||
|
||||
failregex = ^%(__prefix_line)s%(authfail_re)s$
|
||||
|
||||
ignoreregex =
|
||||
|
||||
datepattern = ^\[?%%ExY%%Exm%%Exd-%%ExH:%%ExM:%%ExS\]?
|
||||
^{DATE}
|
||||
|
|
@ -227,14 +227,11 @@ action_mwl = %(action_)s
|
|||
action_xarf = %(action_)s
|
||||
xarf-login-attack[service=%(__name__)s, sender="%(sender)s", logpath="%(logpath)s", port="%(port)s"]
|
||||
|
||||
# ban & send a notification to one or more of the 50+ services supported by Apprise.
|
||||
# See https://github.com/caronc/apprise/wiki for details on what is supported.
|
||||
#
|
||||
# You may optionally over-ride the default configuration line (containing the Apprise URLs)
|
||||
# by using 'apprise[config="/alternate/path/to/apprise.cfg"]' otherwise
|
||||
# /etc/fail2ban/apprise.conf is sourced for your supported notification configuration.
|
||||
# ban & send a notification to one or more of the 120+ services supported by Apprise.
|
||||
# action = %(action_)s
|
||||
# apprise
|
||||
# apprise[config="/alternate/path/to/apprise.yaml", args='--tag fail2ban']
|
||||
# See https://appriseit.com/services/ for details on what is supported.
|
||||
# Or action.d/apprise.conf for more details how to configure or customize it.
|
||||
|
||||
# ban IP on CloudFlare & send an e-mail with whois report and relevant log lines
|
||||
# to the destemail.
|
||||
|
|
@ -501,7 +498,7 @@ backend = %(syslog_backend)s
|
|||
[froxlor-auth]
|
||||
|
||||
port = http,https
|
||||
logpath = %(syslog_authpriv)s
|
||||
logpath = %(syslog_user)s
|
||||
backend = %(syslog_backend)s
|
||||
|
||||
|
||||
|
|
@ -724,8 +721,7 @@ backend = %(syslog_backend)s
|
|||
# Since UDP is connection-less protocol, spoofing of IP and imitation
|
||||
# of illegal actions is way too simple. Thus enabling of this filter
|
||||
# might provide an easy way for implementing a DoS against a chosen
|
||||
# victim. See
|
||||
# http://nion.modprobe.de/blog/archives/690-fail2ban-+-dns-fail.html
|
||||
# victim.
|
||||
# Please DO NOT USE this jail unless you know what you are doing.
|
||||
#
|
||||
# IMPORTANT: see filter.d/named-refused for instructions to enable logging
|
||||
|
|
@ -995,3 +991,7 @@ logpath = /var/log/daemon.log
|
|||
[vaultwarden]
|
||||
port = http,https
|
||||
logpath = /var/log/vaultwarden.log
|
||||
|
||||
[xrdp]
|
||||
port = 3389
|
||||
logpath = /var/log/xrdp-sesman.log
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ banaction = nftables
|
|||
banaction_allports = nftables[type=allports]
|
||||
|
||||
sshd_backend = systemd
|
||||
postfix_backend = systemd
|
||||
|
||||
syslog_mail = /var/log/mail.log
|
||||
|
||||
|
|
|
|||
|
|
@ -212,8 +212,8 @@ class Beautifier:
|
|||
else:
|
||||
msg = "These IP addresses/networks are ignored:\n"
|
||||
for ip in response[:-1]:
|
||||
msg += "|- " + ip + "\n"
|
||||
msg += "`- " + response[-1]
|
||||
msg += "|- " + str(ip) + "\n"
|
||||
msg += "`- " + str(response[-1])
|
||||
elif inC[2] in ("failregex", "addfailregex", "delfailregex",
|
||||
"ignoreregex", "addignoreregex", "delignoreregex"):
|
||||
if len(response) == 0:
|
||||
|
|
|
|||
|
|
@ -354,6 +354,11 @@ class DefinitionInitConfigReader(ConfigReader):
|
|||
if v is None: v = getopt(opt)
|
||||
self._initOpts['known/'+opt] = v
|
||||
if opt not in self._initOpts:
|
||||
# overwrite also conditional init options (from init?... section):
|
||||
cond = SafeConfigParserWithIncludes.CONDITIONAL_RE.match(opt)
|
||||
if cond:
|
||||
optc, cond = cond.groups()
|
||||
v = pOpts.get(optc, v)
|
||||
if v is None: v = getopt(opt)
|
||||
self._initOpts[opt] = v
|
||||
if all and self.has_section("Definition"):
|
||||
|
|
|
|||
|
|
@ -89,7 +89,7 @@ class FilterReader(DefinitionInitConfigReader):
|
|||
stream.insert(0 if opt == 'usedns' else prio0idx,
|
||||
["set", jailName, opt, value])
|
||||
prio0idx += 1
|
||||
elif opt in ('datepattern'):
|
||||
elif opt == 'datepattern':
|
||||
stream.append(["set", jailName, opt, value])
|
||||
elif opt == 'journalmatch':
|
||||
for match in value.split("\n"):
|
||||
|
|
|
|||
|
|
@ -323,15 +323,17 @@ def _merge_copy_dicts(x, y):
|
|||
|
||||
# regex, to extract list of options:
|
||||
OPTION_CRE = re.compile(r"^([^\[]+)(?:\[(.*)\])?\s*$", re.DOTALL)
|
||||
# regex, matching option name (inclusive conditional option, like n?family=inet6):
|
||||
OPTION_NAME_CRE = r'[\w\-_\.]+(?:\?[\w\-_\.]+=[\w\-_\.]+)?'
|
||||
# regex, to iterate over single option in option list, syntax:
|
||||
# `action = act[p1="...", p2='...', p3=...]`, where the p3=... not contains `,` or ']'
|
||||
# since v0.10 separator extended with `]\s*[` for support of multiple option groups, syntax
|
||||
# `action = act[p1=...][p2=...]`
|
||||
OPTION_EXTRACT_CRE = re.compile(
|
||||
r'\s*([\w\-_\.]+)=(?:"([^"]*)"|\'([^\']*)\'|([^,\]]*))(?:,|\]\s*\[|$|(?P<wrngA>.+))|,?\s*$|(?P<wrngB>.+)', re.DOTALL)
|
||||
r'\s*('+OPTION_NAME_CRE+r')=(?:"([^"]*)"|\'([^\']*)\'|([^,\]]*))(?:,|\]\s*\[|$|(?P<wrngA>.+))|,?\s*$|(?P<wrngB>.+)', re.DOTALL)
|
||||
# split by new-line considering possible new-lines within options [...]:
|
||||
OPTION_SPLIT_CRE = re.compile(
|
||||
r'(?:[^\[\s]+(?:\s*\[\s*(?:[\w\-_\.]+=(?:"[^"]*"|\'[^\']*\'|[^,\]]*)\s*(?:,|\]\s*\[)?\s*)*\])?\s*|\S+)(?=\n\s*|\s+|$)', re.DOTALL)
|
||||
r'(?:[^\[\s]+(?:\s*\[\s*(?:'+OPTION_NAME_CRE+r'=(?:"[^"]*"|\'[^\']*\'|[^,\]]*)\s*(?:,|\]\s*\[)?\s*)*\])?\s*|\S+)(?=\n\s*|\s+|$)', re.DOTALL)
|
||||
|
||||
def extractOptions(option):
|
||||
match = OPTION_CRE.match(option)
|
||||
|
|
|
|||
|
|
@ -394,6 +394,7 @@ class Actions(JailThread, Mapping):
|
|||
# raw ticket info:
|
||||
"raw-ticket": lambda self: repr(self.__ticket),
|
||||
# jail info:
|
||||
"jail.name": lambda self: self.__jail.name,
|
||||
"jail.banned": lambda self: self.__jail.actions.banManager.size(),
|
||||
"jail.banned_total": lambda self: self.__jail.actions.banManager.getBanTotal(),
|
||||
"jail.found": lambda self: self.__jail.filter.failManager.size(),
|
||||
|
|
@ -640,12 +641,12 @@ class Actions(JailThread, Mapping):
|
|||
If actions specified, don't flush list - just execute unban for
|
||||
given actions (reload, obsolete resp. removed actions).
|
||||
"""
|
||||
log = True
|
||||
log = "Unban" if not stop else "Repeal Ban"
|
||||
if actions is None:
|
||||
logSys.debug(" Flush ban list")
|
||||
lst = self.banManager.flushBanList()
|
||||
else:
|
||||
log = False # don't log "[jail] Unban ..." if removing actions only.
|
||||
log = None # don't log "[jail] Unban ..." if removing actions only.
|
||||
lst = iter(self.banManager)
|
||||
cnt = 0
|
||||
# first we'll execute flush for actions supporting this operation:
|
||||
|
|
@ -686,7 +687,7 @@ class Actions(JailThread, Mapping):
|
|||
cnt, self.banManager.size(), self._jail.name)
|
||||
return cnt
|
||||
|
||||
def __unBan(self, ticket, actions=None, log=True):
|
||||
def __unBan(self, ticket, actions=None, log="Unban"):
|
||||
"""Unbans host corresponding to the ticket.
|
||||
|
||||
Executes the actions in order to unban the host given in the
|
||||
|
|
@ -704,7 +705,7 @@ class Actions(JailThread, Mapping):
|
|||
ip = ticket.getID()
|
||||
aInfo = self._getActionInfo(ticket)
|
||||
if log:
|
||||
logSys.notice("[%s] Unban %s", self._jail.name, ip)
|
||||
logSys.notice("[%s] %s %s", self._jail.name, log, ip)
|
||||
for name, action in unbactions.items():
|
||||
try:
|
||||
logSys.debug("[%s] action %r: unban %s", self._jail.name, name, ip)
|
||||
|
|
|
|||
|
|
@ -165,8 +165,8 @@ class DateDetectorCache(object):
|
|||
r"%b %d, %ExY %I:%M:%S %p",
|
||||
# ASSP: Apr-27-13 02:33:06
|
||||
r"^%b-%d-%Exy %k:%M:%S",
|
||||
# 20050123T215959, 20050123 215959, 20050123 85959
|
||||
r"%ExY%Exm%Exd(?:T| ?)%ExH%ExM%ExS(?:[.,]%f)?(?:\s*%z)?",
|
||||
# 20050123T215959, 20050123 215959, 20050123 85959, 20050123-21:59:59
|
||||
r"%ExY%Exm%Exd(?:-|T| ?)%ExH:?%ExM:?%ExS(?:[.,]%f)?(?:\s*%z)?",
|
||||
# prefixed with optional named time zone (monit):
|
||||
# PDT Apr 16 21:05:29
|
||||
r"(?:%Z )?(?:%a )?%b %d %k:%M:%S(?:\.%f)?(?: %ExY)?",
|
||||
|
|
@ -252,6 +252,8 @@ class DateDetector(object):
|
|||
"There is already a template with name %s" % name)
|
||||
self.__known_names.add(name)
|
||||
self.__templates.append(DateDetectorTemplate(template))
|
||||
logSys.debug(" date pattern regex for `%s`: `%s`",
|
||||
getattr(template, 'pattern', ''), template.regex)
|
||||
|
||||
def appendTemplate(self, template):
|
||||
"""Add a date template to manage and use in search of dates.
|
||||
|
|
@ -289,16 +291,15 @@ class DateDetector(object):
|
|||
|
||||
DD_patternCache.set(key, template)
|
||||
|
||||
self._appendTemplate(template)
|
||||
logSys.info(" date pattern `%r`: `%s`",
|
||||
logSys.info(" date pattern `%s`: `%s`",
|
||||
getattr(template, 'pattern', ''), template.name)
|
||||
logSys.debug(" date pattern regex for %r: %s",
|
||||
getattr(template, 'pattern', ''), template.regex)
|
||||
self._appendTemplate(template)
|
||||
|
||||
def addDefaultTemplate(self, filterTemplate=None, preMatch=None, allDefaults=True):
|
||||
"""Add Fail2Ban's default set of date templates.
|
||||
"""
|
||||
ignoreDup = len(self.__templates) > 0
|
||||
cnt = 0
|
||||
for template in (
|
||||
DateDetector._defCache.templates if allDefaults else DateDetector._defCache.defaultTemplates
|
||||
):
|
||||
|
|
@ -311,6 +312,11 @@ class DateDetector(object):
|
|||
wrap=lambda s: RE_DATE_PREMATCH.sub(lambda m: DateTemplate.unboundPattern(s), preMatch))
|
||||
# append date detector template (ignore duplicate if some was added before default):
|
||||
self._appendTemplate(template, ignoreDup=ignoreDup)
|
||||
cnt += 1
|
||||
if preMatch:
|
||||
logSys.info(" default date pattern for `%r`: %d template(s)", preMatch, cnt)
|
||||
else:
|
||||
logSys.info(" default %sdate pattern: %d template(s)", "filtered " if filterTemplate else "", cnt)
|
||||
|
||||
@property
|
||||
def templates(self):
|
||||
|
|
|
|||
|
|
@ -475,6 +475,10 @@ class Filter(JailThread):
|
|||
# Generate the failure attempt for the IP:
|
||||
unixTime = MyTime.time()
|
||||
ticket = FailTicket(ip, unixTime, matches=matches)
|
||||
# check it shall be ignored:
|
||||
if self._inIgnoreIPList(ip, ticket):
|
||||
return 0
|
||||
# add attempt (found failure):
|
||||
logSys.info(
|
||||
"[%s] Attempt %s - %s", self.jailName, ip, datetime.datetime.fromtimestamp(unixTime).strftime("%Y-%m-%d %H:%M:%S")
|
||||
)
|
||||
|
|
@ -485,7 +489,6 @@ class Filter(JailThread):
|
|||
# report to observer - failure was found, for possibly increasing of it retry counter (asynchronous)
|
||||
if Observers.Main is not None:
|
||||
Observers.Main.add('failureFound', self.jail, ticket)
|
||||
|
||||
return 1
|
||||
|
||||
##
|
||||
|
|
@ -1111,8 +1114,8 @@ class FileFilter(Filter):
|
|||
def getFailures(self, filename, inOperation=None):
|
||||
if self.idle: return False
|
||||
log = self.getLog(filename)
|
||||
if log is None:
|
||||
logSys.error("Unable to get failures in %s", filename)
|
||||
if log is None and self.active:
|
||||
logSys.log(logging.MSG, "Unable to get failures in %s", filename)
|
||||
return False
|
||||
# We should always close log (file), otherwise may be locked (log-rotate, etc.)
|
||||
try:
|
||||
|
|
|
|||
|
|
@ -301,7 +301,7 @@ class FilterSystemd(JournalFilter): # pragma: systemd no cover
|
|||
date = logentry.get('_SOURCE_REALTIME_TIMESTAMP')
|
||||
if date is None:
|
||||
date = logentry.get('__REALTIME_TIMESTAMP')
|
||||
return (date.isoformat(), time.mktime(date.timetuple()) + date.microsecond/1.0E6)
|
||||
return (date.isoformat(), date.timestamp())
|
||||
|
||||
##
|
||||
# Format journal log entry into syslog style
|
||||
|
|
|
|||
|
|
@ -739,11 +739,11 @@ class IPAddrSet(set):
|
|||
|
||||
class FileIPAddrSet(IPAddrSet):
|
||||
|
||||
# RE matching file://...
|
||||
RE_FILE_IGN_IP = re.compile(r'^file:/{0,2}(.*)$')
|
||||
# RE matching file://... (absolute as well as relative file name)
|
||||
RE_FILE_IGN_IP = re.compile(r'^file:(?:/{0,2}(?=/(?!/|.{1,2}/))|/{0,2})(.*)$')
|
||||
|
||||
fileName = ''
|
||||
_shortRepr = None
|
||||
_reprName = None
|
||||
maxUpdateLatency = 1 # latency in seconds to update by changes
|
||||
_nextCheck = 0
|
||||
_fileStats = ()
|
||||
|
|
@ -798,12 +798,9 @@ class FileIPAddrSet(IPAddrSet):
|
|||
logSys.warning("Retrieving IPs set from %r failed: %s", self.fileName, e)
|
||||
|
||||
def __repr__(self):
|
||||
if not self._shortRepr:
|
||||
shortfn = os.path.basename(self.fileName)
|
||||
if shortfn != self.fileName:
|
||||
shortfn = '.../' + shortfn
|
||||
self._shortRepr = 'file:' + shortfn + ')'
|
||||
return self._shortRepr
|
||||
if self._reprName is None:
|
||||
self._reprName = 'file:' + ('/' if self.fileName.startswith('/') else '') + self.fileName
|
||||
return self._reprName
|
||||
|
||||
def __contains__(self, ip):
|
||||
# load if needed:
|
||||
|
|
|
|||
|
|
@ -353,7 +353,6 @@ class Transmitter:
|
|||
return self.__server.getBanTime(name)
|
||||
elif command[1] == "attempt":
|
||||
value = command[2:]
|
||||
if self.__quiet: return
|
||||
return self.__server.addAttemptIP(name, *value)
|
||||
elif command[1].startswith("bantime."):
|
||||
value = command[2]
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@ import subprocess
|
|||
import sys
|
||||
from threading import Lock
|
||||
import time
|
||||
import types
|
||||
from ..helpers import getLogger, _merge_dicts, uni_decode
|
||||
from collections import OrderedDict
|
||||
|
||||
|
|
@ -352,6 +353,7 @@ class Utils():
|
|||
def load_python_module(pythonModule):
|
||||
pythonModuleName = os.path.splitext(
|
||||
os.path.basename(pythonModule))[0]
|
||||
mod = importlib.machinery.SourceFileLoader(
|
||||
pythonModuleName, pythonModule).load_module()
|
||||
ldr = importlib.machinery.SourceFileLoader(pythonModuleName, pythonModule)
|
||||
mod = types.ModuleType(ldr.name)
|
||||
ldr.exec_module(mod)
|
||||
return mod
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ import threading
|
|||
import unittest
|
||||
import re
|
||||
import sys
|
||||
import types
|
||||
import importlib
|
||||
|
||||
from ..dummyjail import DummyJail
|
||||
|
|
@ -175,7 +176,8 @@ try:
|
|||
super(SMTPActionTest, self).tearDown()
|
||||
|
||||
except ImportError as e:
|
||||
print("I: Skipping smtp tests: %s" % e)
|
||||
if tuple(sys.version_info) <= (3, 11):
|
||||
print("I: Skipping smtp tests: %s" % e)
|
||||
|
||||
|
||||
try:
|
||||
|
|
@ -295,10 +297,11 @@ try:
|
|||
self.jail = DummyJail()
|
||||
pythonModule = os.path.join(CONFIG_DIR, "action.d", "smtp.py")
|
||||
pythonModuleName = os.path.basename(pythonModule.rstrip(".py"))
|
||||
customActionModule = importlib.machinery.SourceFileLoader(
|
||||
pythonModuleName, pythonModule).load_module()
|
||||
ldr = importlib.machinery.SourceFileLoader(pythonModuleName, pythonModule)
|
||||
mod = types.ModuleType(ldr.name)
|
||||
ldr.exec_module(mod)
|
||||
|
||||
self.action = customActionModule.Action(
|
||||
self.action = mod.Action(
|
||||
self.jail, "test", host="localhost:%i" % self.port)
|
||||
|
||||
self.action.ssl = True
|
||||
|
|
@ -309,4 +312,5 @@ try:
|
|||
super(AIOSMTPActionTest, self).tearDown()
|
||||
|
||||
except ImportError as e:
|
||||
print("I: Skipping SSL smtp tests: %s" % e)
|
||||
if tuple(sys.version_info) >= (3, 10):
|
||||
print("I: Skipping SSL smtp tests: %s" % e)
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ import unittest
|
|||
|
||||
from ..client.beautifier import Beautifier
|
||||
from ..version import version
|
||||
from ..server.ipdns import IPAddr
|
||||
from ..server.ipdns import IPAddr, FileIPAddrSet
|
||||
from ..exceptions import UnknownJailException, DuplicateJailException
|
||||
|
||||
class BeautifierTest(unittest.TestCase):
|
||||
|
|
@ -297,6 +297,13 @@ class BeautifierTest(unittest.TestCase):
|
|||
output += "`- 10.0.2.1"
|
||||
self.assertEqual(self.b.beautify(response), output)
|
||||
|
||||
def testIgnoreIPFile(self):
|
||||
self.b.setInputCmd(["set", "sshd", "addignoreip"])
|
||||
response = [FileIPAddrSet("/test/file-ipaddr-set")]
|
||||
output = ("These IP addresses/networks are ignored:\n"
|
||||
"`- file://test/file-ipaddr-set")
|
||||
self.assertEqual(self.b.beautify(response), output)
|
||||
|
||||
def testFailRegex(self):
|
||||
self.b.setInputCmd(["get", "sshd", "failregex"])
|
||||
output = "No regular expression is defined"
|
||||
|
|
|
|||
|
|
@ -878,7 +878,7 @@ class JailsReaderTest(LogCaptureTestCase):
|
|||
self.assertTrue(jails.getOptions()) # reads fine
|
||||
# grab all filter names
|
||||
filters = set(os.path.splitext(os.path.split(a)[1])[0]
|
||||
for a in glob.glob(os.path.join('config', 'filter.d', '*.conf'))
|
||||
for a in glob.glob(os.path.join(CONFIG_DIR, 'filter.d', '*.conf'))
|
||||
if not (a.endswith('common.conf') or a.endswith('-aggressive.conf')))
|
||||
# get filters of all jails (filter names without options inside filter[...])
|
||||
filters_jail = set(
|
||||
|
|
|
|||
|
|
@ -1125,9 +1125,9 @@ class Fail2banServerTest(Fail2banClientServerBase):
|
|||
"3 ticket(s) in 'test-jail2", all=True, wait=MID_WAITTIME)
|
||||
# stop/start and unban/restore ban:
|
||||
self.assertLogged(
|
||||
"[test-jail2] Unban 192.0.2.4",
|
||||
"[test-jail2] Unban 192.0.2.8",
|
||||
"[test-jail2] Unban 192.0.2.9",
|
||||
"[test-jail2] Repeal Ban 192.0.2.4",
|
||||
"[test-jail2] Repeal Ban 192.0.2.8",
|
||||
"[test-jail2] Repeal Ban 192.0.2.9",
|
||||
"Jail 'test-jail2' stopped",
|
||||
"Jail 'test-jail2' started",
|
||||
"[test-jail2] Restore Ban 192.0.2.4",
|
||||
|
|
|
|||
|
|
@ -6,3 +6,6 @@
|
|||
|
||||
# failJSON: { "time": "2007-03-05T14:41:21", "match": true , "host": "1.2.3.4" }
|
||||
1.2.3.4 - - [05/Mar/2007:14:41:21 +0100] "HEAD /123.html/trackback/ HTTP/1.0" 301 459 "http://www.mydomain.tld/123.html/trackback" "TrackBack/1.02"
|
||||
|
||||
# failJSON: { "time": "2024-08-18T22:08:39", "match": true , "host": "192.0.2.222", "desc": "vhost in accesslog, gh-1594" }
|
||||
www.sitename.com 192.0.2.222 - - [18/Aug/2024:21:08:39 +0100] "GET /filename.jpg HTTP/1.1" 403 332 "-" "TrackBack/1.02"
|
||||
|
|
|
|||
|
|
@ -3,3 +3,5 @@
|
|||
66.249.66.1 - - - [31/Jan/2015:14:29:44 ] fail2ban.org "GET / HTTP/1.1" 200 814 "-" "Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)" + 293 1149 546
|
||||
# failJSON: { "time": "2015-01-31T14:29:44", "match": false, "host": "51.159.55.100" }
|
||||
51.159.55.100 - - - [31/Jan/2015:14:29:44 ] fail2ban.org "GET / HTTP/1.1" 200 814 "-" "NOT A __GOOGLE_BOT__" + 293 1149 546
|
||||
# failJSON: { "time": "2024-08-18T22:08:39", "match": true , "host": "192.0.2.222", "desc": "vhost in accesslog, gh-1594" }
|
||||
www.sitename.com 192.0.2.222 - - [18/Aug/2024:21:08:39 +0100] "GET / HTTP/1.1" 403 332 "-" "Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)"
|
||||
|
|
|
|||
|
|
@ -108,6 +108,8 @@ Nov 4 18:30:40 localhost asterisk[32229]: NOTICE[32257]: chan_sip.c:23417 in han
|
|||
# PJSip Errors
|
||||
# failJSON: { "time": "2016-05-06T07:08:09", "match": true, "host": "192.0.2.6" }
|
||||
[2016-05-06 07:08:09] NOTICE[17103] res_pjsip/pjsip_distributor.c: Request from '"test1" <sip:test1@2.3.4.5>' failed for '192.0.2.6:5678' (callid: deadbeef) - No matching endpoint found
|
||||
# failJSON: { "time": "2016-05-06T07:08:09", "match": true, "host": "192.0.2.7", "desc": "Test for No matching endpoint found with retry counts (pattern 1)" }
|
||||
[2016-05-06 07:08:09] NOTICE[17103] res_pjsip/pjsip_distributor.c: Request 'INVITE' from '"test2" <sip:test2@3.4.5.6>' failed for '192.0.2.7:5679' (callid: cafebabe) - No matching endpoint found after 5 tries in 2.500 ms
|
||||
|
||||
# # FreePBX Warnings
|
||||
# #_dis_failJSON: { "time": "2016-05-06T07:08:09", "match": true, "host": "192.0.2.4" }
|
||||
|
|
|
|||
|
|
@ -147,6 +147,9 @@ Aug 29 15:33:53 server dovecot: managesieve-login: Disconnected: Too many invali
|
|||
|
||||
# failJSON: { "time": "2004-08-29T01:49:33", "match": true , "host": "192.0.2.5", "desc": "matches in aggressive mode, avoid slow RE, gh-3370" }
|
||||
Aug 29 01:49:33 server dovecot[459]: imap-login: Disconnected: Connection closed: read(size=1026) failed: Connection reset by peer (no auth attempts in 0 secs): user=<>, rip=192.0.2.5, lip=127.0.0.1, TLS handshaking: read(size=1026) failed: Connection reset by peer
|
||||
# failJSON: { "time": "2004-08-22T12:09:41", "match": true , "host": "192.0.2.6", "desc": "matches in aggressive mode, new format with `Login aborted` and `(no_auth_attempts)`" }
|
||||
Aug 22 12:09:41 server dovecot: imap-login: Login aborted: Connection closed: read(size=653) failed: Connection reset by peer (no auth attempts in 1 secs) (no_auth_attempts): user=<>, rip=192.0.2.6, lip=192.0.2.1, TLS: read(size=653) failed: Connection reset by peer, session=<qMLsbvY8PLSkXGoP>
|
||||
|
||||
# failJSON: { "time": "2004-08-29T01:49:33", "match": true , "host": "192.0.2.5", "desc": "matches in aggressive mode, avoid slow RE, gh-3370" }
|
||||
Aug 29 01:49:33 server dovecot[459]: imap-login: Disconnected: Connection closed: SSL_accept() failed: error:1408F10B:SSL routines:ssl3_get_record:wrong version number (no auth attempts in 0 secs): user=<>, rip=192.0.2.5, lip=127.0.0.1, TLS handshaking: SSL_accept() failed: error:1408F10B:SSL routines:ssl3_get_record:wrong version number
|
||||
# failJSON: { "time": "2004-08-29T01:49:33", "match": true , "host": "192.0.2.5", "desc": "matches in aggressive mode, avoid slow RE, gh-3370" }
|
||||
|
|
@ -162,3 +165,8 @@ Aug 29 16:06:58 s166-62-100-187 dovecot: imap-login: Disconnected (disconnected
|
|||
Aug 31 16:15:10 s166-62-100-187 dovecot: imap-login: Disconnected (client didn't finish SASL auth, waited 2 secs): user=<>, method=PLAIN, rip=192.0.2.6, lip=192.168.1.2, TLS: SSL_read() syscall failed: Connection reset by peer, TLSv1.2 with cipher DHE-RSA-AES256-GCM-SHA384 (256/256 bits)
|
||||
# failJSON: { "time": "2004-08-31T16:21:53", "match": true , "host": "192.0.2.7" }
|
||||
Aug 31 16:21:53 s166-62-100-187 dovecot: imap-login: Disconnected (no auth attempts in 4 secs): user=<>, rip=192.0.2.7, lip=192.168.1.2, TLS handshaking: SSL_accept() syscall failed: Connection reset by peer
|
||||
|
||||
# failJSON: { "time": "2004-08-22T12:09:41", "match": true , "host": "192.0.2.7", "desc": "disconnected during TLS handshake (no application protocol)" }
|
||||
Aug 22 12:09:41 server dovecot: imap-login: Login aborted: Connection closed: SSL_accept() failed: error:0A0000EB:SSL routines::no application protocol (disconnected during TLS handshake) (tls_handshake_not_finished): user=<>, rip=192.0.2.7, lip=192.0.2.1, TLS handshaking: SSL_accept() failed: error:0A0000EB:SSL routines::no application protocol, session=<J5HwbvY8QrSkXGoP>
|
||||
# failJSON: { "time": "2004-08-22T12:09:41", "match": true , "host": "192.0.2.7", "desc": "disconnected during TLS handshake (no shared cipher)" }
|
||||
Aug 22 12:09:41 server dovecot: imap-login: Login aborted: Connection closed: SSL_accept() failed: error:0A0000C1:SSL routines::no shared cipher (disconnected during TLS handshake) (tls_handshake_not_finished): user=<>, rip=192.0.2.7, lip=192.0.2.1, TLS handshaking: SSL_accept() failed: error:0A0000C1:SSL routines::no shared cipher, session=<Q23ybvY8RLSkXGoP>
|
||||
|
|
|
|||
|
|
@ -1,5 +1,11 @@
|
|||
# filterOptions: [{"type": "1"}]
|
||||
# failJSON: { "time": "2005-05-21T00:56:27", "match": true , "host": "1.2.3.4" }
|
||||
May 21 00:56:27 jomu Froxlor: [Login Action 1.2.3.4] Unknown user 'user' tried to login.
|
||||
# failJSON: { "time": "2005-05-21T00:57:38", "match": true , "host": "1.2.3.4" }
|
||||
May 21 00:57:38 jomu Froxlor: [Login Action 1.2.3.4] User 'admin' tried to login with wrong password.
|
||||
|
||||
# filterOptions: [{}, {"type": "2"}]
|
||||
# failJSON: { "time": "2025-09-21T17:46:18", "match": true , "host": "1.2.3.4" }
|
||||
2025-09-21T17:46:18.311379+02:00 hostname froxlor[1055219]: froxlor.WARNING: User tried to login with wrong password. {"source":"login","action":"50","user":"1.2.3.4"} []
|
||||
# failJSON: { "time": "2025-09-21T16:30:13", "match": true , "host": "1.2.3.4" }
|
||||
2025-09-21T16:30:13.118232+02:00 hostname froxlor[1054438]: froxlor.WARNING: Unknown user tried to login. {"source":"login","action":"50","user":"1.2.3.4"} []
|
||||
|
|
|
|||
|
|
@ -13,11 +13,17 @@
|
|||
# failJSON: { "time": "2014-04-03T22:20:40", "match": true, "host": "192.0.2.2", "desc": "trying injection on user name"}
|
||||
2014/04/03 22:20:40 [error] 30708#0: *3 user "test": password mismatch, client: 127.0.0.1, server: test, request: "GET / HTTP/1.1", host: "localhost:8443"": was not found in "/etc/nginx/.htpasswd", client: 192.0.2.2, server: , request: "GET / HTTP/1.1", host: "localhost:8443"
|
||||
|
||||
# failJSON: { "time": "2025-09-07T21:20:40", "match": true, "host": "192.0.2.120", "desc": "PAM auth failure, gh-4071"}
|
||||
2025/09/07 21:20:40 [error] 23141#23141: *24470 PAM: user 'username' - not authenticated: Authentication failure, client: 192.0.2.120, server: webdav.sub.domain, request: "GET / HTTP/2.0", host: "webdav.sub.domain"
|
||||
|
||||
# filterOptions: [{"logtype": "journal"}]
|
||||
|
||||
# failJSON: { "match": true, "host": "192.0.2.3", "desc": "systemd journal message, with optional extra timestamp, gh-3646"}
|
||||
host nginx[983478]: 2023/12/09 21:35:20 [error] 983478#983478: *3 user "fakeusername" was not found in "/var/lib/nginx/htpasswd-for-host.example.com", client: 192.0.2.3, server: host.example.com, request: "GET / HTTP/2.0", host: "host.example.com"
|
||||
|
||||
# failJSON: { "match": true, "host": "192.0.2.120", "desc": "systemd journal message, PAM auth failure, gh-4071"}
|
||||
host nginx[23141]: host nginx: 2025/09/07 21:20:40 [error] 23141#23141: *24470 PAM: user 'username' - not authenticated: Authentication failure, client: 192.0.2.120, server: webdav.sub.domain, request: "GET / HTTP/2.0", host: "webdav.sub.domain"
|
||||
|
||||
# filterOptions: [{"mode": "fallback"}]
|
||||
|
||||
# failJSON: { "time": "2020-11-25T14:42:16", "match": true , "host": "142.93.180.14" }
|
||||
|
|
@ -29,6 +35,13 @@ host nginx[983478]: 2023/12/09 21:35:20 [error] 983478#983478: *3 user "fakeuser
|
|||
# failJSON: { "time": "2020-11-25T16:02:45", "match": false }
|
||||
2020/11/25 16:02:45 [error] 76952#76952: *5645766 connect() failed (111: Connection refused) while connecting to upstream, client: 5.126.32.148, server: www.google.de, request: "GET /admin/config HTTP/2.0", upstream: "http://127.0.0.1:3000/admin/config", host: "www.google.de"
|
||||
|
||||
# failJSON: { "time": "2025-07-09T19:20:38", "match": true , "host": "192.0.2.23", "desc": "SSL failure: bad key share (gh-4142)" }
|
||||
2025/07/09 19:20:38 [crit] 3075615#3075615: *2489 SSL_do_handshake() failed (SSL: error:0A00006C:SSL routines::bad key share) while SSL handshaking, client: 192.0.2.23, server: 0.0.0.0:443
|
||||
# failJSON: { "time": "2025-07-09T20:18:52", "match": true , "host": "192.0.2.24", "desc": "SSL failure: bad record type (gh-4142)" }
|
||||
2025/07/09 20:18:52 [crit] 60993#60993: *16611546 SSL_do_handshake() failed (SSL: error:0A0001BB:SSL routines::bad record type error:0A000139:SSL routines::record layer failure) while SSL handshaking, client: 192.0.2.24, server: 0.0.0.0:443
|
||||
# failJSON: { "time": "2025-07-09T22:27:36", "match": true , "host": "192.0.2.17", "desc": "SSL failure: alert number 121 (gh-4142)" }
|
||||
2025/07/09 22:27:36 [crit] 60993#60993: *16700609 SSL_read() failed (SSL: error:0A000461:SSL routines::reason(1121):SSL alert number 121) while waiting for request, client: 192.0.2.17, server: 0.0.0.0:443
|
||||
|
||||
# filterOptions: [{"mode": "aggressive"}]
|
||||
# failJSON: { "time": "2020-11-25T14:42:16", "match": true , "host": "142.93.180.14" }
|
||||
2020/11/25 14:42:16 [crit] 76952#76952: *2454307 SSL_do_handshake() failed (SSL: error:1408F0C6:SSL routines:ssl3_get_record:packet length too long) while SSL handshaking, client: 142.93.180.14, server: 0.0.0.0:443
|
||||
|
|
|
|||
|
|
@ -11,6 +11,18 @@
|
|||
# failJSON: { "time": "2016-09-30T08:36:06", "match": true, "host": "2001:db8::80da:af6b:8b2c" }
|
||||
2016/09/30 08:36:06 [error] 22923#0: *4758725916 limiting requests, excess: 15.243 by zone "one", client: 2001:db8::80da:af6b:8b2c, server: example.com, request: "GET / HTTP/1.1", host: "example.com"
|
||||
|
||||
# failJSON: { "time": "2025-08-01T04:24:17", "match": true , "host": "206.189.215.97" }
|
||||
2025/08/01 04:24:17 [warn] 4772#4772: *68 delaying request, excess: 0.841, by zone "req_limit", client: 206.189.215.97, server: myserver.net, request: "GET /ab2h HTTP/1.1", host: "22.18.134.49"
|
||||
|
||||
# failJSON: { "time": "2025-08-01T14:32:27", "match": true , "host": "104.248.81.143" }
|
||||
2025/08/01 14:32:27 [warn] 31733#31733: *21 delaying request, excess: 0.850, by zone "req_limit", client: 104.248.81.143, server: myserver.net, request: "GET /favicon.ico HTTP/1.1", host: "myserver.net", referrer: "https://myserver.net/"
|
||||
|
||||
# failJSON: { "time": "2025-08-03T03:17:28", "match": true , "host": "128.199.22.141" }
|
||||
2025/08/03 03:17:28 [error] 25808#25808: *598 limiting connections by zone "conn_limit", client: 128.199.22.141, server: myserver.net, request: "GET /favicon.ico HTTP/1.1", host: "84.108.142.49", referrer: "https://xxx.com/"
|
||||
|
||||
# failJSON: { "time": "2025-08-03T13:56:22", "match": true , "host": "162.240.161.123" }
|
||||
2025/08/03 13:56:22 [error] 943#943: *60 limiting connections by zone "conn_limit", client: 162.240.161.123, server: myserver.net, request: "GET /.env HTTP/1.1", host: "app.myserver.net"
|
||||
|
||||
# filterOptions: [{"logtype": "journal"}]
|
||||
|
||||
# failJSON: { "match": true , "host": "192.0.2.2" }
|
||||
|
|
|
|||
|
|
@ -151,7 +151,7 @@ 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" }
|
||||
# failJSON: { "time": "2004-11-04T09:11:01", "match": true , "host": "192.0.2.152", "user": "admin", "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
|
||||
|
||||
# ---------------------------------------
|
||||
|
|
@ -187,6 +187,13 @@ Jun 8 23:14:28 proxy2 postfix/postscreen[473]: COMMAND TIME LIMIT from [192.0.2
|
|||
# failJSON: { "time": "2005-06-08T23:14:54", "match": true , "host": "192.0.2.26", "desc": "abusive clients hitting command limit (gh-3040)" }
|
||||
Jun 8 23:14:54 proxy2 postfix/postscreen[473]: COMMAND COUNT LIMIT from [192.0.2.26]:15592 after RCPT
|
||||
|
||||
# failJSON: { "time": "2004-09-17T18:19:20", "match": true , "host": "192.0.2.25" }
|
||||
Sep 17 18:19:20 mxhost postfix/smtpd[12345]: NOQUEUE: lost connection after CONNECT from unknown[192.0.2.25]
|
||||
|
||||
# failJSON: { "time": "2004-09-19T12:10:57", "match": true , "host": "192.0.2.123", "desc": "Connection rate limit exceeded, gh-4073" }
|
||||
Sep 19 12:10:57 hostname postfix/smtpd[23244]: warning: Connection rate limit exceeded: 31 from spamhost.domain.org[192.0.2.123] for service smtpd
|
||||
# failJSON: { "time": "2004-09-19T12:10:58", "match": true , "host": "192.0.2.227", "desc": "Message delivery request rate limit exceeded, gh-3265" }
|
||||
Sep 19 12:10:58 hostname postfix/smtpd[14059]: warning: Message delivery request rate limit exceeded: 334 from spam.example.com[192.0.2.227] for service submission
|
||||
|
||||
# filterOptions: [{}, {"mode": "ddos"}, {"mode": "aggressive"}]
|
||||
# failJSON: { "match": false, "desc": "don't affect lawful data (sporadical connection aborts within DATA-phase, see gh-1813 for discussion)" }
|
||||
|
|
|
|||
|
|
@ -57,6 +57,9 @@ Feb 27 15:49:02 batman sm-mta[88377]: s1REn1un088377: ruleset=check_rcpt, arg1=<
|
|||
# failJSON: { "time": "2005-02-27T22:44:42", "match": true , "host": "123.69.106.50" }
|
||||
Feb 27 22:44:42 batman sm-mta[30972]: s1RLieRP030972: ruleset=check_rcpt, arg1=<existing-user@example.com>, relay=[123.69.106.50], reject=553 5.1.8 <existing-user@example.com>... Domain of sender address lf@ibuv.net does not exist
|
||||
|
||||
# failJSON: { "time": "2005-02-27T22:44:43", "match": true , "host": "192.0.2.100" }
|
||||
Feb 27 22:44:43 batman sm-mta[4012]: 56CF8Qni004012: ruleset=check_rcpt, arg1=<existing-user@example.com>, relay=[192.0.2.100] (may be forged), reject=451 4.1.8 Domain of sender address test.whatever@service.example.com does not resolve
|
||||
|
||||
# failJSON: { "time": "2005-02-23T21:18:47", "match": true , "host": "76.72.174.70" }
|
||||
Feb 23 21:18:47 batman sm-mta[93301]: s1NKIkZa093301: [76.72.174.70]: EXPN root [rejected]
|
||||
|
||||
|
|
@ -94,6 +97,11 @@ Nov 3 11:35:30 Microsoft sendmail[26254]: rA37ZTSC026252: <anton@domain.com>...
|
|||
# failJSON: { "match": false, "desc": "Different mail ID shouldn't match" }
|
||||
Nov 3 11:35:30 Microsoft sendmail[26254]: rA37ZTSC026255: from=<anton@domain.com>, size=0, class=0, nrcpts=0, bodytype=8BITMIME, proto=ESMTP, daemon=MTA, relay=163.23.32.95.dsl-dynamic.vsi.ru [95.32.23.163]
|
||||
|
||||
# failJSON: { "match": false, "desc": "Add User unknown" }
|
||||
Jun 17 14:37:39 <mail.notice> robin sm-mta[2794]: 55HIbcGI002794: <baduser@yourhost.com>... User unknown
|
||||
# failJSON: { "time": "2005-06-17T14:37:39", "match": true, "host": "192.168.1.45", "desc": "BSD style log format with no hostname for the relay." }
|
||||
Jun 17 14:37:39 <mail.info> robin sm-mta[2794]: 55HIbcGI002794: from=<root@yourhost.com>, size=108, class=0, nrcpts=0, proto=ESMTP, daemon=MTA-v4, relay=[192.168.1.45]
|
||||
|
||||
# filterOptions: {"mode": "extra"}
|
||||
|
||||
# failJSON: { "time": "2005-03-06T16:55:28", "match": true , "host": "192.0.2.194", "desc": "wrong resp. non RFC compiant (ddos prelude?), MTA-mode" }
|
||||
|
|
@ -112,3 +120,12 @@ Mar 29 22:51:43 server sendmail[3529565]: xA32R2PQ3529565: [192.0.2.2] did not i
|
|||
Mar 29 22:51:45 server sm-mta[50437]: 06QDQnNf050437: example.com [192.0.2.3] did not issue MAIL/EXPN/VRFY/ETRN during connection to IPv4
|
||||
# failJSON: { "time": "2005-03-29T22:51:46", "match": true , "host": "2001:DB8::1", "desc": "IPv6" }
|
||||
Mar 29 22:51:46 server sm-mta[50438]: 06QDQnNf050438: example.com [IPv6:2001:DB8::1] did not issue MAIL/EXPN/VRFY/ETRN during connection to IPv6
|
||||
|
||||
# filterOptions: {"mode": "aggressive"}
|
||||
|
||||
# failJSON: { "time": "2005-07-31T13:03:43", "match": true, "host": "139.162.120.196" }
|
||||
Jul 31 13:03:43 <mail.notice> alarmpi sm-mta[24291]: 56VFYCxS024291: lost input channel from mail.aqicn.org [139.162.120.196] to MTA-v4 after rcpt
|
||||
|
||||
# failJSON: { "time": "2005-06-18T08:05:17", "match": true, "host": "45.125.66.67" }
|
||||
Jun 18 08:05:17 <mail.notice> myhost sm-mta[17002]: 55IC59VD017002: ruleset=check_rcpt, arg1=<spameri@tiscali.it>, relay=[45.125.66.67], reject=450 4.4.0 <spameri@tiscali.it>... Relaying temporarily denied. Cannot resolve PTR record for 45.125.66.67
|
||||
|
||||
|
|
|
|||
|
|
@ -21,3 +21,6 @@
|
|||
|
||||
# failJSON: { "time": "2024-08-30T20:11:28", "match": true , "host": "2001:db8::b6d3:95d7:1425:766d" }
|
||||
[2024-08-31 02:11:28.892+0800][vaultwarden::api::core::two_factor::authenticator][ERROR] Invalid TOTP code! Server time: 2024-08-30 18:11:28 UTC IP: 2001:db8::b6d3:95d7:1425:766d
|
||||
|
||||
# failJSON: { "time": "2024-08-30T20:11:30", "match": true , "host": "192.0.2.7" }
|
||||
[2024-08-31 02:11:30.123+0800][vaultwarden::api::admin][ERROR] Invalid admin token! IP: 192.0.2.7. Username: alice
|
||||
|
|
|
|||
37
fail2ban/tests/files/logs/xrdp
Normal file
37
fail2ban/tests/files/logs/xrdp
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
#
|
||||
# /var/log/xrdp-sesman.log -- should be about the same on any linux distro
|
||||
#
|
||||
|
||||
# failJSON: { "time": "2022-04-07T12:11:06", "match": true, "host": "10.171.161.151"}
|
||||
[20220407-12:11:06] [INFO ] AUTHFAIL: user=badtypist ip=::ffff:10.171.161.151 time=1649351466
|
||||
|
||||
# ip injection: 10.171.161.151 should be matched as the host; 192.168.0.1 is an innocent, injected address
|
||||
# failJSON: { "time": "2022-04-07T12:11:24", "match": true, "host": "10.171.161.151", "desc": "specifying ip address as username"}
|
||||
[20220407-12:11:24] [INFO ] AUTHFAIL: user=192.168.0.1 ip=::ffff:10.171.161.151 time=1649351484
|
||||
|
||||
# ip injection: 10.171.161.151 should be matched as the host; 192.168.0.4 is an innocent, injected address
|
||||
# failJSON: { "time": "2022-04-07T12:22:02", "match": true, "host": "10.171.161.151", "desc": "more devious log injection"}
|
||||
[20220407-12:22:02] [INFO ] AUTHFAIL: user=loginjector ip=192.168.0.4 time=123456789\n[20220407-12:16:59] [INFO ] AUTHFAIL: user=endinjection ip=::ffff:10.171.161.151 time=1649352122
|
||||
|
||||
|
||||
#
|
||||
# /var/log/messages -- RHEL/Fedora family
|
||||
#
|
||||
|
||||
# failJSON: { "time": "2005-04-07T12:11:06", "match": true, "host": "10.171.161.151"}
|
||||
Apr 7 12:11:06 servername xrdp-sesman[41441]: [INFO ] AUTHFAIL: user=badtypist ip=::ffff:10.171.161.151 time=1649351466
|
||||
|
||||
# ip injection: 10.171.161.151 should be matched as the host; 192.168.0.1 is an innocent, injected address
|
||||
# failJSON: { "time": "2005-04-07T12:11:24", "match": true, "host": "10.171.161.151", "desc": "specifying ip address as username"}
|
||||
Apr 7 12:11:24 servername xrdp-sesman[41441]: [INFO ] AUTHFAIL: user=192.168.0.1 ip=::ffff:10.171.161.151 time=1649351484
|
||||
|
||||
# ip injection: 10.171.161.151 should be matched as the host; 192.168.0.4 is an innocent, injected address
|
||||
# failJSON: { "time": "2005-04-07T12:22:02", "match": true, "host": "10.171.161.151", "desc": "more devious log injection"}
|
||||
Apr 7 12:22:02 servername xrdp-sesman[41441]: [INFO ] AUTHFAIL: user=loginjector ip=192.168.0.4 time=123456789\n[20220407-12:16:59] [INFO ] AUTHFAIL: user=endinjection ip=::ffff:10.171.161.151 time=1649352122
|
||||
|
||||
# ip injection: innocent, injected ip 192.168.0.4 in a line that shouldn't contain a host
|
||||
# failJSON: { "match": false }
|
||||
Apr 7 12:22:02 servername xrdp[52415]: [INFO ] xrdp_wm_log_msg: login failed for user loginjector ip=192.168.0.4 time=12345\n[20220407-12:16:59] [INFO ] AUTHFAIL: user=endinjection
|
||||
|
||||
# failJSON: { "match": false }
|
||||
Apr 7 12:22:02 servername xrdp[52415]: [INFO ] n[20220407-12:16:59] [INFO ] AUTHFAIL: user=endinjection
|
||||
|
|
@ -617,14 +617,14 @@ class IgnoreIP(LogCaptureTestCase):
|
|||
self.pruneLog()
|
||||
self.assertFalse(self.filter.inIgnoreIPList(FailTicket("2001:db8::ffff")))
|
||||
self.assertLogged("returned successfully 1")
|
||||
# by user-name (ignore tester):
|
||||
self.filter.ignoreCommand = 'if [ "<F-USER>" = "tester" ]; then exit 0; fi; exit 1'
|
||||
# by user-name (ignore tester), also test jail.name tag:
|
||||
self.filter.ignoreCommand = 'echo "jail:<jail.name>"; if [ "<F-USER>" = "tester" ]; then exit 0; fi; exit 1'
|
||||
self.pruneLog()
|
||||
self.assertTrue(self.filter.inIgnoreIPList(FailTicket("tester", data={'user': 'tester'})))
|
||||
self.assertLogged("returned successfully 0")
|
||||
self.assertLogged("stdout: %r" % 'jail:DummyJail', "returned successfully 0", all=True)
|
||||
self.pruneLog()
|
||||
self.assertFalse(self.filter.inIgnoreIPList(FailTicket("root", data={'user': 'root'})))
|
||||
self.assertLogged("returned successfully 1", all=True)
|
||||
self.assertLogged("stdout: %r" % 'jail:DummyJail', "returned successfully 1", all=True)
|
||||
|
||||
def testIgnoreCache(self):
|
||||
# like both test-cases above, just cached (so once per key)...
|
||||
|
|
|
|||
|
|
@ -393,6 +393,13 @@ class Transmitter(TransmitterBase):
|
|||
# resulted to ban for "192.0.2.2" but not for "192.0.2.1":
|
||||
self.assertLogged("Ban 192.0.2.2", wait=True)
|
||||
self.assertNotLogged("Ban 192.0.2.1")
|
||||
# check attempt will be ignored by ignore facilities:
|
||||
ip = "192.0.2.1"
|
||||
self.transm.proceed(["set", self.jailName, "addignoreip", ip])
|
||||
self.assertLogged("Add %r to ignore list" % (ip,), wait=True)
|
||||
self.assertEqual(attempt(ip, ["test failure %d" % i for i in (3,4,5)]), (0, 0))
|
||||
self.assertLogged("Ignore %s by ip" % (ip,), wait=True)
|
||||
self.assertNotLogged("Ban 192.0.2.1")
|
||||
|
||||
@with_alt_time
|
||||
def testJailBanList(self):
|
||||
|
|
@ -1343,11 +1350,11 @@ class ServerConfigReaderTests(LogCaptureTestCase):
|
|||
r"`done`",
|
||||
),
|
||||
'ip4-start': (
|
||||
r"`nft add set inet f2b-table addr-set-j-w-nft-mp \{ type ipv4_addr\; \}`",
|
||||
r"`nft add set inet f2b-table addr-set-j-w-nft-mp \{ type ipv4_addr\; flags interval\; \}`",
|
||||
r"`nft add rule inet f2b-table f2b-chain $proto dport \{ $(echo 'http,https' | sed s/:/-/g) \} ip saddr @addr-set-j-w-nft-mp reject`",
|
||||
),
|
||||
'ip6-start': (
|
||||
r"`nft add set inet f2b-table addr6-set-j-w-nft-mp \{ type ipv6_addr\; \}`",
|
||||
r"`nft add set inet f2b-table addr6-set-j-w-nft-mp \{ type ipv6_addr\; flags interval\; \}`",
|
||||
r"`nft add rule inet f2b-table f2b-chain $proto dport \{ $(echo 'http,https' | sed s/:/-/g) \} ip6 saddr @addr6-set-j-w-nft-mp reject`",
|
||||
),
|
||||
'flush': (
|
||||
|
|
@ -1355,10 +1362,10 @@ class ServerConfigReaderTests(LogCaptureTestCase):
|
|||
"`{ nft flush set inet f2b-table addr6-set-j-w-nft-mp 2> /dev/null; } || ",
|
||||
),
|
||||
'stop': (
|
||||
r"`{ nft -a list chain inet f2b-table f2b-chain | grep -oP '@addr-set-j-w-nft-mp\s+.*\s+\Khandle\s+(\d+)$'; } | while read -r hdl; do`",
|
||||
r"`{ nft -a list chain inet f2b-table f2b-chain | sed -nE 's/.*@addr-set-j-w-nft-mp\s+.*\s+\#\s*(handle\s+[0-9]+)$/\1/p'; } | while read -r hdl; do`",
|
||||
r"`nft delete rule inet f2b-table f2b-chain $hdl; done`",
|
||||
r"`nft delete set inet f2b-table addr-set-j-w-nft-mp`",
|
||||
r"`{ nft -a list chain inet f2b-table f2b-chain | grep -oP '@addr6-set-j-w-nft-mp\s+.*\s+\Khandle\s+(\d+)$'; } | while read -r hdl; do`",
|
||||
r"`{ nft -a list chain inet f2b-table f2b-chain | sed -nE 's/.*@addr6-set-j-w-nft-mp\s+.*\s+\#\s*(handle\s+[0-9]+)$/\1/p'; } | while read -r hdl; do`",
|
||||
r"`nft delete rule inet f2b-table f2b-chain $hdl; done`",
|
||||
r"`nft delete set inet f2b-table addr6-set-j-w-nft-mp`",
|
||||
),
|
||||
|
|
@ -1389,11 +1396,11 @@ class ServerConfigReaderTests(LogCaptureTestCase):
|
|||
r"`nft -- add chain inet f2b-table f2b-chain \{ type filter hook input priority -1 \; \}`",
|
||||
),
|
||||
'ip4-start': (
|
||||
r"`nft add set inet f2b-table addr-set-j-w-nft-ap \{ type ipv4_addr\; \}`",
|
||||
r"`nft add set inet f2b-table addr-set-j-w-nft-ap \{ type ipv4_addr\; flags interval\; \}`",
|
||||
r"`nft add rule inet f2b-table f2b-chain meta l4proto \{ tcp,udp \} ip saddr @addr-set-j-w-nft-ap reject`",
|
||||
),
|
||||
'ip6-start': (
|
||||
r"`nft add set inet f2b-table addr6-set-j-w-nft-ap \{ type ipv6_addr\; \}`",
|
||||
r"`nft add set inet f2b-table addr6-set-j-w-nft-ap \{ type ipv6_addr\; flags interval\; \}`",
|
||||
r"`nft add rule inet f2b-table f2b-chain meta l4proto \{ tcp,udp \} ip6 saddr @addr6-set-j-w-nft-ap reject`",
|
||||
),
|
||||
'flush': (
|
||||
|
|
@ -1401,10 +1408,10 @@ class ServerConfigReaderTests(LogCaptureTestCase):
|
|||
"`{ nft flush set inet f2b-table addr6-set-j-w-nft-ap 2> /dev/null; } || ",
|
||||
),
|
||||
'stop': (
|
||||
r"`{ nft -a list chain inet f2b-table f2b-chain | grep -oP '@addr-set-j-w-nft-ap\s+.*\s+\Khandle\s+(\d+)$'; } | while read -r hdl; do`",
|
||||
r"`{ nft -a list chain inet f2b-table f2b-chain | sed -nE 's/.*@addr-set-j-w-nft-ap\s+.*\s+\#\s*(handle\s+[0-9]+)$/\1/p'; } | while read -r hdl; do`",
|
||||
r"`nft delete rule inet f2b-table f2b-chain $hdl; done`",
|
||||
r"`nft delete set inet f2b-table addr-set-j-w-nft-ap`",
|
||||
r"`{ nft -a list chain inet f2b-table f2b-chain | grep -oP '@addr6-set-j-w-nft-ap\s+.*\s+\Khandle\s+(\d+)$'; } | while read -r hdl; do`",
|
||||
r"`{ nft -a list chain inet f2b-table f2b-chain | sed -nE 's/.*@addr6-set-j-w-nft-ap\s+.*\s+\#\s*(handle\s+[0-9]+)$/\1/p'; } | while read -r hdl; do`",
|
||||
r"`nft delete rule inet f2b-table f2b-chain $hdl; done`",
|
||||
r"`nft delete set inet f2b-table addr6-set-j-w-nft-ap`",
|
||||
),
|
||||
|
|
@ -1669,6 +1676,106 @@ class ServerConfigReaderTests(LogCaptureTestCase):
|
|||
r"`ipset -exist del f2b-j-w-iptables-ipset-ap6 2001:db8::`",
|
||||
),
|
||||
}),
|
||||
# iptables-ipset (allports + drop) --
|
||||
('j-w-ipt-ipset-ap-drp', 'iptables-ipset[name=%(__name__)s, type="allports", blocktype="DROP"]', {
|
||||
'ip4': (' f2b-j-w-ipt-ipset-ap-drp ',), 'ip6': (' f2b-j-w-ipt-ipset-ap-drp6 ',),
|
||||
'*-start-stop-check': (
|
||||
# iterator over protocol is same for both families:
|
||||
"`for chain in $(echo 'INPUT' | sed 's/,/ /g'); do for proto in $(echo 'tcp' | sed 's/,/ /g'); do`",
|
||||
"`done; done`",
|
||||
),
|
||||
'ip4-start': (
|
||||
"`ipset -exist create f2b-j-w-ipt-ipset-ap-drp hash:ip timeout 0 maxelem 65536 `",
|
||||
"`{ iptables -w -C $chain -p $proto -m set --match-set f2b-j-w-ipt-ipset-ap-drp src -j DROP >/dev/null 2>&1; } || "
|
||||
"{ iptables -w -I $chain -p $proto -m set --match-set f2b-j-w-ipt-ipset-ap-drp src -j DROP; }",
|
||||
),
|
||||
'ip6-start': (
|
||||
"`ipset -exist create f2b-j-w-ipt-ipset-ap-drp6 hash:ip timeout 0 maxelem 65536 family inet6`",
|
||||
"`{ ip6tables -w -C $chain -p $proto -m set --match-set f2b-j-w-ipt-ipset-ap-drp6 src -j DROP >/dev/null 2>&1; } || "
|
||||
"{ ip6tables -w -I $chain -p $proto -m set --match-set f2b-j-w-ipt-ipset-ap-drp6 src -j DROP; }",
|
||||
),
|
||||
'flush': (
|
||||
"`ipset flush f2b-j-w-ipt-ipset-ap-drp`",
|
||||
"`ipset flush f2b-j-w-ipt-ipset-ap-drp6`",
|
||||
),
|
||||
'stop': (
|
||||
"`iptables -w -D $chain -p $proto -m set --match-set f2b-j-w-ipt-ipset-ap-drp src -j DROP`",
|
||||
"`ipset flush f2b-j-w-ipt-ipset-ap-drp`",
|
||||
"`ipset destroy f2b-j-w-ipt-ipset-ap-drp 2>/dev/null || { sleep 1; ipset destroy f2b-j-w-ipt-ipset-ap-drp; }`",
|
||||
"`ip6tables -w -D $chain -p $proto -m set --match-set f2b-j-w-ipt-ipset-ap-drp6 src -j DROP`",
|
||||
"`ipset flush f2b-j-w-ipt-ipset-ap-drp6`",
|
||||
"`ipset destroy f2b-j-w-ipt-ipset-ap-drp6 2>/dev/null || { sleep 1; ipset destroy f2b-j-w-ipt-ipset-ap-drp6; }`",
|
||||
),
|
||||
'ip4-check': (
|
||||
r"""`iptables -w -C $chain -p $proto -m set --match-set f2b-j-w-ipt-ipset-ap-drp src -j DROP`""",
|
||||
),
|
||||
'ip6-check': (
|
||||
r"""`ip6tables -w -C $chain -p $proto -m set --match-set f2b-j-w-ipt-ipset-ap-drp6 src -j DROP`""",
|
||||
),
|
||||
'ip4-ban': (
|
||||
r"`ipset -exist add f2b-j-w-ipt-ipset-ap-drp 192.0.2.1 timeout 0`",
|
||||
),
|
||||
'ip4-unban': (
|
||||
r"`ipset -exist del f2b-j-w-ipt-ipset-ap-drp 192.0.2.1`",
|
||||
),
|
||||
'ip6-ban': (
|
||||
r"`ipset -exist add f2b-j-w-ipt-ipset-ap-drp6 2001:db8:: timeout 0`",
|
||||
),
|
||||
'ip6-unban': (
|
||||
r"`ipset -exist del f2b-j-w-ipt-ipset-ap-drp6 2001:db8::`",
|
||||
),
|
||||
}),
|
||||
# iptables-ipset (allports + REJECT with icmp?6? host-unreachable) --
|
||||
('j-w-ipt-ipset-ap-rwhu', 'iptables-ipset[name=%(__name__)s, type="allports", '
|
||||
+'blocktype="REJECT --reject-with icmp-host-unreachable", '
|
||||
+'blocktype?family=inet6="REJECT --reject-with icmp6-host-unreachable"]', {
|
||||
'ip4': (' f2b-j-w-ipt-ipset-ap-rwhu ',), 'ip6': (' f2b-j-w-ipt-ipset-ap-rwhu6 ',),
|
||||
'*-start-stop-check': (
|
||||
# iterator over protocol is same for both families:
|
||||
"`for chain in $(echo 'INPUT' | sed 's/,/ /g'); do for proto in $(echo 'tcp' | sed 's/,/ /g'); do`",
|
||||
"`done; done`",
|
||||
),
|
||||
'ip4-start': (
|
||||
"`ipset -exist create f2b-j-w-ipt-ipset-ap-rwhu hash:ip timeout 0 maxelem 65536 `",
|
||||
"`{ iptables -w -C $chain -p $proto -m set --match-set f2b-j-w-ipt-ipset-ap-rwhu src -j REJECT --reject-with icmp-host-unreachable >/dev/null 2>&1; } || "
|
||||
"{ iptables -w -I $chain -p $proto -m set --match-set f2b-j-w-ipt-ipset-ap-rwhu src -j REJECT --reject-with icmp-host-unreachable; }",
|
||||
),
|
||||
'ip6-start': (
|
||||
"`ipset -exist create f2b-j-w-ipt-ipset-ap-rwhu6 hash:ip timeout 0 maxelem 65536 family inet6`",
|
||||
"`{ ip6tables -w -C $chain -p $proto -m set --match-set f2b-j-w-ipt-ipset-ap-rwhu6 src -j REJECT --reject-with icmp6-host-unreachable >/dev/null 2>&1; } || "
|
||||
"{ ip6tables -w -I $chain -p $proto -m set --match-set f2b-j-w-ipt-ipset-ap-rwhu6 src -j REJECT --reject-with icmp6-host-unreachable; }",
|
||||
),
|
||||
'flush': (
|
||||
"`ipset flush f2b-j-w-ipt-ipset-ap-rwhu`",
|
||||
"`ipset flush f2b-j-w-ipt-ipset-ap-rwhu6`",
|
||||
),
|
||||
'stop': (
|
||||
"`iptables -w -D $chain -p $proto -m set --match-set f2b-j-w-ipt-ipset-ap-rwhu src -j REJECT --reject-with icmp-host-unreachable`",
|
||||
"`ipset flush f2b-j-w-ipt-ipset-ap-rwhu`",
|
||||
"`ipset destroy f2b-j-w-ipt-ipset-ap-rwhu 2>/dev/null || { sleep 1; ipset destroy f2b-j-w-ipt-ipset-ap-rwhu; }`",
|
||||
"`ip6tables -w -D $chain -p $proto -m set --match-set f2b-j-w-ipt-ipset-ap-rwhu6 src -j REJECT --reject-with icmp6-host-unreachable`",
|
||||
"`ipset flush f2b-j-w-ipt-ipset-ap-rwhu6`",
|
||||
"`ipset destroy f2b-j-w-ipt-ipset-ap-rwhu6 2>/dev/null || { sleep 1; ipset destroy f2b-j-w-ipt-ipset-ap-rwhu6; }`",
|
||||
),
|
||||
'ip4-check': (
|
||||
r"""`iptables -w -C $chain -p $proto -m set --match-set f2b-j-w-ipt-ipset-ap-rwhu src -j REJECT --reject-with icmp-host-unreachable`""",
|
||||
),
|
||||
'ip6-check': (
|
||||
r"""`ip6tables -w -C $chain -p $proto -m set --match-set f2b-j-w-ipt-ipset-ap-rwhu6 src -j REJECT --reject-with icmp6-host-unreachable`""",
|
||||
),
|
||||
'ip4-ban': (
|
||||
r"`ipset -exist add f2b-j-w-ipt-ipset-ap-rwhu 192.0.2.1 timeout 0`",
|
||||
),
|
||||
'ip4-unban': (
|
||||
r"`ipset -exist del f2b-j-w-ipt-ipset-ap-rwhu 192.0.2.1`",
|
||||
),
|
||||
'ip6-ban': (
|
||||
r"`ipset -exist add f2b-j-w-ipt-ipset-ap-rwhu6 2001:db8:: timeout 0`",
|
||||
),
|
||||
'ip6-unban': (
|
||||
r"`ipset -exist del f2b-j-w-ipt-ipset-ap-rwhu6 2001:db8::`",
|
||||
),
|
||||
}),
|
||||
# iptables (oneport) --
|
||||
('j-w-iptables', 'iptables[name=%(__name__)s, bantime="10m", port="http", protocol="tcp", chain="<known/chain>"]', {
|
||||
'ip4': ('`iptables ', 'icmp-port-unreachable'), 'ip6': ('`ip6tables ', 'icmp6-port-unreachable'),
|
||||
|
|
|
|||
|
|
@ -1 +0,0 @@
|
|||
D /run/fail2ban 0755 root root -
|
||||
|
|
@ -7,13 +7,13 @@ PartOf=iptables.service firewalld.service ip6tables.service ipset.service nftabl
|
|||
[Service]
|
||||
Type=simple
|
||||
Environment="PYTHONNOUSERSITE=1"
|
||||
ExecStartPre=/bin/mkdir -p /run/fail2ban
|
||||
RuntimeDirectory=fail2ban
|
||||
StateDirectory=fail2ban
|
||||
ExecStart=@BINDIR@/fail2ban-server -xf start
|
||||
# if should be logged in systemd journal, use following line or set logtarget to sysout in fail2ban.local
|
||||
# ExecStart=@BINDIR@/fail2ban-server -xf --logtarget=sysout start
|
||||
ExecStop=@BINDIR@/fail2ban-client stop
|
||||
ExecReload=@BINDIR@/fail2ban-client reload
|
||||
PIDFile=/run/fail2ban/fail2ban.pid
|
||||
Restart=on-failure
|
||||
RestartPreventExitStatus=0 255
|
||||
|
||||
|
|
|
|||
|
|
@ -245,8 +245,23 @@ Arguments can be passed to actions to override the default values from the [Init
|
|||
[name=value,name2=value,name3="values,values"]
|
||||
|
||||
.RE
|
||||
Values can also be quoted (required when value includes a ","). More that one action can be specified (in separate lines).
|
||||
Values can also be quoted (required when value includes a "," or space). More that one action can be specified (in separate lines).
|
||||
.br
|
||||
The action specific arguments can also affect conditional parameters, so for instance to submit different values to different chains
|
||||
firstly pass the argument affecting all chains, e.g. \fIblocktype\fR, then for IPv6 chain, e. g. \fIblocktype?family=inet6\fR.
|
||||
Examples:
|
||||
.RS
|
||||
.nf
|
||||
|
||||
# pass blocktype to DROP for all chains:
|
||||
banaction_allports = iptables-ipset[type=allports, blocktype=DROP]
|
||||
# pass different blocktype for IPv4 and IPv6 chains:
|
||||
banaction = iptables-ipset[type=multiport, blocktype="REJECT --reject-with icmp-host-unreachable", blocktype?family=inet6="REJECT --reject-with icmp6-host-unreachable"]
|
||||
|
||||
.fi
|
||||
.RE
|
||||
.RE
|
||||
|
||||
.TP
|
||||
.B ignoreself
|
||||
boolean value (default true) indicates the banning of own IP addresses should be prevented
|
||||
|
|
@ -437,28 +452,67 @@ two commands to be executed.
|
|||
The following tags are substituted in the actionban, actionunban and actioncheck (when called before actionban/actionunban) commands.
|
||||
.TP
|
||||
.B ip
|
||||
IPv4 IP address to be banned. e.g. 192.168.0.2
|
||||
IPv4 or IPv6 IP address to be banned. e.g. 192.168.0.2 or 2001:db8::1
|
||||
.TP
|
||||
.B family
|
||||
IP address family as a string. e.g. inet4 or inet6
|
||||
.TP
|
||||
.B ip-rev
|
||||
Reverse DNS PTR record for the IP address, or empty string if unavailable.
|
||||
.TP
|
||||
.B ip-host
|
||||
Hostname resolved from the IP address.
|
||||
.TP
|
||||
.B fid
|
||||
Failure ID (ticket identifier) for this ban event.
|
||||
.TP
|
||||
.B failures
|
||||
number of times the failure occurred in the log file. e.g. 3
|
||||
.TP
|
||||
.B ipfailures
|
||||
As per \fBfailures\fR, but total of all failures for that ip address across all jails from the fail2ban persistent database. Therefore the database must be set for this tag to function.
|
||||
.TP
|
||||
.B ipjailfailures
|
||||
As per \fBipfailures\fR, but total based on the IPs failures for the current jail.
|
||||
Number of times the failure occurred in the log file for this specific ticket. e.g. 3
|
||||
.TP
|
||||
.B time
|
||||
UNIX (epoch) time of the ban. e.g. 1357508484
|
||||
.TP
|
||||
.B bantime
|
||||
Effective ban duration in seconds for this ticket.
|
||||
.TP
|
||||
.B bancount
|
||||
Number of times this IP address has been banned (cumulative count).
|
||||
.TP
|
||||
.B matches
|
||||
concatenated string of the log file lines of the matches that generated the ban. Many characters interpreted by shell get escaped to prevent injection, nevertheless use with caution.
|
||||
Concatenated string of the log file lines of the matches that generated the ban. Many characters interpreted by shell get escaped to prevent injection, nevertheless use with caution.
|
||||
.TP
|
||||
.B restored
|
||||
Flag indicating whether the ticket was restored from database (1) or is a new ban (0). Can be used in actions to skip certain operations for restored bans.
|
||||
.TP
|
||||
.B F-*
|
||||
Free-form match tags captured from the filter using \fI<F-TAG>...</F-TAG>\fR syntax in failregex. For example, if filter captures \fI<F-USER>john</F-USER>\fR, the tag \fI<F-USER>\fR will contain "john" and can be used in action commands.
|
||||
.TP
|
||||
.B ipfailures
|
||||
As per \fBfailures\fR, but total of all failures for that IP address across all jails from the fail2ban persistent database. Therefore the database must be set for this tag to function.
|
||||
.TP
|
||||
.B ipjailfailures
|
||||
As per \fBipfailures\fR, but total based on the IP's failures for the current jail only.
|
||||
.TP
|
||||
.B ipmatches
|
||||
As per \fBmatches\fR, but includes all lines for the IP which are contained with the fail2ban persistent database. Therefore the database must be set for this tag to function.
|
||||
As per \fBmatches\fR, but includes all lines for the IP which are contained within the fail2ban persistent database across all jails. Therefore the database must be set for this tag to function.
|
||||
.TP
|
||||
.B ipjailmatches
|
||||
As per \fBipmatches\fR, but matches are limited for the IP and for the current jail.
|
||||
As per \fBipmatches\fR, but matches are limited to the IP and the current jail only.
|
||||
.TP
|
||||
.B raw-ticket
|
||||
String representation of the raw ticket object. Primarily useful for debugging purposes.
|
||||
.TP
|
||||
.B jail.banned
|
||||
Number of currently banned IP addresses in the jail at the time of this action.
|
||||
.TP
|
||||
.B jail.banned_total
|
||||
Total cumulative number of bans that have occurred in this jail since fail2ban started.
|
||||
.TP
|
||||
.B jail.found
|
||||
Number of current failure tickets in the jail's fail manager.
|
||||
.TP
|
||||
.B jail.found_total
|
||||
Total cumulative number of failures that have been detected in this jail since fail2ban started.
|
||||
|
||||
.SH "PYTHON ACTION FILES"
|
||||
Python based actions can also be used, where the file name must be \fI[actionname].py\fR. The Python file must contain a variable \fIAction\fR which points to Python class. This class must implement a minimum interface as described by \fIfail2ban.server.action.ActionBase\fR, which can be inherited from to ease implementation.
|
||||
|
|
|
|||
10
setup.py
10
setup.py
|
|
@ -157,13 +157,6 @@ too many password failures. It updates firewall rules
|
|||
to reject the IP address or executes user defined
|
||||
commands.'''
|
||||
|
||||
if setuptools:
|
||||
setup_extra = {
|
||||
'test_suite': "fail2ban.tests.utils.gatherTests",
|
||||
}
|
||||
else:
|
||||
setup_extra = {}
|
||||
|
||||
data_files_extra = []
|
||||
if os.path.exists('/var/run'):
|
||||
# if we are on the system with /var/run -- we are to use it for having fail2ban/
|
||||
|
|
@ -249,8 +242,7 @@ setup(
|
|||
('/var/lib/fail2ban',
|
||||
''
|
||||
),
|
||||
] + data_files_extra,
|
||||
**setup_extra
|
||||
] + data_files_extra
|
||||
)
|
||||
|
||||
# Do some checks after installation
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue