Security / Server Setup

CentOS 7, 8: ban bad IPs and networks with FirewallD

by , , revisited on


We have by far the largest RPM repository with dynamic stable NGINX modules and VMODs for Varnish 4.1 and 6.0 LTS. If you want to install NGINX, Varnish and lots of useful modules for them, this is your one stop repository to get all performance related software.
You have to maintain an active subscription in order to be able to use the repository!

A couple of days ago, I have stumbled upon a DDoS attack with a server I’ve been managing. Few dozens of IPs have been repeatedly accessing the least cacheable pages causing server strain.

If you were in a similar situation, you ask yourself what can you do?

Let’s block the bad guys with the power of CentOS 7 standard firewall – FirewallD.

Meet FirewallD

Starting from CentOS/RHEL 7, a new firewall is bundled with the operating system – FirewallD.
It is actually a wrapper for the kernel’s net filtering module.

FirewallD allows you to manage the firewall rules using the concept of zones.
If you haven’t already, install it, run it and enable at boot time.

sudo yum -y install firewalld
sudo systemctl start firewalld
sudo systemctl enable firewalld

Investigate the bad guys

Finding the offending IP addresses is relatively easy. Say you are hosting a website powered by NGINX.

While having an unexpected load issue, trying to look up a few IP addresses from access.log usually confirms that the traffic does not have a genuine nature.

To get back to the sane load, see if those offending IP addresses belong to the same network for bulk blocking.

I took a few sample IPs which were hitting the server like crazy and used whois utility to find out network information.

sudo yum -y install whois
whois 95.211.246.234

Doing the same for all of those IP addresses I could see what was in common for them – the provider. Each whois output had this at the bottom:

route:          95.211.0.0/16
descr:          LEASEWEB
origin:         AS60781
remarks:        LeaseWeb
mnt-by:         LEASEWEB-NL-MNT
created:        2014-03-11T14:28:00Z
last-modified:  2015-09-30T23:00:04Z
source:         RIPE

The LeaseWeb, being a VPS provider, has no genuine website users coming from it. So is fine to be blocked.
In all probability, someone rented servers with them and used this for the bad cause.

Understand the drop FirewallD zone

By default, Firewalld comes with several predefined zones. I won’t go into details about them, but rather say that there is a convenient drop zone. Its description:

Any incoming network packets are dropped, there is no reply. Only outgoing network connections are possible.

This is just what we want. Accept no packets from those bad networks, yet still, have the ability to talk to them, e.g. in case, there is a server at LeaseWeb that hosts a useful API endpoint, etc.

FirewallD also supports ipsets for efficient storage of many IP addresses and networks. While we’re going to block only one network in our example, it’s good to learn how to leverage ipsets for the task. This will come in handy when we want to block lots and lots of IP addresses further.

Ban Them!

Initial Setup

Let’s get started and create our ipset which will contain all the IP networks we want to block:

firewall-cmd --permanent --new-ipset=networkblock --type=hash:net --option=maxelem=1000000 --option=family=inet --option=hashsize=4096

Next, we add our ipset to the drop firewall zone:

firewall-cmd --permanent --zone=drop --add-source=ipset:networkblock

Apply all the changes now with:

firewall-cmd --reload

Ban a network

In our case, we want to block the network 95.211.0.0/16. To ban it from our server, we simply add this network to our networkblock ipset:

firewall-cmd --permanent --ipset=networkblock --add-entry=95.211.0.0/16
firewall-cmd --reload

As you see, the commands are quite readable and you can easily add more bad networks for banning someone else. You will only need two lines. To add another network to ban list:

firewall-cmd --permanent --ipset=networkblock --add-entry=142.4.192.0/19
firewall-cmd --reload

Block SemrushBot

firewall-cmd --permanent --ipset=networkblock --add-entry=46.229.168.0/24
firewall-cmd --reload

If you are very picky or know for sure that the offender is coming from a single IP, just use /32 network (which corresponds to a single IP):

firewall-cmd --ipset=networkblock --add-entry=1.2.3.4/32
firewall-cmd --reload

Bulk Blocking many IP addresses

If you have a list of IP addresses to block (text file, each IP on a separate line), you can easily import that to your block list:

firewall-cmd --permanent --ipset=networkblock --add-entries-from-file=/path/to/blocklist.txt
firewall-cmd --reload

That’s about it for today. Happy Internet wars 🙂

P.S. for even easier blocking and setup, check out fds helper program.


Also published on Medium.

  1. alebal

    Hi, I would add a lot of ip with your code (about 100), I usually use ubuntu, in ubuntu I use this to add a list of ip from a .txt file.
    while read line; do sudo ufw insert 1 deny from $line to any; done < /var/www/html/cidr.txt

    I try this, but it doesn’t do anything…

    while read line; do sudo firewall-cmd --permanent --ipset=networkblock --add-entry=$line done < /var/www/html/ufw.txt
    

    I'm not so good in CentOS... it's my first installation, am I missing something?

    Reply
    • Danila Vershinin

      The most efficient would be:

      firewall-cmd --permanent --ipset=networkblock --add-entries-from-file=/path/to/blocklist.txt
      firewall-cmd --reload
      

      Thanks for asking.

      Reply

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.