From e5fdceffae601359bf6aec9e005c18968b9e3acb Mon Sep 17 00:00:00 2001 From: Rafael Soje Date: Thu, 29 Oct 2026 22:44:29 -0300 Subject: [PATCH] filter.d/authelia: add new filter and jail for Authelia Add filter and jail configuration for Authelia 2FA/SSO portal, supporting standard key-value (file) and structured JSON logging formats with respective unit test samples. Closes gh-4005 --- ChangeLog | 1 + config/filter.d/authelia.conf | 38 ++++++++++++++++++++++++++++++ config/jail.conf | 5 ++++ fail2ban/tests/files/logs/authelia | 29 +++++++++++++++++++++++ 4 files changed, 73 insertions(+) create mode 100644 config/filter.d/authelia.conf create mode 100644 fail2ban/tests/files/logs/authelia diff --git a/ChangeLog b/ChangeLog index b19adfbe..47f26fa0 100644 --- a/ChangeLog +++ b/ChangeLog @@ -20,6 +20,7 @@ ver. 1.1.2-dev-1 (20??/??/??) - development nightly edition `paths-arch.conf`, `paths-fedora.conf`, `paths-opensuse.conf` - nftables, `paths-freebsd.conf`, `paths-osx.conf ` - pf; ### New Features and Enhancements +* `filter.d/authelia.conf` - new filter and jail for Authelia 2FA/SSO authentication portal supporting file and json log formats (gh-4005) * `filter.d/cowrie.conf` - new filter and jail for Cowrie SSH/Telnet honeypot JSON log output (gh-4216) * `filter.d/gitlab.conf` - `logtype` option `json` adding support for the `application_json.log` format that superseded the deprecated `application.log`; default type `file` keeps the previous behaviour (gh-3566, gh-4230) diff --git a/config/filter.d/authelia.conf b/config/filter.d/authelia.conf new file mode 100644 index 00000000..f5394aeb --- /dev/null +++ b/config/filter.d/authelia.conf @@ -0,0 +1,38 @@ +# Fail2Ban filter for Authelia +# +# Detecting unauthorized access to Authelia authentication portal +# (https://github.com/authelia/authelia) +# +# Supports two logging formats via logtype option: +# logtype = file (default, standard key-value text format) +# logtype = json (structured JSON format) +# + +[INCLUDES] + +# Load customizations if any available +after = authelia.local + +[Definition] + +# Log format: "file" (standard key-value text) or "json" +logtype = file + +failregex = /failregex> +datepattern = /datepattern> +ignoreregex = + +journalmatch = _SYSTEMD_UNIT=authelia.service + +[lt_file] + +datepattern = {^LN-BEG}time="{DATE}"\s+ +grp = (?:\w+=("(?:[^\\"]|\\.)*"|\S+)\s+)* +failregex = ^\s*%(grp)smsg="Unsuccessful \S+ authentication attempt by user '(?:[^\\']|\\.)*'[^"]*" %(grp)sremote_ip= + +[lt_json] + +datepattern = "time":"{DATE}" +grp = (?:"\w+":("(?:[^\\"]|\\.)*"|\S+),\s*)* +failregex = ^{%(grp)s"msg":"Unsuccessful \S+ authentication attempt by user '(?:[^\\']|\\.)*'[^"]*",%(grp)s"remote_ip":"" + ^{%(grp)s"remote_ip":"",%(grp)s"msg":"Unsuccessful \S+ authentication attempt by user '(?:[^\\']|\\.)*'[^"]*" diff --git a/config/jail.conf b/config/jail.conf index 8f02e9af..d56d9f66 100644 --- a/config/jail.conf +++ b/config/jail.conf @@ -864,6 +864,11 @@ port = 500,4500 protocol = udp logpath = /usr/local/vpnserver/security_log/*/sec.log +[authelia] +# for structured JSON log set: filter = authelia[logtype=json] +port = http,https,9091 +logpath = /var/log/authelia/authelia.log + [gitlab] # for the newer application_json.log set: filter = gitlab[mode=json] port = http,https diff --git a/fail2ban/tests/files/logs/authelia b/fail2ban/tests/files/logs/authelia new file mode 100644 index 00000000..f848d39d --- /dev/null +++ b/fail2ban/tests/files/logs/authelia @@ -0,0 +1,29 @@ +# Authelia authentication log samples (standard text / file format) +# failJSON: { "time": "2025-06-24T15:47:29", "match": true, "host": "10.10.10.4" } +time="2025-06-24T15:47:29+02:00" level=error msg="Unsuccessful 1FA authentication attempt by user 'example'" error="authentication failed. Cause: error occurred performing bind: LDAP Result Code 49 \"Invalid Credentials\": " method=POST path=/api/firstfactor remote_ip=10.10.10.4 + +# failJSON: { "time": "2025-06-24T15:47:35", "match": true, "host": "192.168.1.50" } +time="2025-06-24T15:47:35+02:00" level=error msg="Unsuccessful TOTP authentication attempt by user 'john'" method=POST path=/api/secondfactor/totp remote_ip=192.168.1.50 + +# failJSON: { "time": "2025-06-24T15:47:40", "match": true, "host": "2001:db8::1" } +time="2025-06-24T15:47:40+02:00" level=error msg="Unsuccessful Duo authentication attempt by user 'admin'" remote_ip=2001:db8::1 + +# a successful login must not match +# failJSON: { "match": false } +time="2025-06-24T15:50:00+02:00" level=info msg="Successful 1FA authentication attempt by user 'example'" method=POST path=/api/firstfactor remote_ip=10.10.10.4 + +# Authelia authentication log samples (JSON format) +# filterOptions: [{"logtype": "json"}] + +# failJSON: { "time": "2025-06-24T15:49:10", "match": true, "host": "10.10.10.4" } +{"error":"authentication failed. Cause: error occurred performing bind: LDAP Result Code 49 \"Invalid Credentials\": ","level":"error","method":"POST","msg":"Unsuccessful 1FA authentication attempt by user 'example'","path":"/api/firstfactor","remote_ip":"10.10.10.4","time":"2025-06-24T15:49:10+02:00"} + +# failJSON: { "time": "2025-06-24T15:49:10", "match": true, "host": "2001:db8::1" } +{"error":"authentication failed","level":"error","method":"POST","msg":"Unsuccessful TOTP authentication attempt by user 'admin'","path":"/api/secondfactor/totp","remote_ip":"2001:db8::1","time":"2025-06-24T15:49:10+02:00"} + +# failJSON: { "time": "2025-06-24T15:49:10", "match": true, "host": "192.168.1.100" } +{"level":"error","remote_ip":"192.168.1.100","msg":"Unsuccessful WebAuthn authentication attempt by user 'alice'","time":"2025-06-24T15:49:10+02:00"} + +# a successful JSON login must not match +# failJSON: { "match": false } +{"level":"info","method":"POST","msg":"Successful 1FA authentication attempt by user 'example'","path":"/api/firstfactor","remote_ip":"10.10.10.4","time":"2025-06-24T15:50:00+02:00"}