diff --git a/ChangeLog b/ChangeLog index 3879d226..08719d26 100644 --- a/ChangeLog +++ b/ChangeLog @@ -96,6 +96,9 @@ ver. 1.1.1-dev-1 (20??/??/??) - development nightly edition - 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) * `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) diff --git a/config/filter.d/nginx-http-auth.conf b/config/filter.d/nginx-http-auth.conf index 454e9186..ff59f4e3 100644 --- a/config/filter.d/nginx-http-auth.conf +++ b/config/filter.d/nginx-http-auth.conf @@ -8,16 +8,18 @@ before = nginx-error-common.conf mode = normal -__err_type = <_ertp-> +__err_type = (?:error|crit) -_ertp-auth = error -mdre-auth = ^%(__prefix_line)suser "(?:[^"]+|.*?)":? (?:password mismatch|was not found in "[^\"]*"), client: , 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: +__suffix_line = , client: (?:, (?:server|request|host|referrer): (?:"[^"]*"|\S*)){0,4} + +prefregex = ^%(__prefix_line)s.*%(__suffix_line)s\s*$ + +mdre-auth = ^user "(?:[^"]+|.*?)":? (?:password mismatch|was not found in "[^\"]*")$ + ^(?:PAM: )?user '(?:[^']+|.*?)' - not authenticated: Authentication failure$ +mdre-fallback = ^SSL_do_handshake\(\) failed \(SSL: error:\S+(?: \S+){1,3} too (?:long|short)\)[^,]* -_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 diff --git a/fail2ban/tests/files/logs/nginx-http-auth b/fail2ban/tests/files/logs/nginx-http-auth index 6402cf8e..d7595b1a 100644 --- a/fail2ban/tests/files/logs/nginx-http-auth +++ b/fail2ban/tests/files/logs/nginx-http-auth @@ -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" }