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

Commit e47995d

Browse files
committed
Merge branch 'security/session-ip-validator'
Fixes issues with proxy server/ip detection. Fixes zendframework/zendframework#3095 - However, a different approach is taken than that used in that pull request.

File tree

1 file changed

+170
-0
lines changed

1 file changed

+170
-0
lines changed

src/PhpEnvironment/RemoteAddress.php

Lines changed: 170 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,170 @@
1+
<?php
2+
/**
3+
* Zend Framework (http://framework.zend.com/)
4+
*
5+
* @link http://github.com/zendframework/zf2 for the canonical source repository
6+
* @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
7+
* @license http://framework.zend.com/license/new-bsd New BSD License
8+
* @package Zend_Http
9+
*/
10+
11+
namespace Zend\Http\PhpEnvironment;
12+
13+
/**
14+
* Functionality for determining client IP address.
15+
*
16+
* @category Zend
17+
* @package Zend_Http
18+
*/
19+
class RemoteAddress
20+
{
21+
/**
22+
* Whether to use proxy addresses or not.
23+
*
24+
* As default this setting is disabled - IP address is mostly needed to increase
25+
* security. HTTP_* are not reliable since can easily be spoofed. It can be enabled
26+
* just for more flexibility, but if user uses proxy to connect to trusted services
27+
* it's his/her own risk, only reliable field for IP address is $_SERVER['REMOTE_ADDR'].
28+
*
29+
* @var bool
30+
*/
31+
protected $useProxy = false;
32+
33+
/**
34+
* List of trusted proxy IP addresses
35+
*
36+
* @var array
37+
*/
38+
protected $trustedProxies = array();
39+
40+
/**
41+
* HTTP header to introspect for proxies
42+
*
43+
* @var string
44+
*/
45+
protected $proxyHeader = 'HTTP_X_FORWARDED_FOR';
46+
47+
48+
/**
49+
* Changes proxy handling setting.
50+
*
51+
* This must be static method, since validators are recovered automatically
52+
* at session read, so this is the only way to switch setting.
53+
*
54+
* @param bool $useProxy Whether to check also proxied IP addresses.
55+
* @return RemoteAddress
56+
*/
57+
public function setUseProxy($useProxy = true)
58+
{
59+
$this->useProxy = $useProxy;
60+
return $this;
61+
}
62+
63+
/**
64+
* Checks proxy handling setting.
65+
*
66+
* @return bool Current setting value.
67+
*/
68+
public function getUseProxy()
69+
{
70+
return $this->useProxy;
71+
}
72+
73+
/**
74+
* Set list of trusted proxy addresses
75+
*
76+
* @param array $trustedProxies
77+
* @return RemoteAddress
78+
*/
79+
public function setTrustedProxies(array $trustedProxies)
80+
{
81+
$this->trustedProxies = $trustedProxies;
82+
return $this;
83+
}
84+
85+
/**
86+
* Set the header to introspect for proxy IPs
87+
*
88+
* @param string $header
89+
* @return RemoteAddress
90+
*/
91+
public function setProxyHeader($header = 'X-Forwarded-For')
92+
{
93+
$this->proxyHeader = $this->normalizeProxyHeader($header);
94+
return $this;
95+
}
96+
97+
/**
98+
* Returns client IP address.
99+
*
100+
* @return string IP address.
101+
*/
102+
public function getIpAddress()
103+
{
104+
$ip = $this->getIpAddressFromProxy();
105+
if ($ip) {
106+
return $ip;
107+
}
108+
109+
// direct IP address
110+
if (isset($_SERVER['REMOTE_ADDR'])) {
111+
return $_SERVER['REMOTE_ADDR'];
112+
}
113+
114+
return '';
115+
}
116+
117+
/**
118+
* Attempt to get the IP address for a proxied client
119+
*
120+
* @return false|string
121+
*/
122+
protected function getIpAddressFromProxy()
123+
{
124+
if (!$this->useProxy) {
125+
return false;
126+
}
127+
128+
$header = $this->proxyHeader;
129+
130+
if (!isset($_SERVER[$header]) || empty($_SERVER[$header])) {
131+
return false;
132+
}
133+
134+
// Extract IPs
135+
$ips = explode(',', $_SERVER[$header]);
136+
// trim, so we can compare against trusted proxies properly
137+
$ips = array_map('trim', $ips);
138+
// remove trusted proxy IPs
139+
$ips = array_diff($ips, $this->trustedProxies);
140+
141+
// Any left?
142+
if (empty($ips)) {
143+
return false;
144+
}
145+
146+
// Return right-most
147+
$ip = array_pop($ips);
148+
return $ip;
149+
}
150+
151+
152+
/**
153+
* Normalize a header string
154+
*
155+
* Normalizes a header string to a format that is compatible with
156+
* $_SERVER
157+
*
158+
* @param string $header
159+
* @return string
160+
*/
161+
protected function normalizeProxyHeader($header)
162+
{
163+
$header = strtoupper($header);
164+
$header = str_replace('-', '_', $header);
165+
if (0 !== strpos($header, 'HTTP_')) {
166+
$header = 'HTTP_' . $header;
167+
}
168+
return $header;
169+
}
170+
}

0 commit comments

Comments
 (0)