760 lines
31 KiB
Markdown
760 lines
31 KiB
Markdown
# Архитектура Magos
|
||
|
||
## Обзор системы
|
||
|
||
**Magos** - это система управления WAF (Web Application Firewall) контейнерами на базе Nginx/Angie, которая:
|
||
|
||
- Автоматически разворачивает и управляет Docker-контейнерами с Nginx
|
||
- Настраивает балансировщик Angie для распределения трафика
|
||
- Интегрируется с API ServicePipe для получения конфигурации
|
||
- Поддерживает graceful shutdown при масштабировании и миграции
|
||
- Обеспечивает изоляцию клиентов через отдельные контейнеры
|
||
- Поддерживает два WAF-вендора: **PTAF** (Docker-контейнеры) и **SW/SolidWall** (нативный процесс)
|
||
|
||
### Ключевые особенности:
|
||
|
||
- **Многоклиентовая архитектура** - каждый клиент имеет свои контейнеры
|
||
- **Поддержка двух вендоров** - PTAF (Docker) и SolidWall (нативный nginx)
|
||
- **Динамическое управление портами** - автоматическое выделение портов из пулов с учётом всех состояний сокетов
|
||
- **Кэширование данных** - минимизация обращений к API
|
||
- **Failover БД** - автоматическое переключение между primary/secondary
|
||
- **Graceful draining** - безопасное удаление контейнеров без потери трафика
|
||
- **Умный lock-файл** - автоматическая очистка при падении процесса
|
||
|
||
---
|
||
|
||
## Компоненты системы
|
||
|
||
### 1. Основные файлы программы
|
||
|
||
```
|
||
main.go # Точка входа, основной цикл обработки
|
||
config.go # Управление конфигурацией
|
||
db.go # Работа с PostgreSQL
|
||
api.go # Интеграция с ServicePipe API
|
||
types.go # Структуры данных
|
||
utils.go # Утилиты и вспомогательные функции
|
||
```
|
||
|
||
### 2. Управление контейнерами
|
||
|
||
```
|
||
containers_part1.go # Создание и настройка контейнеров
|
||
containers_part2.go # Управление жизненным циклом контейнеров
|
||
drain.go # Graceful shutdown и миграция
|
||
```
|
||
|
||
### 3. Генерация конфигураций
|
||
|
||
```
|
||
nginx.go # Генерация конфигов Nginx и Angie
|
||
ports.go # Управление портами
|
||
ptaf_processor.go # Обработка PTAF-клиентов
|
||
sw_processor.go # Обработка SW/SolidWall-клиентов
|
||
```
|
||
|
||
---
|
||
|
||
## Поддерживаемые WAF-вендоры
|
||
|
||
### PTAF (Positive Technologies Application Firewall)
|
||
|
||
**Схема проксирования:**
|
||
```
|
||
Клиент → Angie (хост) → Docker-контейнер (PTAF nginx) → Origin
|
||
```
|
||
|
||
- Контейнеры поднимаются через docker-compose
|
||
- Angie — фронтенд-балансировщик, конфиги в `/etc/angie/http.d/angie-ptaf-{clientTitle}.conf`
|
||
- Nginx внутри контейнера — WAF-агент, конфиги в `/home/install/conf/ptaf-nginx/`
|
||
- Порты выделяются автоматически из диапазонов 18000-20999 (HTTP) и 21000-23999 (HTTPS)
|
||
|
||
### SW / SolidWall
|
||
|
||
**Схема проксирования:**
|
||
```
|
||
Клиент → solidwall-nginx (WAF, публичный) → solidwall-nginx (внутренний) → Origin
|
||
```
|
||
|
||
- Работает без Docker, напрямую на хосте
|
||
- Двойное проксирование через внутренние порты 8000 (HTTP) и 9000 (HTTPS)
|
||
- Конфиги: `/etc/solidwall-nginx/sites-available/solidwall-{clientTitle}-{l7ResourceID}.conf`
|
||
- Симлинки в `sites-enabled/`
|
||
- Утилита **не трогает**: `nginx.conf`, директорию `ssl/`, `default.conf`
|
||
|
||
---
|
||
|
||
## Архитектура данных
|
||
|
||
### База данных PostgreSQL
|
||
|
||
#### Таблица `instances_new`
|
||
Связь hostname → instance (waf_instance)
|
||
|
||
```sql
|
||
hostname | instance
|
||
------------|------------
|
||
waf-host-01 | instance-a
|
||
waf-host-01 | instance-b
|
||
waf-host-02 | instance-c
|
||
```
|
||
|
||
#### Таблица `client_info`
|
||
Основная информация о клиентах
|
||
|
||
```sql
|
||
Поля:
|
||
- client_title # Уникальный идентификатор клиента
|
||
- containers_count # Количество контейнеров (0 = drain всех)
|
||
- ptaf_config # Строка подключения к PTAF-серверу (CONNECTION_STRING)
|
||
- fluent_bit_port # Порт для FluentBit логирования
|
||
- waf_instance # Instance для привязки к хосту
|
||
- docker_image # Docker-образ для контейнеров клиента (переопределяет глобальный)
|
||
- docker_image_download # URL для скачивания образа
|
||
- debug # Режим отладки (bool, влияет на лог-уровень)
|
||
- shm_size # Размер /dev/shm в GB (дефолт: 1)
|
||
```
|
||
|
||
**Важно:** `waf_instance` определяет на каком хосте должен работать клиент
|
||
|
||
**containers_count = 0:** все контейнеры клиента помечаются для drain, Angie-конфиг удаляется
|
||
|
||
#### Таблица `apps_settings`
|
||
Настройки каждого L7 ресурса (домена)
|
||
|
||
```sql
|
||
Основные поля:
|
||
- l7resourceid # ID ресурса из ServicePipe API
|
||
- client_title # Связь с client_info
|
||
- waf_enabled # Включен ли WAF
|
||
- waf_vendor # 'ptaf' или 'sw'
|
||
- mode # auto/manual/disabled
|
||
|
||
Порты:
|
||
- custom_input_http_ports[] # HTTP порты для прослушивания (Angie/SW)
|
||
- custom_input_https_ports[] # HTTPS порты для прослушивания (Angie/SW)
|
||
- custom_output_http_ports[] # HTTP порты для проксирования к origin
|
||
- custom_output_https_ports[] # HTTPS порты для проксирования к origin
|
||
|
||
Кастомизация Nginx (PTAF):
|
||
- upstream_nginx_custom # Кастомные upstream директивы
|
||
- server_nginx_custom # Кастомный server блок / SERVER_BLOCK
|
||
- location_nginx_custom # Кастомные location директивы
|
||
- server_directives_nginx_custom # Дополнительные server директивы
|
||
|
||
Кастомизация Angie:
|
||
- upstream_angie_custom # Кастомные upstream директивы
|
||
- server_angie_custom # Кастомный server блок / SERVER_BLOCK
|
||
- location_angie_custom # Кастомные location директивы
|
||
- server_directives_angie_custom # Дополнительные server директивы
|
||
- custom_angie_ssl # Полная замена SSL директив
|
||
- custom_sw_nginx_ssl # Кастомные SSL директивы для SW
|
||
|
||
Специальные настройки:
|
||
- sni # 0 = keepalive on, 1 = keepalive off
|
||
- ssl_enabled # true/false (по умолчанию true)
|
||
- max_fails # Попыток до пометки сервера недоступным (дефолт 5)
|
||
- fail_timeout # Время восстановления сервера (дефолт 15с)
|
||
- balancing_method # Метод балансировки: least_conn, ip_hash, random и др.
|
||
- proxy_next_upstream_codes # HTTP-коды для proxy_next_upstream (дефолт: 500,502,503,504)
|
||
- ptaf_fallback_code # Код ответа ptaf_fallback: число или 'pass' (дефолт: 418)
|
||
```
|
||
|
||
#### Таблица `sp_info` (кэш API данных)
|
||
Кэширует данные из ServicePipe API
|
||
|
||
```sql
|
||
Поля:
|
||
- sid # l7resourceid
|
||
- domain_name # Основной домен
|
||
- aliases # JSON массив алиасов
|
||
- origins # JSON массив origin серверов
|
||
- updated_at # Timestamp обновления
|
||
```
|
||
|
||
**TTL кэша:** 10 минут
|
||
|
||
#### Таблица `manual_info`
|
||
Ручное управление (альтернатива API)
|
||
|
||
```sql
|
||
Поля:
|
||
- sid # l7resourceid
|
||
- domain_name # Основной домен
|
||
- aliases # JSON массив алиасов
|
||
- origins # JSON массив origin серверов
|
||
```
|
||
|
||
**Примечание:** Данные из `manual_info` не имеют TTL и всегда актуальны
|
||
|
||
#### Таблица `ips`
|
||
Настройки IP сетей
|
||
|
||
```sql
|
||
Поля:
|
||
- id (always = 1)
|
||
- antibot_networks[] # Массив CIDR для antibot
|
||
- waf_networks[] # Массив CIDR для WAF (фильтруются из origins)
|
||
```
|
||
|
||
---
|
||
|
||
## Процесс работы
|
||
|
||
### 1. Инициализация
|
||
|
||
```go
|
||
main() → initConfig() → connectToDB()
|
||
```
|
||
|
||
**Шаги:**
|
||
1. Создание lock-файла `/var/lock/ptaf-main.lock` с PID (умная проверка — автоматически удаляет если процесс уже не существует)
|
||
2. Подключение к БД (primary → secondary fallback)
|
||
3. Загрузка IP сетей из таблицы `ips`
|
||
4. Получение hostname текущего сервера
|
||
5. Определение instances для этого хоста
|
||
6. Для PTAF-хостов: проверка/скачивание Docker-образов (по одному на клиента)
|
||
|
||
### 2. Основной цикл обработки
|
||
|
||
```
|
||
┌─────────────────────────────────────────┐
|
||
│ Глобальная проверка drain-контейнеров │
|
||
│ (processAllDrainingContainersGlobally) │
|
||
└─────────────────────────────────────────┘
|
||
↓
|
||
┌─────────────────────────────────────────┐
|
||
│ Для каждого instance на этом хосте │
|
||
└─────────────────────────────────────────┘
|
||
↓
|
||
┌─────────────────────────────────────────┐
|
||
│ Получить всех клиентов для instance │
|
||
│ (getClientInfoByInstance) │
|
||
└─────────────────────────────────────────┘
|
||
↓
|
||
┌─────────────────────────────────────────┐
|
||
│ Определить vendor (ptaf/sw) │
|
||
│ → processPTAFClient / processSWClient │
|
||
└─────────────────────────────────────────┘
|
||
↓
|
||
┌─────────────────────────────────────────┐
|
||
│ Финальная проверка drain Angie-конфигов│
|
||
│ (processDrainingAngieConfigs) │
|
||
└─────────────────────────────────────────┘
|
||
```
|
||
|
||
### 3. Обработка PTAF-клиента
|
||
|
||
```
|
||
1. Проверка принадлежности хоста к WAF instance
|
||
├─ Не принадлежит → handleClientMigration (drain всех контейнеров + Angie конфига)
|
||
└─ Принадлежит → продолжаем
|
||
|
||
2. containers_count = 0?
|
||
└─ Да → drain всех контейнеров + Angie конфига, выход
|
||
|
||
3. cleanStaleDrainMarkers — очистка устаревших маркеров
|
||
|
||
4. fetchPTAFResourcesData — получение данных ресурсов из API/кеша
|
||
|
||
5. resolvePortsForClient — загрузка/выделение портов
|
||
├─ .ports.json существует → переиспользуем порты
|
||
├─ Scale up → сохраняем старые порты, добавляем новые
|
||
└─ Нет файла → выделяем все заново
|
||
|
||
6. generateAngieConfigsWithoutReload — генерация Angie конфига
|
||
|
||
7. setupContainers — генерация конфигов и управление контейнерами
|
||
├─ Запущен недавно, порты не слушают → пересоздаём
|
||
├─ Compose изменился → пересоздаём
|
||
├─ Конфиг изменился → nginx -s reload
|
||
└─ Новый → запускаем (с ожиданием освобождения портов)
|
||
|
||
8. Проверка портов → reload Angie если нужно
|
||
|
||
9. processDrainingContainers — drain лишних контейнеров
|
||
```
|
||
|
||
### 4. Обработка SW-клиента
|
||
|
||
```
|
||
1. Проверка принадлежности хоста к WAF instance
|
||
└─ Не принадлежит → пропускаем (миграция не реализована для SW)
|
||
|
||
2. Создание директорий: sites-available, sites-enabled, /var/log/solidwall
|
||
|
||
3. Для каждого ресурса:
|
||
- Генерация конфига solidwall-{clientTitle}-{l7ResourceID}.conf
|
||
- Создание симлинка в sites-enabled
|
||
|
||
4. solidwall-nginx -t + solidwall-nginx -s reload (если конфиги изменились)
|
||
```
|
||
|
||
### 5. Сбор данных о ресурсах
|
||
|
||
Для каждого ресурса определяется режим работы через поле `mode`:
|
||
|
||
#### Режим `auto` (по умолчанию)
|
||
```
|
||
1. Проверка кэша sp_info (TTL 10 мин)
|
||
├─ Данные свежие → использовать
|
||
└─ Данные устарели → API запрос
|
||
2. API запросы (с retry × 3):
|
||
├─ GET /l7/resource/{id}/global → domain_name
|
||
├─ GET /l7/alias/global?l7ResourceId={id} → aliases
|
||
└─ GET /l7/origin/global?l7ResourceId={id} → origins
|
||
3. Фильтрация origins (удалить WAF IP)
|
||
4. Сохранение в sp_info
|
||
```
|
||
|
||
#### Режим `manual`
|
||
```
|
||
1. Чтение из таблицы manual_info
|
||
2. Фильтрация origins (удалить WAF IP)
|
||
3. API и кэш игнорируются
|
||
```
|
||
|
||
#### Режим `disabled`
|
||
```
|
||
Ресурс полностью пропускается
|
||
```
|
||
|
||
---
|
||
|
||
## Управление портами
|
||
|
||
### Диапазоны портов
|
||
|
||
```go
|
||
const (
|
||
HTTPPortStart = 18000 // HTTP: 18000-20999 (3000 портов)
|
||
HTTPPortEnd = 20999
|
||
HTTPSPortStart = 21000 // HTTPS: 21000-23999 (3000 портов)
|
||
HTTPSPortEnd = 23999
|
||
)
|
||
```
|
||
|
||
**Важно:** На хостах необходимо зарезервировать этот диапазон чтобы ядро не использовало его для исходящих ephemeral-соединений:
|
||
```bash
|
||
sysctl -w net.ipv4.ip_local_reserved_ports=18000-23999
|
||
```
|
||
|
||
### Алгоритм выделения портов
|
||
|
||
```
|
||
┌────────────────────────────────────────────────┐
|
||
│ 1. Получить занятые порты (ss -tuanl) │
|
||
│ Включает: LISTEN, ESTAB, TIME-WAIT │
|
||
└────────────────────────────────────────────────┘
|
||
↓
|
||
┌────────────────────────────────────────────────┐
|
||
│ 2. Загрузить сохраненные порты │
|
||
│ из .ports.json (если есть) │
|
||
│ ├─ Scale up → сохранить старые, добавить │
|
||
│ └─ Нет файла → выделить все заново │
|
||
└────────────────────────────────────────────────┘
|
||
↓
|
||
┌────────────────────────────────────────────────┐
|
||
│ 3. Для каждого ресурса × контейнера: │
|
||
│ - Определить нужные порты │
|
||
│ - Выделить свободные Docker порты │
|
||
└────────────────────────────────────────────────┘
|
||
↓
|
||
┌────────────────────────────────────────────────┐
|
||
│ 4. Сохранить в .ports.json │
|
||
└────────────────────────────────────────────────┘
|
||
```
|
||
|
||
### Структура портов
|
||
|
||
```go
|
||
type PortMapping struct {
|
||
HTTPPorts map[int]int // map[customPort]dockerPort
|
||
HTTPSPorts map[int]int // map[customPort]dockerPort
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## Docker-образ
|
||
|
||
Образ задаётся на двух уровнях с приоритетом клиента над глобальным:
|
||
|
||
| Уровень | Источник |
|
||
|---------|----------|
|
||
| Глобальный | `DOCKER_IMAGE` в `/etc/magos/magos.env` |
|
||
| Клиентский | `docker_image` в таблице `client_info` |
|
||
|
||
Если образ отсутствует локально — скачивается tar-архив по URL из `docker_image_download` (или `DOCKER_IMAGE_URL`) и загружается через `docker load`. Одинаковые образы проверяются только один раз за запуск.
|
||
|
||
---
|
||
|
||
## Режим отладки (debug)
|
||
|
||
Поле `debug` в `client_info`. При `debug = true`:
|
||
|
||
**docker-compose.yml:**
|
||
```yaml
|
||
- PTAF_DEBUG=True
|
||
- ERROR_LOG_LEVEL=debug
|
||
```
|
||
|
||
**nginx.conf:**
|
||
```nginx
|
||
env PTAF_LOG_LEVEL=DEBUG;
|
||
env DEBUG=true;
|
||
error_log stderr debug;
|
||
```
|
||
|
||
**Angie server-блоки:**
|
||
```nginx
|
||
client_body_buffer_size 1m;
|
||
```
|
||
|
||
**Важно:** включение debug режима вызывает пересоздание контейнера.
|
||
|
||
---
|
||
|
||
## Graceful Shutdown и миграция
|
||
|
||
### Типы drain операций
|
||
|
||
#### 1. Масштабирование вниз (Scale Down)
|
||
**Timeout:** 90 секунд
|
||
```
|
||
Триггер: containers_count уменьшен в БД
|
||
Действие: лишние контейнеры помечаются маркером /tmp/ptaf-drain-ptaf_{client}_{num}
|
||
Через 90с: docker-compose down + удаление файлов
|
||
```
|
||
|
||
#### 2. Отключение клиента (containers_count = 0)
|
||
**Timeout:** 90 секунд
|
||
```
|
||
Триггер: containers_count = 0
|
||
Действие: все контейнеры + Angie-конфиг помечаются для drain
|
||
Через 90с: удаление контейнеров и конфига Angie
|
||
```
|
||
|
||
#### 3. Миграция между хостами
|
||
**Timeout:** 3600 секунд (1 час)
|
||
```
|
||
Триггер: waf_instance изменился в БД
|
||
Действие: контейнеры и Angie-конфиг помечаются маркером :migration
|
||
Через 1ч: проверка актуальности → удаление если клиент не вернулся
|
||
```
|
||
|
||
### Формат маркеров
|
||
|
||
```
|
||
/tmp/ptaf-drain-ptaf_{clientTitle}_{001} — контейнер (содержит timestamp или timestamp:migration)
|
||
/tmp/ptaf-angie-drain-{clientTitle} — Angie конфиг (аналогичный формат)
|
||
```
|
||
|
||
---
|
||
|
||
## Кастомизация конфигов через SERVER_BLOCK
|
||
|
||
Формат для полей `server_nginx_custom` и `server_angie_custom`:
|
||
|
||
```
|
||
[SERVER_BLOCK:443:example.com:www.example.com]
|
||
proxy_ssl_certificate /etc/ssl/certs/example.crt;
|
||
proxy_ssl_certificate_key /etc/ssl/private/example.key;
|
||
proxy_ssl_server_name on;
|
||
[/SERVER_BLOCK]
|
||
```
|
||
|
||
Синтаксис: `[SERVER_BLOCK:{порт}:{server_name}:{alias1}:{alias2}...]`
|
||
|
||
- Поддерживает произвольное количество алиасов
|
||
- Несколько SERVER_BLOCK в одном поле — поддерживается
|
||
- Для Angie: SERVER_BLOCK создаёт отдельный server-блок с проксированием на контейнеры
|
||
- Для nginx: SERVER_BLOCK создаёт отдельный server-блок с проксированием на origin
|
||
|
||
---
|
||
|
||
## Метод балансировки
|
||
|
||
Поле `balancing_method` в `apps_settings`. Записывается **без** точки с запятой:
|
||
|
||
```sql
|
||
UPDATE apps_settings SET balancing_method = 'least_conn' WHERE l7resourceid = 12345;
|
||
```
|
||
|
||
Допустимые значения: `least_conn`, `ip_hash`, `random`, `random two least_conn` и др.
|
||
|
||
Применяется первой строкой в upstream-блоке для Angie, nginx и SW.
|
||
|
||
---
|
||
|
||
## proxy_next_upstream
|
||
|
||
Поле `proxy_next_upstream_codes` в `apps_settings`. Записывается через запятую **без** `http_` префикса:
|
||
|
||
```sql
|
||
-- Убрать 500 из списка (бэкенд вернул 500, Angie не должен делать retry)
|
||
UPDATE apps_settings SET proxy_next_upstream_codes = '502,503,504' WHERE l7resourceid = 12345;
|
||
```
|
||
|
||
Дефолт: `500,502,503,504`. Итоговая строка в конфиге:
|
||
```nginx
|
||
proxy_next_upstream error timeout invalid_header http_502 http_503 http_504;
|
||
```
|
||
|
||
---
|
||
|
||
## Запуск контейнеров
|
||
|
||
### Ожидание освобождения портов
|
||
|
||
Перед запуском контейнера утилита проверяет занятость портов через `ss -tuanl` (все состояния включая TIME-WAIT и ESTAB). Порт считается занятым если:
|
||
- Есть `LISTEN` сокет
|
||
- Есть `ESTAB` от `docker-proxy` (старый контейнер ещё не остановился)
|
||
|
||
После остановки контейнера при пересоздании:
|
||
1. Ожидаем закрытия ESTAB соединений Angie (до 30 сек)
|
||
2. Ожидаем полного освобождения портов (до 180 сек)
|
||
3. Запуск нового контейнера (до 3 попыток с паузой 3 сек)
|
||
|
||
### Проверка после запуска
|
||
|
||
Если контейнер запущен менее 5 минут и порты не слушают — автоматическое пересоздание.
|
||
|
||
---
|
||
|
||
## Константы и лимиты
|
||
|
||
### Производительность
|
||
|
||
```go
|
||
DefaultWorkerProcesses = 4 // Nginx worker processes
|
||
DefaultWorkerConnections = 64000 // Соединений на worker
|
||
worker_rlimit_nofile = 1048576 // Лимит файловых дескрипторов
|
||
```
|
||
|
||
### Timeouts
|
||
|
||
```go
|
||
ContainerDrainTimeout = 90 // Секунд для scale down / отключения
|
||
MigrationDrainTimeout = 3600 // Секунд для миграции (1 час)
|
||
APITimeout = 120 // Секунд для API запросов
|
||
CacheTTL = 600 // Секунд (10 минут) для sp_info
|
||
MaxLockAge = 15 мин // После этого lock считается устаревшим
|
||
```
|
||
|
||
### Буферы (Angie и nginx)
|
||
|
||
```nginx
|
||
proxy_buffers 8 64k;
|
||
proxy_buffer_size 64k;
|
||
proxy_busy_buffers_size 128k;
|
||
large_client_header_buffers 4 128k;
|
||
```
|
||
|
||
### shm_size
|
||
|
||
По умолчанию `1gb`. Управляется через поле `shm_size` в `client_info`.
|
||
|
||
---
|
||
|
||
## Безопасность
|
||
|
||
### Фильтрация IP адресов
|
||
|
||
**WAF Networks** - исключаются из origins (предотвращение routing loops)
|
||
|
||
**Antibot Networks** - используются для идентификации antibot трафика
|
||
|
||
### SSL/TLS
|
||
|
||
**Дефолтные настройки (Angie):**
|
||
```nginx
|
||
ssl_protocols TLSv1.2 TLSv1.3;
|
||
ssl_ciphers HIGH:!aNULL:!MD5;
|
||
ssl_prefer_server_ciphers on;
|
||
ssl_session_cache shared:SSL:10m;
|
||
ssl_session_timeout 10m;
|
||
```
|
||
|
||
**Кастомизация через `custom_angie_ssl`** — полная замена дефолтов для Angie
|
||
**Кастомизация через `custom_sw_nginx_ssl`** — полная замена дефолтов для SW
|
||
|
||
### mTLS
|
||
|
||
**Автоматическая замена путей:**
|
||
```
|
||
/etc/ssl/certs/ → /opt/ptaf/conf/main/
|
||
/etc/ssl/private/ → /opt/ptaf/conf/main/
|
||
```
|
||
|
||
Применяется во всех custom директивах, содержащих `proxy_ssl_certificate`
|
||
|
||
### Lock-файл
|
||
|
||
При старте утилита:
|
||
1. Читает PID из существующего lock-файла
|
||
2. Если процесс не существует → удаляет устаревший lock и продолжает
|
||
3. Если процесс работает > 15 минут → предупреждение и подсказка как убить
|
||
4. При завершении → lock удаляется через `defer`
|
||
|
||
---
|
||
|
||
## Логирование
|
||
|
||
### Структура логов nginx
|
||
|
||
```
|
||
/var/log/ptaf_nginx/{client-title}/ptaf-agent001/
|
||
├── {sid}_{domain}_access.log
|
||
└── {sid}_{domain}_error.log
|
||
```
|
||
|
||
### Формат access лога (JSON)
|
||
|
||
```json
|
||
{
|
||
"SID": 12345,
|
||
"server_name": "example.com",
|
||
"request_id": "abc123",
|
||
"app_name": "example.com",
|
||
"proxyed_to": "192.168.1.1:443",
|
||
"upstream_status": "200",
|
||
"response_status_code": 200,
|
||
"request_time": 0.056
|
||
}
|
||
```
|
||
|
||
Поле `request_id` берётся из заголовка `X-Request-ID`.
|
||
|
||
### Уровни логирования программы
|
||
|
||
```
|
||
✓ — Успешная операция
|
||
○ — Информация (без изменений)
|
||
⚠ — Предупреждение
|
||
→ — Действие/переход
|
||
└─ — Детали операции
|
||
❌ — Критическая ошибка
|
||
ℹ — Информационное сообщение
|
||
```
|
||
|
||
---
|
||
|
||
## Мониторинг и логирование
|
||
|
||
### FluentBit интеграция
|
||
|
||
Активируется через поле `fluent_bit_port` в `client_info`:
|
||
|
||
```yaml
|
||
environment:
|
||
- EVENT_SENDER_ENABLED=1
|
||
- EVENT_SENDER_HOST=172.17.0.1
|
||
- EVENT_SENDER_PORT={fluent_bit_port}
|
||
- EVENT_SENDER_TIMEOUT=3
|
||
```
|
||
|
||
---
|
||
|
||
## Troubleshooting
|
||
|
||
### Проблема: Контейнер не запускается
|
||
|
||
**Проверить:**
|
||
1. `docker logs ptaf_{client}_{num}`
|
||
2. Наличие конфигов в `/home/install/conf/ptaf-nginx/`
|
||
3. Занятость портов: `ss -tuanl | grep {port}`
|
||
4. Права на `/var/log/ptaf_nginx/` (должны быть 0777)
|
||
5. Зомби docker-proxy процессы: `ps aux | grep docker-proxy | grep -v grep`
|
||
|
||
### Проблема: Порты конфликтуют
|
||
|
||
**Действия:**
|
||
1. Проверить `ss -tuanl | grep :{port}` — все состояния сокетов
|
||
2. Проверить `cat /proc/net/tcp | grep -i "$(printf '%04X' {port})"` — таблица ядра
|
||
3. Убедиться что `ip_local_reserved_ports=18000-23999` установлен на хосте
|
||
4. Удалить `.ports.json` — порты будут перевыделены при следующем запуске
|
||
|
||
### Проблема: Lock-файл не удалился
|
||
|
||
**Действия:**
|
||
1. Magos автоматически удалит lock если процесс уже не существует
|
||
2. Если процесс завис: `kill {PID} && rm /var/lock/ptaf-main.lock`
|
||
3. PID записан в lock-файле: `cat /var/lock/ptaf-main.lock`
|
||
|
||
### Проблема: Клиент не мигрирует
|
||
|
||
**Проверить:**
|
||
1. `waf_instance` в `client_info`
|
||
2. Записи в `instances_new`
|
||
3. Наличие маркеров `/tmp/ptaf-drain-*`
|
||
4. Логи программы на обоих хостах
|
||
|
||
### Проблема: SW nginx не перезагружается
|
||
|
||
**Проверить:**
|
||
1. `solidwall-nginx -t`
|
||
2. Наличие симлинков в `sites-enabled/`
|
||
3. Синтаксис в `sites-available/*.conf`
|
||
|
||
---
|
||
|
||
## Расширение системы
|
||
|
||
### Добавление нового клиента (PTAF)
|
||
|
||
```sql
|
||
INSERT INTO client_info (client_title, containers_count, waf_instance)
|
||
VALUES ('new-client', 2, 'instance-a');
|
||
|
||
INSERT INTO apps_settings (l7resourceid, client_title, waf_vendor, waf_enabled, mode)
|
||
VALUES (12345, 'new-client', 'ptaf', true, 'auto');
|
||
```
|
||
|
||
### Добавление нового клиента (SW)
|
||
|
||
```sql
|
||
INSERT INTO client_info (client_title, containers_count, waf_instance)
|
||
VALUES ('new-sw-client', 0, 'sw-instance-a'); -- containers_count игнорируется для SW
|
||
|
||
INSERT INTO apps_settings (l7resourceid, client_title, waf_vendor, waf_enabled, mode)
|
||
VALUES (12346, 'new-sw-client', 'sw', true, 'auto');
|
||
```
|
||
|
||
### Включение debug-режима для клиента
|
||
|
||
```sql
|
||
UPDATE client_info SET debug = true WHERE client_title = 'CLIENT001';
|
||
```
|
||
|
||
### Задать индивидуальный Docker-образ для клиента
|
||
|
||
```sql
|
||
UPDATE client_info
|
||
SET
|
||
docker_image = 'ptaf-core-nginx-agent:release-4.3.1.431839-debian-bullseye-nginx-1.28.0',
|
||
docker_image_download = 'https://example.com/image.tar'
|
||
WHERE client_title = 'CLIENT001';
|
||
```
|
||
|
||
### Увеличить shared memory для контейнера
|
||
|
||
```sql
|
||
UPDATE client_info SET shm_size = 8 WHERE client_title = 'CLIENT001';
|
||
```
|
||
|
||
### Настроить балансировку
|
||
|
||
```sql
|
||
UPDATE apps_settings SET balancing_method = 'least_conn' WHERE l7resourceid = 12345;
|
||
```
|
||
|
||
### Настроить ptaf_fallback
|
||
|
||
```sql
|
||
-- Пропускать трафик если WAF недоступен
|
||
UPDATE apps_settings SET ptaf_fallback_code = 'pass' WHERE l7resourceid = 12345;
|
||
|
||
-- Вернуть 503 вместо 418
|
||
UPDATE apps_settings SET ptaf_fallback_code = '503' WHERE l7resourceid = 12345;
|
||
```
|