One of the problems of running my own servers and hosting my own sites is that for some reason people like to hack them and try to guess passwords with SSH. Fail2ban solves this problem by allowing only a few failed login attempts before banning the offending server for a specified duration of time. This is enough to make it so brute force attacks on your websites can be detoured.
But I had another issue too in that I have several sites that are on wordpress (like this one) and some that are old Ruby on Rails applications that I don’t want to update. With the WordPress blogs I just keep getting hammered by people trying to guess the wordpress user and password and trying to login. This loads my server pretty hard. With the ruby on rails application I have people that keep creating a ton of users. Here is how I used fail2ban to make this nonsense stop.
Borrowing from this idea I implemented fail2ban I didn’t bother adding any plugins. If people keep trying to login after 3 attempts they are banned. This is implemented as follows:
[Definition] failregex = <HOST>.*POST.*(wp-login\.php|xmlrpc\.php).* 200
[wordpress] enabled = true ignoreip = 127.0.0.1/8 <my ip address> port = http,https filter = wordpress logpath = /var/log/nginx/access.log maxretry = 3 bantime = 3600
And with a simple: systemctl restart fail2ban it was up and running. Here we see it worked great:
tail -f /var/log/fail2ban.log
2020-02-13 18:52:36,452 fail2ban.filter : INFO [wordpress] Found 184.108.40.206 - 2020-02-13 18:52:36 2020-02-13 18:52:38,181 fail2ban.filter : INFO [wordpress] Found 220.127.116.11 - 2020-02-13 18:52:38 2020-02-13 18:52:40,361 fail2ban.filter : INFO [wordpress] Found 18.104.22.168 - 2020-02-13 18:52:40 2020-02-13 18:52:40,959 fail2ban.actions : NOTICE [wordpress] Ban 22.214.171.124
Awesome! Sorry my Romainan friend 126.96.36.199, looks like you are banned.
My web application has a slightly different error message when someone keeps creating pages. The log looks like:
www.cookingwright.com:443 188.8.131.52 - - [13/Feb/2020:19:55:44 -0700] "POST /users HTTP/1.0" 302 4365 "https://cookingwright.com/signup" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.87 Safari/537.36 OPR/54.0.2952.51"
To make this work, I need a regular expression that captures the essense of this post. This is for people who keep creating new people. Really in this silly family app we have, you only need to make one user. So let’s ban them if they make more than one user.
[Definition] failregex = www.cookingwright.com:443 <HOST>.*POST.*(signup).*
[cw] enabled = true ignoreip = 127.0.0.1/8 <my ip address> port = http,https filter = cw logpath = /var/log/apache2/other_vhosts_access.log maxretry = 2 bantime = 36000
Yah! Now we’ve stopped people from adding a bunch of users to a webservice that really is only for my family, but you can make a login if you really want to :-).
In each case, fail2ban really just uses a regular expression to determine what to filter and who to ban. This flexibility makes it a great tool for securing many applications, not just SSH!