245 lines
26 KiB
Markdown
245 lines
26 KiB
Markdown
# Лекция: Прямой и обратный прокси. Балансировка нагрузки
|
||
|
||
## Прямой прокси
|
||
|
||
Представьте, что вы планируете проверить своё здоровье в многопрофильном медицинском центре, который регулярно посещаете. Но по какой‑то причине вы не желаете напрямую взаимодействовать с персоналом медучреждения. У вас есть личный помощник, который от вашего имени решает подобного рода задачи. По этой же причине медицинский персонал никогда не взаимодействует с вами напрямую, только с вашим помощником. В этом сценарии вас можно ассоциировать с ноутбуком, через который ищет информацию в интернете, а ваш личный помощник — это прокси‑сервер, который действует как посредник между вашей частной сетью, к которой подключён ноутбук, и общедоступным интернетом, куда отправляются ваши запросы. Прокси‑сервер защищает ноутбук, фильтруя трафик и блокируя вредоносные веб‑сайты и скрипты, прежде чем ответ будет перенаправлен обратно.
|
||
|
||
Представим другой сценарий. В вашей компании работает много сотрудников и все они ходят в интернет. К примеру, один сотрудник из отдела маркетинга посещает какой‑то сомнительный веб‑ресурс, возможно вредоносный, и нажимает на ссылку, чтобы загрузить новый инструмент для презентаций. С этого сайта злоумышленники в качестве ответа отправляют на его компьютер вместе с загружаемым дистрибутивом ещё и вирус. Когда вредоносный контент проникнет во внутреннюю сеть через компьютер этого сотрудника, он может нанести реальный вред всей компании.
|
||
|
||
Поэтому для защиты внутренней сети вы можете настроить весь интернет‑трафик всех компьютеров сотрудников так, что он будет проходить через прокси‑сервер, который станет «привратником» внутренней сети вашей организации. Вы можете внести в «чёрный список» любые веб‑сайты, которые должны быть недоступными для посещения сотрудниками компании. Он действует как щит между вашей частной сетью и общедоступным интернетом. А также он может регистрировать пользовательскую активность, чтобы показать, какие сайты посещают сотрудники.
|
||
|
||
Прокси‑сервер имеет ещё одну важную функцию, которая заключается в кешировании ответов. Например, сотрудник компании открыл какое‑то видео на сайте и решил его посмотреть, тогда прокси сохранит его локально. И если другие сотрудники тоже захотят посмотреть это же видео, прокси отдаст кешированную копию вместо того, чтобы снова скачивать её. Таким образом он сэкономит пропускную способность и уменьшит лишний трафик, поступающий через интернет.
|
||
|
||
Такой вид прокси называется **прямым прокси‑сервером (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` с записью о проксировании хотя бы одного запроса.
|
||
|