Add ability to detect real developer IP on remote server
- Slava.Aurim
- Member | 19
Hello guys!
Tracy is awesome & very esthetic! But unfortunately it does not detect real ip-addreses of developer on remote host, if server is behind the proxy.
I had such problem on the remote server of my hosting provider: $_SERVER[‘REMOTE_ADDR’] was changed on each request. And the code below did not show Tracy on remote server:
// exit( $_SERVER['REMOTE_ADDR'] ); // uncomment to see ip-address
$developerIp = '92.55.170.174';
\Tracy\Debugger::enable($developerIp);
To solve the problem, I inspected the $_SERVER to find the real IP. And later I found a good function on stackoverflow.com and slightly modified it. The code below is dirty solution but it works for me:
$developerIp = '92.55.175.209';
$userIp = getRealIp();
//exit($userIp); // uncomment to see ip-address
$debugMode = $userIp === $developerIp ? \Tracy\Debugger::DEVELOPMENT : \Tracy\Debugger::DETECT;
\Tracy\Debugger::enable($debugMode);
And this the function to get real IP:
(Please, check if it is right and settles the most of cases?)
function getRealIp()
{
$proxyHeaders = [
'CLIENT_IP',
'FORWARDED',
'FORWARDED_FOR',
'FORWARDED_FOR_IP',
'HTTP_CLIENT_IP',
'HTTP_FORWARDED',
'HTTP_FORWARDED_FOR',
'HTTP_FORWARDED_FOR_IP',
'HTTP_PC_REMOTE_ADDR',
'HTTP_PROXY_CONNECTION',
'HTTP_VIA',
'HTTP_X_CLUSTER_CLIENT_IP',
'HTTP_X_FORWARDED',
'HTTP_X_FORWARDED_FOR',
'HTTP_X_FORWARDED_FOR_IP',
'HTTP_X_IMFORWARDS',
'HTTP_XROXY_CONNECTION',
'VIA',
'X_FORWARDED',
'X_FORWARDED_FOR',
];
// check is there some proxy header?
foreach ($proxyHeaders as $proxyHeader)
{
if (!isset($_SERVER[$proxyHeader])) {
continue;
}
$IP = $_SERVER[$proxyHeader];
// extract 1-st IP (it's real) from comma-list
// for example: [HTTP_X_FORWARDED_FOR] => 92.55.170.174, 66.102.9.80
if (strpos($IP, ',')) {
list($IP) = explode(',', $IP);
}
// cut out the port number
if (strpos($IP, ':')) {
list($IP) = explode(':', $IP);
}
// check is valid IP
if (filter_var($IP, FILTER_VALIDATE_IP)) {
return $IP;
}
}
// return standart IP property if no proxy was found
return $_SERVER['REMOTE_ADDR'];
}
I suggest to add this function to Tracy\Debugger (or maybe in Nette\Http\Request ?) , and use it from Tracy\Debugger::detectDebugMode method.
Last edited by Slava.Aurim (2016-08-13 15:26)
- pata.kusik111
- Member | 78
Hello,
a functionality similar to this, eg recognition of http_x_forwarded and
forwarded headers can be found in http\requestFactory.
However there is one issue, why this cannot be easily directly implemented in
Tracy. Or at least not with the function you suggested. Your function does not
work for some headers and IPv6 (for example look at Forwarded header
specification) and you have no validation, whether the headers were sent from
trusted proxy. Then if would be very easy to forge the headers, especially of
servers without proxy.
I am not saying it is not possible, just that the issue is much more complicated that you painted here.
- Slava.Aurim
- Member | 19
Do I understand right, that my solution is not safe enough? How to solve it by simple way?
- Check whether the Http\RequestFactory all kinds of proxy header?
- Can I pass to RequestFactory ip-range of trusted proxy-ip, like ‘92.55.175.*’, in order to avoid forging forwarded headers?
- Can you show me simple example – how get real user ip using RequestFactory with passed trusted proxy ip-range?
- Whether it's excessive overhead – using Http\RequestFactory for initializing Tracy\Debugger?
- Is there another simple way (not using IP) to identify developer and enable the debugger for it?
I would be very grateful for your help!
Last edited by Slava.Aurim (2016-08-19 06:12)
- Jan Tvrdík
- Nette guru | 2595
@Slava.Aurim Using Http\RequestFactory
with IP range for
trusted proxy is quite simple
$httpRequestFactory = new Http\RequestFactory();
$httpRequestFactory->setProxy('92.55.175.0/24'); // 92.55.175.0 - 92.55.175.255
$httpRequest = $httpRequestFactory->createHttpRequest();
$realIp = $httpRequst->getRemoteAddress();
Whether it's excessive overhead – using Http\RequestFactory for initializing Tracy\Debugger?
Http\RequestFactory
is very fast, but does handle a lot more
stuff than just getting real IP address. However tracy/tracy
cannot
depend o nette/http
.
- Slava.Aurim
- Member | 19
@JanTvrdík thanks for example! And what does mean “0/24”?
I looked into the method Nette\Http\Helpers::ipMatch($ip, $mask)
,
but was not able to understand how it works. Argument $mask is extremely
non-obvious. Could you give me several examples for correct ip masks and explain
it format? In my opinion, it would be more obvious format for proxy ip-range:
'92.55.175.*'
or ['92.55.175.0', '92.55.175.255']
or
maybe even a list of
ranges: ['92.55.175.0-92.55.175.100', '92.55.175.200-92.55.175.255']
Last edited by Slava.Aurim (2016-08-19 18:58)
- Slava.Aurim
- Member | 19
Did I understand correctly that number after slash indicates the size in bits of the lead (left) invariable part of the ip address? And the maximum size (for ipv4) is 32 bits?
Last edited by Slava.Aurim (2016-08-19 19:44)
- Slava.Aurim
- Member | 19
Maybe someone find useful this CIDR tool. For a better understanding of the concept of cidr addressing, you can use CIDR Address Range calculator: http://www.subnet-calculator.com/cidr.php