Symfony, reverse proxies and IP protection

JoliCode - JoliCodeBlog - 12/04
Following an issue encountered on one of my projects, I had to dive into how IP protection works in Symfony applications when at least one reverse proxy is in front of them. After some research, trial and error, I thought it was the perfect opportunity to go back to the basics, then
Cet article est aussi disponible en 🇫🇷 Français : Symfony, reverse proxies et protection par IP.

Following an issue encountered on one of my projects, I had to dive into how IP protection works in Symfony applications when at least one reverse proxy is in front of them. After some research, trial and error, I thought it was the perfect opportunity to go back to the basics, then explain how to find the origin of the problem and solve it. But first, let’s put it in some context.

Section intitulée contextContext ✍️

The project we write about here is composed of several Symfony applications. Locally, we use a Docker infrastructure which is driven by some Fabric tasks to simplify our DX (this was the premise of our docker-starter – 7 years ago). Our goal was to have a local infrastructure for development looking like the future production infrastructure. Here is what it looks like:

As our applications are based on the old Symfony architecture, we still use the front controllers web/app.php, web/app_dev.php. The app_dev.php is even deployed in production – to simplify remote debugging – but is only accessible from our office IPs.

<?php use Symfony\Component\ErrorHandler\Debug; use Symfony\Component\HttpFoundation\Request; require __DIR__ . '/../app/autoload.php'; // … $request = Request::createFromGlobals(); if (!\Symfony\Component\HttpFoundation\IpUtils::checkIp($request->getClientIp(), [ 'XXX.XXX.XXX.XXX', // IP JoliCode '127.0.0.1', // localhost 'fe80::1', '::1', ])) { exit(); } $kernel = new AppKernel(dev, true); $response = $kernel->handle($request); $response->send(); $kernel->terminate($request, $response);

Since last week, our continuous integration has turned red 🔴 and all functional tests failed with the following error:

The request has both a trusted "FORWARDED" header and a trusted "X_FORWARDED_FOR" header, conflicting with each other. You should either configure your proxy to remove one of them, or configure your project to distrust the offending one.

Roughly speaking, with the stack trace, we understand that the $request->getClientIp() method – called in our app_dev.php – raises an error because it detects several conflicting headers. For the moment, this error is still a bit unclear. Let’s start by understanding the logic for how to find client’s IP 🤓.

Section intitulée retrieve-client-s-ipRetrieve client’s IP 🪧

Retrieving the IP of the client that calls our PHP app may seem like a trivial issue. Not at all!

Section intitul...
[Courte citation de 8% de l'article original]

Loading...