From 7d82c82fd98b4496dac88154b5ed034f5b5276db Mon Sep 17 00:00:00 2001 From: LinQhost Managed hosting Date: Tue, 4 May 2021 10:29:25 +0200 Subject: [PATCH 1/6] Make it possible to exempt ips from the rate-limiter --- cfg/conf.sample.php | 4 ++ composer.json | 5 ++- composer.lock | 70 +++++++++++++++++++++++++++++- lib/Configuration.php | 1 + lib/Persistence/TrafficLimiter.php | 51 ++++++++++++++++++++++ 5 files changed, 128 insertions(+), 3 deletions(-) diff --git a/cfg/conf.sample.php b/cfg/conf.sample.php index e958c88d..0837645b 100644 --- a/cfg/conf.sample.php +++ b/cfg/conf.sample.php @@ -135,6 +135,10 @@ markdown = "Markdown" ; Set this to 0 to disable rate limiting. limit = 10 +; Set ips (v4|v6) which should be exempted for the rate-limit. CIDR also supported. Needed to be comma separated. +; Unset for enabling and invalid values will be ignored +; eg: exemptedIp = '1.2.3.4,10.10.10/24' + ; (optional) if your website runs behind a reverse proxy or load balancer, ; set the HTTP header containing the visitors IP address, i.e. X_FORWARDED_FOR ; header = "X_FORWARDED_FOR" diff --git a/composer.json b/composer.json index 899c863f..ff79af99 100644 --- a/composer.json +++ b/composer.json @@ -26,7 +26,8 @@ "require" : { "php" : "^5.6.0 || ^7.0 || ^8.0", "paragonie/random_compat" : "2.0.19", - "yzalis/identicon" : "2.0.0" + "yzalis/identicon" : "2.0.0", + "mlocati/ip-lib": "^1.14" }, "require-dev" : { "phpunit/phpunit" : "^4.6 || ^5.0" @@ -39,4 +40,4 @@ "config" : { "autoloader-suffix" : "DontChange" } -} \ No newline at end of file +} diff --git a/composer.lock b/composer.lock index 80d2276f..66a9c8a6 100644 --- a/composer.lock +++ b/composer.lock @@ -4,8 +4,76 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "9d110873bf15a6abd66734e8a818134c", + "content-hash": "8138b0e4bb3fcaab9ca4c02bbe35d891", "packages": [ + { + "name": "mlocati/ip-lib", + "version": "1.14.0", + "source": { + "type": "git", + "url": "https://github.com/mlocati/ip-lib.git", + "reference": "882bc0e115970a536b13bcfa59f312783fce08c8" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/mlocati/ip-lib/zipball/882bc0e115970a536b13bcfa59f312783fce08c8", + "reference": "882bc0e115970a536b13bcfa59f312783fce08c8", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "require-dev": { + "ext-pdo_sqlite": "*", + "phpunit/dbunit": "^1.4 || ^2 || ^3 || ^4", + "phpunit/phpunit": "^4.8 || ^5.7 || ^6.5" + }, + "type": "library", + "autoload": { + "psr-4": { + "IPLib\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Michele Locati", + "email": "mlocati@gmail.com", + "homepage": "https://github.com/mlocati", + "role": "Author" + } + ], + "description": "Handle IPv4, IPv6 addresses and ranges", + "homepage": "https://github.com/mlocati/ip-lib", + "keywords": [ + "IP", + "address", + "addresses", + "ipv4", + "ipv6", + "manage", + "managing", + "matching", + "network", + "networking", + "range", + "subnet" + ], + "funding": [ + { + "url": "https://github.com/sponsors/mlocati", + "type": "github" + }, + { + "url": "https://paypal.me/mlocati", + "type": "other" + } + ], + "time": "2020-12-31T11:30:02+00:00" + }, { "name": "paragonie/random_compat", "version": "v2.0.19", diff --git a/lib/Configuration.php b/lib/Configuration.php index 2a326caf..133059d3 100644 --- a/lib/Configuration.php +++ b/lib/Configuration.php @@ -82,6 +82,7 @@ class Configuration 'limit' => 10, 'header' => null, 'dir' => 'data', + 'exemptedIp' => null, ), 'purge' => array( 'limit' => 300, diff --git a/lib/Persistence/TrafficLimiter.php b/lib/Persistence/TrafficLimiter.php index a16cd0b3..31f107ff 100644 --- a/lib/Persistence/TrafficLimiter.php +++ b/lib/Persistence/TrafficLimiter.php @@ -1,4 +1,5 @@ getKey('limit', 'traffic')); self::setPath($conf->getKey('dir', 'traffic')); + self::setExemptedIp($conf->getKey('exemptedIp', 'traffic')); + if (($option = $conf->getKey('header', 'traffic')) !== null) { $httpHeader = 'HTTP_' . $option; if (array_key_exists($httpHeader, $_SERVER) && !empty($_SERVER[$httpHeader])) { @@ -99,6 +124,32 @@ class TrafficLimiter extends AbstractPersistence if (self::$_limit < 1) { return true; } + + // Check if $_ipKey is exempted from ratelimiting + if (!is_null(self::$_exemptedIp)) { + $exIp_array = explode(",", self::$_exemptedIp); + foreach ($exIp_array as $ipRange) { + // Match $_ipKey to $ipRange and if it matches it will return with a true + $address = \IPLib\Factory::addressFromString($_SERVER[self::$_ipKey]); + $range = \IPLib\Factory::rangeFromString(trim($ipRange)); + // If $range is null something went wrong (possible invalid ip given in config) + if ($range == null) { + $contained = false; + } else { + // Ip-lib does throws and exception when something goes wrong, if so we want to catch it and set contained to false + try { + $contained = $address->matches($range); + } catch (Exception $e) { + // If something is wrong with matching the ip, we set $contained to false + $contained = false; + } + } + // Matches return true! + if ($contained == true) { + return true; + } + } + } $file = 'traffic_limiter.php'; if (self::_exists($file)) { From b21efd8336c12f39bcf07e5ba9d0387ceee9955d Mon Sep 17 00:00:00 2001 From: rodehoed Date: Tue, 4 May 2021 11:01:46 +0200 Subject: [PATCH 2/6] Code quality --- lib/Persistence/TrafficLimiter.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/Persistence/TrafficLimiter.php b/lib/Persistence/TrafficLimiter.php index 31f107ff..46eddc45 100644 --- a/lib/Persistence/TrafficLimiter.php +++ b/lib/Persistence/TrafficLimiter.php @@ -62,11 +62,11 @@ class TrafficLimiter extends AbstractPersistence } /** - * set a list of ip(ranges) as array + * set a list of ip(ranges) as string * * @access public * @static - * @param array $exemptedIps + * @param string $exemptedIps */ public static function setExemptedIp($exemptedIp) { @@ -139,7 +139,7 @@ class TrafficLimiter extends AbstractPersistence // Ip-lib does throws and exception when something goes wrong, if so we want to catch it and set contained to false try { $contained = $address->matches($range); - } catch (Exception $e) { + } catch (\Exception $e) { // If something is wrong with matching the ip, we set $contained to false $contained = false; } From 805eb288d92be1716214156af50b69dbf88a0afd Mon Sep 17 00:00:00 2001 From: rodehoed Date: Tue, 4 May 2021 11:14:11 +0200 Subject: [PATCH 3/6] QA --- lib/Persistence/TrafficLimiter.php | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/lib/Persistence/TrafficLimiter.php b/lib/Persistence/TrafficLimiter.php index 46eddc45..06916c59 100644 --- a/lib/Persistence/TrafficLimiter.php +++ b/lib/Persistence/TrafficLimiter.php @@ -82,7 +82,6 @@ class TrafficLimiter extends AbstractPersistence */ public static function setConfiguration(Configuration $conf) { - self::setLimit($conf->getKey('limit', 'traffic')); self::setPath($conf->getKey('dir', 'traffic')); self::setExemptedIp($conf->getKey('exemptedIp', 'traffic')); @@ -127,11 +126,11 @@ class TrafficLimiter extends AbstractPersistence // Check if $_ipKey is exempted from ratelimiting if (!is_null(self::$_exemptedIp)) { - $exIp_array = explode(",", self::$_exemptedIp); + $exIp_array = explode(',', self::$_exemptedIp); foreach ($exIp_array as $ipRange) { // Match $_ipKey to $ipRange and if it matches it will return with a true $address = \IPLib\Factory::addressFromString($_SERVER[self::$_ipKey]); - $range = \IPLib\Factory::rangeFromString(trim($ipRange)); + $range = \IPLib\Factory::rangeFromString(trim($ipRange)); // If $range is null something went wrong (possible invalid ip given in config) if ($range == null) { $contained = false; From c3ad4a4b4d48946e89785171b83093f3527d5cf5 Mon Sep 17 00:00:00 2001 From: rodehoed Date: Tue, 4 May 2021 11:18:06 +0200 Subject: [PATCH 4/6] QA --- lib/Persistence/TrafficLimiter.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/Persistence/TrafficLimiter.php b/lib/Persistence/TrafficLimiter.php index 06916c59..005fa5f2 100644 --- a/lib/Persistence/TrafficLimiter.php +++ b/lib/Persistence/TrafficLimiter.php @@ -30,7 +30,7 @@ class TrafficLimiter extends AbstractPersistence * @var int */ private static $_limit = 10; - + /** * listed ips are exempted from limits, defaults to null * From 4296b43832a59862e7d4abf56e48475ead37c80e Mon Sep 17 00:00:00 2001 From: rodehoed Date: Tue, 4 May 2021 11:19:34 +0200 Subject: [PATCH 5/6] QA --- lib/Persistence/TrafficLimiter.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/Persistence/TrafficLimiter.php b/lib/Persistence/TrafficLimiter.php index 005fa5f2..ba0ac33e 100644 --- a/lib/Persistence/TrafficLimiter.php +++ b/lib/Persistence/TrafficLimiter.php @@ -123,7 +123,7 @@ class TrafficLimiter extends AbstractPersistence if (self::$_limit < 1) { return true; } - + // Check if $_ipKey is exempted from ratelimiting if (!is_null(self::$_exemptedIp)) { $exIp_array = explode(',', self::$_exemptedIp); From a806a6455eb4591e55ab6e6e90a4d64aa729f95d Mon Sep 17 00:00:00 2001 From: rodehoed Date: Tue, 4 May 2021 11:20:24 +0200 Subject: [PATCH 6/6] QA --- lib/Configuration.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/Configuration.php b/lib/Configuration.php index 133059d3..da62a1d0 100644 --- a/lib/Configuration.php +++ b/lib/Configuration.php @@ -79,9 +79,9 @@ class Configuration 'markdown' => 'Markdown', ), 'traffic' => array( - 'limit' => 10, - 'header' => null, - 'dir' => 'data', + 'limit' => 10, + 'header' => null, + 'dir' => 'data', 'exemptedIp' => null, ), 'purge' => array(