When placing a Drupal 8 site behind a reverse proxy then the URL and session generator ignore the X-Forwarded-Host request header.
Url generator
Absolute URLs are being generated based upon the Host header instead of the X-Forwarded-Host header even when the settings.php is configured to allow reverse proxies. Invoking Drupal::request()->getHost() results in the correct host. The problem is caused by the url generator service being initialized before the ReverseProxySubscriber has a chance to assign trusted reverse proxies.
Session generator
Retrieving session cookie parameters from session_get_cookie_params() results in the domain matching the Host header instead of X-Forwarded-Host.
Proposed fix
This solution moves the trusted proxy logic from ReverseProxySubscriber to drupal_handle_request()
// Create a request object from the HttpFoundation.
$request = Request::createFromGlobals();
// Get the current settings.
$settings = \Drupal\Component\Utility\Settings::getSingleton();
// Check whether the reverse proxy settings should be used.
if ($settings->get('reverse_proxy', 0)) {
// Allow the request to use the reverse proxy headers.
$reverse_proxy_header = $settings->get('reverse_proxy_header', 'HTTP_X_FORWARDED_FOR');
$request::setTrustedHeaderName($request::HEADER_CLIENT_IP, $reverse_proxy_header);
$reverse_proxy_addresses = $settings->get('reverse_proxy_addresses', array());
$request::setTrustedProxies($reverse_proxy_addresses);
// Set the session cookie domain to the correct host.
ini_set('session.cookie_domain', ".{$request->getHost()}");
}
// Attach the request to the dependency container.
\Drupal::getContainer()->set('request', $request);
| Comment | File | Size | Author |
|---|---|---|---|
| #9 | drupal-incorrect-host-using-reverse-proxy-2179937-9.patch | 1.13 KB | freblasty |
| #6 | drupal-incorrect-host-using-reverse-proxy-2179937-6.patch | 1.13 KB | freblasty |
Comments
Comment #1
freblasty commentedOn a side note: creating file URL does not use the URL generator but uses the global variables to generate an URL.
Comment #2
freblasty commentedChanging to higher priority.
Comment #3
freblasty commentedThis issue is still present in 8.0.0-beta2.
Comment #4
freblasty commentedComment #5
freblasty commenteddrupal_handle_request()no longer exists. Proposed solution mentioned above is no longer valid, see attached patch in next comment.Comment #6
freblasty commentedComment #7
freblasty commentedComment #9
freblasty commentedPatch based on latest HEAD.
Comment #10
freblasty commentedComment #12
dawehnerWe should really ensure that we do have tests.
Comment #14
freblasty commented@dawehner: what tests do you have in mind?
Comment #17
freblasty commentedFor what I can see the problem should be fixed with introduction of #2304949: Port HTTP Host header DoS fix from SA-CORE-2014-003 as they switch to using
$request->getHost()and$request->getSchemeAndHttpHost(). However can't test this at the moment. Will update the issue status asap.Comment #19
gabesulliceTriaging this as part of DrupalCon New Orleans 2016.
Comment #20
acbramley commentedI believe we are hitting this issue on 8.1.1.
We have Drupal behind a reverse proxy, when we first enter $request->getHost(); it doesn't contain the trusted proxies settings so the host is being read from the HOST header rather than X-FORWARDED-HOST, on subsequent entries to that function it's correct.
Comment #25
mithenks commentedPlease take a look at 2972310 - Reverse proxy settings not used.
Comment #32
imyaro commentedI think this ticket should be closed - this issue fixed in the latest Drupal versions.
Comment #33
thursday_bw commented"I think this ticket should be closed - this issue fixed in the latest Drupal versions." I don't see any evidence or even suggestion of this having been fixed, and since i'm looking at it on Drupal 10 going "this looks exactly like my issue", I am going to re-open it.
Rather than re-open this ticket, I will mark this related issue, I think they are duplicates: https://www.drupal.org/project/drupal/issues/2998728