New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for getting the real client IP behind proxies #10653

Merged
merged 1 commit into from Aug 27, 2014
File filter...
Filter file types
Jump to file or symbol
Failed to load files and symbols.
+72 −6
Diff settings

Always

Just for now

Copy path View file
@@ -62,6 +62,12 @@
/* List of trusted domains, to prevent host header poisoning ownCloud is only using these Host headers */
'trusted_domains' => array('demo.owncloud.org', 'otherdomain.owncloud.org:8080'),
/* List of trusted proxy servers */
'trusted_proxies' => array('203.0.113.45', '198.51.100.128'),
/* Headers that should be trusted as client IP address in combination with `trusted_proxies` */
'forwarded_for_headers' => array('HTTP_X_FORWARDED', 'HTTP_FORWARDED_FOR'),
/* Theme to use for ownCloud */
"theme" => "",
Copy path View file
@@ -28,7 +28,7 @@ public function setSystemValue($key, $value) {
*
* @param string $key the key of the value, under which it was saved
* @param mixed $default the default value to be returned if the value isn't set
* @return string the saved value
* @return mixed the value or $default
*/
public function getSystemValue($key, $default = '') {
return \OCP\Config::getSystemValue($key, $default);
Copy path View file
@@ -15,6 +15,34 @@ class OC_Request {
const REGEX_LOCALHOST = '/^(127\.0\.0\.1|localhost)(:[0-9]+|)$/';
/**
* Returns the remote address, if the connection came from a trusted proxy and `forwarded_for_headers` has been configured
* then the IP address specified in this header will be returned instead.
* Do always use this instead of $_SERVER['REMOTE_ADDR']
* @return string IP address
*/
public static function getRemoteAddress() {
$remoteAddress = $_SERVER['REMOTE_ADDR'];
$trustedProxies = \OC::$server->getConfig()->getSystemValue('trusted_proxies', array());
if(is_array($trustedProxies) && in_array($remoteAddress, $trustedProxies)) {
$forwardedForHeaders = \OC::$server->getConfig()->getSystemValue('forwarded_for_headers', array());
foreach($forwardedForHeaders as $header) {
if (array_key_exists($header, $_SERVER) === true) {
foreach (explode(',', $_SERVER[$header]) as $IP) {
$IP = trim($IP);
if (filter_var($IP, FILTER_VALIDATE_IP) !== false) {
return $IP;
}
}
}
}
}
return $remoteAddress;
}
/**
* Check overwrite condition
* @param string $type
Copy path View file
@@ -43,7 +43,7 @@ class Config {
* Gets a value from config.php
* @param string $key key
* @param mixed $default = null default value
* @return string the value or $default
* @return mixed the value or $default
*
* This function gets the value from config.php. If it does not exist,
* $default will be returned.
Copy path View file
@@ -47,7 +47,7 @@ public function setSystemValue($key, $value);
*
* @param string $key the key of the value, under which it was saved
* @param string $default the default value to be returned if the value isn't set
* @return string the saved value
* @return mixed the value or $default
*/
public function getSystemValue($key, $default = '');
Copy path View file
@@ -9,21 +9,53 @@
class Test_Request extends PHPUnit_Framework_TestCase {
public function setUp() {
OC_Config::setValue('overwritewebroot', '/domain.tld/ownCloud');
OC::$server->getConfig()->setSystemValue('overwritewebroot', '/domain.tld/ownCloud');
OC::$server->getConfig()->setSystemValue('trusted_proxies', array());
OC::$server->getConfig()->setSystemValue('forwarded_for_headers', array());
}
public function tearDown() {
OC_Config::setValue('overwritewebroot', '');
OC::$server->getConfig()->setSystemValue('overwritewebroot', '');
OC::$server->getConfig()->setSystemValue('trusted_proxies', array());
OC::$server->getConfig()->setSystemValue('forwarded_for_headers', array());
}
public function testScriptNameOverWrite() {
$_SERVER['REMOTE_ADDR'] = '10.0.0.1';
$_SERVER["SCRIPT_FILENAME"] = __FILE__;
$_SERVER['SCRIPT_FILENAME'] = __FILE__;
$scriptName = OC_Request::scriptName();
$this->assertEquals('/domain.tld/ownCloud/tests/lib/request.php', $scriptName);
}
public function testGetRemoteAddress() {
$_SERVER['REMOTE_ADDR'] = '10.0.0.2';
$_SERVER['HTTP_X_FORWARDED'] = '10.4.0.5, 10.4.0.4';
$_SERVER['HTTP_X_FORWARDED_FOR'] = '192.168.0.233';
// Without having specified a trusted remote address
$this->assertEquals('10.0.0.2', OC_Request::getRemoteAddress());
// With specifying a trusted remote address but no trusted header
OC::$server->getConfig()->setSystemValue('trusted_proxies', array('10.0.0.2'));
$this->assertEquals('10.0.0.2', OC_Request::getRemoteAddress());
// With specifying a trusted remote address and trusted headers
OC::$server->getConfig()->setSystemValue('trusted_proxies', array('10.0.0.2'));
OC::$server->getConfig()->setSystemValue('forwarded_for_headers', array('HTTP_X_FORWARDED'));
$this->assertEquals('10.4.0.5', OC_Request::getRemoteAddress());
OC::$server->getConfig()->setSystemValue('forwarded_for_headers', array('HTTP_CLIENT_IP', 'HTTP_X_FORWARDED_FOR', 'HTTP_X_FORWARDED'));
$this->assertEquals('192.168.0.233', OC_Request::getRemoteAddress());
// With specifying multiple trusted remote addresses and trusted headers
OC::$server->getConfig()->setSystemValue('trusted_proxies', array('10.3.4.2', '10.0.0.2', '127.0.3.3'));
OC::$server->getConfig()->setSystemValue('forwarded_for_headers', array('HTTP_X_FORWARDED'));
$this->assertEquals('10.4.0.5', OC_Request::getRemoteAddress());
OC::$server->getConfig()->setSystemValue('forwarded_for_headers', array('HTTP_CLIENT_IP', 'HTTP_X_FORWARDED_FOR', 'HTTP_X_FORWARDED'));
$this->assertEquals('192.168.0.233', OC_Request::getRemoteAddress());
}
/**
* @dataProvider rawPathInfoProvider
* @param $expected
ProTip! Use n and p to navigate between commits in a pull request.