Skip to content
This repository has been archived by the owner on Jan 30, 2020. It is now read-only.

Commit

Permalink
Merge branch 'security/session-ip-validator'
Browse files Browse the repository at this point in the history
Fixes issues with proxy server/ip detection.

Fixes zendframework/zendframework#3095

- However, a different approach is taken than that used in that pull request.
  • Loading branch information
Showing 1 changed file with 170 additions and 0 deletions.
170 changes: 170 additions & 0 deletions src/PhpEnvironment/RemoteAddress.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,170 @@
<?php
/**
* Zend Framework (http://framework.zend.com/)
*
* @link http://github.com/zendframework/zf2 for the canonical source repository
* @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
* @package Zend_Http
*/

namespace Zend\Http\PhpEnvironment;

/**
* Functionality for determining client IP address.
*
* @category Zend
* @package Zend_Http
*/
class RemoteAddress
{
/**
* Whether to use proxy addresses or not.
*
* As default this setting is disabled - IP address is mostly needed to increase
* security. HTTP_* are not reliable since can easily be spoofed. It can be enabled
* just for more flexibility, but if user uses proxy to connect to trusted services
* it's his/her own risk, only reliable field for IP address is $_SERVER['REMOTE_ADDR'].
*
* @var bool
*/
protected $useProxy = false;

/**
* List of trusted proxy IP addresses
*
* @var array
*/
protected $trustedProxies = array();

/**
* HTTP header to introspect for proxies
*
* @var string
*/
protected $proxyHeader = 'HTTP_X_FORWARDED_FOR';


/**
* Changes proxy handling setting.
*
* This must be static method, since validators are recovered automatically
* at session read, so this is the only way to switch setting.
*
* @param bool $useProxy Whether to check also proxied IP addresses.
* @return RemoteAddress
*/
public function setUseProxy($useProxy = true)
{
$this->useProxy = $useProxy;
return $this;
}

/**
* Checks proxy handling setting.
*
* @return bool Current setting value.
*/
public function getUseProxy()
{
return $this->useProxy;
}

/**
* Set list of trusted proxy addresses
*
* @param array $trustedProxies
* @return RemoteAddress
*/
public function setTrustedProxies(array $trustedProxies)
{
$this->trustedProxies = $trustedProxies;
return $this;
}

/**
* Set the header to introspect for proxy IPs
*
* @param string $header
* @return RemoteAddress
*/
public function setProxyHeader($header = 'X-Forwarded-For')
{
$this->proxyHeader = $this->normalizeProxyHeader($header);
return $this;
}

/**
* Returns client IP address.
*
* @return string IP address.
*/
public function getIpAddress()
{
$ip = $this->getIpAddressFromProxy();
if ($ip) {
return $ip;
}

// direct IP address
if (isset($_SERVER['REMOTE_ADDR'])) {
return $_SERVER['REMOTE_ADDR'];
}

return '';
}

/**
* Attempt to get the IP address for a proxied client
*
* @return false|string
*/
protected function getIpAddressFromProxy()
{
if (!$this->useProxy) {
return false;
}

$header = $this->proxyHeader;

if (!isset($_SERVER[$header]) || empty($_SERVER[$header])) {
return false;
}

// Extract IPs
$ips = explode(',', $_SERVER[$header]);
// trim, so we can compare against trusted proxies properly
$ips = array_map('trim', $ips);
// remove trusted proxy IPs
$ips = array_diff($ips, $this->trustedProxies);

// Any left?
if (empty($ips)) {
return false;
}

// Return right-most
$ip = array_pop($ips);
return $ip;
}


/**
* Normalize a header string
*
* Normalizes a header string to a format that is compatible with
* $_SERVER
*
* @param string $header
* @return string
*/
protected function normalizeProxyHeader($header)
{
$header = strtoupper($header);
$header = str_replace('-', '_', $header);
if (0 !== strpos($header, 'HTTP_')) {
$header = 'HTTP_' . $header;
}
return $header;
}
}

0 comments on commit e47995d

Please sign in to comment.