Description
Q | A |
---|---|
Bug report? | yes |
Feature request? | no |
BC Break report? | no |
RFC? | no |
Symfony version | 4.0.2 |
I'm testing a package that helps with setting Trusted Proxies in Laravel apps. It's included in Laravel out of the box as of Laravel 5.5.
For Symfony 4, which Laravel 5.6 will be using, when I attempt to set X-Forwarded-*
as untrusted, and the Forwarded
header as trusted, I receive the Symfony\Component\HttpFoundation\Exception\ConflictingHeadersException
exception:
Symfony\Component\HttpFoundation\Exception\ConflictingHeadersException: 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.
This occurs because the request has both X-Forwarded-*
headers and a Forwarded
header. However, I believe I should be able to do that and tell Symfony which to trust and which to ignore (especially based on the exception message).
Since the Request
object has no explicit way to set a header as un-trusted, I assume this is implicitly done by telling Symfony which headers to trust. (Of course let me know if this assumption is incorrect!)
So, while one option is obviously to adjust a proxy to NOT include X-Forwarded-*
and only use Forwarded
, it seems the project should also ignore non-trusted headers if both style headers are present. Currently it doesn't seem to.
Here is code to reproduce it:
<?php
require_once('vendor/autoload.php');
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
$server = [
'HTTP_FORWARDED' => 'for=173.174.200.40:443; proto=https; host=serversforhackers.com',
'HTTP_X_FORWARDED_FOR' => '173.174.200.38', // X-Forwarded-For -- getClientIp()
'HTTP_X_FORWARDED_HOST' => 'svrs4hkrs.com', // X-Forwarded-Host -- getHosts()
'HTTP_X_FORWARDED_PORT' => '80', // X-Forwarded-Port -- getPort()
'HTTP_X_FORWARDED_PROTO' => 'http', // X-Forwarded-Proto -- getScheme() / isSecure()
'SERVER_PORT' => 8888,
'HTTP_HOST' => 'localhost',
'REMOTE_ADDR' => '192.168.10.10',
];
$request = Request::create('http://localhost:8888/tag/proxy', 'GET', [], [], [], $server, null);
$request->setTrustedProxies(['192.168.10.10'], Request::HEADER_FORWARDED);
var_dump($request->getClientIp()); // This throws a `ConflictingHeadersException`
This expects to use the Forwarded
header to get the real client IP address. The X-Forwarded-*
headers are present merely to test that we can in fact ignore untrusted headers. Instead, we get the thrown exception.
I believe the getTrustedValues()
method here is the culprit, altho farther up the chain may be where a "fix" for this (if indeed a bug) resides, to eliminate the X-Forwarded-*
headers as being used if not trusted.