Laravel 5.5 Now Includes TrustedProxy

Published on by

Laravel 5.5 Now Includes TrustedProxy image

Laravel v5.5 was released just a week ago at Laracon EU. You may have noticed that the v5.5 composer.json file requires the fideloper/proxy composer package. For me, this is one of those packages I must include immediately on every project because I use Amazon Web Services and Google Cloud every day, so I am thankful Laravel 5.5 includes this package by default.

Setting up the package is a breeze, and I especially appreciate that this package takes care of redundant setup. Let’s briefly cover what this package provides for Laravel, and why it’s an important package in the Laravel ecosystem.

What Does the TrustedProxy Package Do?

On a high level, Trusted Proxy tells Laravel about proxies that can be trusted and how to map X-Forwarded-* headers from the request.

The package readme probably does a better job summarizing:

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

This is useful if your web servers sit behind a load balancer, HTTP cache, or other intermediary (reverse) proxy.

Laravel uses Symfony for handling Requests and Responses. These classes have the means to handle proxies. However, for security reasons, they must be informed of which proxies to “trust” before they will attempt to read the X-Forwarded-* headers.

Laravel does not have a simple configuration option for “trusting” proxies out of the box. This package simply provides one.

Working with Proxies

It’s commonplace for developers to need to work with cloud providers like Amazon Web Services and Content Delivery Networks (CDN) like Cloudflare for full site delivery, with the application sitting behind these services instead of being exposed directly to the world. Also, your application might even be behind a chain of proxies.

When your website or application has DNS pointed at CloudFlare, for example, the HTTP requests get proxied from CloudFlare to your application.

For example, ou might notice a few CloudFlare headers in the HTTP responses on Laravel News:

$ curl -I https://laravel-news.com/laravel-5-5
HTTP/1.1 200 OK
Date: Wed, 13 Sep 2017 04:15:50 GMT
Content-Type: text/html; charset=UTF-8
Connection: keep-alive
Cache-Control: no-cache
Server: cloudflare-nginx
CF-RAY: 39d849a3df7a39e2-PHX

You can see a couple headers (CF-RAY and Server for example) being sent back in the cURL response. CloudFlare is proxying the request to the actual application, getting the response, appending a few headers, and sending the response back to the end-user.

Since CloudFlare is proxying between the end user and the application, all requests look the same to the application. To let the application know important details about the originating request, proxies send along X-Forwarded* headers.

Here are a few common headers that proxies will send along:

  • X-Forwarded-For – a standard header for defining the originating IP address (reference)
  • X-Forwarded-Host – a de-facto standard header for identifying the original host requested by the client in the Host HTTP header (reference)
  • X-Forwarded-Proto – a de-facto standard header for identifying the protocol, such as HTTP or HTTPS (reference)
  • X-Forwarded-Port – helps you identify the port that the client used to connect to the load balancer (reference)

Not all proxies use the de-facto standard headers, but this package can help you map those headers so that the underlying Symfony request object knows how to trust the proxy and get the correct values.

HTTPS -> HTTP

If you terminate TLS/SSL at the load-balancer level, your application might receive requests internally on HTTP, but actually the originating request from users is HTTPS. If you are in this situation, your application will receive header like this (among others) from the proxy:

X-Forwarded-Proto: https

The TrustProxies middleware automatically makes the Request object aware of the proxy headers by calling Symfony’s HttpFoundation Request::setTrustedProxies() method, and thus any PHP-generated URIs will know to use HTTPS, even though the request was made via HTTP. Without calling setTrustedProxies(), a Laravel application wouldn’t know about the originating request and how to properly deal with that request.

Configuration

The fideloper/proxy package provides the following Laravel configuration so you can adapt the package to work in a variety of settings, including providing mapping if your proxies use non-standard header names:

<?php
 
return [
 
/*
* Set trusted proxy IP addresses.
*
* Both IPv4 and IPv6 addresses are
* supported, along with CIDR notation.
*
* The "*" character is syntactic sugar
* within TrustedProxy to trust any proxy
* that connects directly to your server,
* a requirement when you cannot know the address
* of your proxy (e.g. if using Rackspace balancers).
*
* The "**" character is syntactic sugar within
* TrustedProxy to trust not just any proxy that
* connects directly to your server, but also
* proxies that connect to those proxies, and all
* the way back until you reach the original source
* IP. It will mean that $request->getClientIp()
* always gets the originating client IP, no matter
* how many proxies that client's request has
* subsequently passed through.
*/
'proxies' => [
'192.168.1.10',
],
 
/*
* Or, to trust all proxies that connect
* directly to your server, uncomment this:
*/
# 'proxies' => '*',
 
/*
* Or, to trust ALL proxies, including those that
* are in a chain of forwarding, uncomment this:
*/
# 'proxies' => '**',
 
/*
* Default Header Names
*
* Change these if the proxy does
* not send the default header names.
*
* Note that headers such as X-Forwarded-For
* are transformed to HTTP_X_FORWARDED_FOR format.
*
* The following are Symfony defaults, found in
* \Symfony\Component\HttpFoundation\Request::$trustedHeaders
*
* You may optionally set headers to 'null' here if you'd like
* for them to be considered untrusted instead. Ex:
*
* Illuminate\Http\Request::HEADER_CLIENT_HOST => null,
*
* WARNING: If you're using AWS Elastic Load Balancing or Heroku,
* the FORWARDED and X_FORWARDED_HOST headers should be set to null
* as they are currently unsupported there.
*/
'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',
Illuminate\Http\Request::HEADER_CLIENT_PORT => 'X_FORWARDED_PORT',
]
];

The configuration allows you to define the IP addresses you want to trust, or you can trust all direct proxies with * and any proxy in a chain of proxies with **. Please consult the documentation carefully, as well as the final part of this article to read about locking down your applications that are behind proxies.

You can create the config/trustedproxy.php configuration by running vendor:publish:

php artisan vendor:publish --provider="Fideloper\Proxy\TrustedProxyServiceProvider"

In Laravel 5.5, running vendor:publish without arguments will use an interactive mode which makes publishing the vendor file even easier.

Learn More

Symfony has a short write-up How to Configure Symfony to Work behind a Load Balancer or Reverse Proxy with some valuable information. Specifically, the following security considerations are crucial when working with proxies:

Some reverse proxies (like Amazon’s Elastic Load Balancers) don’t have a static IP address or even a range that you can target with the CIDR notation. In this case, you’ll need to – very carefully – trust all proxies.

  1. Configure your web server(s) to not respond to traffic from any clients other than your load balancers. For AWS, this can be done with security groups.
  2. Once you’ve guaranteed that traffic will only come from your trusted reverse proxies, configure Symfony to always trust incoming request.

Check out fideloper/proxy, which has an extensive readme on how to set up the TrustProxies middleware and configuration with a ton of information on the subject.

Paul Redmond photo

Staff writer at Laravel News. Full stack web developer and author.

Cube

Laravel Newsletter

Join 40k+ other developers and never miss out on new tips, tutorials, and more.

Laravel Forge logo

Laravel Forge

Easily create and manage your servers and deploy your Laravel applications in seconds.

Laravel Forge
Tinkerwell logo

Tinkerwell

The must-have code runner for Laravel developers. Tinker with AI, autocompletion and instant feedback on local and production environments.

Tinkerwell
No Compromises logo

No Compromises

Joel and Aaron, the two seasoned devs from the No Compromises podcast, are now available to hire for your Laravel project. ⬧ Flat rate of $7500/mo. ⬧ No lengthy sales process. ⬧ No contracts. ⬧ 100% money back guarantee.

No Compromises
Kirschbaum logo

Kirschbaum

Providing innovation and stability to ensure your web application succeeds.

Kirschbaum
Shift logo

Shift

Running an old Laravel version? Instant, automated Laravel upgrades and code modernization to keep your applications fresh.

Shift
Bacancy logo

Bacancy

Supercharge your project with a seasoned Laravel developer with 4-6 years of experience for just $2500/month. Get 160 hours of dedicated expertise & a risk-free 15-day trial. Schedule a call now!

Bacancy
Lucky Media logo

Lucky Media

Get Lucky Now - the ideal choice for Laravel Development, with over a decade of experience!

Lucky Media
Lunar: Laravel E-Commerce logo

Lunar: Laravel E-Commerce

E-Commerce for Laravel. An open-source package that brings the power of modern headless e-commerce functionality to Laravel.

Lunar: Laravel E-Commerce
LaraJobs logo

LaraJobs

The official Laravel job board

LaraJobs
SaaSykit: Laravel SaaS Starter Kit logo

SaaSykit: Laravel SaaS Starter Kit

SaaSykit is a Multi-tenant Laravel SaaS Starter Kit that comes with all features required to run a modern SaaS. Payments, Beautiful Checkout, Admin Panel, User dashboard, Auth, Ready Components, Stats, Blog, Docs and more.

SaaSykit: Laravel SaaS Starter Kit
Rector logo

Rector

Your partner for seamless Laravel upgrades, cutting costs, and accelerating innovation for successful companies

Rector
MongoDB logo

MongoDB

Enhance your PHP applications with the powerful integration of MongoDB and Laravel, empowering developers to build applications with ease and efficiency. Support transactional, search, analytics and mobile use cases while using the familiar Eloquent APIs. Discover how MongoDB's flexible, modern database can transform your Laravel applications.

MongoDB

The latest

View all →
The Inertia.js v2 Beta is Here image

The Inertia.js v2 Beta is Here

Read article
Mastering Laravel, No Compromises, and SourceDive with Joel Clermont image

Mastering Laravel, No Compromises, and SourceDive with Joel Clermont

Read article
Now you can install PHP and the Laravel installer with a single command image

Now you can install PHP and the Laravel installer with a single command

Read article
WireSpy is a Sleek New Debug Bar for Laravel Livewire image

WireSpy is a Sleek New Debug Bar for Laravel Livewire

Read article
The Laracon AU schedule is now live image

The Laracon AU schedule is now live

Read article
Supercharge PhpStorm with Laravel Idea image

Supercharge PhpStorm with Laravel Idea

Read article