yum
upgrades for production use, this is the repository for you.
Active subscription is required.
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 a bad cause.
Quick and simple blocking with fds
The new utility program for FirewallD is fds
. You can use it to easily block single IP addresses, entire networks, and even countries.
Install fds
by running:
sudo yum -y install https://extras.getpagespeed.com/release-latest.rpm
sudo yum -y install fds
Block a single IP:
sudo fds block 95.211.0.0
Block a network:
sudo fds block 95.211.0.0/16
Block a country:
sudo fds block China
To list countries available for blocking, run:
sudo fds list countries
To unblock a country or a network/IP, use unblock
:
sudo fds unblock 95.211.0.0/16
sudo fds unblock China
To reset all the blocks (remove them), run:
sudo fds reset
The fds
utility makes it very easy to block arbitrary networks and even has the ability to integrate with Cloudflare.
You can read more in the official documentation for fds
, or simply run man fds
.
You can also perform the same blocking using a lower-level firewall-cmd
program.
For details, read further.
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 --permanent --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
We now know how to ban entire networks using FirewallD.
If you want to exclude specific IP addresses from blocking, read on how to whitelist IP addresses in FirewallD.
That’s about it for today. Happy Internet wars 🙂
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…
I'm not so good in CentOS... it's my first installation, am I missing something?
Danila Vershinin
The most efficient would be:
Thanks for asking.
Khurram
How would you list the ipset address?
Danila Vershinin
Either:
Or:
Arthur Lee
What country are supported for block? I saw this command: sudo fds block China I blocked Iraq (but had to type it with a capital “I”. What other countries can I block and which ones are known for high malicious/spam/fraud type activities?
Arthur Lee
Also – how can I see a list of IPs that I have blocked using FDS? What is the exact command to see this. sudo firewall-cmd –zone=public –list-all doesn’t show anything I blocked with FDS.
Danila Vershinin
All the blocked networks/countries are stored in networkblock* and fds-“country code”-* IP sets.
So you can see all the IP/networks blocked using standard mechanisms of either FirewallD or regular
ipset
utility:sudo ipset -L
.The very recent version of
fds
allows to do that easier with:To see what countries are available for blocking, you can run:
Since the new version is quite fresh, you might have to
yum clean all
thenyum update fds
to upgrade to it.Which countries you want to block/not block would vary based on the location of genuine visitors and is a question you might better answer yourself.
But as a rule of thumb, if you are not doing any business (if that is for E-Commerce) in a country, then it can be blocked to reduce unwanted traffic.
I’m hoping China is not offended for being used as an example of blocking 🙂
Arthur Lee
How do you install FDS on RHEL 8.3?
I keep getting an error:
Last metadata expiration check: 0:30:39 ago on Sun 21 Mar 2021 06:06:33 PM EDT.
release-latest.rpm 35 kB/s | 16 kB 00:00
Error:
Problem: conflicting requests
– nothing provides epel-release needed by getpagespeed-extras-release-10-16.noarch
(try to add ‘–skip-broken’ to skip uninstallable packages or ‘–nobest’ to use not only best candidate packages)
Danila Vershinin
Install EPEL repository first:
Arthur Lee
I’m using your commands:
sudo yum -y install https://extras.getpagespeed.com/release-latest.rpm
sudo yum -y install fds
Arthur Lee
Here is the error I am getting after installing:
[root@mail ~]# sudo fds block 218.92.0.184
Traceback (most recent call last):
File “/bin/fds”, line 6, in
from pkg_resources import load_entry_point
File “/usr/lib/python3.6/site-packages/pkg_resources/init.py”, line 3095, in
@_call_aside
File “/usr/lib/python3.6/site-packages/pkg_resources/init.py”, line 3079, in _call_aside
f(*args, **kwargs)
File “/usr/lib/python3.6/site-packages/pkg_resources/__init__.py”, line 3108, in _initialize_master_working_set
working_set = WorkingSet._build_master()
File “/usr/lib/python3.6/site-packages/pkg_resources/__init__.py”, line 570, in _build_master
ws.require(__requires__)
File “/usr/lib/python3.6/site-packages/pkg_resources/__init__.py”, line 888, in require
needed = self.resolve(parse_requirements(requirements))
File “/usr/lib/python3.6/site-packages/pkg_resources/__init__.py”, line 774, in resolve
raise DistributionNotFound(req, requirers)
pkg_resources.DistributionNotFound: The ‘setuptools_scm’ distribution was not found and is required by fds
I tried rebooting the RHEL 8.3 server and same thing. I tried blocking by country and same thing.
Can you help me please?
Danila Vershinin
Please update to latest version:
yum clean all; yum update fds
Arthur Lee
Thank you! That worked perfectly.
Arthur Lee
Oh – it worked for blocking an IP but not a country:
[root@mail ~]# fds block china
china does not look like a correct IP, region, or a country name
Am I doing something wrong?
Danila Vershinin
China should be capitalized 🙂
Arthur Lee
Thank you.
Arthur Lee
Perfect. Thank you so much.
Arthur Lee
Is there a command to refresh the country list contents that you get from IPDeny? for example after 6 months of running FDS, I would like to update the list of blocked IPs by country. Maybe you have an official document of all the FDS commands with examples I can use? thank you. If I can PayPal you for your help please let me know.
Danila Vershinin
The command is
fds cron
. The recentfds
package you have installed already includes a cron job that runs this command every night, so the IP sets are synced daily and there’s nothing you want/have to do about it. There is documentation with the commands in the official GitHub page for fds. From there you can ask questions, raise issues, and find the donate link.Arthur Lee
Sent you 5 coffee. Thank you again.
Arthur Lee
Might need a modification for RHEL here. : )
[root@mail ~]# fds cron
Traceback (most recent call last):
File “/usr/bin/fds”, line 11, in
load_entry_point(‘fds==0.0.16’, ‘console_scripts’, ‘fds’)()
File “/usr/lib/python3.6/site-packages/fds/fds.py”, line 196, in main
return action_cron()
File “/usr/lib/python3.6/site-packages/fds/fds.py”, line 74, in action_cron
fw.update_ipsets()
File “/usr/lib/python3.6/site-packages/fds/FirewallWrapper.py”, line 239, in update_ipsets
self.block_country(country_name, reload=False)
File “/usr/lib/python3.6/site-packages/fds/FirewallWrapper.py”, line 290, in block_country
log.info(‘Blocking {} {}’.format(country.name, country.getFlag()))
AttributeError: ‘str’ object has no attribute ‘name’
[root@mail ~]#
Danila Vershinin
Thanks. That should be fixed with newer version. Update the same with
yum clean all; yum update fds
Brandon Xavier
I keep getting the following when trying to install:
https://extras.getpagespeed.com/redhat/7/x86_64/RPMS/python2-msgpack-0.6.1-2.el7.x86_64.rpm: [Errno 14] HTTPS Error 403 – Forbidden
Any suggestions?
Danila Vershinin
This happens because you weren’t subscribed to the commercial repository. Disable that part if no intention to subscribe (fds can be installed without it):
Gio
Hi Danila,
hoping You are doing well :
question : ERROR: COMMAND_FAILED: ‘/usr/sbin/ipset restore’ failed: ipset v7.1: Error in line 6: Syntax error: ‘5.188.62.255’ is invalid as number
How can I remove this entry ?
thx
Danila Vershinin
I suppose you’re getting this when running
firewall-cmd --reload
. You can see what entries have been added wrong by checking persistent storage for the ipset at/etc/firewalld/ipsets/networkblock.xml
and adding fixes for erroneous data.