DEV Community

Rogerio Taques
Rogerio Taques

Posted on

8 1

An easy way to get the (real) client IP in PHP

Here we go with another post! 🤘

In the other day I noticed all IPs recorded from visitor on one of my apps were the same, with a very little variation each-other! Aha~ found a bug!

Well, not much! 🙄 After a quick Google search I figured out that those IPs were all from CloudFlare (the CDN provider my apps are behind)! So, CloudFlare replaces the commonly used $_SERVER['REMOTE_ADDR'] variable with their own IP.

Fair enough!

So, if you're reading this, the chances are you are facing a similar problem and are looking for a solution ... or perhaps you're just curious, which is fine too. 🤪

Here's a very simple way to get the (real) client IP address. Note that the sintax used here is PHP7+, which means for earlier versions you're gonna need to apply some chained ifs and elses.

<?php

# PHP7+
$clientIP = $_SERVER['HTTP_CLIENT_IP'] 
    ?? $_SERVER["HTTP_CF_CONNECTING_IP"] # when behind cloudflare
    ?? $_SERVER['HTTP_X_FORWARDED'] 
    ?? $_SERVER['HTTP_X_FORWARDED_FOR'] 
    ?? $_SERVER['HTTP_FORWARDED'] 
    ?? $_SERVER['HTTP_FORWARDED_FOR'] 
    ?? $_SERVER['REMOTE_ADDR'] 
    ?? '0.0.0.0';

# Earlier than PHP7
$clientIP = '0.0.0.0';

if (isset($_SERVER['HTTP_CLIENT_IP'])) {
    $clientIP = $_SERVER['HTTP_CLIENT_IP'];
} elseif (isset($_SERVER['HTTP_CF_CONNECTING_IP'])) {
    # when behind cloudflare
    $clientIP = $_SERVER['HTTP_CF_CONNECTING_IP']; 
} elseif (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) {
    $clientIP = $_SERVER['HTTP_X_FORWARDED_FOR'];
} elseif (isset($_SERVER['HTTP_X_FORWARDED'])) {
    $clientIP = $_SERVER['HTTP_X_FORWARDED'];
} elseif (isset($_SERVER['HTTP_FORWARDED_FOR'])) {
    $clientIP = $_SERVER['HTTP_FORWARDED_FOR'];
} elseif (isset($_SERVER['HTTP_FORWARDED'])) {
    $clientIP = $_SERVER['HTTP_FORWARDED'];
} elseif (isset($_SERVER['REMOTE_ADDR'])) {
    $clientIP = $_SERVER['REMOTE_ADDR'];
}

echo "My client IP: ", $clientIP;

Enter fullscreen mode Exit fullscreen mode

Happy coding! 👋

Sentry image

Hands-on debugging session: instrument, monitor, and fix

Join Lazar for a hands-on session where you’ll build it, break it, debug it, and fix it. You’ll set up Sentry, track errors, use Session Replay and Tracing, and leverage some good ol’ AI to find and fix issues fast.

RSVP here →

Top comments (5)

Collapse
 
arvin profile image
Arvin

Good post Rogerio :)

I also had to unmask the real IP when I started using Cloudflare.
Since my projects were hosted on my own server and it was more than one project, I decided to use mod_remoteip instead of tweaking the code everywhere, and already get the real IP when I’m using $_SERVER[‘REMOTE_ADDR’].

More on this for those who are in the same situation: support.cloudflare.com/hc/en-us/ar...

Collapse
 
rogeriotaques profile image
Rogerio Taques

That’s an awesome solution, Arvin! Thanks for sharing. 🙏👏🤩

Collapse
 
tbwcjw profile image
tbwcjw • Edited

This is not a very clean solution. If Else statements are clunky. Here's my version.

function getClientIP(): string {
    $ipHeaders = [
        'HTTP_CLIENT_IP',
        'HTTP_CF_CONNECTING_IP',
        'HTTP_X_FORWARDED_FOR',
        'HTTP_X_FORWARDED',
        'HTTP_FORWARDED_FOR',
        'HTTP_FORWARDED',
        'REMOTE_ADDR'
    ];

    foreach ($ipHeaders as $header) {
        if (!empty($_SERVER[$header])) {
            return $_SERVER[$header];
        }
    }

    return '0.0.0.0';
}

$clientIP = getClientIP();
Enter fullscreen mode Exit fullscreen mode
Collapse
 
jboada profile image
jboada

Hi Rogerio,

Awesome solution!

Collapse
 
rileyjones profile image
riley jones • Edited

I had the same problem. I used the "REMOTE_ADDR" method on my website and it was showing up my cloudflare ip address. I wanted to echo the users ip, so this answer helped me out a ton.

Sentry image

See why 4M developers consider Sentry, “not bad.”

Fixing code doesn’t have to be the worst part of your day. Learn how Sentry can help.

Learn more

👋 Kindness is contagious

Please leave a ❤️ or a friendly comment on this post if you found it helpful!

Okay