LoginSignup
1
0

More than 3 years have passed since last update.

Getting Real Visitor IP in a Laravel Application regardless of how many in-betweens

Last updated at Posted at 2018-09-16

Recently I worked on a project that happens to be architected this way. (Not my decision)

React.js Frontend -> GraphQL Server -> Cloudflare -> Laravel Backend REST APIs

Naturally getting the real IP of the visitor is very troublesome. Previously when it was just Cloudflare sitting in front of the Laravel app. Getting the visitor IP is a simple case of configuring https://github.com/fideloper/TrustedProxy and you can continue to use your usual request()->ip()

However, in this new architecture, you have a GraphQL server in front of Cloudflare, making things not as straight forward.

But still, the solution is simple after some dive into Laravel's source code

  1. Make your GraphQL server forward the visitor IP to Cloudflare on the X_FORWARDED_FORheader.
  2. In your Laravel App, when you fetch the request IP, instead of doing request()->ip(), do last(request()->getClientIps())
  3. Done!

Now for the explanation:

  1. First, read the Cloudflare docs on X-Forwarded-For
  2. In short, the real visitor IP is the last one on X-Forwarded-For header
  3. Now let's look at the code behind Laravel's request()->getClientIps()
    /**
     * Returns the client IP addresses.
     *
     * In the returned array the most trusted IP address is first, and the
     * least trusted one last. The "real" client IP address is the last one,
     * but this is also the least trusted one. Trusted proxies are stripped.
     *
     * Use this method carefully; you should use getClientIp() instead.
     *
     * @return array The client IP addresses
     *
     * @see getClientIp()
     */
    public function getClientIps()
    {
        $ip = $this->server->get('REMOTE_ADDR');

        if (!$this->isFromTrustedProxy()) {
            return array($ip);
        }

        return $this->getTrustedValues(self::HEADER_X_FORWARDED_FOR, $ip) ?: array($ip);
    }

As we can see we need to grab the last item in the array returned by getClientIps(). In PHP there is the end(&$array) method but doing so will give you PHP Fatal error: Only variables can be passed by reference error so you would need an extra line to assign the response of getClientIps() to a variable first.

$clientIps = request()->getClientIps();
$visitorIp = end($clientIps);

But thankfully, Laravel has a last($array) helper method which avoids the need for that and calls end(&$array) behind the scenes.

    /**
     * Get the last element from an array.
     *
     * @param  array  $array
     * @return mixed
     */
    function last($array)
    {
        return end($array);
    }

I hope this article helps anyone who is facing a simular issue. Good night :)

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0