Skip to content
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

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

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
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 actual host may be stored in a ``X-Forwarded-Host`` header.

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, null);
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
does not filter out the ``Forwarded`` header. If you have access to the Varnish
configuration file, you can configure Varnish to remove the ``Forwarded``
header:

.. 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
:ref:`the cookbook <cookbook-request-untrust-header>`.

.. _varnish-x-forwarded-headers:

Routing and X-FORWARDED Headers
Expand Down
28 changes: 27 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,29 @@ 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.

.. _cookbook-request-untrust-header:

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
do not filter it by default. Ideally, you would configure this
in your proxy. If this is not possible, you can tell Symfony to distrust
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