Skip to content

Commit 6aacd7d

Browse files
committed
Make proxy IP parsing aware of multiple proxies
Signed-off-by: Michal Čihař <michal@cihar.com>
1 parent c4a5953 commit 6aacd7d

2 files changed

Lines changed: 57 additions & 24 deletions

File tree

libraries/ip_allow_deny.lib.php

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -30,23 +30,30 @@ function PMA_getIp()
3030
return $direct_ip;
3131
}
3232

33-
$trusted_header_value
34-
= PMA_getenv($GLOBALS['cfg']['TrustedProxies'][$direct_ip]);
35-
$matches = array();
33+
/**
34+
* Parse header in form:
35+
* X-Forwarded-For: client, proxy1, proxy2
36+
*/
37+
// Get header content
38+
$value = PMA_getenv($GLOBALS['cfg']['TrustedProxies'][$direct_ip]);
39+
// Grab first element what is client adddress
40+
$value = explode(',', $value)[0];
41+
// Extract IP address
3642
// the $ checks that the header contains only one IP address,
3743
// ?: makes sure the () don't capture
44+
$matches = array();
3845
$is_ip = preg_match(
3946
'|^(?:[0-9]{1,3}\.){3,3}[0-9]{1,3}$|',
40-
$trusted_header_value, $matches
47+
$value, $matches
4148
);
4249

4350
if ($is_ip && (count($matches) == 1)) {
4451
// True IP behind a proxy
4552
return $matches[0];
4653
}
4754

48-
/* Return true IP */
49-
return $direct_ip;
55+
// We could not parse header
56+
return false;
5057
} // end of the 'PMA_getIp()' function
5158

5259

test/libraries/PMA_ip_allow_deny_test.php

Lines changed: 44 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -51,32 +51,58 @@ public function setUp()
5151
* Test for PMA_getIp
5252
*
5353
* @return void
54+
*
55+
* @dataProvider proxyIPs
5456
*/
55-
public function testGetIp()
57+
public function testGetIp($remote, $header, $expected, $proxyip = null)
5658
{
57-
//$_SERVER['REMOTE_ADDR'] is empty
58-
$this->assertEquals(
59-
false,
60-
PMA_getIp()
61-
);
59+
unset($_SERVER['REMOTE_ADDR']);
60+
unset($_SERVER['TEST_FORWARDED_HEADER']);
61+
$GLOBALS['cfg']['TrustedProxies'] = array();
62+
63+
if (!is_null($remote)) {
64+
$_SERVER['REMOTE_ADDR'] = $remote;
65+
}
66+
67+
if (!is_null($header)) {
68+
if (is_null($proxyip)) {
69+
$proxyip = $remote;
70+
}
71+
$GLOBALS['cfg']['TrustedProxies'][$proxyip] = 'TEST_FORWARDED_HEADER';
72+
$_SERVER['TEST_FORWARDED_HEADER'] = $header;
73+
}
6274

63-
$_SERVER['REMOTE_ADDR'] = "101.0.0.25";
6475
$this->assertEquals(
65-
"101.0.0.25",
76+
$expected,
6677
PMA_getIp()
6778
);
6879

69-
//proxy
70-
$var_name = "direct_ip";
71-
$direct_ip = $_SERVER['REMOTE_ADDR'];
72-
$GLOBALS['cfg']['TrustedProxies'][$direct_ip] = $var_name;
73-
$_SERVER[$var_name] = "192.168.0.1";
74-
$this->assertEquals(
75-
"192.168.0.1",
76-
PMA_getIp()
80+
unset($_SERVER['REMOTE_ADDR']);
81+
unset($_SERVER['TEST_FORWARDED_HEADER']);
82+
$GLOBALS['cfg']['TrustedProxies'] = array();
83+
}
84+
85+
/**
86+
* Data provider for PMA_getIp tests
87+
*
88+
* @return array
89+
*/
90+
public function proxyIPs()
91+
{
92+
return array(
93+
// Nothing set
94+
array(null, null, false),
95+
// Remote IP set
96+
array('101.0.0.25', null, '101.0.0.25'),
97+
// Proxy
98+
array('101.0.0.25', '192.168.10.10', '192.168.10.10'),
99+
// Several proxies
100+
array('101.0.0.25', '192.168.10.1, 192.168.100.100', '192.168.10.1'),
101+
// Invalid proxy
102+
array('101.0.0.25', 'invalid', false),
103+
// Direct IP with proxy enabled
104+
array('101.0.0.25', '192.168.10.10', '101.0.0.25', '10.10.10.10'),
77105
);
78-
unset($_SERVER[$var_name]);
79-
unset($GLOBALS['cfg']['TrustedProxies'][$direct_ip]);
80106
}
81107

82108
/**

0 commit comments

Comments
 (0)