Log Invalid Login Attempts for Fail2ban and upstream server action

I was hoping Discourse could log invalid login attempts to file, even if it is something you have to configure to do so. Then I could create a custom filter and jail for discourse

I use a centralized fail2ban server. the way it works is all my Containers, Docker images, VMs have a custom ban action:

in fail2ban you specify the action to take in your jail, such as:
action = iptables-allports

then all you have to do is edit that action:
sudo nano /etc/fail2ban/action.d/iptables-allports.conf

actionban = <iptables> -I f2b-<name> 1 -s <ip> -j <blocktype>
      curl -s "https://fail2ban.YourDomain.com:35553/fail2ban.php?token=D2f3Ydy45f6y5FRTfyeFrtYErt&action=add&source=TEST_HOST&reason=TEST_FILTER&ip=111.222.333.444"

With this setup your container/docker/vm will fail2ban them locally, but it will also relay this information to your central fail2ban server. The central server can also take all collected IPs and make them available as txt banlist such as: https://fail2ban.YourDomain.com/banned.txt

Then you can have your pfsense firewall subscribe to this banlist, and you can even share the list with other pfsense routers. This way if they try breaking in on one application, they get banned from everything. This has worked great for me for years.

And all that I need to implement this for discourse is for discourse to write an entry to a log file when there is an invalid login attempt :slight_smile:

1 Like

did you figure out how to hook or log this?

Thanks

1 Like

Bump. This seems like a very good idea!

Where does Discourse store and show logs?

The NGINX logs
Occasionally NGINX logs may contain some extra tips, they are located at:

cd /var/discourse
./launcher enter app
cd /var/log/nginx
The files access.log and error.log will be there as well as a bunch of rotated compressed files. Running less access.log.2.gz will automatically decompress and display the logfile for you.

This directory is also available on the host at /var/discourse/shared/standalone/log/var-log/nginx .

Unfortunately, the nginx error.log and access.log files do not log any invalid login attempts.

Can anyone suggest another avenue?

Thank you.

1 Like

Agree. It would be great to hook into a fail2ban kind of automated exponential backoff.

1 Like

curious - is this feature request being tracked or planned yet? It would be a good security feature.

log (or hook for) failed login attempts by IP address

Thank you!

1 Like

The nginx access.log file should have lines with 403 responses to the login route that you need for this. Have you checked the logs?

1 Like

ahhh, thank you! I wonder how to access it from outside the docker image/container

Hello @Falco thanks for the reply. I promptly checked the logs just now, a correct password attempt and incorrect password attempt look the same to me (200 response):

(I sanitized the IP address and domain, the rest is untouched)

bad password:

[20/Dec/2021:08:07:31 -0800] "community.example.com" 10.111.222.33 "GET /session/csrf HTTP/1.1" "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:95.0) Gecko/20100101 Firefox/95.0" "session/csrf" 200 1185 "https://community.example.com/" 0.016 0.017 "-"
[20/Dec/2021:08:07:32 -0800] "community.example.com" 10.111.222.33 "POST /session HTTP/1.1" "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:95.0) Gecko/20100101 Firefox/95.0" "session/create" 200 1111 "https://community.example.com/" 0.552 0.550 "-"

good password:

[20/Dec/2021:08:24:50 -0800] "community.example.com" 10.111.222.33 "GET /session/csrf HTTP/1.1" "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:95.0) Gecko/20100101 Firefox/95.0" "session/csrf" 200 1185 "https://community.example.com/" 0.020 0.020 "-"
[20/Dec/2021:08:24:51 -0800] "community.example.com" 10.111.222.33 "POST /session HTTP/1.1" "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:95.0) Gecko/20100101 Firefox/95.0" "session/create" 200 2251 "https://community.example.com/" 1.216 1.216 "-"

so since they are both returning a 200 response, you cannot use this for fail2ban, you will ban all users good or bad password.

2 Likes

Twitter uses 400 for wrong password, but Facebook, LinkedIn, Google and Amazon returns a 200. IMO a 200 sounds wrong, but it appears to be the “normal” thing?

Maybe you can start with a plugin that hooks into this method here

And does what you need?

3 Likes

awesome, thanks for the reply! soon as I get a little bit of downtime I will try making a plugin to generate this info! ( all I need is the ip address logged to a file when somebody tries logging in with an incorrect password eg: invalid login attempt from IP 10.111.222.33 )

3 Likes

thank you! I hope to use this plugin; let me know if you can make it available.

Did you ever get this working? I am very interested in using fail2ban with my discourse instance as well.

I’m writing on the roles of selfmade webmaster and pure end user, but…

Invalid login is error 200 by definition. Sure, it can and should be internal error of an app, and at some point generate something else, like error 403 plus something else like sending recovering link, but it shouldn’t or can’t happend right away.

Fail2ban is a nice tool but really overrated. Let’s forget docker, because it makes everything harder, but just the fact it can bypass iptables of VPS is really haze thing for me. But bots have tendency change IP after every 3rd attempt and that makes Fail2ban quite toothless against pure brute attack via login.

Script kiddies are another story, of course. Thay copy&paste everything they find, give a spin and don’t play with IPs. Then Fail2ban can stop them, even they can rarely do anything harm, but increasing load. The real issue is amount of script kiddies when there is instant flood.

But as long as VPS can handle such situation it just doesn’t matter. Now is 2023 and mostly those a-holes are knocking ancient vulnerabilites of wordpress on discourse-site :wink:

But we should have some logic to stop constant logins, no matter it is not an everyday threat, I reckon.