Як сконфігурувати Symfony, щоб вона працювала за розподільником навантаження або зворотним проксі

Дата оновлення перекладу 2022-11-01

Як сконфігурувати Symfony, щоб вона працювала за розподільником навантаження або зворотним проксі

Коли ви розгортаєте свій додаток, ви можете знаходитися за розподільником навантаження (наприклад, еластичне розподілення навантаження AWS) або зворотним проксі (наприклад, Varnish для кешування).

У більшості випадків це не викликає проблем з Symfony. Але коли запит проходить через проксі, відправдяється певна інформація запиту, використовуючи або стандартний заголовок Forwarded, або заголовки X-Forwarded-*. Наприклад, замість читання заголовку REMOTE_ADDR (який тепер буде IP-адресою вашого зворотного проксі), справжній IP користувача зберігатиметься у стандартному заголовку Forwarded: for="..." або заголовку X-Forwarded-For.

Якщо ви не сконфігуруєте Symfony так, щоб вона шукала такі заголовки, то ви отримуватимете неправильну інфорамцію про IP-адресу клієнта, незалежно від того, чи підключається він через HTTPS, чи ні, клієнтського порту та запитуваного імені хосту.

Вирішення: setTrustedProxies()

Щоб виправити це, вам потрібно сказати Symfony, яким IP-адресам зворотного проксі можна довіряти, і які заголовки використовує ваш проксі для відправки інформації:

  • YAML
  • XML
  • PHP
1
2
3
4
5
6
7
8
9
# config/packages/framework.yaml
framework:
    # ...
    # IP-адреса (або діапазон) вашого проксі
    trusted_proxies: '192.0.0.1,10.0.0.0/8'
    # довіряти *всім* заголовкам "X-Forwarded-*"
    trusted_headers: ['x-forwarded-for', 'x-forwarded-host', 'x-forwarded-proto', 'x-forwarded-port', 'x-forwarded-prefix']
    # або, якщо ваш проксі замість цього використовує заголовок "Forwarded"
    trusted_headers: ['forwarded']

Caution

Включення опції Request::HEADER_X_FORWARDED_HOST робить додаток вразливим до атак заголовків хостингу HTTP. Переконайтеся в тому, що прооксі дійсно відправляє заголловок x-forwarded-host.

Обʼєкт Запит має декілька констант Request::HEADER_*, які контролюють, яким заголовкам вашого зворотного проксі можна довіряти. Аргумент є полем біту, так що ви також можете передати власне значення (наприклад, 0b00110).

Caution

Функція "довірені проксі" не працює, як очікується, при використанні модуля nginx realip. Відключіть цей модуль при обслуговуванні додатків Symfony.

Але що, якщо IP мого зворотнго проксі постійно змінюється!

Деякі зворотні проксі (на кшталт Еластичного розподілення навантаження AWS) не мають статичної IP-адреси або навіть діапазону, який ви можете охопити за допомогою CIDS примітки. В такому випадку вам потрібно буде - дуже обережно - довіряти всім проксі.

  1. Сконфігуруйте ваш(і) веб-сервер(и), щоб вони не відповідали на трафік будь-яких клієнтів, окрім ваших розподілювачів навантаження. Для AWS це можна зробити за допомогою груп безпеки.
  2. Коли ви гарантували, що трафік буде виходити лише від довірених зворотних проксі, сконфігуруйте Symfony завжди довіряти вхідному запиту:

    1
    2
    3
    4
    5
    6
    # config/packages/framework.yaml
    framework:
        # ...
        # довіряти *всім* запитам (рядок 'REMOTE_ADDR' замінюється під час
        # прогону на $_SERVER['REMOTE_ADDR'])
        trusted_proxies: '127.0.0.1,REMOTE_ADDR'

Ось і все! Критично важливо, щоб ви запобігли трафіку з усіх недовірених джерел. Якщо ви доозволите сторонній трафік, він може "підробити" справжні IP-адреси та іншу інформацію.

Tip

У додатках, що використовують Symfony Flex , ви можете встановити змінну середовища TRUSTED_PROXIES:

1
2
# .env
TRUSTED_PROXIES=127.0.0.1,REMOTE_ADDR
1
2
3
4
# config/packages/framework.yaml
framework:
    # ...
    trusted_proxies: '%env(TRUSTED_PROXIES)%'

Якщо ви також використовуєте зворотний проксі над вашим балансувальником навантаження (наприклад, CloudFront), виклику $request->server->get('REMOTE_ADDR') буде недостатньо, так як він буде довіряти лише вузллу, що знаходиться прямо над вашим додатком (в даному випадку - вашому балансувальнику наванатаження). Вам також потрібно додати IP-адреси або діапазон будь-якого додаткового проксі (наприклад, IP-діапазони CloudFront) до масиву довірених проксі.

Користувацькі заголовки при використанні зворотного проксі

Деякі зворотні проксі (на кшталт CloudFront з CloudFront-Forwarded-Proto) можуть змушувати вас використовувати користувацький заголовок. Наприклад, у вас є Custom-Forwarded-Proto замість X-Forwarded-Proto.

В такому випадку вам знадобиться встановити заголовок X-Forwarded-Proto зі значенням Custom-Forwarded-Proto достатньо рано у вашому додатку, тобто, перед обробкою запиту:

1
2
3
4
5
6
// public/index.php

// ...
$_SERVER['HTTP_X_FORWARDED_PROTO'] = $_SERVER['HTTP_CUSTOM_FORWARDED_PROTO'];
// ...
$response = $kernel->handle($request);