diff --git a/src/IpAddress.php b/src/IpAddress.php index aaeeabd..0376dba 100644 --- a/src/IpAddress.php +++ b/src/IpAddress.php @@ -33,14 +33,14 @@ class IpAddress implements MiddlewareInterface * * @var array */ - protected $trustedWildcard; + protected $trustedWildcards; /** * List of trusted proxy IP CIDR ranges * * @var array */ - protected $trustedCidr; + protected $trustedCidrs; /** * Name of the attribute added to the ServerRequest object @@ -86,23 +86,10 @@ public function __construct( foreach ($trustedProxies as $proxy) { if (strpos($proxy, '*') !== false) { // Wildcard IP address - // IPv6 is 8 parts separated by ':' - if (strpos($proxy, '.') > 0) { - $delim = '.'; - $parts = 4; - } else { - $delim = ':'; - $parts = 8; - } - $this->trustedWildcard[] = explode($delim, $proxy, $parts); + $this->trustedWildcards[] = $this->parseWildcard($proxy); } elseif (strpos($proxy, '/') > 6) { // CIDR notation - list($subnet, $bits) = explode('/', $proxy, 2); - $subnet = ip2long($subnet); - $mask = -1 << (32 - $bits); - $min = $subnet & $mask; - $max = $subnet | ~$mask; - $this->trustedCidr[] = [$min, $max]; + $this->trustedCidrs[] = $this->parseCidr($proxy); } else { // String-match IP address $this->trustedProxies[] = $proxy; @@ -113,11 +100,46 @@ public function __construct( if ($attributeName) { $this->attributeName = $attributeName; } + if (!empty($headersToInspect)) { $this->headersToInspect = $headersToInspect; } } + /** + * @param string $ipAddress + * @return array + */ + private function parseWildcard(string $ipAddress) + { + // IPv4 has 4 parts separated by '.' + // IPv6 has 8 parts separated by ':' + if (strpos($ipAddress, '.') > 0) { + $delim = '.'; + $parts = 4; + } else { + $delim = ':'; + $parts = 8; + } + + return explode($delim, $ipAddress, $parts); + } + + /** + * @param string $ipAddress + * @return array + */ + private function parseCidr(string $ipAddress) + { + list($subnet, $bits) = explode('/', $ipAddress, 2); + $subnet = ip2long($subnet); + $mask = -1 << (32 - $bits); + $min = $subnet & $mask; + $max = $subnet | ~$mask; + + return [$min, $max]; + } + /** * {@inheritDoc} * @@ -180,7 +202,7 @@ protected function determineClientIpAddress($request) } // Wildcard Match - if ($this->checkProxyHeaders && $this->trustedWildcard) { + if ($this->checkProxyHeaders && $this->trustedWildcards) { // IPv4 has 4 parts separated by '.' // IPv6 has 8 parts separated by ':' if (strpos($ipAddress, '.') > 0) { @@ -190,8 +212,9 @@ protected function determineClientIpAddress($request) $delim = ':'; $parts = 8; } + $ipAddrParts = explode($delim, $ipAddress, $parts); - foreach ($this->trustedWildcard as $proxy) { + foreach ($this->trustedWildcards as $proxy) { if (count($proxy) !== $parts) { continue; // IP version does not match } @@ -199,7 +222,7 @@ protected function determineClientIpAddress($request) foreach ($proxy as $i => $part) { if ($part !== '*' && $part !== $ipAddrParts[$i]) { $match = false; - break;// IP does not match, move to next proxy + break; // IP does not match, move to next proxy } } if ($match) { @@ -210,11 +233,11 @@ protected function determineClientIpAddress($request) } // CIDR Match - if ($this->checkProxyHeaders && $this->trustedCidr) { + if ($this->checkProxyHeaders && $this->trustedCidrs) { // Only IPv4 is supported for CIDR matching $ipAsLong = ip2long($ipAddress); if ($ipAsLong) { - foreach ($this->trustedCidr as $proxy) { + foreach ($this->trustedCidrs as $proxy) { if ($proxy[0] <= $ipAsLong && $ipAsLong <= $proxy[1]) { $checkProxyHeaders = true; break; @@ -223,7 +246,7 @@ protected function determineClientIpAddress($request) } } - if (!$this->trustedProxies && !$this->trustedWildcard && !$this->trustedCidr) { + if (!$this->trustedProxies && !$this->trustedWildcards && !$this->trustedCidrs) { $checkProxyHeaders = true; } @@ -279,6 +302,7 @@ protected function isValidIpAddress($ip) if (filter_var($ip, FILTER_VALIDATE_IP, $flags) === false) { return false; } + return true; } diff --git a/tests/IpAddressTest.php b/tests/IpAddressTest.php index cb8526f..948ecdb 100644 --- a/tests/IpAddressTest.php +++ b/tests/IpAddressTest.php @@ -138,7 +138,6 @@ public function testIpIsNullIfMissingAndProxiesAreConfigured() $this->assertSame(null, $ipAddress); } - public function testXForwardedForIp() { $middleware = new IPAddress(true, []); @@ -163,7 +162,7 @@ public function testXForwardedForIpWithPort() $this->assertSame('192.168.1.3', $ipAddress); } - public function testProxyIpIsIgnored() + public function testProxyIpIsIgnoredWhenNoArgumentsProvided() { $middleware = new IPAddress(); $env = [ @@ -294,7 +293,6 @@ public function testCustomHeader() $this->assertSame('192.168.1.3', $ipAddress); } - public function testPSR15() { $middleware = new IPAddress();