31

I have developed a PHP webservice. I would like to log all incoming connections of the WS clients, which are consuming this web service. How can I obtain the client's IP address? The value of

$_SERVER['HTTP_CLIENT_IP']
seems to be always empty.
simon
  • 12,666
  • 26
  • 78
  • 113

10 Answers10

50

This should be what you want:

$_SERVER['REMOTE_ADDR']

The IP address from which the user is viewing the current page.

http://php.net/manual/en/reserved.variables.server.php

Tom Haigh
  • 57,217
  • 21
  • 114
  • 142
  • I tried this, the value seems to be empty as well. I'm consuming the web service from a Java client on a local network. Maybe I'll just try outputting all the server variables to see if any of them contains the requesting IP address. – simon Sep 17 '09 at 09:53
  • What web server and php version are you using and how is it configured? – Tom Haigh Sep 17 '09 at 10:11
  • 1
    The web server is Apache 2.2.1.1 and PHP version is 5.2.8. The PHP code I'm developing is running as a part of the KnowledgeTree 3.6.1 server. I've also tried reading the IP address from the (knowledgeTree) built-in functions session->resolveIp etc, but without success. – simon Sep 17 '09 at 11:29
24

Actually, I would suggest using this function to cover all of your bases, such as people using proxies, shared networks etc.:

function getUserIpAddr()
{
    if (!empty($_SERVER['HTTP_CLIENT_IP'])) //if from shared
    {
        return $_SERVER['HTTP_CLIENT_IP'];
    }
    else if (!empty($_SERVER['HTTP_X_FORWARDED_FOR']))   //if from a proxy
    {
        return $_SERVER['HTTP_X_FORWARDED_FOR'];
    }
    else
    {
        return $_SERVER['REMOTE_ADDR'];
    }
}
Ben G
  • 26,091
  • 34
  • 103
  • 170
  • 7
    This can be easily spoofed by sending a fake X-Forwarded-For header! – Emil Vikström Jul 12 '12 at 13:00
  • Good point. Proly makes sense to make sure that there's no mismatch between REMTOE_ADDR and HTTP_X_FORWARDED_FOR if you want to catch fakes – Ben G Jul 12 '12 at 18:29
  • Actually the whole point of proxies is that there will be a mismatch between REMOTE_ADDR and HTTP_X_FORWARDED_FOR. – jayarjo Feb 16 '14 at 20:59
8

Make sure not to trust data sent from the client. $_SERVER['REMOTE_ADDR'] contains the real IP address of the connecting party. That is the most reliable value you can find.

However, they can be behind a proxy server in which case the proxy may have set the $_SERVER['HTTP_X_FORWARDED_FOR'], but this value is easily spoofed. It can be set by someone without a proxy to whatever value the user wants, or the IP can be an internal IP from the LAN behind the proxy.

This means that if you are going to save the $_SERVER['HTTP_X_FORWARDED_FOR'], make sure you also save the $_SERVER['REMOTE_ADDR'] value, e.g., by saving both values in different fields in your database.

If you are going to save the IP to a database as a string, make sure you have space for at least 45 characters. IPv6 is here to stay and those addresses are larger than the older IPv4 addresses.

Emil Vikström
  • 90,431
  • 16
  • 141
  • 175
5

The functions getUserIpAddr() and getRealIpAddr() are not reliable!

The only reliable IP is from $ip = $_SERVER["REMOTE_ADDR"]; Otherwise anyone could fake his IP address by sending the CLIENT_IP header for example.

This Firefox Addon can help you send custom headers. Sending the CLIENT_IP=x.x.x.x header to a server running any of the functions on this page, would mean that clients can choose any IP they want...

idragosalex
  • 1,585
  • 1
  • 12
  • 8
2

Are you using some kind of framework for your webservice? I saw some frameworks (For instance Agavi) which intentionally delete all the $SERVER data because they want to enfore you to use the validated values from a framework service.

Malax
  • 9,436
  • 9
  • 48
  • 64
2

If this dont do the job i dont know what does..

    function getClientIP() {
        if (isset($_SERVER)) {

           if (isset($_SERVER["HTTP_X_FORWARDED_FOR"]))
               return $_SERVER["HTTP_X_FORWARDED_FOR"];

           if (isset($_SERVER["HTTP_CLIENT_IP"]))
               return $_SERVER["HTTP_CLIENT_IP"];

           return $_SERVER["REMOTE_ADDR"];
        }

        if (getenv('HTTP_X_FORWARDED_FOR'))
           return getenv('HTTP_X_FORWARDED_FOR');

        if (getenv('HTTP_CLIENT_IP'))
           return getenv('HTTP_CLIENT_IP');

    return getenv('REMOTE_ADDR');
}
Johan Wikström
  • 921
  • 8
  • 18
1

My preferred function:

    public static function get_remote_ip() {
        if(isset($_SERVER['REMOTE_ADDR']) && !empty($_SERVER['REMOTE_ADDR'])) {
            return $_SERVER['REMOTE_ADDR'];
        } 

        if(isset($_SERVER['HTTP_X_FORWARDED_FOR']) && !empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
            return $_SERVER['HTTP_X_FORWARDED_FOR'];
        }

        return null;
    }
Justin
  • 42,716
  • 77
  • 201
  • 296
0

You might try

<?php
var_dump($_SERVER);

to see all vars. But that actually also depends on the backend your script is running at. Is that Apache?

Vladislav Rastrusny
  • 29,378
  • 23
  • 95
  • 156
0
<?php 
 $ip=$_SERVER['REMOTE_ADDR'];
 echo "Your IP Address is $ip"; 
 ?> 

and to insert into database just use $ip

-1
<?php
function getIP() {
$ip;
if (getenv("HTTP_CLIENT_IP"))
$ip = getenv("HTTP_CLIENT_IP");
else if(getenv("HTTP_X_FORWARDED_FOR"))
$ip = getenv("HTTP_X_FORWARDED_FOR");
else if(getenv("REMOTE_ADDR"))
$ip = getenv("REMOTE_ADDR");
else
$ip = "UNKNOWN";
return $ip;

}

//-----------------------------------------------

//Usage:


$client_ip=getIP();
echo "Your IP :".$client_ip;
?>
Tarun Gupta
  • 6,305
  • 2
  • 42
  • 39
  • This is easily spoofed by a fake X-Forwarded-For header. – Emil Vikström Mar 18 '13 at 07:25
  • Then you can try $_SERVER to get the info of client. This was just another way one can use. – Tarun Gupta Mar 26 '13 at 07:32
  • My downvote is for treating X-Forwarded-For and Client-IP HTTP headers as if they are the same thing as (or even better than!) the remote address. They are not. They are easy to fake so they should not be trusted at all, except possibly in an internal network. *If* you are going to read those headers, make sure you to *also* save the real remote address. Your address does not reflect that at all so I hope nobody uses this function in a real environment. – Emil Vikström Mar 26 '13 at 07:50
  • Emil Vikstrom .. thats why i have replied that this is one of another way .. i am not suggesting it to anybody , – Tarun Gupta Apr 06 '13 at 11:33