Using ipset to efficiently block multiple IP addresses

1. Introduction

In the last article Stopping an SSH Brute force Attack I talked about the nature of an SSH brute force attack and how to stop it manually. Since then my server has been getting a huge number of attacks. It’s impossible to stop them manually because that would mean blocking every single IP one by one. So It occurred to me to create a tool that does that automatically. We won’t be doing that in this article. Instead we will be first exploring an efficient way of blocking thousands of IP addresses.

2. The problem

In the last article, I mentioned how to block malicious ip addresses using iptables. But since i was getting bombarded with these attacks. Soon enough, I had more iptables rules than I could handle. The server was struggling also because of all the rules it had to check before allowing every single packet.

$ sudo iptable -t raw -L PREROUTING
Chain PREROUTING (policy ACCEPT)
target     prot opt source               destination
DROP       all  --  61.177.*.*           anywhere
DROP       all  --  139.59.*.*           anywhere
DROP       all  --  130.162.*.*          anywhere
DROP       all  --  195.49.*.*           anywhere
DROP       all  --  61.238.*.*           anywhere
DROP       all  --  218.92.*.*           anywhere
DROP       all  --  43.155.*.*           anywhere
...

3. The solution

So to solve this issue, we will use an ipset. It’s a configurable list of IP addresses that can efficiently reduce the number of rules we need to create Which, in turn, will reduce the number of rules that the kernel needs to check before allowing every single packet.

first things first, install ipset package. You can do that in a debian based distro as follows:

$ sudo apt install ipset
Reading package lists... Done
Building dependency tree
Reading state information... Done
ipset is already the newest version (6.38-1.2).
0 upgraded, 0 newly installed, 0 to remove and 0 not upgraded.

Let’s create our first ipset with the name badips :

$ sudo ipset create badips iphash

Now we will configure an iptables rule to block any packet that is coming from any IP addresses in the ipset badips:

$ sudo iptables -t raw -I PREROUTING -m set --match-set badips src -j DROP

Now we can just add the malicious IP addresses, that we want to block, to the badips set as follows:

$ sudo ipset add badips 1.1.1.1

To reiterate, we created a list of IP addresses called badips and we told iptables to block any packet coming from an IP address that is part of that list. Whenever we want to block a new IP, we just have to add it to the list.