Today we gonna explore a interesting security issue and solution for it. While most organization are using centralized logging and centralized firewalls, services running on standalone servers or VMs have been always a target to malicious actors. In today post we will dive into authentication failures and ways to protect ourselves from those. In our scenario we will be protecting a mail server, which is running postfix and dovecot locally. However the method described here is not limited to the services mentioned above and can be applied to a large number of others.
What’s the issue
If you happened to administer a mail server or SSH server you most probably have noticed a lot of authentication failures from different IP addresses. There are several tools which can be used to fight those authentication attempts like Fail2ban, but my experience with those have never been much of success.
Is there a way to stop these attacks
Searching online didn’t help me a lot so I decided to try and create something on own solution. The requirements were simple -
to run on Rocky Linux and to read logs and extract IPs from a failed authentication attempts. Extraction should be done through
regular expressions, but as I tought simple grep isn’t enough. So it looks like the desired solution consist of two parts -
getting the IPs and blocking them.
Firewalld and ipsets
Rocky Linux is coming by default with firewalld daemon, which is responsible for managing the firewall rules and filtering traffic.
However blocking specific IP should be done through rich rule, which is not very managable option. Another option is creating
an ipset and blocking all the traffic from the IP addresses in it. Ipsets can be created with some options likes family (ipv4 or ipv6),
timeout, maximum number of entries in the ipset, etc. You can check all of them in the man pages man ipset. Once the ipset
is defined you can easily add/remove entries in it. In my solution I were considering adding a timeout of the entries, but finally
I decided to go without it. In summary all of the traffic from the IP addresses in the list will be dropped.
Python and logs
The second part was extracting the IP addresses from the logs and we decide to use Python on this one. After some back a nd forth with the source of the authentication failures the initial population of the ipset will be through the existing log files. For the future updates I prefer to use journald and read it every 24 hours (with crontab) and add new entries to the banned IP list.
The result
As the moment of this writing the blogged entries on the mail host, where we implement our solution is around 5000 IP addresses. The number of authentication attempts has dropped significally and for the last several days we have several new IP address added. The solution has no noticeable effect on the machine loading so far.
All of code with technical details can be found in Github.
Useful resources
man firewall-cmdman firewalld.ipsetman ipset- Python3 Regex Howto