Today I want to make available to everyone a PHP (Hypertext Preprocessor) script that allows any user to be slowed down if the limits set for loading a web page are reached. If you are looking for something to stop DDOS attacks you are not in the right place; if you are looking for something to inhibit access- [Access the simple access to a website as a visitor] - to web pages based on the maximum number of requests in a limited time this little PHP script can help you. Whether to limit access to an API (Application Programming Interface) or limit access to sensitive areas (such as not allowing continuous updating of the page in critical areas such as registration or authentication) you are in the right place to learn to do it in a professional, fast and efficient way. To do this in a high-performance way we need a “no-sql” database and precisely for this script we use an even more high-performance database with “in-memory” technology, i.e. a database that writes to volatile memory. When I publish a script I like to do it in a free way, without particular dependencies, without locking it up in functions or classes if it is not necessary; however, it is still possible to create a function or even encapsulate it in a class, as you wish.
This is the script [Apache-2.0 license]:
<?php /** * ratelimit short summary. * * @version 1.0 * @author oskar @ myincorporate.org * * $time_period = Time period is specified in seconds (3600 seconds is 1 hour , 86400 seconds is 1 day) * $max_calls_limit = max calls allowed in that timespan * $total_user_calls = the toal calls the user has made * clients headers: * X-RateLimit-Limit: It is for providing max capacity. * X-RateLimit-Remaining: It is for clarifiying the remaning limits (tokens). * X-RateLimit-Reset: The time at which the rate limit resets, specified in UTC epoch time (in seconds) */ $redis = new Redis(); //connection to redis memory database $redis->connect('127.0.0.1', 6379); //password for redis $redis->auth(''); //select the database in memory (can be changed from 0 to max 16) $redis->select(0); //You can edit this part to set custom values $max_calls_limit = 500; $time_period = 3600; $total_user_calls = 0; //End of the editable part //It is possible to edit this part to implement the authentication system, just change the $user_code_ratelimit variable with the token used by the authentication system. //Get the visitor's IP (also if behind proxy) if (isset($_SERVER["HTTP_CF_CONNECTING_IP"])): $_SERVER['REMOTE_ADDR'] = $_SERVER["HTTP_CF_CONNECTING_IP"]; $_SERVER['HTTP_CLIENT_IP'] = $_SERVER["HTTP_CF_CONNECTING_IP"]; endif; $client = @$_SERVER['HTTP_CLIENT_IP']; $forward = @$_SERVER['HTTP_X_FORWARDED_FOR']; $remote = $_SERVER['REMOTE_ADDR']; if (filter_var($client, FILTER_VALIDATE_IP)): $user_code_ratelimit = $client; elseif (filter_var($forward, FILTER_VALIDATE_IP)): $user_code_ratelimit = $forward; else: $user_code_ratelimit = $remote; endif; //End of the editable part //hash the usercode created $user_code_ratelimit_hashed = hash('sha256', $user_code_ratelimit); //check the in-memory database and update it if needed if (!$redis->exists($user_code_ratelimit_hashed)): $redis->set($user_code_ratelimit_hashed, 1); $redis->expire($user_code_ratelimit_hashed, $time_period); $total_user_calls = 1; else: $redis->INCR($user_code_ratelimit_hashed); $total_user_calls = $redis->get($user_code_ratelimit_hashed); if ($total_user_calls > $max_calls_limit): echo "The rate limit is exceeded. Please try again later."; exit(); endif; endif; //settings header for the client (important: put this before any output, if this is not possible comment these 3 lines) header('X-RateLimit-Limit: '.$max_calls_limit); header('X-RateLimit-Remaining: '.$max_calls_limit-$total_user_calls); header('X-RateLimit-Reset: '.$time_period); ?>
You can view the script directly on my Github here: https://github.com/OskarCosimo/rate-limit/
How does the script work?
This script contains useful comments that can be used to modify variables as desired. The connection to the database occurs easily in a single step, via the call $redis->connect(‘127.0.0.1’, 6379) where 127.0.0.1 is the internal address of the server (localhost) and 6379 is the port used from the database (it is the default one); the variable $redis->auth(‘ ‘) is the database password (set during the installation phase) while the variable $redis->select(0) is the number of the database to use (Redis can have a maximum of 16 different databases , this is useful if you want to create multiple scripts that read from different databases). The $time_period variable and the $max_calls_limit variable are the only two variables that should be modified (in addition to those relating to the database connection) and consist of specifying the time period (expressed in seconds) and the maximum number of requests (int without decimals) that is possible to do. The variable $user_code_ratelimit is the one that takes care of having an identifier of the user who made the request to the server, by default we take the IP address of the visitor but this variable can also be set with the user code saved on a database that is refers to user authentication; this script, therefore, can also be integrated with any authentication system and with a small modification it is also possible to increase the number of requests allowed for already registered users.
What is Redis
Redis is an open source in-memory data store that can be used as a database, cache, or message broker. It’s often used for caching web pages and reducing the load on servers. Redis also has some features that make it attractive for use as a database, such as support for transactions and publish/subscribe messaging.
How to install Redis on your server
The official guide for install Redis in every operating system is here: https://redis.io/docs/latest/operate/oss_and_stack/install/install-redis
Is this system used on MYETV?
Yes, this system is used and will be used more frequently to protect against the numerous MYETV accesses; to increase the number of available requests it will be necessary to register on the platform- [Platform: the set of the main domain and all the subdomain of a particular website; also the computer architecture and equipment using a particular operating system] - .