Firewalling and brute force mitigation

So many bad guys everywhere. Paranoia you say? Well, take a look at your mail log. While I was preparing this guide I could barely follow it. The mail server I used for testing was by far not ready and I already got visits by a bunch of foreign IP addresses trying to guess accounts of email users. Scoundrels constantly scan the internet for mail servers and do not tire to find a way to abuse them. Let’s do something about that before they actually guess email accounts successfully.

First install the nftables package:

apt install nftables

Basic firewall rules with nftables

Let’s begin by blocking all incoming network ports except those that are needed to run your mail server. Previous versions of Debian used the iptables tool to help you add firewall rules. Debian Buster comes with a newer version of the Linux kernel that is moving from iptables to nftables. The good news is that you can still use iptables commands. The bad news is that most tools do not yet support nftables. However one distant future day the old syntax will not work any more so let’s dive straight into the new syntax and use nftables.

First let’s make the iptables command use nftables. Run:

update-alternatives --config iptables

You will be able to choose between iptables-nft (the new stuff) and iptables-legacy (the old stuff). Go with iptables-nft. Now the iptables command will manage nftables rules. However you can explicitly use the iptables-legacy command if you want to access the old-school iptables rules.

So where would you store the firewall rules? The recommended way is to create a file /etc/nftables.conf and add rules there. Although the new syntax takes some getting used to, it is at least pretty readable. This is my default file for new mail servers:

You should see “Active: active (exited)” as the status. It is normal that its status is “exited” because there is no permanent process running. The rules are applied just once and that’s it.

Although nftables has been there for quite a while many projects still do not support it. Fortunately an important tool to block off attackers does: fail2ban. The “#include” line shown in the file above refers to that.

Brute-force attacks

Let’s install fail2ban:

apt install fail2ban

This is a pretty little tool. It knows about a lot of patterns in your log files that show something harmful. The software runs in the background and follows the various log files. Each new line in the log is compared against regular expressions. If a match is found it blocks the IP address that was mentioned in the log. However by default fail2ban uses the deprecated iptables tool. Let’s make it use nftables, too.

Once again edit your /etc/nftables.conf file and at the end add this line:

As the firewall just needs to block IP addresses you might be tempted to use ‘table ip’ instead of ‘table inet’. However ‘ip’ only deals with IPv4 packets. You would have to manage ‘ip’ and ‘ipv6’ tables. So I am just going with ‘table inet’ here which is more versatile.

Restart nftables…

systemctl restart nftables

…and you should see a new table called fail2ban if you run:

nft list tables

Very nice. fail2ban just needs a little fine-tuning to use that table. Create a new file /etc/fail2ban/action.d/nftables-common.local that overrides the settings in the nftables-common.conf file and write:

[Init]
nftables_table = fail2ban
blocktype = drop

What it means…

nftables_table = fail2ban(That is the name of the nftables table you just created. There fail2ban will add IP addresses to be blocked.)

blocktype = drop(This way we just ignore attackers. Packets from them are thrown away instead of answered with an ICMP response.)

Create another file /etc/fail2ban/jail.local with…

[DEFAULT]
banaction = nftables-multiport
chain = input

If you are curious and would like to get informed about every attacker that was blocked you may add “action = %(action_mwl)s” that also gets WHOIS information about the attacker. However this gets boring quickly and often WHOIS information is censored anyway – especially from organisations that are home to spammers.

By default an IP address gets blocked for 10 minutes (bantime) if more than 5 (maxretry) failures happened within 10 minutes (findtime). Check the jail.conf file for more information and feel free to add your preferred values to your jail.local file.

Also by default only failed login attempts using SSH are detected. There are lots of filters for other events and you just need to enable them. This once again goes into your jail.local file. I suggest you add these lines:

You may wonder why in the example above I suggest defining port in the dovecot section. The reason is Debian bug #867374. The default configuration calls the service “imap” instead of “imap2” and that leads to an error because there is no “imap” service defined in /etc/services.

After all these changes it is a good idea to check if your fail2ban configuration is still valid:

fail2ban-server -t

Is fail2ban happy? Great. Restart fail2ban after your last change:

systemctl restart fail2ban

To see what fail2ban did take a look at /var/log/fail2ban.log. This is what it looked like after a few minutes:

nftables is pretty efficient with handling multiple IP addresses. It uses sets which are basically lists of IP addresses. iptables used to have the ipset functionality for that purpose. You can see in the output that it uses sets it names “elements”.

sorry, for me the nftables is completely new, someone can help me, after installing and configuring it closes my ssh port I can not enter, likewise close my bind9 dns ports since on that server I have the dns.

yeah, almost through your tutorial — thanks a lot at this point 🙂
I noticed the listing of chain f2b-postfix-ispmail, which reminds me of iptables syntax. Since nftables are used in this tutorial, might these lines be a leftover of a previous version?

If any of the content on workaround.org has made your daily life less miserable you are invited to donate via Paypal to email@christoph-haas.de. I also have a wish list of Amazon things for my projects if you would like to surprise me. However please don't feel obliged.