views:

380

answers:

8

i still confused on this subject And ask for any help and reference on how to check visitor IP address via PHP.

i'm know it seem lazy to ask something before attempt to code something to show. but right now, i also googling to find it. hopefully someone can give general broad answer or some link to read.

btw, what to be consider when we had to code some feature like this ?


Thanks for everyone

ps: Thank you very much everybody. It's been an enlightening arguments. Frankly, i choose the answer more as respect rather then the true in it. Cause until now i still don't know the right one. maybe i need another years of learning before i got firm understanding of the topic itself.

+1  A: 

If your client is surfing through a proxy server, then $_SERVER['REMOTE_ADDR'] just returns the IP address of the proxy server — not of the client’s machine. That’s not very reliable. This might be a better solution:

function get_ip_address() {
 foreach (array('HTTP_CLIENT_IP', 'HTTP_X_FORWARDED_FOR', 'HTTP_X_FORWARDED', 'HTTP_X_CLUSTER_CLIENT_IP', 'HTTP_FORWARDED_FOR', 'HTTP_FORWARDED', 'REMOTE_ADDR') as $key) {
  if (array_key_exists($key, $_SERVER)) {
   foreach (explode(',', $_SERVER[$key]) as $ip) {
    $ip = trim($ip); // just to be safe
    if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4 | FILTER_FLAG_IPV6 | FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE) !== false) {
     self::$ip = $ip;
     return $ip;
    }
   }
  }
 }
}

This has already been discussed on Stack Overflow before. Please refer to “What is the most accurate way to retrieve a user’s correct IP address in PHP?”. The above code is an optimized version of the accepted answer to that question.

However, do note that getting IP addresses is never fully reliable: http://stackoverflow.com/questions/1672827/php-ajax-remote-addr-set-to-ip-of-bogus-network-adapter/1678748#1678748

Mathias Bynens
Oh no, such a stupid code
Col. Shrapnel
@col. Shrapnel : how come ?
justjoe
@justjoe It was asked for the IP address, not the "HTTP header that may be looks like IP address".
Col. Shrapnel
@Col calling the code stupid and saying it doesn't answer the question are two very different things.
Mike B
@Col. Shrapnel: Are you saying simply using `$_SERVER['REMOTE_ADDR']` is more reliable than this? Both a HTTP header and `$_SERVER['REMOTE_ADDR']` are easy enough to spoof if you want to. Retrieval of IP addresses is never fully reliable, but this code obviously tries a little harder.
Mathias Bynens
@Mike any code that returns only one IP address and this address ns not the REMOTE_ADDR is stupid. Period.
Col. Shrapnel
@Mathias 1. Go spoof IP address as easy as HTTP header. 2. IP address is always more reliable than HTTP header. 3. This code tries and fail.
Col. Shrapnel
@Col How many ways can you rephrase the same thing? I'm asking you to explain WHY it is ill-advised to use anything but `REMOTE_ADDR` and all you seem to respond with is simple insults. I'm not trying to start a religious argument. I'm sure you have a very good reason. I'm just trying to find out what it is.
Mike B
@Mike I have said it many times already. The only IP address (in terms of TCP/IP protocol) which PHP has is REMOTE_ADDR. The rest is just HTTP headers.
Col. Shrapnel
To chime in... The `REMOTE_ADDR` is **not** spoofable. It's the address the TCP/IP protocol confirmed in a three-way handshake in order to establish a two-way connection, so your server can send something back to the client. HTTP headers OTOH are set by the client and could be anything. Also, what business of yours is it to look behind proxies and what could you gain? A bunch of `10.0.1.x` addresses probably, which don't help you much either.
deceze
Like I said, if someone doesn’t want his `REMOTE_ADDR` to be known, he can just use a proxy. It’s not even hard: you can even do it by browsing to http://proxy.org/ and entering a URL. Of course the HTTP header check isn’t bulletproof either, but at least it tries to see which IP address is behind the proxy. I have no idea where you’re getting the `10.0.1.x` stuff from, can you prove this?
Mathias Bynens
@Mathias If somebody wants to **hide** his address, he'll use an anonymizing proxy that doesn't forward the real address in the HTTP headers. The only real forwarded addresses you'll get will probably be internal IPs of corporate networks that are routing all outgoing traffic through a proxy. And those won't help you much at all.
deceze
@deceze …and the proxy IP address, as retrieved through `$_SERVER['REMOTE_ADDR']`, will?
Mathias Bynens
@Mathias At least it's the only address you can be sure is real. Why would you even want to use the other addresses if, as you say, the method is not bulletproof (far from it actually)? Depending on how you use this information, it may even open you up to spoofing. Users that want to be anonymous can be so anyway. In 99% of all other cases you'll get a corporate proxy server but can't see the users IP inside the network... So what?
deceze
@all + @deceze : thank you but i'm confuse how to pick the right answer. shoud i go with bynens or col. Shrapnel ? probably i will need a year to able to pick this by myself ;(
justjoe
@deceze “At least it's the only address you can be sure is real.” — It might be a ‘real’ address, but what good is that when you don’t know if it’s really the IP of the user or that of a proxy server?
Mathias Bynens
@justjoe: My answer might give an inaccurate result when the IP address is faked by spoofing a HTTP header, the other answers give inaccurate results when a proxy server is used. It’s up to you to decide which one you like best, but either way, do note that getting IP addresses is never fully reliable (as I mentioned in my answer).
Mathias Bynens
@Mathias So you can't be sure about anything, but you *can* be sure that you have had at least a "physical connection" to `REMOTE_ADDR`. I'd take that over pie-in-the-sky information any day. It really comes down to how you want to use this information. Identifying a client? IPs aren't a good source of ID anyway. Blacklist or whitelist a client? You'll definitely want a non-spoofable address here. Geo-locating a client? Halfway decent reason, but again, for what? Blocking content for certain countries? Anonymized proxies FTW. Language detection? Don't do it. What's left to use IPs for?
deceze
@Mathias you just play with words and fail to see the reasons. The reasons are: 1. there is no use for the private IP address. From where we took it? From the headers you so much fond on. Why don't you check it yourself? 2. If you think that REMOTE_ADDR is inaccurete, you can record everything you want, but not instead of REMOTE_ADDR. Just add your headers to the IP. It won't give you much insurance but at least you won't spoil the only one real IP address with some bullshit.
Col. Shrapnel
+4  A: 

See $_SERVER, specifically:

$_SERVER['REMOTE_ADDR'];
jasonbar
If your client is surfing through a proxy server, then `$_SERVER['REMOTE_ADDR']` just returns the IP address of the proxy server — not of the client’s machine. That’s not very reliable. This might be a better solution: http://stackoverflow.com/questions/2505697/how-to-code-feature-on-checking-visitor-ip-address-in-php/2505718#2505718However, do note that getting IP addresses is never fully reliable: http://stackoverflow.com/questions/1672827/php-ajax-remote-addr-set-to-ip-of-bogus-network-adapter/1678748#1678748
Mathias Bynens
@Mathais Bynens: As or more reliable than any HTTP header you could possibly try and detect. And it doesn't require a boatload of code.
jasonbar
+2  A: 

General broad answer: everything PHP knows about client is stored in the $_SERVER variable. So, do this code everytime you want particular info to see if you can find something relevant:

echo "<pre>";
print_r($_SERVER);
echo "</pre>";
//or just
phpinfo(32);

$_SERVER['REMOTE_ADDR'] is the only IP address you can get, though it can be not a "client address".

Col. Shrapnel
+3  A: 

hi to get user ip you should use this

$ip=$_SERVER['REMOTE_ADDR']

Sanjay
If your client is surfing through a proxy server, then `$_SERVER['REMOTE_ADDR']` just returns the IP address of the proxy server — not of the client’s machine. That’s not very reliable. This might be a better solution: http://stackoverflow.com/questions/2505697/how-to-code-feature-on-checking-visitor-ip-address-in-php/2505718#2505718However, do note that getting IP addresses is never fully reliable: http://stackoverflow.com/questions/1672827/php-ajax-remote-addr-set-to-ip-of-bogus-network-adapter/1678748#1678748
Mathias Bynens
@Mathias Well, can you decide at last which one is "not very reliable"? And how can an HTTP header be more reliable than IP address?
Col. Shrapnel
you will find your anser inthis ,when user use proxy server.function getRealIpAddr(){ if (!empty($_SERVER['HTTP_CLIENT_IP'])) //check ip from share internet { $ip=$_SERVER['HTTP_CLIENT_IP']; } elseif (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) //to check ip is pass from proxy { $ip=$_SERVER['HTTP_X_FORWARDED_FOR']; } else { $ip=$_SERVER['REMOTE_ADDR']; } return $ip;}this functionfirst attempt is to get the direct IP address of client’s machine, if not available then try for forwarded for IP address using HTTP_X_FORWARDED_FOR.
Sanjay
@Sanjay it is not IP addresses you choose from, but HTTP headers.
Col. Shrapnel
+1  A: 

$ip = $_SERVER['REMOTE_ADDR'];

echo "IP address is : " :.$ip;

this would serve the purpose

terrific
A: 

i suggest you use a third party ip to geo converter to calculate the location. since you wouldnt have to bare the db space.. acuracy and the queries.

all you will need to do is something like

http://third-party-url.com?ip=IP_ADDRESS

and it gives back an xml or an array of data.

u can use that to do what ever you want later on.

here are two websites which are popular. http://www.hostip.info/ http://simplegeo.com/

there are many such sites.. may be others can add them here

Harsha M V
+4  A: 

Ok, justjoe, I see you got confused with this arguement and there is my big part in it.

Some more explanations for you.

The answer depends on the task. You have 2 options:

If you need only one IP address, you can use only REMOTE_ADDR and nothing else. Take a look at the web-server's access log: there is only one IP address and it's REMOTE_ADDR one. At least it guaraneed you valid IP address. In many cases, like traffic counter, it's the only thing you can rely on. Thes is general answer to the "How to get an IP address" question.

If you want to record an address that can be more precise probably - so, noone forbids you from recording many addresses, not one. But of course, you have to record these HTTP headers along with REMOTE_ADDR, not instead of it. There is some use for such a throng of addresses. But you can't rely on it too much. But you can dig some info from it, if you care.

The only case for the FORWARDED_FOR header is misconfigured webserver, who place the real IP into this variable. In this case it can be used as an IP address. But of course it must be done manually, in the every particular case, not as the general recommendation. But anyway I'd quit such a webserver as it can be not only one misconfig in it.

Col. Shrapnel
thank you very much for the explanation. now i understand what to be consider when creating such feature. I use it for tracking user. While about the scope of ip, i think i only need one. It's important have the right ip. but the code is not obligate to have the real one Everyhing will be store in database. It's more like manual blacklist / whitelist feature.
justjoe
A: 

just use this at the top of your code:

if(function_exists('apache_request_headers'))
{
    $headers = apache_request_headers();

    if(array_key_exists('X-Forwarded-For', $headers))
    {
        $ips = explode(',',$headers['X-Forwarded-For'],2);
        $_SERVER["REMOTE_ADDR"]= trim($ips[0]);
    } 
}

it will make sure that $_SERVER["REMOTE_ADDR"] always keep proper ip on load balancers apps or no.

Marcin
And always keep the wrong IP in case when there are no misconfigured load balancers at all.
Col. Shrapnel
if there is X-Forwarded-For then how you can have misconfigured load balancers ?, plus if you concern about things like that you won't be porbably using load balancers as well which means above code won't apply to you anyway...
Marcin
because X-Forwarded-For **is not** the load balancer exclusive feature as you probably think. but just very common HTTP header and can be added by any proxy or router.
Col. Shrapnel