28

Почему Nginx пишет IP прокси вместо IP клиента

Сидишь за reverse proxy, CDN или балансировщиком - открываешь access-лог, а там один и тот же IP на всех запросах. Обычно 127.0.0.1, адрес ingress-контроллера или внутренний IP прокси.

На этом фоне ломаются rate limiting, fail2ban, аудит и любые расследования: Nginx честно пишет адрес своего непосредственного соседа, а не исходного клиента.

Почему так.

$remote_addr - это адрес узла, который напрямую установил соединение с Nginx. Если перед ним стоит прокси, то для Nginx клиентом является именно прокси.

Настоящий IP пользователя обычно приезжает отдельно:

  • в X-Real-IP;

  • в X-Forwarded-For;

  • в заголовке конкретного CDN;

  • через PROXY protocol, если перед нами L4-балансировщик.

Но просто взять значение HTTP-заголовка и записать его в лог - плохая идея:

log_format main '$http_x_real_ip - $request';

Любой клиент может сам отправить:

X-Real-IP: 1.1.1.1

и подложить в ваши логи произвольный адрес.

Правильная схема - не доверять заголовку самому по себе, а доверять конкретному прокси, который этот заголовок формирует.

Для этого в Nginx есть штатный ngx_http_realip_module.

Проверяем, собран ли он в текущем бинарнике:

nginx -V 2>&1 | tr ' ' '\n' | grep -- --with-http_realip_module

Если Nginx собираете сами, понадобится флаг:

--with-http_realip_module

В пакетах популярных дистрибутивов модуль обычно уже включён, но проверять лучше конкретный установленный бинарник.

Настраиваем доверенный прокси:

set_real_ip_from 10.42.0.10;

set_real_ip_from 10.42.0.11;

real_ip_header X-Real-IP;

После этого Nginx будет заменять $remote_addr адресом из X-Real-IP, но только если соединение пришло от узла из set_real_ip_from.

Важно: указывайте точные адреса или минимальную подсеть балансировщиков.

Вот так делать нежелательно:

set_real_ip_from 10.0.0.0/8;

Этой настройкой вы разрешаете любому узлу из всей сети 10.0.0.0/8 подменять клиентский IP. Лучше доверять конкретным адресам прокси или выделенному сегменту.

Сам origin при этом желательно закрыть от прямого доступа извне через firewall, security group или network policy. Иначе клиент сможет обойти прокси и прийти непосредственно к Nginx.

На самом прокси X-Real-IP должен перезаписываться, а не слепо передаваться от клиента:

proxy_set_header X-Real-IP $remote_addr;

Не так:

proxy_set_header X-Real-IP $http_x_real_ip;

Во втором случае прокси просто протащит значение, которое прислал пользователь.

В чём ловушка с X-Forwarded-For

Этот заголовок содержит цепочку адресов через запятую:

X-Forwarded-For: client, proxy-1, proxy-2

Если в инфраструктуре несколько доверенных прокси, можно настроить Nginx так:

set_real_ip_from 10.42.0.10;

set_real_ip_from 10.42.0.11;

real_ip_header X-Forwarded-For;

real_ip_recursive on;

Тогда Nginx будет разбирать цепочку справа налево, пропуская доверенные адреса из set_real_ip_from, и выберет последний недоверенный адрес.

Например:

X-Forwarded-For: 1.1.1.1, 203.0.113.25, 10.42.0.10

Если 10.42.0.10 - доверенный внутренний прокси, а 203.0.113.25 - адрес клиента, добавленный доверенным edge-прокси, Nginx выберет 203.0.113.25, а не подставленный пользователем 1.1.1.1.

Но это работает безопасно только тогда, когда вся доверенная цепочка прокси известна и перечислена в set_real_ip_from.

После обработки модулем:

  • $remote_addr - восстановленный адрес клиента;

  • $realip_remote_addr - исходный адрес узла, который подключился к Nginx;

  • $http_x_forwarded_for - заголовок в том виде, в котором он приехал.

Для диагностики удобно логировать всё сразу:

log_format main

'client=$remote_addr '

'peer=$realip_remote_addr '

'xff="$http_x_forwarded_for" '

'request="$request" '

'status=$status';

Так можно понять не только какой IP выбрал Nginx, но и от какого прокси пришло соединение и какую цепочку тот передал.

Rate limiting после этого тоже сможет работать по реальному клиентскому адресу - если ключ зоны построен на $remote_addr или $binary_remote_addr:

limit_req_zone $binary_remote_addr

zone=per_ip:10m

rate=10r/s;

Использовать для лимитов сырой $http_x_forwarded_for не стоит: это строка с цепочкой адресов, которую при неправильной настройке прокси можно подделать или постоянно менять.

С fail2ban та же логика: он увидит реальный адрес только в том случае, если анализирует поле лога, в котором записан обработанный $remote_addr.

Если перед Nginx стоит TCP-балансировщик, HTTP-заголовков может не быть вообще. Тогда обычно используется PROXY protocol:

server {

listen 443 ssl proxy_protocol;

set_real_ip_from 10.42.0.10;

real_ip_header proxy_protocol;

}

PROXY protocol также нельзя принимать от кого угодно: источник соединения должен быть ограничен доверенными балансировщиками.

После изменения конфигурации:

nginx -t && systemctl reload nginx

Проверяем:

tail -f /var/log/nginx/access.log

Смотрим одновременно на client, peer и xff. Проверка только первого поля лога мало что доказывает: важно видеть всю цепочку и понимать, почему Nginx выбрал именно этот адрес.

Очень краткий вывод

Не доверяйте заголовку с IP.
Доверяйте конкретному прокси, который этот заголовок сформировал.

Лига Сисадминов

2.7K постов19.2K подписчика

Правила сообщества

Мы здесь рады любым постам связанным с рабочими буднями специалистов нашей сферы деятельности.

Темы

Политика

Теги

Популярные авторы

Сообщества

18+

Теги

Популярные авторы

Сообщества

Игры

Теги

Популярные авторы

Сообщества

Юмор

Теги

Популярные авторы

Сообщества

Отношения

Теги

Популярные авторы

Сообщества

Здоровье

Теги

Популярные авторы

Сообщества

Путешествия

Теги

Популярные авторы

Сообщества

Спорт

Теги

Популярные авторы

Сообщества

Хобби

Теги

Популярные авторы

Сообщества

Сервис

Теги

Популярные авторы

Сообщества

Природа

Теги

Популярные авторы

Сообщества

Бизнес

Теги

Популярные авторы

Сообщества

Транспорт

Теги

Популярные авторы

Сообщества

Общение

Теги

Популярные авторы

Сообщества

Юриспруденция

Теги

Популярные авторы

Сообщества

Наука

Теги

Популярные авторы

Сообщества

IT

Теги

Популярные авторы

Сообщества

Животные

Теги

Популярные авторы

Сообщества

Кино и сериалы

Теги

Популярные авторы

Сообщества

Экономика

Теги

Популярные авторы

Сообщества

Кулинария

Теги

Популярные авторы

Сообщества

История

Теги

Популярные авторы

Сообщества

Недвижимость и ремонт

Теги

Популярные авторы

Сообщества