1. 1
  2. 2
  3. 3
  4. 4
  5. 5
  6. 6

# конспект · шаг 6 из 6

Конспект: заголовки к бэкенду и realip

выжимка - её можно унести в заметки

Что бэкенд знает о клиенте - и почему по умолчанию почти ничего.

Что видит бэкенд без настройки

Что Значение по умолчанию Почему
Host app:8000 nginx подставляет $proxy_host из proxy_pass
IP клиента адрес nginx соединение открыл он
схема http между nginx и бэкендом TLS обычно нет

Четыре строки, которые пишут почти всегда

proxy_set_header Host              $host;
proxy_set_header X-Real-IP         $remote_addr;
proxy_set_header X-Forwarded-For   $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
клиент 203.0.113.9 → CDN 10.0.0.5 → nginx
пришло:  X-Forwarded-For: 203.0.113.9
уйдёт:   X-Forwarded-For: 203.0.113.9, 10.0.0.5

Без X-Forwarded-Proto приложение строит ссылки на http:// и получает бесконечный редирект за TLS-терминатором.

realip: сделать адрес настоящим

set_real_ip_from 10.0.0.5;        # адрес самого прокси, а не его подсеть
real_ip_header X-Forwarded-For;

После этого $remote_addr сам становится адресом клиента - и его же видят логи, limit_req и allow/deny. Настоящий адрес соединения остаётся в $realip_remote_addr, и в лог пишут оба.

X-Forwarded-For recursive off (умолчание) recursive on
203.0.113.9, 172.24.0.99 172.24.0.99 203.0.113.9
8.8.8.8, 9.9.9.9, 172.24.0.99 172.24.0.99 9.9.9.9

off берёт последний адрес цепочки - тот, что вписал твой прокси, подделать его нельзя. on идёт влево мимо доверенных и нужен, когда доверенных прокси перед nginx больше одного: тогда последний адрес цепочки - это адрес дальнего прокси. Список доверия - только точные адреса прокси.

CORS

Разрешение даёт Access-Control-Allow-Origin, источник в нём ровно один, флаг always обязателен. Непростые запросы предваряются OPTIONS, которому нужен успешный ответ (обычно 204) со списком методов, заголовков и Max-Age. Несколько источников разруливают картой с белым списком. Со звёздочкой браузер не отдаст скрипту ответ на запрос с куками - но простой запрос и куки на сервер уйдут; непростой без разрешения preflight не уйдёт вовсе.

Ловушки джокера

  • X-Forwarded-For - не доверенные данные. Клиент может прислать любой адрес, и он доедет до бэкенда даже без единой строки настройки. Доверенным его делает только set_real_ip_from.
  • real_ip_recursive on с широким списком доверия - дыра. Замер на цепочке из двух nginx: при списке 172.24.0.0/16 подделанный 8.8.8.8 попадает в логи, при списке из одного адреса прокси - нет.
  • Заголовки исчезают уровнем ниже. proxy_set_header наследуется всё или ничего: одна своя строка в location отменяет весь набор. Симптом - Host молча вернулся к app:8000. Лечится отдельным файлом и include.
  • В nginx 1.31.8 при HTTP/1.1 пустой Host возвращается к адресу из proxy_pass. Это поведение появилось в 1.31.4; старые версии проверяй отдельно. Остальные заголовки пустое значение убирает.
  • Место директив realip - http или server. В location подмена срабатывает не для всех фаз.
  • Без always CORS-заголовок пропадает на 4xx и 5xx, и ошибка приложения приходит во фронтенд как «CORS policy».

Комментарии

Пока нет комментариев. Будь первым!

Оставить комментарий

Комментарий появится после проверки. Email не публикуется. Войти, чтобы не вводить имя каждый раз.