Имеется N серверов nginx в режиме обратного прокси, за которыми находится приложение, отвечающее по HTTP.
Требования:
- Приложение должно получать в заголовке
X-Forwarded-Forцепочку всех IP-адресов — клиента и всех пройденных nginx. - Злоумышленник не должен иметь возможности подменить или подсунуть свой
X-Forwarded-For. - Решение должно быть реализовано с использованием
docker-composeи включать минимум 3 nginx и приложение. - Протокол тестирования с использованием
curl.
- nginx1, nginx2, nginx3 — три прокси-сервера, соединённые в одну Docker-сеть.
- app — Flask-приложение, отображающее заголовки запроса.
Возможны следующие сценарии:
- Прямой запрос к одному nginx → приложение
- Цепочка: nginx1 → nginx2 → nginx3 → приложение
- Комбинации с произвольным стартом и продолжением
Расположено в ./app/app.py. Выводит:
X-Forwarded-For— цепочка проксиX-Real-IP— не используется (для безопасности)remote_addr— адрес последнего прокси с точки зрения Flask- Полный список заголовков
Ключевые элементы:
map $http_first_nginx $set_first_header {
"" "true"; # Если заголовка нет — это первый nginx
default "false";
}map $http_x_proxy_chain $already_proxied {
"~$server_addr" "true";
default "false";
}set $x_forwarded_for $proxy_add_x_forwarded_for;
if ($set_first_header = "true") {
set $first_nginx "$server_addr";
set $x_forwarded_for "$remote_addr"; # Игнорируем внешний X-Forwarded-For
}
proxy_set_header X-Forwarded-For $x_forwarded_for;
proxy_set_header First-nginx "$first_nginx";Таким образом, если клиент подаст свой X-Forwarded-For, он будет проигнорирован.
upstream backend_servers {
server nginx1:80;
server nginx2:80;
server nginx3:80;
server app:8000;
}
if ($already_proxied = "true") {
set $target_upstream "app:8000"; # Прекращаем цепочку
}docker-compose up --buildПриложение будет доступно через:
http://localhost:8081— nginx1http://localhost:8082— nginx2http://localhost:8083— nginx3- Напрямую:
http://localhost:8000
curl -s http://localhost:8081Ожидаемый результат:
X-Forwarded-For (chain): 172.20.0.1
Где
172.20.0.1— IP Docker-клиента. ВнешнийX-Forwarded-Forпроигнорирован.
curl -H "X-Forwarded-For: 1.2.3.4" http://localhost:8081Ожидаемый результат:
X-Forwarded-For (chain): 172.20.0.1
Поддельный заголовок проигнорирован — безопасность обеспечена.
curl -H "First-nginx: " http://localhost:8081/?via=nginx2На данный момент автоматическая цепочка не поддерживается напрямую через URL. Для тестирования цепочек можно настроить
proxy_passмежду nginx вручную.
Альтернативный сценарий:
Можно отправить запрос на nginx1, который проксирует на nginx2, а тот — на nginx3, и далее в приложение. Для этого требуется предварительная настройка маршрутов.
Логи nginx показывают формирование заголовков:
172.20.0.1 - localhost "X-Forwarded-For: 172.20.0.1"
- Заголовок
X-Forwarded-Forкорректно формируется с нуля, игнорируя клиентский. - Поддерживается возможность построения цепочки прокси. <<<<<<< HEAD
- Решение безопасно, прозрачно и масштабируемо.
Примерно 1 час. Фактически 8, изза отсутствия практики.
Спасибо за задание! Будут еще - присылайте