Amrinder Singh
Amrinder Singh

Reputation: 5532

How to get client IP address in Laravel 5+

I am trying to get the client's IP address in Laravel.

It is easy to get a client's IP in PHP by using $_SERVER["REMOTE_ADDR"]. It is working fine in core PHP, but when I use the same thing in Laravel, it returns the server IP instead of the visitor's IP.

Upvotes: 188

Views: 422938

Answers (18)

shalini
shalini

Reputation: 1300

Add namespace

use Illuminate\Http\Request;

Then call the function

Request::ip();

Upvotes: 38

Alhdrin Gungon
Alhdrin Gungon

Reputation: 61

   protected function getIp(){
        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) === true){
                foreach (explode(',', $_SERVER[$key]) as $ip){
                    if (filter_var(trim($ip), FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE) !== false){
                        return $ip;
                    }
                }
            }
        }
        return request()->ip(); 
    }

Upvotes: 0

Sebastien Horin
Sebastien Horin

Reputation: 11069

Note: This answer is outdated and dangerous. Request::ip() will, since Laravel 5.5, return the correct IP address if configured to trust the load balancer's headers. The "custom method" presented here allows clients to set any IP address they like.

If you are under a load balancer, Laravel's \Request::ip() always returns the balancer's IP:

            echo $request->ip();
            // server IP

            echo \Request::ip();
            // server IP

            echo \request()->ip();
            // server IP

            echo $this->getIp(); //see the method below
            // client IP

This custom method returns the real client IP:

public function getIp(){
    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) === true){
            foreach (explode(',', $_SERVER[$key]) as $ip){
                $ip = trim($ip); // just to be safe
                if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE) !== false){
                    return $ip;
                }
            }
        }
    }
    return request()->ip(); // it will return the server IP if the client IP is not found using this method.
}

In addition to this, I suggest you be very careful using Laravel's throttle middleware: It uses Laravel's Request::ip() as well, so all your visitors will be identified as the same user and you will hit the throttle limit very quickly. I experienced this in a live environment and this caused big issues.

To fix this:

Illuminate\Http\Request.php

    public function ip()
    {
        //return $this->getClientIp(); //original method
        return $this->getIp(); // the above method
    }

You can now also use Request::ip(), which should return the real IP in production.

Upvotes: 156

Majbah Habib
Majbah Habib

Reputation: 8558

Solution 1: You can use this type of function for getting client IP

public function getClientIPaddress(Request $request) {
    $clientIp = $request->ip();
    return $clientIp;
}

Solution 2: if the solution1 is not providing accurate IP then you can use this function for getting visitor real IP.

 public function getClientIPaddress(Request $request) {

    if (isset($_SERVER["HTTP_CF_CONNECTING_IP"])) {
        $_SERVER['REMOTE_ADDR'] = $_SERVER["HTTP_CF_CONNECTING_IP"];
        $_SERVER['HTTP_CLIENT_IP'] = $_SERVER["HTTP_CF_CONNECTING_IP"];
    }
    $client  = @$_SERVER['HTTP_CLIENT_IP'];
    $forward = @$_SERVER['HTTP_X_FORWARDED_FOR'];
    $remote  = $_SERVER['REMOTE_ADDR'];

    if(filter_var($client, FILTER_VALIDATE_IP)){
        $clientIp = $client;
    }
    elseif(filter_var($forward, FILTER_VALIDATE_IP)){
        $clientIp = $forward;
    }
    else{
        $clientIp = $remote;
    }

    return $clientIp;
 }

N.B: When you have used load-balancer/proxy-server in your production server then you need to used solution 2 for getting real visitor ip.

Upvotes: -1

bluestar0505
bluestar0505

Reputation: 701

In Laravel 7&8, I am using below methoths.

In Controller

use Illuminate\Http\Request;

public function index(Request $request)
{
    $request->ip();
    return view('users.index');
}

In Blade

Request::ip()

Anywhere

request()->ip()

Upvotes: 0

Soura Ghosh
Soura Ghosh

Reputation: 917

This below function will help you to give the client's IP address -

public function getUserIpAddr(){
       $ipaddress = '';
       if (isset($_SERVER['HTTP_CLIENT_IP']))
           $ipaddress = $_SERVER['HTTP_CLIENT_IP'];
       else if(isset($_SERVER['HTTP_X_FORWARDED_FOR']))
           $ipaddress = $_SERVER['HTTP_X_FORWARDED_FOR'];
       else if(isset($_SERVER['HTTP_X_FORWARDED']))
           $ipaddress = $_SERVER['HTTP_X_FORWARDED'];
       else if(isset($_SERVER['HTTP_FORWARDED_FOR']))
           $ipaddress = $_SERVER['HTTP_FORWARDED_FOR'];
       else if(isset($_SERVER['HTTP_FORWARDED']))
           $ipaddress = $_SERVER['HTTP_FORWARDED'];
       else if(isset($_SERVER['REMOTE_ADDR']))
           $ipaddress = $_SERVER['REMOTE_ADDR'];
       else
           $ipaddress = 'UNKNOWN';    
       return $ipaddress;
    }

Upvotes: 9

Pejman Zeynalkheyri
Pejman Zeynalkheyri

Reputation: 4832

I tested in Laravel 8.x and you can use:

$request->ip()

For getting the client's IP address.

Upvotes: 12

Munna Khan
Munna Khan

Reputation: 2052

This solution I used in my project. I found other solutions here either incomplete or too complex to understand.

if (! function_exists('get_visitor_IP'))
{
    /**
     * Get the real IP address from visitors proxy. e.g. Cloudflare
     *
     * @return string IP
     */
    function get_visitor_IP()
    {
        // Get real visitor IP behind CloudFlare network
        if (isset($_SERVER["HTTP_CF_CONNECTING_IP"])) {
            $_SERVER['REMOTE_ADDR'] = $_SERVER["HTTP_CF_CONNECTING_IP"];
            $_SERVER['HTTP_CLIENT_IP'] = $_SERVER["HTTP_CF_CONNECTING_IP"];
        }

        // Sometimes the `HTTP_CLIENT_IP` can be used by proxy servers
        $ip = @$_SERVER['HTTP_CLIENT_IP'];
        if (filter_var($ip, FILTER_VALIDATE_IP)) {
           return $ip;
        }

        // Sometimes the `HTTP_X_FORWARDED_FOR` can contain more than IPs 
        $forward_ips = @$_SERVER['HTTP_X_FORWARDED_FOR'];
        if ($forward_ips) {
            $all_ips = explode(',', $forward_ips);

            foreach ($all_ips as $ip) {
                if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE)){
                    return $ip;
                }
            }
        }

        return $_SERVER['REMOTE_ADDR'];
    }
}

Upvotes: -1

samlev
samlev

Reputation: 5942

Looking at the Laravel API:

Request::ip();

Internally, it uses the getClientIps method from the Symfony Request Object:

public function getClientIps()
{
    $clientIps = array();
    $ip = $this->server->get('REMOTE_ADDR');
    if (!$this->isFromTrustedProxy()) {
        return array($ip);
    }
    if (self::$trustedHeaders[self::HEADER_FORWARDED] && $this->headers->has(self::$trustedHeaders[self::HEADER_FORWARDED])) {
        $forwardedHeader = $this->headers->get(self::$trustedHeaders[self::HEADER_FORWARDED]);
        preg_match_all('{(for)=("?\[?)([a-z0-9\.:_\-/]*)}', $forwardedHeader, $matches);
        $clientIps = $matches[3];
    } elseif (self::$trustedHeaders[self::HEADER_CLIENT_IP] && $this->headers->has(self::$trustedHeaders[self::HEADER_CLIENT_IP])) {
        $clientIps = array_map('trim', explode(',', $this->headers->get(self::$trustedHeaders[self::HEADER_CLIENT_IP])));
    }
    $clientIps[] = $ip; // Complete the IP chain with the IP the request actually came from
    $ip = $clientIps[0]; // Fallback to this when the client IP falls into the range of trusted proxies
    foreach ($clientIps as $key => $clientIp) {
        // Remove port (unfortunately, it does happen)
        if (preg_match('{((?:\d+\.){3}\d+)\:\d+}', $clientIp, $match)) {
            $clientIps[$key] = $clientIp = $match[1];
        }
        if (IpUtils::checkIp($clientIp, self::$trustedProxies)) {
            unset($clientIps[$key]);
        }
    }
    // Now the IP chain contains only untrusted proxies and the client IP
    return $clientIps ? array_reverse($clientIps) : array($ip);
} 

Upvotes: 253

pedro.caicedo.dev
pedro.caicedo.dev

Reputation: 2445

I used the Sebastien Horin function getIp and request()->ip() (at global request), because to localhost the getIp function return null:

$this->getIp() ?? request()->ip();

The getIp function:

public function getIp(){
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) === true){
        foreach (explode(',', $_SERVER[$key]) as $ip){
            $ip = trim($ip); // just to be safe
            if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE) !== false){
                return $ip;
            }
        }
    }
}

}

Upvotes: -1

Bing
Bing

Reputation: 1

If you have multiple layer proxies just like CDN + Load Balancer.
Using Laravel Request::ip() function will get right-most proxy IP but not client IP.
You may try following solution.

app/Http/Middleware/TrustProxies.php

protected $proxies = ['0.0.0.0/0'];

Reference: https://github.com/fideloper/TrustedProxy/issues/107#issuecomment-373065215

Upvotes: -1

Yevgeniy Afanasyev
Yevgeniy Afanasyev

Reputation: 41450

There are two things to take care of:

  1. Get a helper function that returns a Illuminate\Http\Request and call the ->ip() method:

    request()->ip();
    
  2. Think of your server configuration, it may use a proxy or load-balancer, especially in an AWS ELB configuration.

If this is your case you need to follow "Configuring Trusted Proxies" or maybe even set a "Trusting All Proxies" option.

Why? Because being your server will be getting your proxy/load-balancer IP instead.

If you are on the AWS balance-loader, go to App\Http\Middleware\TrustProxies and make $proxies declaration look like this:

protected $proxies = '*';

Now test it and celebrate because you just saved yourself from having trouble with throttle middleware. It also relies on request()->ip() and without setting "TrustProxies" up, you could have all your users blocked from logging in instead of blocking only the culprit's IP.

And because throttle middleware is not explained properly in the documentation, I recommend watching "laravel 5.2 tutorial for beginner, API Rate Limiting"

Tested in Laravel 5.7

Upvotes: 26

Vahid Alvandi
Vahid Alvandi

Reputation: 612

In Laravel 5.4 we can't call ip static. This a correct way to get the IP of the user:

 use Illuminate\Http\Request;

public function contactUS(Request $request)
    {
        echo $request->ip();
        return view('page.contactUS');
    }

Upvotes: 8

Philipp Mochine
Philipp Mochine

Reputation: 4705

If you are still getting 127.0.0.1 as the IP, you need to add your "proxy", but be aware that you have to change it before going into production!

Read "Configuring Trusted Proxies".

And add this:

class TrustProxies extends Middleware
{
    /**
     * The trusted proxies for this application.
     *
     * @var array
     */
    protected $proxies = '*';

Now request()->ip() gives you the correct IP.

Upvotes: 7

Todor Todorov
Todor Todorov

Reputation: 2541

For Laravel 5 you can use the Request object. Just call its ip() method, something like:

$request->ip();

Upvotes: 23

Stan Smulders
Stan Smulders

Reputation: 6237

Use request()->ip().

From what I understand, since Laravel 5 it's advised/good practice to use the global functions like:

response()->json($v);
view('path.to.blade');
redirect();
route();
cookie();

And, if anything, when using the functions instead of the static notation my IDE doesn't light up like a Christmas tree.

Upvotes: 81

Aung Bo
Aung Bo

Reputation: 51

If you want client IP and your server is behind aws elb, then user the following code. Tested for laravel 5.3

$elbSubnet = '172.31.0.0/16';
Request::setTrustedProxies([$elbSubnet]);
$clientIp = $request->ip();

Upvotes: 5

Govind Samrow
Govind Samrow

Reputation: 10187

In Laravel 5

public function index(Request $request) {
  $request->ip();
}

Upvotes: 19

Related Questions