toplay Posted November 11, 2006 Share Posted November 11, 2006 The various $_SERVER values listed below are some of the ones I've seen used to try and determine when a user is coming through a proxy and getting at the real web users IP address when available.I'm hoping this post will help us once and for all (at this time anyway) come to some sort of concensus regarding the best approach to grabbing the IP address with PHP.The code listed below are just examples I found and not necessarily correct (if there is such a thing as a one method approach when it comes to this). The example code don't check all the $_SERVER values I have listed (that's not to say that they all should be used or relevant).I'm under the impression:[list][*]That the 'HTTP_VIA' usually contains a proxies name and not necessarily the proxy IP address.[*]The 'HTTP_X_FORWARDED_FOR', when populated, could contain multiple IP addresses separated with commas, and the last one in the list (not the first) would be considered the originating user's IP.[*]A proxy may not necessarily populate any of the proxy related values (i.e. anonymous proxy).[/list]What do you use? What do you think is the correct order of checking these $_SERVER values is (before finally resorting to using the 'REMOTE_ADDR')?Do you know more than these values (as it relates to detecting proxy and obtaining IP address)?[QUOTE]$_SERVER['HTTP_VIA']$_SERVER['HTTP_USER_AGENT_VIA']$_SERVER['HTTP_COMING_FROM'] $_SERVER['HTTP_X_COMING_FROM']$_SERVER['HTTP_X_FORWARDED_FOR']$_SERVER['HTTP_X_FORWARDED']$_SERVER['HTTP_FORWARDED']$_SERVER['HTTP_CLIENT_IP']$_SERVER['HTTP_FROM']$_SERVER['HTTP_PROXY_CONNECTION']$_SERVER['HTTP_XROXY_CONNECTION']$_SERVER['HTTP_PROXY_AUTHORIZATION']$_SERVER['REMOTE_ADDR'][/quote]Example source:[code=php:0]function PMA_getIp(){ global $REMOTE_ADDR; global $HTTP_X_FORWARDED_FOR, $HTTP_X_FORWARDED, $HTTP_FORWARDED_FOR, $HTTP_FORWARDED; global $HTTP_VIA, $HTTP_X_COMING_FROM, $HTTP_COMING_FROM; // Get some server/environment variables values if (empty($REMOTE_ADDR)) { if (!empty($_SERVER) && isset($_SERVER['REMOTE_ADDR'])) { $REMOTE_ADDR = $_SERVER['REMOTE_ADDR']; } else if (!empty($_ENV) && isset($_ENV['REMOTE_ADDR'])) { $REMOTE_ADDR = $_ENV['REMOTE_ADDR']; } else if (@getenv('REMOTE_ADDR')) { $REMOTE_ADDR = getenv('REMOTE_ADDR'); } } // end if if (empty($HTTP_X_FORWARDED_FOR)) { if (!empty($_SERVER) && isset($_SERVER['HTTP_X_FORWARDED_FOR'])) { $HTTP_X_FORWARDED_FOR = $_SERVER['HTTP_X_FORWARDED_FOR']; } else if (!empty($_ENV) && isset($_ENV['HTTP_X_FORWARDED_FOR'])) { $HTTP_X_FORWARDED_FOR = $_ENV['HTTP_X_FORWARDED_FOR']; } else if (@getenv('HTTP_X_FORWARDED_FOR')) { $HTTP_X_FORWARDED_FOR = getenv('HTTP_X_FORWARDED_FOR'); } } // end if if (empty($HTTP_X_FORWARDED)) { if (!empty($_SERVER) && isset($_SERVER['HTTP_X_FORWARDED'])) { $HTTP_X_FORWARDED = $_SERVER['HTTP_X_FORWARDED']; } else if (!empty($_ENV) && isset($_ENV['HTTP_X_FORWARDED'])) { $HTTP_X_FORWARDED = $_ENV['HTTP_X_FORWARDED']; } else if (@getenv('HTTP_X_FORWARDED')) { $HTTP_X_FORWARDED = getenv('HTTP_X_FORWARDED'); } } // end if if (empty($HTTP_FORWARDED_FOR)) { if (!empty($_SERVER) && isset($_SERVER['HTTP_FORWARDED_FOR'])) { $HTTP_FORWARDED_FOR = $_SERVER['HTTP_FORWARDED_FOR']; } else if (!empty($_ENV) && isset($_ENV['HTTP_FORWARDED_FOR'])) { $HTTP_FORWARDED_FOR = $_ENV['HTTP_FORWARDED_FOR']; } else if (@getenv('HTTP_FORWARDED_FOR')) { $HTTP_FORWARDED_FOR = getenv('HTTP_FORWARDED_FOR'); } } // end if if (empty($HTTP_FORWARDED)) { if (!empty($_SERVER) && isset($_SERVER['HTTP_FORWARDED'])) { $HTTP_FORWARDED = $_SERVER['HTTP_FORWARDED']; } else if (!empty($_ENV) && isset($_ENV['HTTP_FORWARDED'])) { $HTTP_FORWARDED = $_ENV['HTTP_FORWARDED']; } else if (@getenv('HTTP_FORWARDED')) { $HTTP_FORWARDED = getenv('HTTP_FORWARDED'); } } // end if if (empty($HTTP_VIA)) { if (!empty($_SERVER) && isset($_SERVER['HTTP_VIA'])) { $HTTP_VIA = $_SERVER['HTTP_VIA']; } else if (!empty($_ENV) && isset($_ENV['HTTP_VIA'])) { $HTTP_VIA = $_ENV['HTTP_VIA']; } else if (@getenv('HTTP_VIA')) { $HTTP_VIA = getenv('HTTP_VIA'); } } // end if if (empty($HTTP_X_COMING_FROM)) { if (!empty($_SERVER) && isset($_SERVER['HTTP_X_COMING_FROM'])) { $HTTP_X_COMING_FROM = $_SERVER['HTTP_X_COMING_FROM']; } else if (!empty($_ENV) && isset($_ENV['HTTP_X_COMING_FROM'])) { $HTTP_X_COMING_FROM = $_ENV['HTTP_X_COMING_FROM']; } else if (@getenv('HTTP_X_COMING_FROM')) { $HTTP_X_COMING_FROM = getenv('HTTP_X_COMING_FROM'); } } // end if if (empty($HTTP_COMING_FROM)) { if (!empty($_SERVER) && isset($_SERVER['HTTP_COMING_FROM'])) { $HTTP_COMING_FROM = $_SERVER['HTTP_COMING_FROM']; } else if (!empty($_ENV) && isset($_ENV['HTTP_COMING_FROM'])) { $HTTP_COMING_FROM = $_ENV['HTTP_COMING_FROM']; } else if (@getenv('HTTP_COMING_FROM')) { $HTTP_COMING_FROM = getenv('HTTP_COMING_FROM'); } } // end if // Gets the default ip sent by the user if (!empty($REMOTE_ADDR)) { $direct_ip = $REMOTE_ADDR; } // Gets the proxy ip sent by the user $proxy_ip = ''; if (!empty($HTTP_X_FORWARDED_FOR)) { $proxy_ip = $HTTP_X_FORWARDED_FOR; } else if (!empty($HTTP_X_FORWARDED)) { $proxy_ip = $HTTP_X_FORWARDED; } else if (!empty($HTTP_FORWARDED_FOR)) { $proxy_ip = $HTTP_FORWARDED_FOR; } else if (!empty($HTTP_FORWARDED)) { $proxy_ip = $HTTP_FORWARDED; } else if (!empty($HTTP_VIA)) { $proxy_ip = $HTTP_VIA; } else if (!empty($HTTP_X_COMING_FROM)) { $proxy_ip = $HTTP_X_COMING_FROM; } else if (!empty($HTTP_COMING_FROM)) { $proxy_ip = $HTTP_COMING_FROM; } // end if... else if... // Returns the true IP if it has been found, else FALSE if (empty($proxy_ip)) { // True IP without proxy return $direct_ip; } else { $is_ip = preg_match('|^([0-9]{1,3}\.){3,3}[0-9]{1,3}|', $proxy_ip, $regs = array()); if ($is_ip && (count($regs) > 0)) { // True IP behind a proxy return $regs[0]; } else { // Can't define IP: there is a proxy but we don't have // information about the true IP return FALSE; } } // end if... else...} // end of the 'PMA_getIp()' function[/code]Another example:[code=php:0]function retrieveIP() {function extractIP(&$ip) { if (ereg ("^([0-9]{1,3}\.){3,3}[0-9]{1,3}", $ip, $array)) return $array; else return false;}function get_IP() { if(@$_SERVER['REMOTE_HOST']) { $array = extractIP(&$_SERVER['REMOTE_HOST']); if ($array && count($array) >= 1) return $array[0]; // first IP in the list } return $_SERVER['REMOTE_ADDR'];}/*-------------------------------------------------- get_real_IP() get the real IP if hidden by proxy --------------------------------------------------*/function get_real_IP() { if(@$_SERVER['HTTP_X_FORWARDED_FOR']) { // case 1.A: proxy && HTTP_X_FORWARDED_FOR is defined $array = extractIP(&$_SERVER['HTTP_X_FORWARDED_FOR']); if ($array && count($array) >= 1) { return $array[0]; // first IP in the list } } if(@$_SERVER['HTTP_X_FORWARDED']) { // case 1.B: proxy && HTTP_X_FORWARDED is defined $array = extractIP(&$_SERVER['HTTP_X_FORWARDED']); if ($array && count($array) >= 1) { return $array[0]; // first IP in the list } } if(@$_SERVER['HTTP_FORWARDED_FOR']) { // case 1.C: proxy && HTTP_FORWARDED_FOR is defined $array = extractIP(&$_SERVER['HTTP_FORWARDED_FOR']); if ($array && count($array) >= 1) { return $array[0]; // first IP in the list } } if(@$_SERVER['HTTP_FORWARDED']) { // case 1.D: proxy && HTTP_FORWARDED is defined $array = extractIP(&$_SERVER['HTTP_FORWARDED']); if ($array && count($array) >= 1) { return $array[0]; // first IP in the list } } if(@$_SERVER['HTTP_CLIENT_IP']) { // case 1.E: proxy && HTTP_CLIENT_IP is defined $array = extractIP(&$_SERVER['HTTP_CLIENT_IP']); if ($array && count($array) >= 1) { return $array[0]; // first IP in the list } } if(@$_SERVER['HTTP_VIA']) { // case 2: // proxy && HTTP_(X_) FORWARDED (_FOR) not defined && HTTP_VIA defined // other exotic variables may be defined return ( $_SERVER['HTTP_VIA']. '_' . $_SERVER['HTTP_X_COMING_FROM']. '_' . $_SERVER['HTTP_COMING_FROM'] ) ; } if(@$_SERVER['HTTP_X_COMING_FROM'] || $_SERVER['HTTP_COMING_FROM'] ) { // case 3: proxy && only exotic variables defined // the exotic variables are not enough, we add the REMOTE_ADDR of the proxy return ( $_SERVER['REMOTE_ADDR'] . '_' . $_SERVER['HTTP_X_COMING_FROM'] . '_' . $_SERVER['HTTP_COMING_FROM'] ) ; } // case 4: no proxy (or tricky case: proxy+refresh) if(@$_SERVER['REMOTE_HOST']) { $array = extractIP(&$_SERVER['REMOTE_HOST']); if ($array && count($array) >= 1) { return $array[0]; // first IP in the list } } return $_SERVER['REMOTE_ADDR'];}if(isset($_SERVER['HTTP_VIA']) && $_SERVER['HTTP_VIA']) // Using proxy! return get_real_IP();else // Not using proxy... return (get_IP()) ? get_IP() : get_real_IP();}?>[/code]EDIT:We could PIN this topic later if people want. Quote Link to comment Share on other sites More sharing options...
Gruzin Posted November 11, 2006 Share Posted November 11, 2006 We could pin this topic :) Quote Link to comment Share on other sites More sharing options...
brendandonhue Posted November 11, 2006 Share Posted November 11, 2006 $_SERVER['REMOTE_ADDR'] -- it always tells you the IP address your server is communicating with. All the others can be faked/forged easily (the user can set them to whatever they want.) Quote Link to comment Share on other sites More sharing options...
toplay Posted November 11, 2006 Author Share Posted November 11, 2006 Thanks for your replies. I don't want this post to be about faked/spoofed stuff. That's known and has been discussed to death.A person should always record the 'REMOTE_ADDR'. But assuming everything is on the up and up, the user's real IP address is not that (when coming through a proxy).For this discussion, we're talking about legitimate users coming through various proxies. Quote Link to comment Share on other sites More sharing options...
brendandonhue Posted November 11, 2006 Share Posted November 11, 2006 For my script, I would assume $_SERVER['REMOTE_ADDR'] is the user's real address. It's the IP my server received the request from and it's the address I'm going to send my reply to. I don't see any point in relying on data that is possibly forged. Quote Link to comment Share on other sites More sharing options...
toplay Posted November 12, 2006 Author Share Posted November 12, 2006 Because most are not forged. I don't see the point of [b]only[/b] keeping the 'REMOTE_ADDR' (which maybe a proxy IP) when it may not trace back to the user.If the user keeps coming from different proxy IP's, and sometimes you can grab what seems their real IP, then it's a way of possibly matching and tracing back to the same user. Quote Link to comment Share on other sites More sharing options...
brendandonhue Posted November 12, 2006 Share Posted November 12, 2006 Sure, in that case I would just save all the info available - print_r($_SERVER, true) Quote Link to comment Share on other sites More sharing options...
toplay Posted November 12, 2006 Author Share Posted November 12, 2006 Let's say you save everything, then how do you know which is the user's real IP address? I don't understand the point of saving everything if one doesn't understand what it means or how to use the data. Also, saving everything is impractical and when you have a large user base takes up a lot of disk space (especially if your tables use UTF-8).Does anyone else have something to say directly relating to the correct order of checking these $_SERVER values? Quote Link to comment Share on other sites More sharing options...
printf Posted November 12, 2006 Share Posted November 12, 2006 $_SERVER variables are never the same on all servers, so you need to limit what works across all servers, if you don't you will end up with a order that will never work on all servers. So you will end up giving less information or worse, no useful information at all. All $_SERVER variables not related to internal pathing can be forged, so why would you even spend that much time on something that has no real value. What I mean is, locks on doors only keep honest people honest, the bad people don't every think about the lock. So all your testing is a very silly waste of time!Sonia Quote Link to comment Share on other sites More sharing options...
swatisonee Posted November 12, 2006 Share Posted November 12, 2006 Sonia - printf,I for one will be really happy to know if i could ban people using fake ips from sending junk info on my contact form. Its contact.php and i get tons of people writing fake email ids (ab@y.com) and for name and address, stuff like 123, 456 etc. So if an ip is fake or a spybot, i want them to hit the submit button (do all their stupid work) and then get a popup saying " your data wont be accepted becoz your ip address is a fake" . i'm eager to see how this post will go forward ! Quote Link to comment Share on other sites More sharing options...
toplay Posted November 12, 2006 Author Share Posted November 12, 2006 swatisonee,One can't tell if it's a fake IP necessarily, but could see if it's on a black list.There are services like the ones I've listed below, that help you determine various components for yourself, and is especially helpful if you accept credit card orders (which should help to reduce chargebacks).FYI:Fraud screen services:http://www.maxmind.com/app/ccvhttp://fraudlabs.com/fraudlabs.aspx##inputhttp://www.cybersource.com/products_and_services/credit_card_fraud_management/fraud_screening/http://precharge.com/global_fraud_screening/ (returns just a fraud score)http://www.orderspy.comhttp://www.serviceobjects.com/Products/default.asphttp://www.modernbill.com/order-verification/howitworks.phphttp://www.nehuenmultimedia.com.ar/html/cardverify.php (free online check 10 a day)http://www.algozone.com/shop/oscommerce_fraud_protection.phpOther stuff:Free IP to Country Database:http://software77.net/cgi-bin/ip-country/geo-ip.plFirst six digits of credit card # (BIN) online lookup (free limited):http://all-nettools.com/toolbox,financialMerchants helping other merchants by way of newsletter/email. Notification to each other about bad IP's and orders (with parts of credit card number listed):http://merchant911.orgIP blacklist: http://www.unixhub.com/block.htmlThe SBL is a realtime database of IP addresses of verified spam sources:http://www.spamhaus.org/sbl/Lookup of known and potential spam sources (open relays, open proxies, open form to mail HTTP gateways, dynamic IP pools, and direct spammers):http://www.njabl.org/IP lookups:http://www.ipaddressguide.com/http://www.dnsstuff.com/http://www.geobytes.com/IpLocator.htm?GetLocation Quote Link to comment Share on other sites More sharing options...
Jenk Posted November 12, 2006 Share Posted November 12, 2006 IP addresses are so unreliable it terms of security, that _any_ time spent on them is wasted time.Don't bother even logigng IP's, there really is no point. Quote Link to comment Share on other sites More sharing options...
toplay Posted November 12, 2006 Author Share Posted November 12, 2006 [quote author=Jenk link=topic=114669.msg466923#msg466923 date=1163356158]IP addresses are so unreliable it terms of security, that _any_ time spent on them is wasted time.Don't bother even logigng IP's, there really is no point. [/quote]I disagree with you. It's helped us evaluate and close fraudulent accounts. Quote Link to comment Share on other sites More sharing options...
brendandonhue Posted November 13, 2006 Share Posted November 13, 2006 [quote author=toplay link=topic=114669.msg466886#msg466886 date=1163348289]Does anyone else have something to say directly relating to the correct order of checking these $_SERVER values?[/quote]That's what I'm saying, there simply is no correct order. All of the values can forged equally easily, it doesn't really matter what order you put the data in if it isn't trustworthy data to start with (a garbage in-garbage out kind of thing.) Quote Link to comment Share on other sites More sharing options...
Gerryc Posted November 21, 2006 Share Posted November 21, 2006 [quote author=brendandonhue link=topic=114669.msg467067#msg467067 date=1163382745][quote author=toplay link=topic=114669.msg466886#msg466886 date=1163348289]Does anyone else have something to say directly relating to the correct order of checking these $_SERVER values?[/quote]That's what I'm saying, there simply is no correct order. All of the values can forged equally easily, it doesn't really matter what order you put the data in if it isn't trustworthy data to start with (a garbage in-garbage out kind of thing.)[/quote]So many negative one minded people.Firstly there are far more users who know how to use a proxy and do so on a regular basis than there are people who know how to manually append headers to every request that they make. So even for security this is a solution that aims to cover a large group of people, while still realizing that the data can't be trusted in some cases.Second, this may be used for something which isn't related to security at all. It could just be used to tell approximatly how many unique users a site is getting. Sure there could be people faking it, but the majority wouldn't so it would give you a more accurate result than just relying on users not being behind a proxy.Thanks for your work and research on this topic toplay, it has helped me a great deal. I wish I could help you out with the order, but unfortunatly I have no idea. I suspect the best way to find out would be to to find out what the biggest commercial proxy server products usually send etc.Luck Quote Link to comment Share on other sites More sharing options...
Gerryc Posted November 21, 2006 Share Posted November 21, 2006 [quote author=toplay link=topic=114669.msg466615#msg466615 date=1163282701][list][*]The 'HTTP_X_FORWARDED_FOR', when populated, could contain multiple IP addresses separated with commas, and the last one in the list (not the first) would be considered the originating user's IP.[/list]...[code=php:0]|^([0-9]{1,3}\.){3,3}[0-9]{1,3}|[/code][/quote]Huh.. these two things seem to contradict each other.Shouldn't the pattern be the following?|([0-9]{1,3}\.){3,3}[0-9]{1,3}$| Quote Link to comment Share on other sites More sharing options...
Seraskier Posted November 21, 2006 Share Posted November 21, 2006 If you are trying to put it into a database for storage. best way to do it is:[code]$_ip = $_SERVER['REMOTE_ADDR'];mysql_query ("insert into users (ip) values ('$_ip')");[/code]Basically it. Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.