Skip to content

Commit

Permalink
feature #4102 Adding a new entry about reverse proxies in the framewo…
Browse files Browse the repository at this point in the history
…rk (weaverryan)

This PR was merged into the 2.3 branch.

Discussion
----------

Adding a new entry about reverse proxies in the framework

Hi guys!

| Q             | A
| ------------- | ---
| Doc fix?      | no
| New docs?     | no
| Applies to    | all (or 2.3+)
| Fixed tickets | #2946 #2491

Per #2491, I wanted to answer the simple question: "What do I need to do in order to configure Symfony if I have a reverse proxy". The `trusted_proxies` is already documented in the reference section, but this is a full walk-through of what you should be doing and why. I've also increased links in several places where notes are needed.

Thanks!

Commits
-------

5ab6c4a Title case fix thanks to @xabbuh!
89e4d9d A bunch of changes thanks to @xabbuh and @stof
81053ab Fixing build error
c55bc2e Adding another note about how AppCache is a reverse proxy at the IP address 127.0.0.1
18af4e8 Adding a new entry about reverse proxies in the framework and linking to it in many places
  • Loading branch information
weaverryan committed Aug 8, 2014
2 parents 3ffc20f + 5ab6c4a commit 35a0f66
Show file tree
Hide file tree
Showing 7 changed files with 126 additions and 3 deletions.
8 changes: 6 additions & 2 deletions book/http_cache.rst
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,10 @@ kernel::
The caching kernel will immediately act as a reverse proxy - caching responses
from your application and returning them to the client.

Now that you're using a "proxy", you'll need to configure ``127.0.0.1`` under
the ``trusted_proxies`` configuration (see :ref:`reference <reference-framework-trusted-proxies>`).
Without this, the client's IP address and a few other things won't report correctly.

.. tip::

The cache kernel has a special ``getLog()`` method that returns a string
Expand Down Expand Up @@ -1005,8 +1009,8 @@ possible.

.. tip::

The listener only responds to local IP addresses or trusted
proxies.
The listener only responds to local IP addresses or
:doc:`trusted proxies </cookbook/request/load_balancer_reverse_proxy>`.

.. note::

Expand Down
5 changes: 5 additions & 0 deletions components/http_foundation/trusting_proxies.rst
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,11 @@
Trusting Proxies
================

.. tip::

If you're using the Symfony Framework, start by reading
:doc:`/cookbook/request/load_balancer_reverse_proxy`.

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
Expand Down
9 changes: 9 additions & 0 deletions cookbook/cache/varnish.rst
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,13 @@ Because Symfony2's cache uses the standard HTTP cache headers, the
proxy. `Varnish`_ is a powerful, open-source, HTTP accelerator capable of serving
cached content quickly and including support for :ref:`Edge Side Includes <edge-side-includes>`.

Trusting Reverse Proxies
------------------------

For ESI to work correctly and for the :ref:`X-FORWARDED <varnish-x-forwarded-headers>`
headers to be used, you need to configure Varnish as a
:doc:`trusted proxy </cookbook/request/load_balancer_reverse_proxy>`.

.. index::
single: Varnish; configuration

Expand Down Expand Up @@ -188,6 +195,8 @@ that will invalidate the cache for a given resource:
}
}
.. _varnish-x-forwarded-headers:

Routing and X-FORWARDED Headers
-------------------------------

Expand Down
1 change: 1 addition & 0 deletions cookbook/map.rst.inc
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,7 @@

* :doc:`/cookbook/request/index`

* :doc:`/cookbook/request/load_balancer_reverse_proxy`
* :doc:`/cookbook/request/mime_type`
* (session) :doc:`/cookbook/session/locale_sticky_session`

Expand Down
1 change: 1 addition & 0 deletions cookbook/request/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,5 @@ Request
.. toctree::
:maxdepth: 2

load_balancer_reverse_proxy
mime_type
103 changes: 103 additions & 0 deletions cookbook/request/load_balancer_reverse_proxy.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
How to Configure Symfony to Work behind a Load Balancer or Reverse Proxy
========================================================================

When you deploy your application, you may be behind a load balancer (e.g.
an AWS Elastic Load Balancer) or a reverse proxy (e.g. Varnish for
:doc:`caching</book/http_cache>`).

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
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 an ``X-Forwarded-For`` header.

.. tip::

If you're using Symfony's :ref:`AppCache<symfony-gateway-cache>` for caching,
then you *are* using a reverse proxy with the IP address ``127.0.0.1``.
You'll need to configure that address as a trusted proxy below.

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
-------------------------

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

.. 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">
<!-- ... -->
</framework>
</container>
.. code-block:: php
// app/config/config.php
$container->loadFromExtension('framework', array(
'trusted_proxies' => array('192.0.0.1', '10.0.0.0/8'),
));
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 :ref:`reference-framework-trusted-proxies`.

That's it! Symfony will now look for the correct ``X-Forwarded-*`` headers
to get information like the client's IP address, host, port and whether or
not the request is using HTTPS.

But what if the IP of my Reverse Proxy Changes Constantly!
----------------------------------------------------------

Some reverse proxies (like Amazon's Elastic Load Balancers) don't have a
static IP address or even a range that you can target with the CIDR notation.
In this case, you'll need to - *very carefully* - trust *all* proxies.

1. Configure your web server(s) to *not* respond to traffic from *any* clients
other than your load balancers. For AWS, this can be done with `security groups`_.

1. 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::

// web/app.php
// ...

Request::setTrustedProxies(array($request->server->get('REMOTE_ADDR')));

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

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 Uses Non-Standard (not X-Forwarded) Headers
------------------------------------------------------------

Most reverse proxies store information on specific ``X-Forwarded-*`` headers.
But if your reverse proxy uses non-standard header names, you can configure
these (:doc:`see reference </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/DeveloperGuide/using-elb-security-groups.html
2 changes: 1 addition & 1 deletion reference/configuration/framework.rst
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@ trusted_proxies
**type**: ``array``

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

.. versionadded:: 2.3
CIDR notation support was introduced in Symfony 2.3, so you can whitelist whole
Expand Down

0 comments on commit 35a0f66

Please sign in to comment.