# Лекция: Прямой и обратный прокси. Балансировка нагрузки ## Прямой прокси Представьте, что вы планируете проверить своё здоровье в многопрофильном медицинском центре, который регулярно посещаете. Но по какой‑то причине вы не желаете напрямую взаимодействовать с персоналом медучреждения. У вас есть личный помощник, который от вашего имени решает подобного рода задачи. По этой же причине медицинский персонал никогда не взаимодействует с вами напрямую, только с вашим помощником. В этом сценарии вас можно ассоциировать с ноутбуком, через который ищет информацию в интернете, а ваш личный помощник — это прокси‑сервер, который действует как посредник между вашей частной сетью, к которой подключён ноутбук, и общедоступным интернетом, куда отправляются ваши запросы. Прокси‑сервер защищает ноутбук, фильтруя трафик и блокируя вредоносные веб‑сайты и скрипты, прежде чем ответ будет перенаправлен обратно. Представим другой сценарий. В вашей компании работает много сотрудников и все они ходят в интернет. К примеру, один сотрудник из отдела маркетинга посещает какой‑то сомнительный веб‑ресурс, возможно вредоносный, и нажимает на ссылку, чтобы загрузить новый инструмент для презентаций. С этого сайта злоумышленники в качестве ответа отправляют на его компьютер вместе с загружаемым дистрибутивом ещё и вирус. Когда вредоносный контент проникнет во внутреннюю сеть через компьютер этого сотрудника, он может нанести реальный вред всей компании. Поэтому для защиты внутренней сети вы можете настроить весь интернет‑трафик всех компьютеров сотрудников так, что он будет проходить через прокси‑сервер, который станет «привратником» внутренней сети вашей организации. Вы можете внести в «чёрный список» любые веб‑сайты, которые должны быть недоступными для посещения сотрудниками компании. Он действует как щит между вашей частной сетью и общедоступным интернетом. А также он может регистрировать пользовательскую активность, чтобы показать, какие сайты посещают сотрудники. Прокси‑сервер имеет ещё одну важную функцию, которая заключается в кешировании ответов. Например, сотрудник компании открыл какое‑то видео на сайте и решил его посмотреть, тогда прокси сохранит его локально. И если другие сотрудники тоже захотят посмотреть это же видео, прокси отдаст кешированную копию вместо того, чтобы снова скачивать её. Таким образом он сэкономит пропускную способность и уменьшит лишний трафик, поступающий через интернет. Такой вид прокси называется **прямым прокси‑сервером (forward proxy)**. ## Обратный прокси Вернёмся к нашей аналогии с многопрофильным медицинским центром. Ваш личный помощник записал вас на проверку здоровья и вы приходите в клинику в назначенное время. Теперь вместо того, чтобы самостоятельно в огромном здании искать нужный кабинет, вы подходите к стойке регистрации. Администратор вас регистрирует, затем приглашает следовать за ним и приводит в нужный кабинет. В этой ситуации администратор — это тоже прокси, но на этот раз на принимающей запрос стороне. Сидит он в клинике в окружении всевозможных кабинетов (в нашем случае серверов) и управляет пациентами (входящими запросами), распределяя их по нужным врачам, этажам и кабинетам, проверяя загруженность и имея обзор всего внутреннего потока. Этот прокси, находящийся на серверной стороне и обрабатывающий входящие клиентские запросы, называется **обратным прокси‑сервером (реверсивным, reverse proxy)**. А равномерное распределение пациентов в клинике — это балансировка нагрузки, которая может быть одной из ключевых функций обратного прокси‑сервера. Обратные прокси решают большинство задач прямых прокси. Например, они действуют как щит. К примеру, когда у вас стоят сотни серверов и все они имеют доступ к конфиденциальным данным или коду, очень опасно предоставлять им прямой доступ в интернет. Поэтому вы просто помещаете один или несколько прокси‑серверов в качестве точек входа и настраиваете для них все меры безопасности. Обратные прокси будут сканировать запросы от внешних клиентов, шифровать трафик, проверять на наличие основных угроз или любых попыток взлома ваших систем, кешировать ответы и вести журнал событий. ## Балансировщик нагрузки Балансировка нагрузки — это лишь одна из множества функций обратного прокси‑сервера. Но многие из вас могут просить: «А что насчёт облачного балансировщика? Зачем нам нужны обратные прокси, когда у нас есть облачный балансировщик, является ли он заменой обратному прокси?» На практике в компаниях с обширными внутренними сетями лучше использовать оба решения. Облачный балансировщик нагрузки находится вне вашего контура и играет роль входной точки в вашу частную сеть, в то время как обратные прокси‑серверы будут маршрутизировать трафик внутри вашей сети. А балансировщик будет распределять нагрузку на обратные прокси‑серверы. Это улучшит защиту и масштабируемость вашей инфраструктуры. Вы, возможно, спросите: «А зачем мне дважды балансировать нагрузку на разных уровнях? Зачем мне нужно вешать это на внутренний прокси, если у меня уже есть балансировщик снаружи?» Обратный прокси‑сервер выполняет более «мелкодисперсную», так сказать, балансировку нагрузки на **прикладном (седьмом) уровне** модели OSI, которая позволит реализовать гораздо более интеллектуальную маршрутизацию к веб‑серверам. В то время как облачный балансировщик нагрузки распределяет трафик на основе более простых алгоритмов, чаще всего на **транспортном (четвёртом) уровне**. На обратном прокси‑сервере вы можете настроить более сложную логику маршрутизации на основе файлов cookie, URL, заголовков запроса. Например, чтобы все запросы от одного и того же пользователя всегда приходили на один и тот же веб‑сервер, обратный прокси будет проверять все связанные данные сеансов, cookie‑файлы и пересылать клиентские запросы на соответствующие серверы. Обратный прокси‑сервер также может обрабатывать прекращение SSL и TLS, и вы можете проверять зашифрованный трафик, чтобы принимать более обоснованные решения по балансировке нагрузки. Это особенно важно при микросервисной архитектуре с десятками и сотнями сервисов. В нашем сценарии медицинского центра это было бы эквивалентно тому, как если бы администратор, например, знал некоторых постоянных пациентов и выбирал для них наиболее удобную комбинацию процедур, или они могли сами выбирать эту последовательность, или администратор предложил бы им ещё «закрытые» акции с выгодными ценами на услуги, и т. д. Описанную схему целесообразно использовать в кластере Kubernetes с микросервисами. Там Ingress‑контроллер, который по сути является обратным прокси‑сервером для Kubernetes, обеспечивает внутреннюю маршрутизацию и безопасность. А облачный балансировщик выступает в качестве первой линии защиты, управляя внешним трафиком и частично фильтруя его, прежде чем он попадёт в кластер. --- # Дополнение: технические аспекты и сравнение прокси ## Различия между прямым и обратным прокси | Характеристика | Прямой прокси (Forward Proxy) | Обратный прокси (Reverse Proxy) | |----------------|--------------------------------|----------------------------------| | **Сторона расположения** | На стороне клиента (внутренняя сеть) | На стороне сервера (в DMZ или периметре) | | **Кто инициирует запросы** | Клиенты (например, компьютеры сотрудников) | Внешние клиенты из интернета | | **Основная цель** | Фильтрация исходящего трафика, анонимизация, кеширование контента | Защита внутренних серверов, балансировка нагрузки, SSL-терминация | | **Прозрачность для клиента** | Клиент часто знает о существовании прокси (настраивает браузер или систему) | Клиент обычно не знает о прокси; он обращается как к обычному серверу | | **Примеры ПО** | Squid, 3proxy, WinGate | Nginx, HAProxy, Apache httpd, Traefik, NPM | ## Дополнительные возможности прокси-серверов - **Аутентификация и авторизация**: Прямой прокси может требовать логин/пароль перед доступом в интернет. Обратный прокси может проверять JWT-токены или сертификаты клиентов. - **Логирование и аудит**: Оба типа прокси сохраняют детальные логи запросов (URL, время, IP-адрес, размер ответа), что необходимо для расследования инцидентов. - **Ограничение скорости (rate limiting)**: Защита от DDoS-атак и злоупотреблений. - **Транскодирование и модификация контента**: Прокси может сжимать изображения, переписывать HTML или добавлять заголовки безопасности (HSTS, CSP). --- # Практическая работа: Настройка Nginx Proxy Manager (NPM) в Docker Desktop ## Цель работы Настроить обратный прокси-сервер на базе Nginx Proxy Manager (NPM) в среде Docker Desktop. Создать прокси для локального веб-приложения, настроить автоматическое получение SSL-сертификата Let's Encrypt и убедиться в работе балансировки нагрузки (на простом примере). ## Необходимое программное обеспечение - **Docker Desktop** (Windows/macOS/Linux) – среда для запуска контейнеров. - **Любой веб-браузер** (для проверки). - **Два простых веб-сервера** для демонстрации балансировки – можно использовать стандартные образы `httpd` или `nginx` с разными index.html. ## Шаг 1. Установка Docker Desktop 1. Скачайте Docker Desktop с официального сайта: [https://www.docker.com/products/docker-desktop/](https://www.docker.com/products/docker-desktop/). 2. Установите, следуя инструкциям (на Windows потребуется включить WSL2 или Hyper-V). 3. После установки запустите Docker Desktop и убедитесь, что в терминале команда `docker --version` выполняется успешно. ## Шаг 2. Подготовка тестовых веб-серверов (для балансировки) Создадим два контейнера, которые будут имитировать бэкенд-серверы. Запустите в терминале: ```bash # Сервер 1 (на порту 8081) docker run -d --name web1 -p 8081:80 nginx:alpine docker exec web1 sh -c 'echo "Hello from Server 1" > /usr/share/nginx/html/index.html' # Сервер 2 (на порту 8082) docker run -d --name web2 -p 8082:80 nginx:alpine docker exec web2 sh -c 'echo "Hello from Server 2" > /usr/share/nginx/html/index.html' ``` Проверьте, что каждый сервер отвечает: откройте в браузере `http://localhost:8081` и `http://localhost:8082`. ## Шаг 3. Установка Nginx Proxy Manager (NPM) через Docker Compose Создайте директорию для проекта, например `npm-demo`, и внутри создайте файл `docker-compose.yml`: ```yaml version: '3.8' services: npm: image: 'jc21/nginx-proxy-manager:latest' restart: unless-stopped ports: - '80:80' # HTTP для прокси и получения сертификатов - '443:443' # HTTPS для прокси - '81:81' # Веб-интерфейс управления NPM environment: DB_SQLITE_FILE: "/data/database.sqlite" volumes: - ./data:/data - ./letsencrypt:/etc/letsencrypt ``` Запустите контейнер: ```bash docker-compose up -d ``` Дождитесь загрузки образа и запуска контейнера. ## Шаг 4. Первоначальная настройка NPM 1. Откройте браузер и перейдите по адресу: `http://localhost:81`. 2. Вход по умолчанию: - **Email**: `admin@example.com` - **Password**: `changeme` 3. Система сразу попросит сменить пароль и указать свои email/имя пользователя. Сделайте это. 4. Вы попадёте в панель управления NPM. ## Шаг 5. Настройка обратного прокси для одного сервера (прямой прокси-эффект для исходящих?) > Примечание: NPM – это прежде всего обратный прокси. Для прямого прокси обычно используют Squid. Но в данной практике мы сосредоточимся на reverse proxy, который является продолжением лекции. Допустим, мы хотим, чтобы внешний запрос по адресу `http://localhost` (или домену, если вы используете реальный) направлялся на `http://web1:80` внутри сети Docker. ### 5.1. Добавление Proxy Host В интерфейсе NPM: - Перейдите в раздел **Proxy Hosts**. - Нажмите **Add Proxy Host**. - Заполните поля: - **Domain Names**: `localhost` (или `test.local`, если настроите локальный DNS или файл hosts). - **Forward Hostname / IP**: `web1` (имя контейнера, так как NPM и web1 в одной сети Docker по умолчанию – сеть `npm-demo_default`). Если web1 запущен на хосте, укажите `host.docker.internal` (Windows/Mac) или IP-адрес. - **Forward Port**: `80`. - Остальное оставьте по умолчанию. Нажмите **Save**. Теперь при обращении к `http://localhost` (через порт 80) NPM перенаправит запрос на web1. ### 5.2. Настройка SSL (если есть реальный домен) Если у вас есть домен, делегированный на IP вашего компьютера (например, `proxy-test.example.com`), можно получить бесплатный сертификат Let's Encrypt: - В том же окне редактирования Proxy Host перейдите на вкладку **SSL**. - Включите **Force SSL** (перенаправление HTTP → HTTPS). - Выберите **Request a new SSL Certificate**. - Укажите email, согласитесь с условиями. - Нажмите **Save**. Сертификат будет получен автоматически. Для локальной разработки (localhost) Let's Encrypt не выдаёт сертификаты, поэтому можно использовать самоподписанный или тестовый. ## Шаг 6. Настройка балансировки нагрузки (два сервера) NPM не имеет встроенного round-robin балансировщика как HAProxy, но можно использовать upstream-блок через кастомную конфигурацию Nginx. Однако NPM позволяет задать **несколько backend-серверов** в поле Forward Hostname/IP с разделителями? Нет, стандартный интерфейс принимает только один адрес. Для полноценной балансировки лучше использовать конфигурацию Nginx напрямую. Тем не менее, в учебных целях можно настроить **два разных proxy host** на разные поддомены или пути. Альтернативно, покажем балансировку через **custom location**: 1. В разделе **Proxy Hosts** выберите созданный хост `localhost`. 2. Перейдите на вкладку **Advanced**. 3. В поле "Custom Nginx Configuration" добавьте: ```nginx upstream backend { server web1:80; server web2:80; } server { listen 80; server_name localhost; location / { proxy_pass http://backend; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; } } ``` **Важно**: Такая конфигурация переопределит настройки из интерфейса. Сохраните изменения. Теперь NPM будет распределять запросы между web1 и web2 по алгоритму round-robin (по умолчанию). Проверьте: многократно обновляя страницу `http://localhost`, вы должны видеть чередование "Hello from Server 1" и "Hello from Server 2". ## Шаг 7. Настройка кеширования (демонстрация) Nginx (и NPM) поддерживает кеширование ответов. Добавим простой кеш для статики. В том же custom location (или в отдельном proxy host) добавьте: ```nginx proxy_cache_path /var/cache/nginx levels=1:2 keys_zone=my_cache:10m max_size=1g inactive=60m use_temp_path=off; server { ... location / { proxy_cache my_cache; proxy_cache_valid 200 302 60m; proxy_cache_valid 404 1m; proxy_pass http://backend; } } ``` Убедитесь, что директория для кеша существует в контейнере (смонтирован том). Для простоты можно опустить, так как цель – показать возможность. ## Шаг 8. Проверка логирования и фильтрации 1. В интерфейсе NPM перейдите в раздел **Access Lists**. 2. Создайте новый Access List, например `BlockBadIPs`. Добавьте правило **Deny** для IP `192.168.1.100` (фиктивный пример). 3. Привяжите этот список к вашему Proxy Host вкладка **Access List** -> выберите созданный список. 4. Проверьте: если запрос приходит с запрещённого IP, прокси вернёт 403. Логи доступа и ошибок хранятся в контейнере NPM. Посмотреть их можно так: ```bash docker logs npm-demo_npm_1 ``` Или зайдите в файловую систему контейнера через `docker exec -it npm-demo_npm_1 sh` и посмотрите `/data/logs`. ## Шаг 9. Очистка (после практики) ```bash docker stop web1 web2 docker rm web1 web2 # В папке с docker-compose.yml: docker-compose down -v ``` ## Результат выполнения практики Студент должен предоставить: - Скриншот работающего интерфейса NPM (порт 81) с добавленным Proxy Host. - Скриншот успешного получения SSL-сертификата (если использовался домен) или подтверждение работы HTTP-прокси на `localhost`. - Скриншот чередования ответов от двух серверов при балансировке (5-10 обновлений страницы). - Вывод команды `docker logs` с записью о проксировании хотя бы одного запроса.