[Solved] fail2ban + nginx

Hello,

I’m trying to enable fail2ban for my nginx basic auth.

Following the docs (https://dietpi.com/docs/software/system_security/#fail2ban), is should be as simple as:

modifying the /etc/fail2ban/jail.conf file, and setting enable = true under the [software] name.

The jail.conf file does however only contain the following lines: https://github.com/MichaIng/DietPi/blob/dc487cab3aa46fdeda81277edf7afc9c6845f44e/dietpi/dietpi-software#L7925-L7943

[DEFAULT]
enabled = true
ignoreip = 127.0.0.1/8
ignorecommand =
backend = systemd
mode = normal
filter = %(__name__)s[mode=%(mode)s]
findtime = 600
maxretry = 3
bantime = 600
banaction = route
action = %(banaction)s[blocktype=blackhole]
[dropbear]
[sshd]
# Mode: normal (default), ddos, extra or aggressive (combines all)
# See "filter.d/sshd.conf" for details.
#mode = normal

As you can see, there is no [nginx-http-auth] header. I’ve tried adding it to the file myself as:

[nginx-http-auth]
# mode = normal
port    = http,https
logpath = /var/log/nginx/error.log
enabled = true

However, when I fail the http auth through the nginx webserver, entries are added to the /var/log/nginx/error.log, but no ban is triggered and the fail2ban log file /var/log/fail2ban.log remains empty.
When I fail ssh logins, bans are triggered - so the fail2ban sshd service is working as intended.

This is the output of fail2ban status:

dietpi@DietPi:~$ sudo service fail2ban status
● fail2ban.service - Fail2Ban Service
     Loaded: loaded (/lib/systemd/system/fail2ban.service; enabled; vendor preset: enabled)
     Active: active (running) since Sun 2022-01-02 18:12:51 GMT; 1h 40min ago
       Docs: man:fail2ban(1)
   Main PID: 14563 (fail2ban-server)
      Tasks: 9 (limit: 4532)
        CPU: 17.638s
     CGroup: /system.slice/fail2ban.service
             └─14563 /usr/bin/python3 /usr/bin/fail2ban-server -xf start

Jan 02 18:12:51 DietPi fail2ban-server[14563]: fail2ban.filter         [14563]: INFO      maxRetry: 3
Jan 02 18:12:51 DietPi fail2ban-server[14563]: fail2ban.filter         [14563]: INFO      findtime: 600
Jan 02 18:12:51 DietPi fail2ban-server[14563]: fail2ban.actions        [14563]: INFO      banTime: 60
Jan 02 18:12:51 DietPi fail2ban-server[14563]: fail2ban.filtersystemd  [14563]: NOTICE  Jail started without 'journalmatch' set. Jail regexs will be checked against all journal entries, which is not advised for performance reasons.
Jan 02 18:12:51 DietPi fail2ban-server[14563]: fail2ban.jail           [14563]: INFO    Jail 'dropbear' started
Jan 02 18:12:51 DietPi fail2ban-server[14563]: fail2ban.jail           [14563]: INFO    Jail 'sshd' started
Jan 02 18:12:51 DietPi fail2ban-server[14563]: fail2ban.filtersystemd  [14563]: NOTICE  Jail started without 'journalmatch' set. Jail regexs will be checked against all journal entries, which is not advised for performance reasons.
Jan 02 18:12:51 DietPi fail2ban-server[14563]: fail2ban.jail           [14563]: INFO    Jail 'nginx-http-auth' started
Jan 02 18:12:51 DietPi fail2ban-server[14563]: Server ready

This is the status of the fail2ban-client:

dietpi@DietPi:~$ sudo fail2ban-client status
Status
|- Number of jail:      3
`- Jail list:   dropbear, nginx-http-auth, sshd

And the status of the fail2ban-client nginx-http-auth jail:

dietpi@DietPi:~$ sudo fail2ban-client status nginx-http-auth
Status for the jail: nginx-http-auth
|- Filter
|  |- Currently failed: 0
|  |- Total failed:     0
|  `- Journal matches:
`- Actions
   |- Currently banned: 0
   |- Total banned:     0
   `- Banned IP list:

I hope you’re able to help.

Best regards, pepsi.

Hi,

I guess you need to have a look if the failed login message fits to the filter definition done in /etc/fail2ban/filter.d/nginx-http-auth.conf

Hello. Thanks your your help.

This is a clip from the error log:

2022/01/03 09:36:11 [error] 19814#19814: send() failed (111: Connection refused) while resolving, resolver: 127.0.0.1:53
2022/01/03 09:36:11 [error] 19814#19814: send() failed (111: Connection refused) while resolving, resolver: 127.0.0.1:53
2022/01/03 09:36:15 [error] 19814#19814: *179 user "admin": password mismatch, client: 111.111.111.111, server: aaa.bbb.ccc, request: "GET /priv/ HTTP/1.1", host: "aaa.bbb.ccc"
2022/01/03 09:36:16 [error] 19814#19814: send() failed (111: Connection refused) while resolving, resolver: 127.0.0.1:53
2022/01/03 09:36:19 [error] 19814#19814: *181 user "admin": password mismatch, client: 111.111.111.111, server: aaa.bbb.ccc, request: "GET /priv/ HTTP/1.1", host: "aaa.bbb.ccc"
2022/01/03 09:36:21 [error] 19814#19814: send() failed (111: Connection refused) while resolving, resolver: 127.0.0.1:53
2022/01/03 09:36:22 [error] 19814#19814: *183 user "admin": password mismatch, client: 111.111.111.111, server: aaa.bbb.ccc, request: "GET /priv/ HTTP/1.1", host: "aaa.bbb.ccc"
2022/01/03 09:36:24 [error] 19814#19814: *184 user "admin": password mismatch, client: 111.111.111.111, server: aaa.bbb.ccc, request: "GET /priv/ HTTP/1.1", host: "aaa.bbb.ccc"
2022/01/03 09:36:26 [error] 19814#19814: send() failed (111: Connection refused) while resolving, resolver: 127.0.0.1:53
2022/01/03 09:36:27 [error] 19814#19814: *186 user "admin": password mismatch, client: 111.111.111.111, server: aaa.bbb.ccc, request: "GET /priv/ HTTP/1.1", host: "aaa.bbb.ccc"
2022/01/03 09:36:30 [error] 19814#19814: *187 user "admin": password mismatch, client: 111.111.111.111, server: aaa.bbb.ccc, request: "GET /priv/ HTTP/1.1", host: "aaa.bbb.ccc"
2022/01/03 09:36:31 [error] 19814#19814: send() failed (111: Connection refused) while resolving, resolver: 127.0.0.1:53
2022/01/03 09:36:32 [error] 19814#19814: *189 user "admin": password mismatch, client: 111.111.111.111, server: aaa.bbb.ccc, request: "GET /priv/ HTTP/1.1", host: "aaa.bbb.ccc"
2022/01/03 09:36:36 [error] 19814#19814: send() failed (111: Connection refused) while resolving, resolver: 127.0.0.1:53

Here is the regex from /etc/fail2ban/filter.d/nginx-http-auth.conf:

 ^ \[error\] \d+#\d+: \*\d+ user "(?:[^"]+|.*?)":? (?:password mismatch|was not found in "[^\"]*"), client: <HOST>, server: \S*, request: "\S+ \S+ HTTP/\d+\.\d+", host: "\S+"(?:, referrer: "\S+")?\s*$

https://regex101.com/ says there’s errors in the regex - so this might the be reason. Is this the right way to test the regex?

Seeing as the regex obtained directly from the github repository https://github.com/fail2ban/fail2ban/blob/095aeda8407b433098df35424cde2764a09566a6/config/filter.d/nginx-http-auth.conf#L8

mdre-auth = ^\s*\[error\] \d+#\d+: \*\d+ user "(?:[^"]+|.*?)":? (?:password mismatch|was not found in "[^\"]*"), client: <HOST>, server: \S*, request: "\S+ \S+ HTTP/\d+\.\d+", host: "\S+"(?:, referrer: "\S+")?\s*$

also yelds an error at https://regex101.com/ I’m thinking that this is not the right way to test it.


Best regards, pepsi.

what kind of web application you are using?

I’m not sure how to answer that, but I’ll try.

I’m running a webserver serving static content through nginx where I’m using http basic auth through https on a rpi4b running the latest version of dietpi.

To test the regex I’m just plugging it into https://regex101.com/ and checking for matches.

Best regards.

the question was more on what the application is exactly as I would like to test myself

As in the nginx configuration?

I can remove the HTTPs and post a minimum configuration to reproduce if that’s what you mean?

ok I found the issue for your configuration. You need to change the backend type within your jail.conf file. By defailt it is set to systemd only. Just set it to auto to allow reading from log files as well.

backend = auto

Once done restart fail2ban

You’re right!

I just tested it, and It works. Thank you very much.

The fail2ban service log now also states that it is polling the logfile:

dietpi@DietPi:/etc/fail2ban$ sudo service fail2ban status
● fail2ban.service - Fail2Ban Service
     Loaded: loaded (/lib/systemd/system/fail2ban.service; enabled; vendor preset: enabled)
     Active: active (running) since Mon 2022-01-03 12:43:27 GMT; 3s ago
       Docs: man:fail2ban(1)
    Process: 36457 ExecStartPre=/bin/mkdir -p /run/fail2ban (code=exited, status=0/SUCCESS)
   Main PID: 36458 (fail2ban-server)
      Tasks: 9 (limit: 4532)
        CPU: 417ms
     CGroup: /system.slice/fail2ban.service
             └─36458 /usr/bin/python3 /usr/bin/fail2ban-server -xf start

Jan 03 12:43:27 DietPi fail2ban-server[36458]: fail2ban.jail           [36458]: INFO    Jail 'nginx-http-auth' uses poller {}
Jan 03 12:43:27 DietPi fail2ban-server[36458]: fail2ban.jail           [36458]: INFO    Initiated 'polling' backend
Jan 03 12:43:27 DietPi fail2ban-server[36458]: fail2ban.filter         [36458]: INFO      maxRetry: 3
Jan 03 12:43:27 DietPi fail2ban-server[36458]: fail2ban.filter         [36458]: INFO      findtime: 600
Jan 03 12:43:27 DietPi fail2ban-server[36458]: fail2ban.actions        [36458]: INFO      banTime: 60
Jan 03 12:43:27 DietPi fail2ban-server[36458]: fail2ban.filter         [36458]: INFO    Added logfile: '/var/log/nginx/error.log' (pos = 0, hash = da39a3ee5e6b4b0d3255bfef95601890afd80709)
Jan 03 12:43:27 DietPi fail2ban-server[36458]: fail2ban.jail           [36458]: INFO    Jail 'dropbear' started
Jan 03 12:43:27 DietPi fail2ban-server[36458]: fail2ban.jail           [36458]: INFO    Jail 'sshd' started
Jan 03 12:43:27 DietPi fail2ban-server[36458]: fail2ban.jail           [36458]: INFO    Jail 'nginx-http-auth' started
Jan 03 12:43:27 DietPi fail2ban-server[36458]: Server ready