|
|
@@ -1,4 +1,5 @@
|
|
|
<?php
|
|
|
+
|
|
|
/**
|
|
|
* PrivateBin
|
|
|
*
|
|
|
@@ -30,6 +31,15 @@ class TrafficLimiter extends AbstractPersistence
|
|
|
*/
|
|
|
private static $_limit = 10;
|
|
|
|
|
|
+ /**
|
|
|
+ * listed ips are exempted from limits, defaults to null
|
|
|
+ *
|
|
|
+ * @access private
|
|
|
+ * @static
|
|
|
+ * @var array
|
|
|
+ */
|
|
|
+ private static $_exemptedIp = null;
|
|
|
+
|
|
|
/**
|
|
|
* key to fetch IP address
|
|
|
*
|
|
|
@@ -51,6 +61,18 @@ class TrafficLimiter extends AbstractPersistence
|
|
|
self::$_limit = $limit;
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * set a list of ip(ranges) as string
|
|
|
+ *
|
|
|
+ * @access public
|
|
|
+ * @static
|
|
|
+ * @param string $exemptedIps
|
|
|
+ */
|
|
|
+ public static function setExemptedIp($exemptedIp)
|
|
|
+ {
|
|
|
+ self::$_exemptedIp = $exemptedIp;
|
|
|
+ }
|
|
|
+
|
|
|
/**
|
|
|
* set configuration options of the traffic limiter
|
|
|
*
|
|
|
@@ -62,6 +84,8 @@ class TrafficLimiter extends AbstractPersistence
|
|
|
{
|
|
|
self::setLimit($conf->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])) {
|
|
|
@@ -83,6 +107,35 @@ class TrafficLimiter extends AbstractPersistence
|
|
|
return hash_hmac($algo, $_SERVER[self::$_ipKey], ServerSalt::get());
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * Validate $_ipKey against configured ipranges. If matched ratelimiter will ignore ip
|
|
|
+ *
|
|
|
+ * @access private
|
|
|
+ * @static
|
|
|
+ * @param string $ipRange
|
|
|
+ * @return bool
|
|
|
+ */
|
|
|
+ private static function matchIp($ipRange = null)
|
|
|
+ {
|
|
|
+ // 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). It's here becaue matches($range) does not accepts null vallue
|
|
|
+ if ($range == null) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ // Ip-lib does throws and exception when something goes wrong, if so we want to catch it and set contained to false
|
|
|
+ try {
|
|
|
+ return $address->matches($range);
|
|
|
+ } catch (\Exception $e) {
|
|
|
+ // If something is wrong with matching the ip, we do nothing
|
|
|
+ }
|
|
|
+
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
/**
|
|
|
* traffic limiter
|
|
|
*
|
|
|
@@ -100,6 +153,16 @@ class TrafficLimiter extends AbstractPersistence
|
|
|
return true;
|
|
|
}
|
|
|
|
|
|
+ // Check if $_ipKey is exempted from ratelimiting
|
|
|
+ if (!is_null(self::$_exemptedIp)) {
|
|
|
+ $exIp_array = explode(',', self::$_exemptedIp);
|
|
|
+ foreach ($exIp_array as $ipRange) {
|
|
|
+ if (self::matchIp($ipRange) === true) {
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
$file = 'traffic_limiter.php';
|
|
|
if (self::_exists($file)) {
|
|
|
require self::getPath($file);
|