Skip to content

[3.3] Finishing setTrustedProxies() changes & trusted_proxies removal #7952

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

Merged
merged 6 commits into from
May 30, 2017
Merged
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
1 change: 1 addition & 0 deletions _build/redirection_map
Original file line number Diff line number Diff line change
Expand Up @@ -338,3 +338,4 @@
/security/target_path /security
/service_container/third_party /service_container
/templating/templating_service /templates
/components/http_foundation/trusting_proxies /request/load_balancer_reverse_proxy
65 changes: 0 additions & 65 deletions components/http_foundation/trusting_proxies.rst

This file was deleted.

21 changes: 3 additions & 18 deletions http_cache/varnish.rst
Original file line number Diff line number Diff line change
Expand Up @@ -20,24 +20,9 @@ Varnish automatically forwards the IP as ``X-Forwarded-For`` and leaves the
trusted proxy, Symfony will see all requests as coming through insecure HTTP
connections from the Varnish host instead of the real client.

Remember to configure :ref:`framework.trusted_proxies <reference-framework-trusted-proxies>`
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 {
unset 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:`How to Configure Symfony to Work behind a Load Balancer or a Reverse Proxy <request-untrust-header>`.
Remember to call the :ref:`Request::setTrustedProxies() <request-set-trusted-proxies>`
method in your front controller so that Varnish is seen as a trusted proxy
and the :ref:`X-Forwarded-* <varnish-x-forwarded-headers>` headers are used.

.. _varnish-x-forwarded-headers:

Expand Down
35 changes: 1 addition & 34 deletions reference/configuration/framework.rst
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ Configuration

* `secret`_
* `http_method_override`_
* `trusted_proxies`_
* `ide`_
* `test`_
* `default_locale`_
Expand Down Expand Up @@ -188,39 +187,7 @@ named ``kernel.http_method_override``.
trusted_proxies
~~~~~~~~~~~~~~~

**type**: ``array``

Configures the IP addresses that should be trusted as proxies. For more
details, see :doc:`/request/load_balancer_reverse_proxy`.

.. configuration-block::

.. code-block:: yaml

# app/config/config.yml
framework:
trusted_proxies: [192.0.0.1, 10.0.0.0/8]

.. code-block:: xml

<!-- app/config/config.xml -->
<?xml version="1.0" encoding="UTF-8" ?>
<container xmlns="http://symfony.com/schema/dic/services"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:framework="http://symfony.com/schema/dic/symfony"
xsi:schemaLocation="http://symfony.com/schema/dic/services
http://symfony.com/schema/dic/services/services-1.0.xsd
http://symfony.com/schema/dic/symfony http://symfony.com/schema/dic/symfony/symfony-1.0.xsd">

<framework:config trusted-proxies="192.0.0.1, 10.0.0.0/8" />
</container>

.. code-block:: php

// app/config/config.php
$container->loadFromExtension('framework', array(
'trusted_proxies' => array('192.0.0.1', '10.0.0.0/8'),
));
The ``trusted_proxies`` option was removed in Symfony 3.3. See :doc:`/request/load_balancer_reverse_proxy`.

ide
~~~
Expand Down
122 changes: 34 additions & 88 deletions request/load_balancer_reverse_proxy.rst
Original file line number Diff line number Diff line change
Expand Up @@ -7,66 +7,48 @@ an AWS Elastic Load Balancer) or a reverse proxy (e.g. Varnish for

For the most part, this doesn't cause any problems with Symfony. But, when
a request passes through a proxy, certain request information is sent using
either the standard ``Forwarded`` header or non-standard special ``X-Forwarded-*``
headers. For example, instead of reading the ``REMOTE_ADDR`` header (which
will now be the IP address of your reverse proxy), the user's true IP will be
stored in a standard ``Forwarded: for="..."`` header or a non standard
``X-Forwarded-For`` header.
either the standard ``Forwarded`` header or ``X-Forwarded-*`` headers. For example,
instead of reading the ``REMOTE_ADDR`` header (which will now be the IP address of
your reverse proxy), the user's true IP will be stored in a standard ``Forwarded: for="..."``
header or a ``X-Forwarded-For`` header.

If you don't configure Symfony to look for these headers, you'll get incorrect
information about the client's IP address, whether or not the client is connecting
via HTTPS, the client's port and the hostname being requested.

Solution: trusted_proxies
-------------------------
.. _request-set-trusted-proxies:

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:
Solution: setTrustedProxies()
-----------------------------

.. configuration-block::
To fix this, you need to tell Symfony which reverse proxy IP addresses to trust
and what headers your reverse proxy uses to send information:

.. code-block:: yaml
.. code-block:: php

# app/config/config.yml
# ...
framework:
trusted_proxies: [192.0.0.1, 10.0.0.0/8]
// web/app.php

.. code-block:: xml
// ...
$request = Request::createFromGlobals();

<!-- app/config/config.xml -->
<?xml version="1.0" encoding="UTF-8" ?>
<container xmlns="http://symfony.com/schema/dic/services"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:framework="http://symfony.com/schema/dic/symfony"
xsi:schemaLocation="http://symfony.com/schema/dic/services
http://symfony.com/schema/dic/services/services-1.0.xsd
http://symfony.com/schema/dic/symfony http://symfony.com/schema/dic/symfony/symfony-1.0.xsd">
// tell Symfony about your reverse proxy
Request::setTrustedProxies(
// the IP address (or range) of your proxy
['192.0.0.1', '10.0.0.0/8'],

<framework:config trusted-proxies="192.0.0.1, 10.0.0.0/8">
<!-- ... -->
</framework:config>
</container>
// trust *all* "X-Forwarded-*" headers
Request::HEADER_X_FORWARDED_ALL

.. code-block:: php
// or, if your proxy instead uses the "Forwarded" header
// Request::HEADER_FORWARDED
Copy link
Member

Choose a reason for hiding this comment

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

we should also mention the HEADER_X_FORWARDED_AWS_ELB constant


// app/config/config.php
$container->loadFromExtension('framework', array(
'trusted_proxies' => array('192.0.0.1', '10.0.0.0/8'),
));
// or, if you're using AWS ELB
// Request::HEADER_X_FORWARDED_AWS_ELB
);

In this example, you're saying that your reverse proxy (or proxies) has
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.
The Request object has several ``Request::HEADER_*`` constants that control exactly
*which* headers from your reverse proxy are trusted. The argument is a bit field,
so you can also pass your own value (e.g. ``0b00110``).
Copy link
Member

Choose a reason for hiding this comment

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

I'm not sure about this part: ... so you can also pass your own value (e.g. 0b00110) Don't you think that'd be super confusing and hard to maintain?


But what if the IP of my Reverse Proxy Changes Constantly!
----------------------------------------------------------
Expand All @@ -79,60 +61,24 @@ In this case, you'll need to - *very carefully* - trust *all* proxies.
other than your load balancers. For AWS, this can be done with `security groups`_.

#. Once you've guaranteed that traffic will only come from your trusted reverse
proxies, configure Symfony to *always* trust incoming request. This is
done inside of your front controller:
proxies, configure Symfony to *always* trust incoming request:

.. code-block:: diff

// web/app.php

// ...
$request = Request::createFromGlobals();
+ Request::setTrustedProxies(array('127.0.0.1', $request->server->get('REMOTE_ADDR')));

// ...
Request::setTrustedProxies(
// trust *all* requests
array('127.0.0.1', $request->server->get('REMOTE_ADDR')),

#. Ensure that the trusted_proxies setting in your ``app/config/config.yml``
is not set or it will overwrite the ``setTrustedProxies()`` call above.
// if you're using ELB, otherwise use a constant from above
Request::HEADER_X_FORWARDED_AWS_ELB
);

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.

.. _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);

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

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

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

Although `RFC 7239`_ recently defined a standard ``Forwarded`` header to disclose
all proxy information, most reverse proxies store information in non-standard
``X-Forwarded-*`` headers.

But if your reverse proxy uses other non-standard header names, you can configure
these (see ":doc:`/components/http_foundation/trusting_proxies`").

The code for doing this will need to live in your front controller (e.g. ``web/app.php``).

.. _`security groups`: http://docs.aws.amazon.com/elasticloadbalancing/latest/classic/elb-security-groups.html
.. _`RFC 7239`: http://tools.ietf.org/html/rfc7239