Fail2Ban is a great tool for protecting your server from brute force attacks.However, it can be quite slow at times, and I’ve noticed it causes the load average to jump when being started.
PyPy is an alternate Python implementation which uses a JIT(Just In Time) interpreter. This makes it faster than CPython, the official Python implementation, in most cases anyway. It is compatible with the vast majority of Python programs and libraries, so I thought it would be worth a try to install Fail2Ban with PyPy for improved performance. According to the README.md file, fail2ban supports PyPy. But, I haven’t been able to find any tutorial on how to do it, so I decided to make one my myself.
For the most part, it’s just like installing Fail2Ban manually with CPython, with a few exceptions. For this tutorial, I will be using my Ubuntu VPS. However, most steps will be the same for all Linux distros, although the package manager you use will likely be different if you’re not on a Debian/Ubuntu based distro.
First, you will need to install PyPy. For those of you on Debian/Ubuntu, just run the following:
sudo apt install pypy
If you’re on another Linux distro, use your distribution’s package manager, or build PyPy yourself.
Now, for installing Fail2Ban!
First, you’ll need to remove the default version if you have it. But, before you do that, backup all your config files(I’m using VestaCP, which makes a ton of custom filters and actions)! You can do this with:
sudo mv /etc/fail2ban /etc/fail2ban.old
Now, you can remove the package, so run:
sudo apt purge fail2ban
Cloning a GitHub repository is always fun. But first, be sure you have git installed:
sudo apt install git
Now, move into the “/tmp” folder, which is cleared upon reboots, and run the following:
cd /tmp git clone https://github.com/fail2ban/fail2ban.git
Then, move into the newly created directory:
Fail2Ban made the install process relatively easy. All you need to run is:
sudo pypy setup.py install
and a bunch of output will be generated, followed by:
Please do not forget to update your configuration files. They are in "/etc/fail2ban/". You can also install systemd service-unit file from "build/fail2ban.service" resp. corresponding init script from "files/*-initd".
Now, be sure to restore your old Fail2Ban configs with:
sudo mv /etc/fail2ban /etc/fail2ban.default sudo mv /etc/fail2ban.old /etc/fail2ban
and, all your custom filters and actions should be fully functional, that is, after you complete the rest of the install.
Ensuring PyPy was used
Just to be on the safe side, you might want to check if Fail2Ban was actually installed with PyPy. To do this, simply look at the top of one of the files, which you can do with the following command:
head $(which fail2ban-server)
And the following output:
#!/usr/bin/pypy # emacs: -*- mode: python; py-indent-offset: 4; indent-tabs-mode: t -*- # vi: set ft=python sts=4 ts=4 sw=4 noet : # This file is part of Fail2Ban. # # Fail2Ban is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version.
Gives us everything we need to know. Just look at the first line, which should be something like:
If it ends with
python, then something went wrong 🙁 . Try again to make sure you didn’t accidentally use
python instead of
Now, all the fail2ban “binaries”(ok, technically, there’s no such thing as binaries with Python, but whatever) are installed in
/usr/local/bin, but there is no easy way to run them. To fix this, go into the
files directory of the GitHub clone, and run the following:
cd /tmp/fail2ban/files sudo cp debian-initd /etc/init.d/fail2ban sudo update-rc.d fail2ban defaults
Then, ensure that everything went well by running:
sudo service fail2ban start
And, if there’s an error, then initd file was not properly installed. If there is no error, then everything went well! You can now check out the
/etc/fail2ban directory and start making changes!
Fail2Ban also comes with a
bash_completion file. So, I did the sensible thing and installed it. Just run:
cd /tmp/fail2ban/files sudo cp bash-completion /usr/share/bash-completion/completions/fail2ban
I honestly have no idea what this does, and whether or not it’s installed by default. But, nothing blew up, so everything appears to have worked 🙂 .
One last check
To be really, really sure Fail2Ban is using PyPy, just check the output of:
ps -aux | grep fail2ban
Which should be something like:
root 22293 0.5 5.6 802636 56768 ? Sl 07:59 0:01 /usr/bin/pypy /usr/local/bin/fail2ban-server --async -b -s /var/run/fail2ban/fail2ban.sock -p /var/run/fail2ban/fail2ban.pid --loglevel INFO --logtarget /var/log/fail2ban.log --syslogsocket auto
In my case, it’s using PyPy!
While fail2ban wasn’t really slowing down my VPS to begin with, it did use the full CPU for a few seconds after it started. Now, there’s no perceivable change in CPU utilization when restarting Fail2Ban. While it didn’t ban anyone yet, it was able to read all of the old config files just fine, and no changes to anything were required to get it to work.
I’m actually not sure if there’s any performance improvement, as there’s not exactly any Fail2Ban benchmark utilities out there. However, PyPy does provide considerable performance improvements over CPython from my testing. I do think it made Fail2Ban faster, because the majority of it is in Python, what PyPy can make faster, and not libraries written in C.
As with building any other package manually, you will need to take care of updates yourself. This means you have to go through the entire process over again whenever there is an update. But, since Fail2Ban doesn’t open up any ports to the outside world, I doubt there’s going to be any remote access exploits found that needs immediate fixing.
You have now successfully installed Fail2Ban using PyPy on your Linux server.
Sources: Fail2Ban Github
If you have any problems, put them in the comments and I will do my best to help. If there are errors with PyPy, ensure the install works with CPython. If not, open an issue. Otherwise, try re-installing PyPy.