FIX getIP from behind a load-balancer that adds many IPs to the header

This commit is contained in:
Daniel Hensby 2016-03-01 12:56:34 +00:00
parent 71bf14d590
commit 817b836870
2 changed files with 43 additions and 2 deletions

View File

@ -669,14 +669,36 @@ class SS_HTTPRequest implements ArrayAccess {
}
if ($headerOverrideIP) {
return $headerOverrideIP;
return $this->getIPFromHeaderValue($headerOverrideIP);
} elseif(isset($_SERVER['REMOTE_ADDR'])) {
return $_SERVER['REMOTE_ADDR'];
} else {
return null;
}
}
/**
* Extract an IP address from a header value that has been obtained. Accepts single IP or comma separated string of
* IPs
*
* @param string $headerValue The value from a trusted header
* @return string The IP address
*/
protected function getIPFromHeaderValue($headerValue) {
if (strpos($headerValue, ',') !== false) {
//sometimes the IP from a load balancer could be "x.x.x.x, y.y.y.y, z.z.z.z" so we need to find the most
// likely candidate
$ips = explode(',', $headerValue);
foreach ($ips as $ip) {
$ip = trim($ip);
if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE)) {
return $ip;
}
}
}
return $headerValue;
}
/**
* Returns all mimetypes from the HTTP "Accept" header
* as an array.

View File

@ -254,4 +254,23 @@ class HTTPRequestTest extends SapphireTest {
$this->assertEquals('home?test=1', $req->getURL(true));
$this->assertEquals('home', $req->getURL());
}
public function testGetIPFromHeaderValue() {
$req = new SS_HTTPRequest('GET', '/');
$reflectionMethod = new ReflectionMethod($req, 'getIPFromHeaderValue');
$reflectionMethod->setAccessible(true);
$headers = array(
'80.79.208.21, 149.126.76.1, 10.51.0.68' => '80.79.208.21',
'52.19.19.103, 10.51.0.49' => '52.19.19.103',
'10.51.0.49, 52.19.19.103' => '52.19.19.103',
'10.51.0.49' => '10.51.0.49',
'127.0.0.1, 10.51.0.49' => '127.0.0.1',
);
foreach ($headers as $header => $ip) {
$this->assertEquals($ip, $reflectionMethod->invoke($req, $header));
}
}
}