Laravel Proxy Package for handling sessions when behind load balancers or other intermediaries.

Last update: Jun 29, 2022

Laravel Trusted Proxies

Build Status Total Downloads

Setting a trusted proxy allows for correct URL generation, redirecting, session handling and logging in Laravel when behind a reverse proxy such as a load balancer or cache.


Installation

Laravel 5.5+ comes with this package. If you are using Laravel 5.5 or greater, you do not need to add this to your project separately.

Laravel 5.0 - 5.4

To install Trusted Proxy, use:

composer require fideloper/proxy:^3.3

Laravel 4

composer require fideloper/proxy:^2.0

Setup

Refer to the docs above for using Trusted Proxy in Laravel 5.5+. For Laravel 4.0 - 5.4, refer to the wiki.

What Does This Do?

Setting a trusted proxy allows for correct URL generation, redirecting, session handling and logging in Laravel when behind a reverse proxy.

This is useful if your web servers sit behind a load balancer (Nginx, HAProxy, Envoy, ELB/ALB, etc), HTTP cache (CloudFlare, Squid, Varnish, etc), or other intermediary (reverse) proxy.

How Does This Work?

Applications behind a reverse proxy typically read some HTTP headers such as X-Forwarded, X-Forwarded-For, X-Forwarded-Proto (and more) to know about the real end-client making an HTTP request.

If those headers were not set, then the application code would think every incoming HTTP request would be from the proxy.

Laravel (technically the Symfony HTTP base classes) have a concept of a "trusted proxy", where those X-Forwarded headers will only be used if the source IP address of the request is known. In other words, it only trusts those headers if the proxy is trusted.

This package creates an easier interface to that option. You can set the IP addresses of the proxies (that the application would see, so it may be a private network IP address), and the Symfony HTTP classes will know to use the X-Forwarded headers if an HTTP requets containing those headers was from the trusted proxy.

Why Does This Matter?

A very common load balancing approach is to send https:// requests to a load balancer, but send http:// requests to the application servers behind the load balancer.

For example, you may send a request in your browser to https://example.org. The load balancer, in turn, might send requests to an application server at http://192.168.1.23.

What if that server returns a redirect, or generates an asset url? The users's browser would get back a redirect or HTML that includes http://192.168.1.23 in it, which is clearly wrong.

What happens is that the application thinks its hostname is 192.168.1.23 and the schema is http://. It doesn't know that the end client used https://example.org for its web request.

So the application needs to know to read the X-Forwarded headers to get the correct request details (schema https://, host example.org).

Laravel/Symfony automatically reads those headers, but only if the trusted proxy configuration is set to "trust" the load balancer/reverse proxy.

Note: Many of us use hosted load balancers/proxies such as AWS ELB/ALB, etc. We don't know the IP address of those reverse proxies, and so you need to trusted all proxies in that case.

The trade-off there is running the security risk of allowing people to potentially spoof the X-Forwarded headers.

IP Addresses by Service

This Wiki page has a list of popular services and their IP addresses of their servers, if available. Any updates or suggestions are welcome!

GitHub

https://github.com/fideloper/TrustedProxy
Comments
  • 1. Symfony Request.php setTrustedProxies Requires Two Arguments

    I see that the call to $request->setTrustedProxies() provides only 1 argument as seen below:

    private function setTrustedProxyIpAddressesToTheCallingIp($request) {
        $request->setTrustedProxies($request->getClientIps());
    }
    

    but setTrustedProxies() now requires two arguments: https://github.com/symfony/http-foundation/blob/master/Request.php#L587

    Unless I am mistaken, TrustedProxy, as is, is no longer working.

    Reviewed by eduardoagarcia at 2017-05-09 16:22
  • 2. Problem with redirect() from Laravel being always http

    If I try to wget the root folder of my app page, then it will redirect me to the /login page via Laravel's redirect() helper method.

    I have a web server behing a load balancer that is the endopoint for SSL. When I open the root url of my app, I get redirected to the /login page if not logged in, an everything works fine and the final result is as expected (I get redirected properly)

    But what happens behind the scene is the following:

    1. I ask for https://app.workstack.io
    2. Load balancer forwards it to the web server that responds with a redirect to HTTP://app.workstack.io/login
    3. Request is sent to the Load Balancer that redirects again to HTTPS://app.workstack.io/login
    4. Finally the request goes through the web server and I output the login page.

    My question is: Is it possible in some way to avoid the extra redirect from http to https? I think it's a similar problem like when using the url() helper, where you need to replace it with secure_url() or it will be output with http instead of https. Is there a way to tell Laravel to use always https by default for all the url generated by its helper methods? (url(), redirect(), etc.)

    I copy here the wget of the request so that it get be more clear

    wget https://app.workstack.io --2016-06-09 22:08:37-- https://app.workstack.io/ Resolving app.workstack.io (app.workstack.io)... 174.143.185.9 Connecting to app.workstack.io (app.workstack.io)|174.143.185.9|:443... connected. HTTP request sent, awaiting response... 302 Found Location: http://app.workstack.io/login [following] --2016-06-09 22:08:37-- http://app.workstack.io/login Connecting to app.workstack.io (app.workstack.io)|174.143.185.9|:80... connected. HTTP request sent, awaiting response... 301 Moved Permanently Location: https://app.workstack.io/login [following] --2016-06-09 22:08:37-- https://app.workstack.io/login Connecting to app.workstack.io (app.workstack.io)|174.143.185.9|:443... connected. HTTP request sent, awaiting response... 200 OK Length: unspecified [text/html] Saving to: ‘index.html.3’

    Thanks a lot for this awesome library btw! :)

    Reviewed by crash13override at 2016-06-09 20:18
  • 3. Multiple layers of load balancers in 4.0

    Our setup has multiple LB IP addresses, first a local one 10.* and then a public one 130.*. Lastly the users IP. This means that TrustedProxy should filter out 10.* and 130.*, but no matter what I do, it only filters out the first IP.

    Everything worked correctly in version 3.*, but after upgrading to 4.*, it stopped working. Doesn't TrustedProxy support multiple layers of load balancers anymore?

    Our environment is Google Cloud Platform with Laravel 5.6 and PHP 7.1.

    Reviewed by niclashedam at 2018-02-08 14:34
  • 4. Request ips wrong order when using a load balancer

    Hi, I recently upgrade one application from Laravel 5.2 to Laravel 5.7 Before the upgrade I was using this library (v3.3) with the configuration below

        'proxies' => '**',
    ...
        'headers' => [
            (defined('Illuminate\Http\Request::HEADER_FORWARDED') ? Illuminate\Http\Request::HEADER_FORWARDED : 'forwarded') => null,
            Illuminate\Http\Request::HEADER_CLIENT_IP    => 'X_FORWARDED_FOR',
            Illuminate\Http\Request::HEADER_CLIENT_HOST  => null,
            Illuminate\Http\Request::HEADER_CLIENT_PROTO => 'X_FORWARDED_PROTO',
            Illuminate\Http\Request::HEADER_CLIENT_PORT  => 'X_FORWARDED_PORT',
        ]
    

    After the upgrade, I added the TrustProxies middleware below

    <?php
    
    namespace App\Http\Middleware;
    
    use Fideloper\Proxy\TrustProxies as Middleware;
    use Illuminate\Http\Request;
    
    class TrustProxies extends Middleware
    {
        /**
         * The trusted proxies for this application.
         *
         * @var array
         */
        protected $proxies = '**';
    
        /**
         * The headers that should be used to detect proxies.
         *
         * @var int
         */
        protected $headers = Request::HEADER_X_FORWARDED_AWS_ELB;
    }
    

    The issue I am having might not be related to this, but basically after the upgrade

    $request->ip() // the ec2 ip
    $request->ips() // [ec2 ip, client ip]
    

    It seems the order or the ips is inverted, I should be getting first the client ip, then any other ip.

    Is this a configuration issue on my side or is there anything else I am missing?

    Reviewed by peppeocchi at 2018-11-08 17:39
  • 5. how to set custom HEADER_X_FORWARD in 4.0

    Hi,

    Prior to 4.0, i could do something like this in config/trustproxy.php :

    'headers' => [
        (defined('Illuminate\Http\Request::HEADER_FORWARDED') ? Illuminate\Http\Request::HEADER_FORWARDED : 'forwarded') => 'FORWARDED',
        Illuminate\Http\Request::HEADER_CLIENT_IP    => 'X_FORWARDED_FOR',
        Illuminate\Http\Request::HEADER_CLIENT_HOST  => 'X_FORWARDED_HOST',
        Illuminate\Http\Request::HEADER_CLIENT_PROTO => 'X_FORWARDED_PROTO_CUSTOM',
        Illuminate\Http\Request::HEADER_CLIENT_PORT  => 'X_FORWARDED_PORT_CUSTOM',
    ]
    

    But with 4.0 i can't find a way to specify custom names for HEADER_CLIENT_PORT and HEADER_CLIENT_PROTO

    Does someone know how to deal with this issue ?

    thx

    Reviewed by olivM at 2018-02-20 08:29
  • 6. Non-Numeric Value encountered

    I had been up and running with you proxy for about a month now on an AWS box with load balancer and Laravel on backend. After an upgrade (at 3.3 now) now getting an error:

    ErrorException in TrustProxies.php line 159:
    A non-numeric value encountered
    in TrustProxies.php line 159
    at HandleExceptions->handleError('2', 'A non-numeric value encountered', '/home/forge/isdb.io/code/Laravel/vendor/fideloper/proxy/src/TrustProxies.php', '159', array('set' => '0', 'key' => 'forwarded')) in /home/forge/isdb.io/code/Laravel/vendor/fideloper/proxy/src/TrustProxies.php line 159
    at TrustProxies->Fideloper\Proxy\{closure}('0', 'forwarded')
    

    Scratching my head with no clue whats happening....any help would be appreciated.

    Thx

    DJK

    Reviewed by kapsoft at 2017-05-30 19:08
  • 7. adding support for AWS ELB. Accept IPs separated by comma.

    1. Accept IPs separated by comma.
      • Probably In a project like Laravel you need to add this config to the .env file and array is not supported in .env
    TRUSTEDPROXY_PROXIES='192.168.1.1, 192.168.1.2'
    
    'proxies' => env('TRUSTEDPROXY_PROXIES', null),
    
    1. Accept headers as a string.
      • Probably In a project like Laravel you need to add this config to the .env file and you can pass the header you want to use as a string:
    TRUSTEDPROXY_HEADERS='HEADER_X_FORWARDED_AWS_ELB'
    
    'headers' => env('TRUSTEDPROXY_HEADERS', 'HEADER_X_FORWARDED_ALL'),
    
    Reviewed by rrpadilla at 2018-12-09 10:13
  • 8. array_keys() error

    Hello I've just upgraded an app from 5.4.36 to 5.5 (via Laravel Shift, with PHP 7.1.13 on Homestead vagrant box.)

    I'm getting this E_WARNING for vendor/fideloper/proxy/src/TrustProxies.php:162, even though to the best of my knowledge I've not configured load balancing etc. at all:

    array_keys() expects parameter 1 to be array, integer given

        protected function getTrustedHeaderSet()
        {
            $trustedHeaderNames = $this->getTrustedHeaderNames();
            $headerKeys = array_keys($this->getTrustedHeaderNames());
    
    

    Composer has fideloper/proxy (3.3.4) (specified as "~3.3")

    I can fix it by simply casting to an array with:

    $headerKeys = array_keys((array) $this->getTrustedHeaderNames());

    Is that adequate? (I know nothing about your package...)

    (Thanks)

    Reviewed by wturrell at 2018-02-01 21:17
  • 9. AWS EBS and Lumen 5.4 - LB IP

    Hi,

    I'm using Elastic Beanstalk (with a load balancer) and Lumen 5.4 - I followed the steps (code included below) however, when calling $request->getClientIp(); I'm still getting the load balancer's IP;

    bootstrap/app.php

     $app->middleware([
         // other middleware
         'Fideloper\Proxy\TrustProxies'
     ]);
    
    // other service providers
    $app->register(Fideloper\Proxy\TrustedProxyServiceProvider::class);
    

    config/trustedproxy.php

    <?php
    
    return [
        'proxies' => [
            '*',
        ],
    
        // These are defaults already set in the config:
        'headers' => [
            (defined('Illuminate\Http\Request::HEADER_FORWARDED') ? Illuminate\Http\Request::HEADER_FORWARDED : 'forwarded') => null,
            \Illuminate\Http\Request::HEADER_CLIENT_IP    => 'X_FORWARDED_FOR',
            \Illuminate\Http\Request::HEADER_CLIENT_HOST  => null,
            \Illuminate\Http\Request::HEADER_CLIENT_PROTO => 'X_FORWARDED_PROTO',
            \Illuminate\Http\Request::HEADER_CLIENT_PORT  => 'X_FORWARDED_PORT',
        ]
    ];
    

    What's actually being forwarded;

    [HTTP_X_FORWARDED_FOR] => 141.105.x.x (real IP)
    [HTTP_X_FORWARDED_PORT] => 80
    [HTTP_X_FORWARDED_PROTO] => http
    

    Am I missing something from this configuration?

    Reviewed by andrew-s at 2017-09-29 14:49
  • 10. [Idea] Load the trusted proxies from an environment variable

    It would be useful to be able to pass a list of trusted proxies via an environment variable, for example TRUSTED_PROXIES=192.168.0.10,172.10.0.4.

    My specific use case is running CachetHQ. They trust CloudFlare's IPs by default, but I need to add my local nginx reverse proxy IP to that list. My only option now is to change that file directly, which isn't ideal.

    Although the reason I'd like this is very specific, there're other cases where it would be useful. For example, trusting different proxies in different environments (dev, qa, staging, production).

    What do you think?

    Reviewed by vitorbaptista at 2017-08-25 12:47
  • 11. laravel 5.4 behind an IBM load balancer

    Hi!

    I'm running 2 laravels behind an IBM Load Balancer and i cant get Trustedproxy to work. I've tried all the configs mentioned in previous issues but i cant make it work.

    thanks!

    Reviewed by sgdmediagroup at 2019-01-30 19:55
  • 12. is Fideloper's TrustedProxy on Laravel 5.5.43?

    Documentation seems to imply its on 5.5 but i dont see... Im on Laravel 5.5.43. I don't seem to see a App\Http\Middleware\TrustProxies.php file at all, so I'd thought i'd ask how to get it in.

    Reviewed by ArianHojatAES at 2022-06-07 22:02
  • 13. ⚠️ ➡️➡️➡️ Laravel 9 issues: Read this before making an issue ⬅️⬅️⬅️

    Laravel 9 has incorporated this package into the core of Laravel.

    See the upgrade guide here: https://laravel.com/docs/9.x/upgrade, search for Trusted Proxies

    image

    Reviewed by fideloper at 2022-02-09 13:26
  • 14. Addressed how wildcards are handled so it functions with multiple load balancers

    This could either be an issue with the documentation and comments, or it could be an issue with the way that wildcards are being handled. Because of that, I have only created this as a draft pull request to prompt discussion on the matter and in the hope that either the code or the documentation are fixed.

    From the documentation and code comments, I am concluding that the intent of using * as a wildcard is to trust all proxies, however; all it currently appears to do is trust the calling IP address and not every IP in the chain.

    For example, if a request goes through the following flow CloudFlare > DigitalOcean > Kubernetes one may end up with the something akin to 123.456.0.1, 172.68.0.1, 104.16.0.1 for the value of $_SERVER['HTTP_X_FORWARDED_FOR'] where 123.456.0.1 is the actual source IP. When using * as a wildcard, this package erroneously returns 104.16.0.1 when calling request()->ip() instead of the expected result.

    This pull request addresses this issue and corrects the order of IPs in tests so that they match what's received in real world scenarios. The reversed IP addresses are also an indicator that this is a code issue, that is, assuming that wasn't the intent, and if it was the intent, then that would ideally be handled in a separate code block or perhaps some comments added to indicate so.

    Other open issues also mention this, for example, https://github.com/fideloper/TrustedProxy/issues/115 and https://github.com/fideloper/TrustedProxy/issues/107

    Reviewed by simonworkhouse at 2020-12-02 10:06
  • 15. Support custom trusted header bitmasks

    This PR adds support for custom bitmasks, which are necessary if your load balancer doesn't support all X-Forwarded-* headers and doesn't support the same subset of X-Forwarded-* headers that AWS ELB uses. I personally ran into this while using ngrok via valet share, which doesn't send HEADER_X_FORWARDED_PORT.

    Reviewed by matt-allan at 2020-02-17 16:05
  • 16. fix "failed to open required file" for config file

    This will fix "failed to open required file" When we use this package (with laravel) inside phar archive.

    The problem happen because realpath will return the full path when the package no longer exist in disk.

    With this pull request the path will be relative and will work inside phar archive.

    Reviewed by Ahed91 at 2017-11-10 08:05
Related tags
Register for multiple Livestorm sessions from an external form. Practical use of Livestorm API with PHP/Javascript.

Livestorm Multi Session Registration Register for multiple Livestorm sessions from an external form. Practical use of Livestorm API with PHP/Javascrip

Dec 24, 2021
Source code behind the Laracasts Larabit: My Favorite Laravel Collections Methods

My Favorite Laravel Collections Methods This is the source code behind the Laracasts Larabit: My Favorite Laravel Collections Methods, and features al

Dec 2, 2021
Source code behind the Laracasts Larabit: Using MySQL JSON Columns with Laravel

Using MySQL JSON Columns with Laravel This is the source code behind the Laracasts Larabit: Using MySQL JSON Columns with Laravel, and features all of

Dec 24, 2021
Source code behind the Laracasts Larabit: Creating and Using Custom Blade Directives

This is the source code behind the Laracasts Larabit: Creating and Using Custom Blade Directives, and features all of the files and code available in that video.

Nov 12, 2021
A lightweight package for handling API error responses.

Laravel API Errors This package provides an easy way to manage and handle error response for JSON API's. Installation You can install the package via

Feb 9, 2022
This package provides new helper functions that take care of handling all the translation hassle and do it for you.

Laravel Translate Message ?? This package provides new helper functions that take care of handling all the translation hassle and do it for you. Insta

Feb 8, 2022
Load files and classes as lazy collections in Laravel.

Lody Load files and classes as lazy collections in Laravel. Installation composer require lorisleiva/lody Usage Lody enables you to fetch all exist

May 21, 2022
Automatically load your helpers in your laravel application.

Laravel AutoHelpers Automatically load your helpers in your laravel application. Installation You can install the package via composer: composer requi

Jul 26, 2021
Load Laravel service providers based on your application's environment.
 Load Laravel service providers based on your application's environment.

Laravel EnvProviders A more finetuned way of managing your service providers in Laravel. This package allows you to configure the environment certain

Mar 26, 2022
Load head metadata from a manifest file which can be shared with a SPA project

Laravel Head Manifest Installation Step 1: Add Laravel Head Manifest to your laravel project composer require critiq/laravel-head-manifest Step 2: Add

Nov 17, 2021
Load .env files for PHP.

PHP DotEnv Loader Simple library to load and get values from .env file(s). Install composer require murilo-perosa/dot-env How to Use Namespace use Mur

Jan 15, 2022
With dadjokes every time you load your control panel you'll be greeted by an epic dad joke on the dashboard.

Filament Dad Jokes Widget With DadJokes every time you load your control panel you'll be greeted by an epic dad joke on the dashboard. Installation Yo

Jun 23, 2022
A package for Myanmar Font, Phone and other Myanmar tools using Laravel Macro

Laravel Myanmar Tools A package for Myanmar Font, Phone and other Myanmar tools using Laravel Macro. Installation composer require pyaesoneaung/larave

Jun 16, 2022
Laravel package for manage your URL redirects in database or other sources to get better SEO results

Laravel 8 and 9 package to manage URL redirections inside your Laravel application using different data sources. It allows a better SEO support for your Laravel site.

May 15, 2022
Jun 24, 2022
A laravel Livewire Dynamic Selects with multiple selects depending on each other values, with infinite levels and totally configurable.
A laravel Livewire Dynamic Selects with multiple selects depending on each other values, with infinite levels and totally configurable.

Livewire Combobox: A dynamic selects for Laravel Livewire A Laravel Livewire multiple selects depending on each other values, with infinite levels of

Jun 9, 2022
A powerful form builder, for Laravel and other frameworks (stand-alone too)

Former A Laravelish way to create and format forms Former outputs form elements in HTML compatible with your favorite CSS framework (Bootstrap and Fou

Jun 10, 2022
Base library for repeated layout fields, content builders and other collection components

laravel-flexible-content This package's only purpose is to build custom repeated layout components, such as Laravel Nova's Flexible Content field or y

May 31, 2022
A Simple PHP Renderer for Slim 3 (or any other PSR-7 project)

PHP Renderer This is a renderer for rendering PHP view scripts into a PSR-7 Response object. It works well with Slim Framework 4. Cross-site scripting

Jun 11, 2022