Detect network-based DDOS attacks and block them in bulk using IPtables in Plesk

DDOS attacks are not always from an army of malicious network of zombie PC’s accross the world. Sometimes, legitimate services such as search engine bots, or other bots such as Semrush or DataForSeo consume too much resources on your hosting server and use > 100% of your CPUs. All the sites and services on your server get slow, and you get spammed by tons of alerts on your email and mobile.

This post was writting with Plesk 18 (Obsidian) and Debian 9 in mind.

Detecting attacks from Plesk’s 360° Monitoring

You can get 1 free server monitor at Plesk 360, if it sends you the kind of alerts shown below then you are probably under attack because something is consuming too many resources on your box.

Inspect the server activity

SSH into the machine and launch the htop command.
The example below is pretty cool but if everything is red and your load average is > to your number of CPUs or VPCUs, you have to mitigate the situation.

Sort the processes by CPU% (press F6, then arrow-down key navigate to PERCENT_CPU and press Enter).

If the top process is Apache / Nginx / PHP and belongs to a user who owns a website that you are hosting, note it down and let’s inspect this!

Acknowledge suspicious activity

If the user owns multiple websites in your Plesk installation, you can use some advice at Plesk KB: How to diagnose a DoS/DDoS attack and find websites under attack on a Plesk server, in particular the second section that describes the counting of the requests per website by parsing the logs for a string that matches a date or hour:

Replace ’02/Oct/2022′ by a relevant string

root@***:/var/www/vhosts/*****/logs# cd /var/www/vhosts/system
root@***:/var/www/vhosts/system# for i in *;do echo -n "$i "; grep '02/Oct/2022' $i/logs/access_ssl_log | awk '{print $1}' | wc -l;done > ~/requests
root@***:/var/www/vhosts/system# cat ~/requests
site1****** 0
site2****** 6
site3****** 21
site4****** 9858
site5****** 52
site6****** 512
site7****** 109
site8****** 4521
site9****** 3449
site10***** 5
site11***** 571
site12***** 309
site13***** 16
germain.lol 1254

Here we can see that site4 is consuming ~half of the server resources.

Take a look at the access logs directory of the website that belongs to the user whose processes are killing your CPU. The logs are located in /var/www/vhosts/domain-name/logs, use the ls -lah command to find large log files. In the example below, 3.7 GB of logs since 6:38 this morning is horrifyingly huge!

Use the tail -f access_ssl_log command to get an idea of what is filling this log so fast:

We can see that Semrush bot and DataForSeo bots are sending many queries.

Bulk blocking

There are many was to block requests, especially when it comes to bots, for example:

  • Custom rules in your .htaccess (or Nginx rules)
  • Custom rules in your robots.txt file
  • Relying on the plesk-apache-badbot fail2ban built-in rules
  • Using an extension such as (D)DoS Deflate Interface

Custom rules imply changing your customer’s website, which you certainly don’t want to do.
The last two ideas didn’t auto-mitigate the attack.
Therefore we have to handle the situation manually.

Single-IP blocking

If all the requests come from the same IP, simply create a basic firewall rule from Plesk admin:

Don’t forget to click « Apply » at the second step after clicking « OK »!

Blocking a company or ISP, aka range-blocking

It may not be a wise idea to block a whole company or ISP, but we’re trying to mitigate an attack here! Of course you don’t want to block all users from all your country’s ISPs at once, but there’s a good chance that you can block large company networks (including web and cloud hosters) without compromising end-users access to the websites you host.

From the logs below, let’s have a look at this DataForSEO’s IP: 161.97.157.176

Find whose IP it is

I like to use crawl-tools.com for this because they gather the data from all RIRs at once (RIPE for Europe, ARIN for USA, etc), it’s more convenient.

From the results we can tell that the said IP belogs to Contabo:

It is an hosting provider, the one used by DataForSEO’s bot.

Is it safe to block all traffic to a hosting provider?
Heck yes!
We want to preserve resources for real human users, not bots.

Beware: by doing so, you’ll be blocking Contabo and all their users, including legitimate users who have setup a VPN and access to your website behind it.

Find all the IPs that this company owns

As you know, a hosting company has many IPs, so we want to find them all – not only the one used by the bots. By definition, bots are deployed under multiple instances, which all have different and changing IPs.

What we are looking for is the « Autonomous System Number » (ASN), in this case: AS51167

Here we can see that the source is RIPE, which is the european RIR.

The easiest way to find all the IPs that belong to an ASN is by using https://ipinfo.io/. Just type in the ASN and all its IP ranges will pop:

Bulk-block IPs in IPtables through Plesk

It would be cumbersome to copy/paste all IPs one by one in the firewall Custom Rule Plesk form.
Here’s my solution to do it en masse.

First, copy-paste all the IP ranges inside a blank Excel spreadsheet:

Then, paste the column A contents into Visual Studio Code to edit multiple lines at once.
It also works with SublimText (shortcuts may vary).

Type ctrl + a to select all,
Type ctrl + shift + i to enter multi-line edit mode,
Type 🡼 to go to the begining of each line and remove extra whitespaces,
Type End to go to the end of each line and add a coma,
Type Del to remove all linebreaks and concatenate all lines into a single one,
Type spacebar to add an extra spacer,
Type End to go to the end of the single line,
Type backspace twice to remove the last space and coma,

You should end up with this:

Now that you have a single-line, coma-separated list of IP ranges, you need to insert it into to IPtables.
However the Plesk firewall Custom Rules form doesn’t accept this syntax:

So you have to SSH into your server again and do it with these commands (obviously you must replace my Contebo’s list with yours):

root@***:~# /usr/local/psa/bin/modules/firewall/settings -s -name 'ddos-contabo' -direction input -action deny -ports '' -remote-addresses "109.205.176.0/22, 109.205.180.0/22, 130.185.118.0/24, 130.185.119.0/24, 144.91.100.0/23, 144.91.102.0/23, 144.91.104.0/23, 144.91.106.0/23, 144.91.108.0/23, 144.91.110.0/23, 144.91.112.0/23, 144.91.114.0/23, 144.91.116.0/23, 144.91.118.0/23, 144.91.120.0/23, 144.91.122.0/23, 144.91.124.0/23, 144.91.126.0/23, 144.91.64.0/23, 144.91.66.0/23, 144.91.68.0/23, 144.91.70.0/23, 144.91.72.0/23, 144.91.74.0/23, 144.91.76.0/23, 144.91.78.0/23, 144.91.80.0/23, 144.91.82.0/23, 144.91.84.0/23, 144.91.86.0/23, 144.91.88.0/23, 144.91.90.0/23, 144.91.92.0/23, 144.91.94.0/23, 144.91.96.0/23, 144.91.98.0/23, 149.102.128.0/21, 149.102.136.0/21, 149.102.144.0/21, 149.102.152.0/21, 161.97.100.0/23, 161.97.102.0/23, 161.97.104.0/23, 161.97.106.0/23, 161.97.108.0/23, 161.97.110.0/23, 161.97.112.0/23, 161.97.114.0/23, 161.97.116.0/23, 161.97.118.0/23, 161.97.120.0/23, 161.97.122.0/23, 161.97.124.0/23, 161.97.126.0/23, 161.97.128.0/19, 161.97.160.0/20, 161.97.176.0/21, 161.97.184.0/22, 161.97.188.0/23, 161.97.64.0/23, 161.97.66.0/23, 161.97.68.0/23, 161.97.70.0/23, 161.97.72.0/23, 161.97.74.0/23, 161.97.76.0/23, 161.97.78.0/23, 161.97.80.0/23, 161.97.82.0/23, 161.97.84.0/23, 161.97.86.0/23, 161.97.88.0/23, 161.97.90.0/23, 161.97.92.0/23, 161.97.94.0/23, 161.97.96.0/23, 161.97.98.0/23, 164.68.100.0/23, 164.68.102.0/23, 164.68.104.0/23, 164.68.106.0/23, 164.68.108.0/23, 164.68.110.0/23, 164.68.112.0/23, 164.68.114.0/23, 164.68.116.0/23, 164.68.118.0/23, 164.68.120.0/23, 164.68.122.0/23, 164.68.124.0/23, 164.68.126.0/23, 164.68.96.0/23, 164.68.98.0/23, 167.86.100.0/23, 167.86.102.0/23, 167.86.104.0/23, 167.86.106.0/23, 167.86.108.0/23, 167.86.110.0/23, 167.86.112.0/23"
Firewall rule was successfully created; rule id: '403'.

root@***:~# /usr/local/psa/bin/modules/firewall/settings -a
Firewall rules were successfully activated, use --confirm command within 60 second(s) to confirm activation, otherwise all changes will be rolled back.

root@***:~# /usr/local/psa/bin/modules/firewall/settings -c
Applying and confirmation of firewall changes should be done via different ssh sessions

Note that the « Confirm » command (last one) must be done from another SSH session.
That is to avoid locking yourself out of your server!

Now you should enjoy seeing your server activity decrease in the htop monitoring screen!

Relevant services you may need to block during your attack mitigation period

ServicesIP ranges
Semrushhttps://ipinfo.io/AS30161
Semrush (2)https://ipinfo.io/AS396982
Semrush (3)https://ipinfo.io/AS209366
Hetznerhttps://ipinfo.io/AS24940
Contabohttps://ipinfo.io/AS51167
OVHhttps://ipinfo.io/AS16276
Dediboxhttps://ipinfo.io/AS12876
Huaweihttps://ipinfo.io/AS136907
Qwanthttps://ipinfo.io/AS199064
China Unicomhttps://ipinfo.io/AS4808
Googlehttps://ipinfo.io/AS396982
Linodehttps://ipinfo.io/AS63949
Aixithttps://ipinfo.io/AS29551
Flyservershttps://ipinfo.io/AS267784
PPTECHNOLOGYhttps://ipinfo.io/AS48090
Triolan (MJ12bot)https://ipinfo.io/AS13188

Quelques bots célèbres :

Crédit : https://ahrefs.com/robot/

Bon courage.

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée.

Ce site utilise Akismet pour réduire les indésirables. En savoir plus sur comment les données de vos commentaires sont utilisées.