Problem/Motivation

Found in #2976394: Allow Symfony 4.4 to be installed in Drupal 8, although Drupal\Tests\Core\StackMiddleware\ReverseProxyMiddlewareTest has an @expectedDeprecation The "Symfony\Component\HttpFoundation\Request::setTrustedHeaderName()" method is deprecated since Symfony 3.3 and will be removed in 4.0. Use the $trustedHeaderSet argument of the Request::setTrustedProxies() method instead., that does not help once updated to Symfony 4 since the method is actually, effectively, absolutely not there anymore.

Proposed resolution

Do a proper deprecation of how custom header settings and replace using a new reverse_proxy_trusted_headers setting instead.

Support for the following settings in deprecated in Drupal 8:

  • reverse_proxy_header
  • reverse_proxy_proto_header
  • reverse_proxy_host_header
  • reverse_proxy_port_heade
  • reverse_proxy_forwarded_header

In Drupal 8 these could be set to custom header names if used by your reverse proxy. Support for this will be dropped in Drupal 9.

Additionally you could set each value to NULL to indicate that the corresponding header was not to be trusted. In Drupal 8.7.0 a new setting has been added to control this reverse_proxy_trusted_headers.

Before

$settings['reverse_proxy_host_header'] = NULL
$settings['reverse_proxy_forwarded_header'] = NULL;

After

$settings['reverse_proxy_trusted_headers'] = \Symfony\Component\HttpFoundation\Request::HEADER_X_FORWARDED_FOR | 
\Symfony\Component\HttpFoundation\Request::HEADER_X_FORWARDED_PROTO | \Symfony\Component\HttpFoundation\Request::HEADER_X_FORWARDED_PORT;

OR

$settings['reverse_proxy_trusted_headers'] = \Symfony\Component\HttpFoundation\Request::HEADER_X_FORWARDED_AWS_ELB

Note the default value for $settings['reverse_proxy_trusted_headers'] is \Symfony\Component\HttpFoundation\Request::HEADER_X_FORWARDED_ALL | \Symfony\Component\HttpFoundation\Request::HEADER_FORWARDED. This value is the most permissive and does not make much sense as reverse proxies do not use both "X-Forwarded-*" headers and "Forwarded" header. Therefore it is recommended to set a value.

Remaining tasks

Do it.

User interface changes

None.

API changes

Don't know yet. Hopefully none.

Data model changes

None.

Release notes snippet

N/A.

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

Gábor Hojtsy created an issue. See original summary.

alexpott’s picture

I had a quick look at this one. Can't immediately see how to set custom trusted header names in SF4.

Berdir’s picture

@alexpott: According to https://symfony.com/blog/fixing-the-trusted-proxies-configuration-for-sy..., it is combined with setTrustedProxies() now, second argument?

alexpott’s picture

Status: Active » Needs review
FileSize
6.11 KB

This deprecation happened in https://github.com/symfony/symfony/pull/25623 but it was a result of https://github.com/symfony/symfony/pull/21830

It seems the ability to have custom headers has been completely removed which means this change becomes something like the patch attached.

@Berdir yeah but the custom header thing is completely gone.

alexpott’s picture

So what's a bit fun is that our implement here isn't really what we want and has never been. Ideally we'd have a setting that tells Symfony\Request what to trust. Atm we do $request::setTrustedProxies($proxies, Request::HEADER_X_FORWARDED_ALL | Request::HEADER_FORWARDED); which doesn't make a great deal of sense. But at least before you could disable certain headings by doing
$settings['reverse_proxy_host_header'] = NULL in settings.php. This is important because AWS ELB doesn't send X-Forwarded-Host. So the patch in #4 is not right. We need a new setting.

alexpott’s picture

Here's step 1 - the new setting. And then we need BC in place for the old ability to set to a NULL to not trust the header.

alexpott’s picture

And here's a BC layer which supports the current behaviour and tells people to move to the new reverse_proxy_trusted_headers setting instead.

alexpott’s picture

This issue is a bit tricky because we didn't really handle the deprecation correctly in #2927746: Update Symfony components to 3.4.*

alexpott’s picture

Issue summary: View changes
Gábor Hojtsy’s picture

Status: Needs review » Needs work
Issue tags: -Needs change record

So the concept basically is that the deprecated setting is not to be used after updating to Symfony 4 on an individual site. That sounds fine. Added that to the change notice draft and fixed up some wording, especially the title: https://www.drupal.org/node/3030558/revisions/view/11285892/11298269

Found these super-minor things:

  1. +++ b/core/lib/Drupal/Core/StackMiddleware/ReverseProxyMiddleware.php
    @@ -58,24 +58,35 @@ public function handle(Request $request, $type = self::MASTER_REQUEST, $catch =
    +        // Set the default value. note that this is the most relaxed setting
    +        // possible and not recommended.
    

    "Note" should be uppercase.

  2. +++ b/core/tests/Drupal/Tests/Core/StackMiddleware/ReverseProxyMiddlewareTest.php
    @@ -47,30 +49,83 @@ public function testNoProxy() {
    +        // For AWS configuration forwarded and x_forwarded_host headers are not
    +        // trusted
    

    Period missing at the end of sentence.

  3. +++ b/sites/default/default.settings.php
    @@ -365,34 +364,31 @@
    + * Specify which headers the reserve proxy uses.
    

    This sounds odd to me. Maybe:

    Specify which headers are used by the reserve proxy.

alexpott’s picture

Status: Needs work » Needs review
FileSize
3.01 KB
13.62 KB

Addressed #10. I went a little bit further on .3 and made it more like what is there for other settings.

Gábor Hojtsy’s picture

Status: Needs review » Reviewed & tested by the community

Looks good to me now.

larowlan’s picture

Status: Reviewed & tested by the community » Fixed

Committed 2aa7c3a and pushed to 8.7.x. Thanks!

  • larowlan committed 2aa7c3a on 8.7.x
    Issue #3030501 by alexpott, Gábor Hojtsy, Berdir: [Symfony 4] Drupal\...

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.

Gábor Hojtsy’s picture

Hm, #2976394-144: Allow Symfony 4.4 to be installed in Drupal 8 still fails with

1) Drupal\Tests\Core\StackMiddleware\ReverseProxyMiddlewareTest::testReverseProxyEnabledLegacy with data set "Proxy with deprecated custom headers" (array(array('127.0.0.2', '127.0.0.3'), null, null), 26, array('The 'reverse_proxy_host_heade...030558', 'The 'reverse_proxy_forwarded_...030558', 'The "Symfony\Component\HttpFo...stead.'))
Error: Call to undefined method Symfony\Component\HttpFoundation\Request::setTrustedHeaderName()

/var/www/html/core/lib/Drupal/Core/StackMiddleware/ReverseProxyMiddleware.php:78
/var/www/html/core/lib/Drupal/Core/StackMiddleware/ReverseProxyMiddleware.php:46
/var/www/html/core/tests/Drupal/Tests/Core/StackMiddleware/ReverseProxyMiddlewareTest.php:151
/var/www/html/core/tests/Drupal/Tests/Core/StackMiddleware/ReverseProxyMiddlewareTest.php:95

2) Drupal\Tests\Core\StackMiddleware\ReverseProxyMiddlewareTest::testReverseProxyEnabledLegacy with data set "Proxy with deprecated custom header" (array(array('127.0.0.2', '127.0.0.3'), null), 30, array('The 'reverse_proxy_forwarded_...030558', 'The "Symfony\Component\HttpFo...stead.'))
Error: Call to undefined method Symfony\Component\HttpFoundation\Request::setTrustedHeaderName()

/var/www/html/core/lib/Drupal/Core/StackMiddleware/ReverseProxyMiddleware.php:78
/var/www/html/core/lib/Drupal/Core/StackMiddleware/ReverseProxyMiddleware.php:46
/var/www/html/core/tests/Drupal/Tests/Core/StackMiddleware/ReverseProxyMiddlewareTest.php:151
/var/www/html/core/tests/Drupal/Tests/Core/StackMiddleware/ReverseProxyMiddlewareTest.php:95

Can we figure out a way to conditionally test it so it does not fail with Symfony 4.

alexpott’s picture

Yeah - let's open a follow-up to skip this test if Request::setTrustedHeaderName() does not exist.