7

I do get track the "real" IP of an user, if he has an proxy wich sends the header of the real IP... does any of have a better solution, or even more headers?

Since this function is used very often in the script, it has to be very fast, and it does not seem in that constellation :/

A few suggestions I came up with, but could not realise:

  • put the headers in the order, what is used the most "in the wild", sothat the functions finishes fast
  • making the pre_match-detecting for IP faster

===

function get_real_ip() { $proxy_headers = array( '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_FORWARDED', 'HTTP_X_FORWARDED_FOR', 'HTTP_X_FORWARDED_FOR_IP', 'HTTP_X_IMFORWARDS', 'HTTP_XROXY_CONNECTION', 'VIA', 'X_FORWARDED', 'X_FORWARDED_FOR' ); foreach($proxy_headers as $proxy_header) { if(isset($_SERVER[$proxy_header]) && preg_match("/^([1-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])(\.([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])){3}$/", $_SERVER[$proxy_header])) /* HEADER ist gesetzt und dies ist eine gültige IP */ { return $_SERVER[$proxy_header]; } else if(stristr(',', $_SERVER[$proxy_header]) !== FALSE) /* Behandle mehrere IPs in einer Anfrage(z.B.: X-Forwarded-For: client1, proxy1, proxy2) */ { $proxy_header_temp = trim(array_shift(explode(',', $_SERVER[$proxy_header]))); /* Teile in einzelne IPs, gib die letzte zurück und entferne Leerzeichen */ if(($pos_temp = stripos($proxy_header_temp, ':')) !== FALSE) $proxy_header_temp = substr($proxy_header_temp, 0, $pos_temp); /* Entferne den Port */ if(preg_match("/^([1-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])(\.([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])){3}$/", $proxy_header_temp) return $proxy_header_temp; } } return $_SERVER['REMOTE_ADDR']; } 
17
  • 3
    ereg is deprecated. Besides that.. you always need to store both the real ip and the "proxy" ip as users can simply add those headers on their own. Commented Mar 24, 2011 at 15:15
  • Thanks, replaced the ereg with the (possibly faster) preg_match and added a part to detect, if the field has more IPs in it like: en.wikipedia.org/wiki/X-Forwarded-For Commented Mar 24, 2011 at 15:42
  • 1
    My real IP is 192.168.0.81. I am curious is there any use of it? Commented Mar 24, 2011 at 15:54
  • what does it mean "used very often in the script"? is there any reason to run it more than once during script runtime? Commented Mar 24, 2011 at 15:57
  • what "IP" you gonna choose if the field has more IPs in it? Why? Commented Mar 24, 2011 at 16:12

2 Answers 2

2

If the proxy sends a header then you can fetch the original IP of the client. If the proxy doesn't, then you can't. Unfortunately (Or maybe fortunately depending on your perspective) it's as simple as that.

What I did at our intranet, is redirect "intranet.mydomain.com" to "intranet" on the webserver, the latter doesn't use the proxy due to out internal network/DNS configuration ... Don't know what you want to do, but this may be useful.

You can also set an exclude list in the browser...

Sign up to request clarification or add additional context in comments.

Comments

1

the regex validation would fail for ipv6 addresses; so I would rather remove that (or try to find a better RegEX).

also stripos($proxy_header_temp, ':') would lead to a not expected behaivour for example for "::1" (localhost, ipv6).

my suggestion with mentioned modifications:

function getIp() { $proxy_headers = array( '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_FORWARDED', 'HTTP_X_FORWARDED_FOR', 'HTTP_X_FORWARDED_FOR_IP', 'HTTP_X_IMFORWARDS', 'HTTP_XROXY_CONNECTION', 'VIA', 'X_FORWARDED', 'X_FORWARDED_FOR' ); $regEx = "/^([1-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])(\.([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])){3}$/"; foreach ($proxy_headers as $proxy_header) { if (isset($_SERVER[$proxy_header])) { /* HEADER ist gesetzt und dies ist eine gültige IP */ return $_SERVER[$proxy_header]; } else if (stristr(',', $_SERVER[$proxy_header]) !== false) { // Behandle mehrere IPs in einer Anfrage //(z.B.: X-Forwarded-For: client1, proxy1, proxy2) $proxy_header_temp = trim( array_shift(explode(',', $_SERVER[$proxy_header])) ); /* Teile in einzelne IPs, gib die letzte zurück und entferne Leerzeichen */ // if IPv4 address remove port if exists if (preg_match($regEx, $proxy_header_temp) && ($pos_temp = stripos($proxy_header_temp, ':')) !== false ) { $proxy_header_temp = substr($proxy_header_temp, 0, $pos_temp); } return $proxy_header_temp; } } return $_SERVER['REMOTE_ADDR']; } 

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.