From aca0dd3f3616f237b529fbae7cf982b0b8db460c Mon Sep 17 00:00:00 2001 From: Rob Allen Date: Mon, 18 Jun 2018 20:59:45 +0100 Subject: [PATCH] Support port number in IP addresses Some environments add port numbers unexpectedly, so remove them for IPv4 addresses. (IPV6 is more complicated, and needs to be addressed separately, if required.) Closes #14 --- src/IpAddress.php | 29 ++++++++++++++++++++++++++--- tests/IpAddressTest.php | 38 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 64 insertions(+), 3 deletions(-) diff --git a/src/IpAddress.php b/src/IpAddress.php index 362d4cc..3199dc9 100644 --- a/src/IpAddress.php +++ b/src/IpAddress.php @@ -120,8 +120,11 @@ protected function determineClientIpAddress($request) $ipAddress = null; $serverParams = $request->getServerParams(); - if (isset($serverParams['REMOTE_ADDR']) && $this->isValidIpAddress($serverParams['REMOTE_ADDR'])) { - $ipAddress = $serverParams['REMOTE_ADDR']; + if (isset($serverParams['REMOTE_ADDR'])) { + $remoteAddr = $this->extractIpAddress($serverParams['REMOTE_ADDR']); + if ($this->isValidIpAddress($remoteAddr)) { + $ipAddress = $remoteAddr; + } } if ($this->checkProxyHeaders @@ -142,6 +145,26 @@ protected function determineClientIpAddress($request) return $ipAddress; } + /** + * Remove port from IPV4 address if it exists + * + * Note: leaves IPV6 addresses alone + * + * @param string $ipAddress + * @return string + */ + protected function extractIpAddress($ipAddress) + { + $parts = explode(':', $ipAddress); + if (count($parts) == 2) { + if (filter_var($parts[0], FILTER_VALIDATE_IP, FILTER_FLAG_IPV4) !== false) { + return $parts[0]; + } + } + + return $ipAddress; + } + /** * Check that a given string is a valid IP address * @@ -179,6 +202,6 @@ private function getFirstIpAddressFromHeader($request, $header) } } - return $headerValue; + return $this->extractIpAddress($headerValue); } } diff --git a/tests/IpAddressTest.php b/tests/IpAddressTest.php index 0afaa17..cb02a96 100644 --- a/tests/IpAddressTest.php +++ b/tests/IpAddressTest.php @@ -34,6 +34,24 @@ public function testIpSetByRemoteAddr() $this->assertSame('192.168.1.1', $ipAddress); } + public function testIpWithPortSetByRemoteAddr() + { + $middleware = new IPAddress(false, [], 'IP'); + + $request = ServerRequestFactory::fromGlobals([ + 'REMOTE_ADDR' => '192.168.1.1:80', + ]); + $response = new Response(); + + $response = $middleware($request, $response, function ($request, $response) use (&$ipAddress) { + // simply store the "ip_address" attribute in to the referenced $ipAddress + $ipAddress = $request->getAttribute('IP'); + return $response; + }); + + $this->assertSame('192.168.1.1', $ipAddress); + } + public function testIpIsNullIfMissing() { $middleware = new IPAddress(); @@ -71,6 +89,26 @@ public function testXForwardedForIp() $this->assertSame('192.168.1.3', $ipAddress); } + public function testXForwardedForIpWithPort() + { + $middleware = new IPAddress(true, ['192.168.1.1']); + + $request = ServerRequestFactory::fromGlobals([ + 'REMOTE_ADDR' => '192.168.1.1:81', + 'HTTP_X_FORWARDED_FOR' => '192.168.1.3:81, 192.168.1.2:81, 192.168.1.1:81' + ]); + $response = new Response(); + + $ipAddress = '123'; + $response = $middleware($request, $response, function ($request, $response) use (&$ipAddress) { + // simply store the "ip_address" attribute in to the referenced $ipAddress + $ipAddress = $request->getAttribute('ip_address'); + return $response; + }); + + $this->assertSame('192.168.1.3', $ipAddress); + } + public function testProxyIpIsIgnored() { $middleware = new IPAddress();