Skip to content

Documented how to configure Symfony correctly with regards to the Forwarded header #6526

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 15 additions & 6 deletions components/http_foundation/trusting_proxies.rst
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,9 @@ Trusting Proxies

If you find yourself behind some sort of proxy - like a load balancer - then
certain header information may be sent to you using special ``X-Forwarded-*``
headers. For example, the ``Host`` HTTP header is usually used to return
the requested host. But when you're behind a proxy, the true host may be
stored in a ``X-Forwarded-Host`` header.
headers or the ``Forwarded`` header. For example, the ``Host`` HTTP header is
usually used to return the requested host. But when you're behind a proxy,
the true host may be stored in a ``X-Forwarded-Host`` header.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe replace "true host" with "actual host" here? (my dev. mind strongly binds true to a boolean value)


Since HTTP headers can be spoofed, Symfony does *not* trust these proxy
headers by default. If you are behind a proxy, you should manually whitelist
Expand All @@ -30,11 +30,19 @@ your proxy.
// only trust proxy headers coming from this IP addresses
Request::setTrustedProxies(array('192.0.0.1', '10.0.0.0/8'));

You should also make sure that your proxy filters unauthorized use of these
headers, e.g. if a proxy natively uses the ``X-Forwarded-For`` header, it
should not allow clients to send ``Forwarded`` headers to Symfony.

If your proxy does not filter headers appropriately, you need to configure
Symfony not to trust the headers your proxy does not filter (see below).

Configuring Header Names
------------------------

By default, the following proxy headers are trusted:

* ``Forwarded`` Used in :method:`Symfony\\Component\\HttpFoundation\\Request::getClientIp`;
* ``X-Forwarded-For`` Used in :method:`Symfony\\Component\\HttpFoundation\\Request::getClientIp`;
* ``X-Forwarded-Host`` Used in :method:`Symfony\\Component\\HttpFoundation\\Request::getHost`;
* ``X-Forwarded-Port`` Used in :method:`Symfony\\Component\\HttpFoundation\\Request::getPort`;
Expand All @@ -43,6 +51,7 @@ By default, the following proxy headers are trusted:
If your reverse proxy uses a different header name for any of these, you
can configure that header name via :method:`Symfony\\Component\\HttpFoundation\\Request::setTrustedHeaderName`::

Request::setTrustedHeaderName(Request::HEADER_FORWARDED, 'X-Forwarded');
Request::setTrustedHeaderName(Request::HEADER_CLIENT_IP, 'X-Proxy-For');
Request::setTrustedHeaderName(Request::HEADER_CLIENT_HOST, 'X-Proxy-Host');
Request::setTrustedHeaderName(Request::HEADER_CLIENT_PORT, 'X-Proxy-Port');
Expand All @@ -51,9 +60,9 @@ can configure that header name via :method:`Symfony\\Component\\HttpFoundation\\
Not Trusting certain Headers
----------------------------

By default, if you whitelist your proxy's IP address, then all four headers
By default, if you whitelist your proxy's IP address, then all five headers
listed above are trusted. If you need to trust some of these headers but
not others, you can do that as well::

// disables trusting the ``X-Forwarded-Proto`` header, the default header is used
Request::setTrustedHeaderName(Request::HEADER_CLIENT_PROTO, '');
// disables trusting the ``Forwarded`` header
Request::setTrustedHeaderName(Request::HEADER_FORWARDED, '');
15 changes: 15 additions & 0 deletions cookbook/cache/varnish.rst
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,21 @@ Remember to configure :ref:`framework.trusted_proxies <reference-framework-trust
in the Symfony configuration so that Varnish is seen as a trusted proxy and the
:ref:`X-Forwarded <varnish-x-forwarded-headers>` headers are used.

Varnish, in its' default configuration, sends the ``X-Forwarded-For`` header but
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

its' -> its

does not filter out the ``Forwarded``. If you have access to the Varnish
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

... the Forwarded. -> ... the Forwarded header.

configuration file, you can configure Varnish to remove the ``Forwarded``
header::
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One of the colons needs to be removed to make the build happy. :)


.. code-block:: varnish4

sub vcl_recv {
remove req.http.Forwarded;
}

If you do not have access to your Varnish configuration, you can instead
configure Symfony to distrust the ``Forwarded`` header as detailed in
:doc:`/cookbook/request/load_balancer_reverse_proxy`.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if you add .. _cookbook-request-untrust-header: before the headline on line 60 of the referenced cookbook article, you can use :ref:the cookbook `` here to directly link to the correct section.


.. _varnish-x-forwarded-headers:

Routing and X-FORWARDED Headers
Expand Down
26 changes: 25 additions & 1 deletion cookbook/request/load_balancer_reverse_proxy.rst
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ via HTTPS, the client's port and the hostname being requested.
Solution: trusted_proxies
-------------------------

This is no problem, but you *do* need to tell Symfony that this is happening
This is no problem, but you *do* need to tell Symfony what is happening
and which reverse proxy IP addresses will be doing this type of thing:

.. configuration-block::
Expand Down Expand Up @@ -62,6 +62,9 @@ the IP address ``192.0.0.1`` or matches the range of IP addresses that use
the CIDR notation ``10.0.0.0/8``. For more details, see the
:ref:`framework.trusted_proxies <reference-framework-trusted-proxies>` option.

You are also saying that you trust that the proxy does not send conflicting
headers, e.g. sending both X-Forwarded-For and Forwarded in the same request.

That's it! Symfony will now look for the correct headers to get information
like the client's IP address, host, port and whether the request is
using HTTPS.
Expand Down Expand Up @@ -95,6 +98,27 @@ That's it! It's critical that you prevent traffic from all non-trusted sources.
If you allow outside traffic, they could "spoof" their true IP address and
other information.

My Reverse Proxy sends X-Forwarded-For but does not filter the Forwarded header
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We use title case in the Symfony docs. This means that this headline has to be capitialized like My Reverse Proxy Sends X-Forwarded-For but does not Filter the Forwarded Header

-------------------------------------------------------------------------------

Many popular proxy implementations do not yet support the Forwarded header and
does not filter it by default configuration. Ideally, you would configure this
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"proxy implementations" is plural, so this needs to be "do not filter it by default." (I would skip configuration here as well)

in your proxy, but if this is not possible, you can tell Symfony to distrust
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is a long sentence, you might want to split it up here: "in your proxy. If this is not possible, you can [...]"

the Forwarded header, while still trusting your proxy's X-Forwarded-For header.

This is done inside of your front controller::

// web/app.php

// ...
Request::setTrustedHeaderName(Request::HEADER_FORWARDED, null);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

previously, we set it to "" (empty string). Let's choose one of these and use it consistently (I think null makes more sense here?)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed


$response = $kernel->handle($request);
// ...

Configuring the proxy server trust is very important, as not doing so will
malicious users to "spoof" their IP address.

My Reverse Proxy Uses Non-Standard (not X-Forwarded) Headers
------------------------------------------------------------

Expand Down