24 KiB
Executable file
Magos - Схема базы данных
Обзор
Magos работает с PostgreSQL базой данных, которая содержит конфигурации WAF платформы. Программа использует несколько основных таблиц для получения информации о хостах, клиентах, приложениях и backend серверах.
Используемые таблицы
- instances_new - информация о хостах/серверах
- client_info - данные клиентов и контейнеров
- apps_settings - настройки приложений и кастомные директивы
- sp_info - кэш данных из API (origins, aliases)
- manual_info - ручные данные (альтернатива API)
- ips - IP адреса для WAF и antibot сетей
Подключение к БД
Параметры подключения
DB_USER=login
DB_PASSWORD=password
DB_NAME=waf_info
DB_PORT=5432
PRIMARY_DB_HOST=10.100.10.8
SECONDARY_DB_HOST=10.100.13.5
Failover логика
- Попытка подключения к Primary DB
- Если неудача → подключение к Secondary DB
- Если обе недоступны → программа останавливается
Функция: connectToDB()
Таблица: instances_new
Назначение
Хранит информацию о хостах/серверах в кластере WAF. Таблица instances (старая) переименована в instances_old и не используется — все запросы идут к instances_new.
Структура
| Поле | Тип | Описание | Пример |
|---|---|---|---|
hostname |
TEXT | Hostname сервера | host01.example.com |
instance |
TEXT | Идентификатор инстанса | waf-prod-01 |
Используемые запросы
Получение instances по hostname
SELECT instance
FROM instances_new
WHERE hostname = $1;
Функция: getInstancesByHostname(hostname string)
Один хост может принадлежать нескольким instances.
Проверка принадлежности хоста к инстансу
SELECT COUNT(*)
FROM instances_new
WHERE hostname = $1 AND instance = $2;
Функция: checkHostBelongsToInstance(hostname, instance string)
Таблица: client_info
Назначение
Хранит информацию о клиентах: количество контейнеров, Docker-образ, режим отладки и привязка к инстансу.
Структура
| Поле | Тип | Описание | Пример |
|---|---|---|---|
id |
SERIAL | Первичный ключ (автоинкремент) | 1 |
client_title |
TEXT | Идентификатор клиента | CLIENT001 |
parent_client_title |
TEXT | Родительский клиент (для grafana_gen) | NULL |
containers_count |
INTEGER | Количество контейнеров (0 = drain всех) | 3 |
ptaf_config |
TEXT | Строка подключения к PTAF-серверу | {...} |
fluent_bit_port |
INTEGER | Порт Fluent Bit | 24224 |
waf_instance |
TEXT | Instance для привязки к хосту | waf-prod-01 |
docker_image |
TEXT | Docker-образ (переопределяет глобальный) | ptaf-core-nginx-agent:release-4.3.1... |
docker_image_download |
TEXT | URL для скачивания tar-архива образа | https://... |
debug |
BOOLEAN | Режим отладки | false |
shm_size |
INTEGER | Размер /dev/shm в GB | 1 |
ptaf_fallback_code |
TEXT | Код ответа ptaf_fallback: число или 'pass' | 418 |
sp_antiddos |
BOOLEAN | Использовать антиддос сети в set_real_ip | true |
real_ip_networks |
INET[] | Кастомные сети для set_real_ip (если sp_antiddos=false) | {10.0.0.0/8} |
worker_processes |
INTEGER | Количество worker процессов nginx | 4 |
one_container |
BOOLEAN | Все SID в один контейнер | true |
sid_block |
TEXT | Блоки SID для разбивки: {sid1,sid2}{sid3} |
NULL |
Используемые запросы
Получение клиентов по instance
SELECT
containers_count,
ptaf_config,
client_title,
fluent_bit_port,
waf_instance,
docker_image,
docker_image_download,
debug,
shm_size,
ptaf_fallback_code,
sp_antiddos,
real_ip_networks,
worker_processes,
one_container,
sid_block
FROM client_info
WHERE waf_instance = $1;
Функция: getClientInfoByInstance(instance string)
Получение клиента по client_title
SELECT
containers_count,
ptaf_config,
client_title,
fluent_bit_port,
waf_instance,
docker_image,
docker_image_download,
debug,
shm_size,
ptaf_fallback_code,
sp_antiddos,
real_ip_networks,
worker_processes,
one_container,
sid_block
FROM client_info
WHERE client_title = $1;
Функция: getClientInfoByClientTitle(clientTitle string)
Миграции
-- Переименование PK (таблица была переименована из nodes в client_info)
ALTER TABLE client_info DROP CONSTRAINT nodes_pkey;
ALTER TABLE client_info ADD COLUMN id SERIAL PRIMARY KEY;
-- Добавление parent_client_title для grafana_gen
ALTER TABLE client_info
ADD COLUMN IF NOT EXISTS parent_client_title TEXT DEFAULT NULL;
ALTER TABLE client_info
ADD COLUMN IF NOT EXISTS docker_image TEXT DEFAULT NULL;
ALTER TABLE client_info
ADD COLUMN IF NOT EXISTS docker_image_download TEXT DEFAULT NULL;
ALTER TABLE client_info
ADD COLUMN IF NOT EXISTS debug BOOLEAN DEFAULT FALSE;
ALTER TABLE client_info
ADD COLUMN IF NOT EXISTS shm_size INTEGER DEFAULT 1;
ALTER TABLE client_info
ADD COLUMN IF NOT EXISTS ptaf_fallback_code TEXT DEFAULT '418';
ALTER TABLE client_info
ADD COLUMN IF NOT EXISTS sp_antiddos BOOLEAN DEFAULT TRUE;
ALTER TABLE client_info
ADD COLUMN IF NOT EXISTS real_ip_networks INET[] DEFAULT NULL;
ALTER TABLE client_info
ADD COLUMN IF NOT EXISTS worker_processes INTEGER DEFAULT 4;
ALTER TABLE client_info
ADD COLUMN IF NOT EXISTS one_container BOOLEAN DEFAULT TRUE;
ALTER TABLE client_info
ADD COLUMN IF NOT EXISTS sid_block TEXT DEFAULT NULL;
Ключевые поля
containers_count
containers_count = 3→ создать ptaf_client_001, ptaf_client_002, ptaf_client_003- При увеличении → новые контейнеры добавляются, существующие не трогаются
- При уменьшении → лишние контейнеры помечаются на graceful drain (90с)
containers_count = 0→ все контейнеры и Angie-конфиг помечаются на drain
docker_image / docker_image_download
Если заполнены — используются вместо глобальных настроек DOCKER_IMAGE и DOCKER_IMAGE_URL из magos.env. Позволяют иметь разные версии агента для разных клиентов.
debug
При true:
- В docker-compose добавляются
PTAF_DEBUG=TrueиERROR_LOG_LEVEL=debug - В nginx.conf:
PTAF_LOG_LEVEL=DEBUG,DEBUG=true,error_log stderr debug - В Angie server-блоки добавляется
client_body_buffer_size 1m
shm_size
Размер разделяемой памяти /dev/shm для Docker-контейнера в гигабайтах. Результат в docker-compose: shm_size: '2gb'. Дефолт: 1.
ptaf_fallback_code
Код HTTP ответа который PTAF возвращает когда WAF-модуль недоступен. Записывается в блок http {} файла nginx.conf — применяется глобально для всех ресурсов контейнера.
UPDATE client_info SET ptaf_fallback_code = 'pass' WHERE client_title = 'CLIENT001';
UPDATE client_info SET ptaf_fallback_code = '503' WHERE client_title = 'CLIENT001';
worker_processes
Количество worker процессов nginx внутри контейнера. Изменение вызывает nginx -s reload без пересоздания контейнера. Дефолт: 4.
UPDATE client_info SET worker_processes = 8 WHERE client_title = 'CLIENT001';
one_container / sid_block
one_container = true (дефолт) — все SID клиента обслуживаются одним набором контейнеров. Стандартный режим.
one_container = false + заполненный sid_block — блочный режим. Каждый блок {} в sid_block создаёт отдельный набор контейнеров только со своими SID.
Формат sid_block: {sid1,sid2}{sid3}{sid4,sid5} — каждая пара фигурных скобок это один блок.
-- Три блока: первый с двумя SID, второй и третий с одним
UPDATE client_info
SET one_container = false,
sid_block = '{10111,10231}{10112}{10113}'
WHERE client_title = 'CLIENT001';
Именование контейнеров в блочном режиме:
- Блок 1 →
{clientTitle}_block1_AZ3_hn01_a001 - Блок 2 →
{clientTitle}_block2_AZ3_hn01_a001
containers_count применяется к каждому блоку — если containers_count=2 и 3 блока → 6 контейнеров суммарно.
SID не указанные ни в одном блоке не обрабатываются.
sp_antiddos = true (дефолт) — в Angie используются антиддос сети из таблицы ips для set_real_ip_from.
sp_antiddos = false + непустой real_ip_networks — вместо антиддос сетей используются кастомные сети из real_ip_networks. WAF сети из ips при этом всегда присутствуют.
UPDATE client_info
SET sp_antiddos = false,
real_ip_networks = '{10.0.0.0/8, 192.168.1.0/24}'
WHERE client_title = 'CLIENT001';
Таблица: apps_settings
Назначение
Основная таблица с настройками приложений и кастомными директивами Nginx/Angie.
Структура
| Поле | Тип | Описание | Значение по умолчанию |
|---|---|---|---|
l7resourceid |
INTEGER | ID ресурса | Первичный ключ |
client_title |
TEXT | Клиент (FK) | — |
waf_enabled |
BOOLEAN | WAF включен | true |
waf_vendor |
TEXT | Вендор: 'ptaf' или 'sw' | — |
mode |
TEXT | auto/manual/disabled | auto |
sni |
INTEGER | SNI режим (0=keepalive on, 1=keepalive off) | 0 |
ssl_enabled |
BOOLEAN | SSL на HTTPS портах | true |
custom_input_http_ports |
INTEGER[] | HTTP порты для прослушивания | {80} |
custom_input_https_ports |
INTEGER[] | HTTPS порты для прослушивания | {443} |
custom_output_http_ports |
INTEGER[] | HTTP порты к backend | {80} |
custom_output_https_ports |
INTEGER[] | HTTPS порты к backend | {443} |
upstream_angie_custom |
TEXT | Кастомные upstream директивы (Angie) | NULL |
upstream_nginx_custom |
TEXT | Кастомные upstream директивы (Nginx/SW) | NULL |
server_angie_custom |
TEXT | Кастомный server блок (Angie) | NULL |
server_nginx_custom |
TEXT | Кастомный server блок (Nginx/SW) | NULL |
server_directives_angie_custom |
TEXT | Кастомные server директивы (Angie) | NULL |
server_directives_nginx_custom |
TEXT | Кастомные server директивы (Nginx/SW) | NULL |
location_angie_custom |
TEXT | Кастомные location блоки (Angie) | NULL |
location_nginx_custom |
TEXT | Кастомные location блоки (Nginx/SW) | NULL |
custom_angie_ssl |
TEXT | Замена SSL директив (Angie) | NULL |
custom_sw_nginx_ssl |
TEXT | Замена SSL директив (SW) | NULL |
max_fails |
INTEGER | Попыток до пометки сервера недоступным | 5 |
fail_timeout |
INTEGER | Время восстановления сервера (сек) | 15 |
balancing_method |
TEXT | Метод балансировки upstream | NULL |
proxy_next_upstream_codes |
TEXT | HTTP-коды для proxy_next_upstream | '500,502,503,504' |
x_sid_check |
BOOLEAN | Маршрутизация в Angie по X-Sid заголовку | false |
Используемые запросы
Получение настроек по client_title
SELECT
l7resourceid,
waf_enabled,
waf_vendor,
mode,
custom_input_http_ports,
custom_input_https_ports,
custom_output_http_ports,
custom_output_https_ports,
upstream_angie_custom,
upstream_nginx_custom,
server_nginx_custom,
server_angie_custom,
location_angie_custom,
location_nginx_custom,
server_directives_angie_custom,
server_directives_nginx_custom,
custom_angie_ssl,
custom_sw_nginx_ssl,
client_title,
sni,
ssl_enabled,
max_fails,
fail_timeout,
balancing_method,
proxy_next_upstream_codes,
x_sid_check
FROM apps_settings
WHERE client_title = $1
ORDER BY l7resourceid ASC;
Функция: getAppsSettingsByClientTitle(clientTitle string)
Миграции
ALTER TABLE apps_settings
ADD COLUMN IF NOT EXISTS custom_sw_nginx_ssl TEXT DEFAULT NULL;
ALTER TABLE apps_settings
ADD COLUMN IF NOT EXISTS balancing_method TEXT DEFAULT NULL;
ALTER TABLE apps_settings
ADD COLUMN IF NOT EXISTS proxy_next_upstream_codes TEXT DEFAULT '500,502,503,504';
ALTER TABLE apps_settings
ADD COLUMN IF NOT EXISTS x_sid_check BOOLEAN DEFAULT FALSE;
Кастомные поля (подробно)
balancing_method
Метод балансировки upstream. Записывается без точки с запятой. Вставляется первой строкой в upstream-блок.
-- Включить least_conn
UPDATE apps_settings SET balancing_method = 'least_conn' WHERE l7resourceid = 12345;
-- Вернуть round-robin (дефолт)
UPDATE apps_settings SET balancing_method = NULL WHERE l7resourceid = 12345;
Допустимые значения: least_conn, ip_hash, random, random two least_conn
proxy_next_upstream_codes
Коды HTTP ответов при которых Angie/nginx переключается на следующий upstream-сервер. Записывается через запятую без префикса http_.
-- Убрать 500 из retry (бэкенд вернул 500, не нужно делать retry)
UPDATE apps_settings
SET proxy_next_upstream_codes = '502,503,504'
WHERE l7resourceid = 12345;
-- Вернуть дефолт
UPDATE apps_settings
SET proxy_next_upstream_codes = NULL
WHERE l7resourceid = 12345;
Итоговая строка в конфиге:
proxy_next_upstream error timeout invalid_header http_502 http_503 http_504;
x_sid_check
При true — Angie маршрутизирует запросы по заголовку X-Sid вместо server_name. Используется когда один и тот же FQDN присутствует в разных тенантах WAF. В связке с блочным режимом (one_container = false) даёт полное решение проблемы конфликта FQDN.
-- Включить маршрутизацию по X-Sid для ресурса
UPDATE apps_settings SET x_sid_check = true WHERE l7resourceid = 10111;
Клиент должен передавать заголовок X-Sid: {l7resourceid} в каждом запросе.
Режим: REPLACE (полная замена keepalive директив)
-- Кастомный keepalive
UPDATE apps_settings
SET upstream_angie_custom = 'keepalive 200;
keepalive_timeout 90s;'
WHERE l7resourceid = 12345;
server_directives_angie_custom / server_directives_nginx_custom
Режим: REPLACE (замена блока дефолтных таймаутов/буферов)
Важно: при использовании кастома нужно указать ВСЕ нужные директивы, включая proxy_set_header X-Request-ID.
server_angie_custom / server_nginx_custom
Поддерживает формат SERVER_BLOCK для создания дополнительных server-блоков:
[SERVER_BLOCK:443:report.example.com:www.report.example.com]
proxy_read_timeout 3600s;
proxy_send_timeout 3600s;
[/SERVER_BLOCK]
Синтаксис: [SERVER_BLOCK:{порт}:{server_name}:{alias1}:{alias2}...]
custom_angie_ssl / custom_sw_nginx_ssl
Полная замена SSL директив. При NULL используются дефолтные:
ssl_certificate ssl/cert.pem;
ssl_certificate_key ssl/key.pem;
ssl_protocols TLSv1.2 TLSv1.3;
Таблица: sp_info (кэш)
Назначение
Кэширует данные из ServicePipe API. TTL: 10 минут.
Структура
| Поле | Тип | Описание |
|---|---|---|
sid |
INTEGER | l7resourceid |
domain_name |
TEXT | Основной домен |
aliases |
JSON | Массив алиасов |
origins |
JSON | Массив origin серверов |
updated_at |
TIMESTAMP | Время последнего обновления |
Таблица: manual_info
Назначение
Ручное управление данными ресурсов (альтернатива API). Используется при mode = 'manual'.
Структура
| Поле | Тип | Описание |
|---|---|---|
sid |
INTEGER | l7resourceid |
domain_name |
TEXT | Основной домен |
aliases |
JSON | Массив алиасов |
origins |
JSON | Массив origin серверов |
Данные не имеют TTL и всегда актуальны.
Таблица: ips
Структура
| Поле | Тип | Описание |
|---|---|---|
id |
INTEGER | Всегда = 1 |
antibot_networks |
TEXT[] | CIDR сети antibot |
waf_networks |
TEXT[] | CIDR сети WAF (исключаются из origins) |
Связи между таблицами
instances_new
↓ (hostname → instance)
client_info (waf_instance)
↓ (client_title)
apps_settings (client_title)
↓ (l7resourceid через API/manual_info)
Origins, Aliases
Примеры типичных операций
Добавить нового PTAF-клиента
INSERT INTO client_info (client_title, containers_count, waf_instance)
VALUES ('NewClient', 2, 'PTAFd_01');
INSERT INTO apps_settings (l7resourceid, client_title, waf_vendor, waf_enabled, mode)
VALUES (99999, 'NewClient', 'ptaf', true, 'auto');
Добавить нового SW-клиента
INSERT INTO client_info (client_title, containers_count, waf_instance)
VALUES ('NewSWClient', 0, 'SWd_01');
INSERT INTO apps_settings (l7resourceid, client_title, waf_vendor, waf_enabled, mode)
VALUES (99998, 'NewSWClient', 'sw', true, 'auto');
Изменить количество контейнеров
-- Увеличить до 5
UPDATE client_info SET containers_count = 5 WHERE client_title = 'CLIENT001';
-- Отключить клиента (drain всех контейнеров)
UPDATE client_info SET containers_count = 0 WHERE client_title = 'CLIENT001';
Включить debug-режим
UPDATE client_info SET debug = true WHERE client_title = 'CLIENT001';
Задать индивидуальный Docker-образ
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';
Настроить балансировку
UPDATE apps_settings SET balancing_method = 'least_conn' WHERE l7resourceid = 12345;
Убрать 500 из retry
UPDATE apps_settings
SET proxy_next_upstream_codes = '502,503,504'
WHERE l7resourceid = 12345;
Добавить кастомные SSL для SW
UPDATE apps_settings
SET custom_sw_nginx_ssl = 'ssl_certificate /etc/solidwall-nginx/ssl/custom.crt;
ssl_certificate_key /etc/solidwall-nginx/ssl/custom.key;
ssl_protocols TLSv1.2 TLSv1.3;'
WHERE l7resourceid = 12345;
Добавить SERVER_BLOCK с увеличенными таймаутами
UPDATE apps_settings
SET server_angie_custom = '[SERVER_BLOCK:443:report.example.com:www.report.example.com]
proxy_read_timeout 3600s;
proxy_send_timeout 3600s;
[/SERVER_BLOCK]'
WHERE l7resourceid = 12345;
Best Practices
NULL vs пустая строка
-- Правильно: NULL для дефолтов
UPDATE apps_settings SET upstream_angie_custom = NULL WHERE l7resourceid = 12345;
-- Неправильно: пустая строка может вызвать ошибки
UPDATE apps_settings SET upstream_angie_custom = '' WHERE l7resourceid = 12345;
Массивы портов
-- Правильно: PostgreSQL array
UPDATE apps_settings SET custom_input_https_ports = '{443, 8443}' WHERE l7resourceid = 12345;
-- Неправильно: строка
UPDATE apps_settings SET custom_input_https_ports = '443,8443' WHERE l7resourceid = 12345;
balancing_method — без точки с запятой
-- Правильно
UPDATE apps_settings SET balancing_method = 'least_conn' WHERE l7resourceid = 12345;
-- Неправильно
UPDATE apps_settings SET balancing_method = 'least_conn;' WHERE l7resourceid = 12345;
Мониторинг БД
-- Количество клиентов на каждом instance
SELECT waf_instance, COUNT(*) as clients_count
FROM client_info
GROUP BY waf_instance;
-- Клиенты с debug-режимом
SELECT client_title FROM client_info WHERE debug = true;
-- Клиенты с индивидуальным образом
SELECT client_title, docker_image FROM client_info WHERE docker_image IS NOT NULL;
-- Ресурсы с маршрутизацией по X-Sid
SELECT client_title, l7resourceid FROM apps_settings WHERE x_sid_check = true;
-- Клиенты в блочном режиме
SELECT client_title, sid_block FROM client_info WHERE one_container = false;
-- Клиенты с нестандартным количеством worker процессов
SELECT client_title, worker_processes FROM client_info WHERE worker_processes != 4;
-- Клиенты без антиддоса
SELECT client_title, real_ip_networks FROM client_info WHERE sp_antiddos = false;
-- Клиенты с кастомным ptaf_fallback
SELECT client_title, ptaf_fallback_code FROM client_info WHERE ptaf_fallback_code != '418';
-- Ресурсы с кастомной балансировкой
SELECT client_title, l7resourceid, balancing_method
FROM apps_settings
WHERE balancing_method IS NOT NULL;
-- Ресурсы с кастомными upstream директивами
SELECT client_title, l7resourceid
FROM apps_settings
WHERE upstream_angie_custom IS NOT NULL
OR upstream_nginx_custom IS NOT NULL;
Индексы (рекомендуемые)
CREATE INDEX idx_instances_new_hostname ON instances_new(hostname);
CREATE INDEX idx_client_info_waf_instance ON client_info(waf_instance);
CREATE INDEX idx_client_info_client_title ON client_info(client_title);
CREATE INDEX idx_apps_settings_client_title ON apps_settings(client_title);
CREATE INDEX idx_apps_settings_l7resourceid ON apps_settings(l7resourceid);