summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorClark Tomlinson <fallen013@gmail.com>2014-08-27 10:32:34 -0400
committerClark Tomlinson <fallen013@gmail.com>2014-08-27 10:32:34 -0400
commitcb0da1178b0872988582ee5fbf6b5b1cb5ea2527 (patch)
tree99f1cf9c15cb69e15d7347a35220157be77b40f2
parent13012fb5f77baac8be21cb91cd84312e61a288e5 (diff)
parent7acdd018a1555c9bc5dcc1702074a10f862bb170 (diff)
downloadnextcloud-server-cb0da1178b0872988582ee5fbf6b5b1cb5ea2527.tar.gz
nextcloud-server-cb0da1178b0872988582ee5fbf6b5b1cb5ea2527.zip
Merge pull request #10653 from owncloud/x-forwarded-for
Add support for getting the real client IP behind proxies
-rwxr-xr-xconfig/config.sample.php6
-rw-r--r--lib/private/allconfig.php2
-rwxr-xr-xlib/private/request.php28
-rw-r--r--lib/public/config.php2
-rw-r--r--lib/public/iconfig.php2
-rw-r--r--tests/lib/request.php38
6 files changed, 72 insertions, 6 deletions
diff --git a/config/config.sample.php b/config/config.sample.php
index 96565556910..d232e18ab08 100755
--- a/config/config.sample.php
+++ b/config/config.sample.php
@@ -62,6 +62,12 @@ $CONFIG = array(
/* 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" => "",
diff --git a/lib/private/allconfig.php b/lib/private/allconfig.php
index eb114546010..ef8673af231 100644
--- a/lib/private/allconfig.php
+++ b/lib/private/allconfig.php
@@ -28,7 +28,7 @@ class AllConfig implements \OCP\IConfig {
*
* @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);
diff --git a/lib/private/request.php b/lib/private/request.php
index 5fd5b3a7197..b063c1f5967 100755
--- a/lib/private/request.php
+++ b/lib/private/request.php
@@ -16,6 +16,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
* @return bool
diff --git a/lib/public/config.php b/lib/public/config.php
index ea3e0c1372a..65dde39cdce 100644
--- a/lib/public/config.php
+++ b/lib/public/config.php
@@ -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.
diff --git a/lib/public/iconfig.php b/lib/public/iconfig.php
index d4a8cdc7381..4865f8bc85b 100644
--- a/lib/public/iconfig.php
+++ b/lib/public/iconfig.php
@@ -47,7 +47,7 @@ interface IConfig {
*
* @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 = '');
diff --git a/tests/lib/request.php b/tests/lib/request.php
index bff84e1b03f..b89bf92ece7 100644
--- a/tests/lib/request.php
+++ b/tests/lib/request.php
@@ -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