diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php index b4ebfd0b45746..d6bed69785f38 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php @@ -64,7 +64,21 @@ public function getConfigTreeBuilder() ->end() ->prototype('scalar') ->validate() - ->ifTrue(function($v) { return !empty($v) && !filter_var($v, FILTER_VALIDATE_IP); }) + ->ifTrue(function($v) { + if (empty($v)) { + return false; + } + + if (false !== strpos($v, '/')) { + list($v, $mask) = explode('/', $v, 2); + + if (strcmp($mask, (int) $mask) || $mask < 1 || $mask > (false !== strpos($v, ':') ? 128 : 32)) { + return true; + } + } + + return !filter_var($v, FILTER_VALIDATE_IP); + }) ->thenInvalid('Invalid proxy IP "%s"') ->end() ->end() diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/ConfigurationTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/ConfigurationTest.php index 7db16658e8e14..f9fc7540ab00b 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/ConfigurationTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/ConfigurationTest.php @@ -51,6 +51,8 @@ public function getTestValidTrustedProxiesData() array(null, array()), array(false, array()), array(array(), array()), + array(array('10.0.0.0/8'), array('10.0.0.0/8')), + array(array('::ffff:0:0/96'), array('::ffff:0:0/96')), ); } diff --git a/src/Symfony/Component/HttpFoundation/Request.php b/src/Symfony/Component/HttpFoundation/Request.php index 867a29b6afc64..32c2d6f07187f 100644 --- a/src/Symfony/Component/HttpFoundation/Request.php +++ b/src/Symfony/Component/HttpFoundation/Request.php @@ -720,10 +720,19 @@ public function getClientIp() $clientIps = array_map('trim', explode(',', $this->headers->get(self::$trustedHeaders[self::HEADER_CLIENT_IP]))); $clientIps[] = $ip; - $trustedProxies = self::$trustProxy && !self::$trustedProxies ? array($ip) : self::$trustedProxies; - $clientIps = array_diff($clientIps, $trustedProxies); + $trustedProxies = self::$trustedProxies ?: array($ip); - return array_pop($clientIps); + foreach (array_reverse($clientIps) as $clientIp) { + foreach ($trustedProxies as $trustedProxy) { + if (IpUtils::checkIp($clientIp, $trustedProxy)) { + continue 2; + } + } + + return $clientIp; + } + + return $clientIp; } /** diff --git a/src/Symfony/Component/HttpFoundation/Tests/RequestTest.php b/src/Symfony/Component/HttpFoundation/Tests/RequestTest.php index a232c25b20c68..520b5d23d5c11 100644 --- a/src/Symfony/Component/HttpFoundation/Tests/RequestTest.php +++ b/src/Symfony/Component/HttpFoundation/Tests/RequestTest.php @@ -786,6 +786,9 @@ public function testGetClientIpProvider() array('88.88.88.88', true, '123.45.67.89', '127.0.0.1, 87.65.43.21, 88.88.88.88', null), array('87.65.43.21', true, '123.45.67.89', '127.0.0.1, 87.65.43.21, 88.88.88.88', array('123.45.67.89', '88.88.88.88')), array('87.65.43.21', false, '123.45.67.89', '127.0.0.1, 87.65.43.21, 88.88.88.88', array('123.45.67.89', '88.88.88.88')), + array('87.65.43.21', true, '123.45.67.89', '87.65.43.21', array('123.45.67.0/24')), + array('123.45.67.89', true, '::1', '123.45.67.89', array('::1')), + array('127.0.0.1', true, '::1', '127.0.0.1, 2620:0:1cfe:face:b00c::3', array('::1', '2620::/32')), ); }