I am recently facing an issue with some haters opening hundreds of tabs on my website to put it down. It’s a WordPress website hosted on a VPS with a 12 threads CPU and 48 GB memory with PHP 8.1. It uses LiteSpeed cache for both logged in and out users, with some private cache rules for ajax-based page fragments.
When they attack, the CPU load stay at 100% for multiple hours and the website is broken (with connections to the DB not working).
It’s protected with Cloudflare free plan but the problem is that it’s seen as legitimate visitors when it’s not really. I can’t find a clean solution to limite a single IP address to a maximum of XX requests per second or minute.
The only thing I found on stackoverflow is a PHP script to store vars in $_SESSION but I’d like to prevent this approach if you have something better to propose.
I asked the question on webmasters.stacjexchange but they kindly closed it since it’s about programming for them so please do not send me to another stack-exchange subsite.
2
Answers
Cloudflare helped, and I decided to refactor some part of the website to limit the number of AJAX calls. I wanted to load different parts of the pages asynchronously to make it looking more 2020 even if it's a PHP Wordpress, but looking at the difference of performance it seems to be a very bad idea.
Nevertheless, Cloudflare rate limiting has been triggered many times last night so it's definitely doing the job. I have read that Sucuri could also be a good alternative to Cloudflare, 10x cheaper.
CloudFlare has rate limiting per IP, which wouldn’t care whether the traffic is considered legitimate or not.
If you’re using a framework, many (such as Laravel) have built-in rate limiting which typically uses middleware and a cache server (eg redis) to keep track of how many requests come from each IP – see https://laravel.com/docs/10.x/rate-limiting
As @ceejayoz says in the comments on the post, ‘hundreds’ of requests shouldn’t be enough to bring down your site so it’s probably a good time to have a look at bottlenecks in your code. For example, one frequent bottleneck is connecting to your database over a non-local IP.