Вопрос или проблема
У меня есть сетевой балансировщик нагрузки, который перенаправляет трафик на контейнер Nginx, работающий в ECS (используя режим сети awsvpc). Моя конфигурация nginx выглядит следующим образом:
user nginx;
worker_processes 1;
error_log /var/log/nginx/error.log info;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
}
http {
server {
allow all;
listen 443 default ssl;
ssl_certificate /etc/nginx/ssl/cert.pem;
ssl_certificate_key /etc/nginx/ssl/privkey.pem;
ssl_trusted_certificate /etc/nginx/ssl/chain.pem;
ssl_prefer_server_ciphers on;
ssl_protocols TLSv1.2;
add_header Strict-Transport-Security "max-age=31536000";
access_log /var/log/nginx/access.log;
location / {
proxy_pass http://blahblahblah;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $remote_addr, $proxy_add_x_forwarded_for;
}
}
}
Однако, когда я смотрю логи, заголовок X-Forwarded-For не содержит “реальный” IP клиента, он просто содержит ряд внутренних IP (один из которых является внутренним IP сетевого балансировщика).
Я понимаю, что сетевой балансировщик нагрузки должен был сохранять “реальный” IP клиента как входящий IP, почему он не отображается в этом заголовке?
Сохранение исходного адреса – С помощью сетевого балансировщика нагрузки исходный IP-адрес и порты источника для входящих соединений остаются неизменными, поэтому программное обеспечение приложения не обязано поддерживать X-Forwarded-For, прокси-протокол или другие обходные пути. Это также означает, что можно использовать обычные правила межсетевого экрана, включая группы безопасности VPC, на целевых экземплярах.
nginx начал поддерживать PROXY-протокол v2 с версии 1.13.11, что произошло примерно через месяц после вашего вопроса. Я столкнулся с этой проблемой сегодня, поэтому, если это будет полезно для кого-то еще:
http {
#...
server {
listen 80 proxy_protocol;
listen 443 ssl proxy_protocol;
#...
}
}
stream {
#...
server {
listen 12345 proxy_protocol;
#...
}
}
Добавьте proxy_protocol
к вашему слушателю. Это позволит вашему nginx принимать подключения по Proxy Protocol V2.
Если вы используете AWS LB, вам необходимо включить Proxy protocol v2 в вашей группе целевых экземпляров:
(Опция “Сохранить IP-адреса клиентов” не кажется необходимой, $proxy_protocol_addr
отображается корректно в логах).
В вашем блоке location конфигурации nginx добавьте следующее:
real_ip_header X-Forwarded-For;
set_real_ip_from <вставьте IP-адрес балансировщика нагрузки>;
Вы можете найти IP-адрес ELB в разделе “Сетевые интерфейсы” в EC2.
Пример:
location ~ \.php$ {
........
real_ip_header X-Forwarded-For;
set_real_ip_from 10.0.1.192;
}
Ответ или решение
Чтобы получить "реальный" IP-адрес клиента в Nginx, работающем за сетевым балансировщиком нагрузки (NLB) AWS, необходимо правильно настроить Nginx для обработки заголовка X-Forwarded-For
и/или использовать протокол Proxy. Рассмотрим шаги, которые необходимо выполнить.
Шаг 1: Включение протокола Proxy
Для начала убедитесь, что ваш сервер Nginx настроен на принятие соединений через протокол Proxy. Это можно сделать, добавив proxy_protocol
в конфигурацию слушателей для портов 80 и 443 вашего Nginx, как показано ниже:
http {
server {
listen 80 proxy_protocol;
listen 443 ssl proxy_protocol;
ssl_certificate /etc/nginx/ssl/cert.pem;
ssl_certificate_key /etc/nginx/ssl/privkey.pem;
# Другие настройки...
}
}
Шаг 2: Включение поддержки протокола Proxy в Target Group NLB
После того, как вы добавили proxy_protocol
в конфигурацию Nginx, вам нужно убедиться, что в вашей группе целей (Target Group) NLB включена поддержка протокола Proxy. Для этого:
- Перейдите в консоль управления AWS.
- Найдите вашу группу целей.
- В настройках группы установите опцию для активации поддержки протокола Proxy V2.
Шаг 3: Настройка заголовка real_ip
Кроме того, вам нужно настроить Nginx так, чтобы он правильно обрабатывал заголовок X-Forwarded-For
. Добавьте следующие строки в ваш блок location
внутри конфигурации сервера:
location / {
proxy_pass http://blahblahblah;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# Настройка для получения реального IP клиента
real_ip_header X-Forwarded-For;
set_real_ip_from <IP-адрес вашего сетевого балансировщика>; # Укажите внутренний IP адрес вашего NLB
}
Шаг 4: Найдите внутренний IP-адрес NLB
Чтобы найти внутренний IP-адрес вашего сетевого балансировщика, выполните следующие шаги:
- Перейдите в консоль EC2 в раздел "Сетевые интерфейсы" (Network Interfaces).
- Найдите сетевой интерфейс, связанный с вашим NLB, и запишите его внутренний IP-адрес.
Пример полной конфигурации
Ниже приведен пример полной конфигурации Nginx с включением всех вышеуказанных шагов:
worker_processes 1;
error_log /var/log/nginx/error.log info;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
}
http {
server {
listen 80 proxy_protocol;
listen 443 ssl proxy_protocol;
ssl_certificate /etc/nginx/ssl/cert.pem;
ssl_certificate_key /etc/nginx/ssl/privkey.pem;
ssl_trusted_certificate /etc/nginx/ssl/chain.pem;
ssl_prefer_server_ciphers on;
ssl_protocols TLSv1.2;
add_header Strict-Transport-Security "max-age=31536000";
access_log /var/log/nginx/access.log;
location / {
proxy_pass http://blahblahblah;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# Получаем реальный IP
real_ip_header X-Forwarded-For;
set_real_ip_from <IP-адрес вашего сетевого балансировщика>;
}
}
}
Заключение
Следуя указанным шагам, вы сможете настроить Nginx для правильной обработки реального IP-адреса клиента, даже когда он находится за сетевым балансировщиком нагрузки AWS. Убедитесь, что вы проверили вашу конфигурацию и перезапустили Nginx для применения изменений.