Система предназначена для автоматической защиты веб-ресурсов от DDoS-атак. Она перехватывает HTTP/HTTPS-трафик, анализирует его в реальном времени, обнаруживает аномалии по IP-адресу, User-Agent, путям, методам запросов и географии, после чего автоматически блокирует вредоносные источники без участия администратора. Управление осуществляется через веб-интерфейс и REST API.
Подробная документация: docs/2_SYSTEM_SPECS.md
| Название | Версия |
|---|---|
| Go | 1.25.6 |
| Docker Engine | 24+ |
| Docker Compose | v2 |
| nftables | любая актуальная (для Agent в режиме nftables) |
| Linux | рекомендуется для продуктивного развёртывания |
| Название | Версия |
|---|---|
| PostgreSQL | 17 |
| MongoDB | 8 |
| MinIO | latest |
| Название | Версия | Назначение |
|---|---|---|
| github.com/gin-gonic/gin | v1.12.0 | HTTP-фреймворк |
| google.golang.org/grpc | v1.79.3 | gRPC-фреймворк |
| google.golang.org/protobuf | v1.36.11 | Сериализация Protocol Buffers |
| github.com/jackc/pgx/v5 | v5.9.1 | Драйвер PostgreSQL |
| go.mongodb.org/mongo-driver/v2 | v2.5.0 | Драйвер MongoDB |
| github.com/golang-jwt/jwt/v5 | v5.3.1 | JWT-токены |
| github.com/golang-migrate/migrate/v4 | v4.19.1 | Миграции БД |
| github.com/minio/minio-go/v7 | v7.0.100 | Клиент MinIO/S3 |
| github.com/rs/zerolog | v1.35.0 | Структурированное логирование |
| github.com/swaggo/gin-swagger | v1.6.1 | Swagger UI |
| golang.org/x/crypto | v0.48.0 | Криптографические функции |
| golang.org/x/oauth2 | v0.36.0 | OAuth2 (GitHub) |
| github.com/Masterminds/squirrel | v1.5.4 | SQL query builder |
REST API Admin Service задокументировано через Swagger и доступно после запуска:
http://localhost:8080/swagger/index.html
Исходники: src/admin/docs/
Все ошибки возвращаются в формате RFC 7807 Problem Details с Content-Type: application/problem+json:
{
"type": "about:blank",
"title": "Bad Request",
"status": 400,
"detail": "email is required",
"instance": "/api/auth/register",
"timestamp": "2026-04-27T10:00:00Z",
"requestId": "01JT..."
}Поле detail содержит конкретное описание ошибки. При статусах 5xx поле detail всегда содержит "internal server error" — реальная причина пишется только в лог.
400 Bad Request — некорректные входные данные:
detail |
Причина |
|---|---|
email is required |
Не передан email |
password is required |
Не передан пароль |
username is required |
Не передан username |
fullname is required |
Не передано полное имя |
organization name is required |
Не передано название организации |
domain is required |
Не передан домен сайта |
domain must be a valid hostname |
Домен не соответствует формату hostname |
invalid or expired verification token |
Токен подтверждения email невалиден или истёк |
invalid or expired password reset token |
Токен сброса пароля невалиден или истёк |
invalid oauth state |
CSRF-проверка OAuth2 не прошла |
invalid organization id |
Некорректный формат ID организации |
invalid user id |
Некорректный формат ID пользователя |
invalid plan id |
Некорректный формат ID тарифного плана |
invalid site id |
Некорректный формат ID сайта |
invalid rule config id |
Некорректный формат ID правила обнаружения |
invalid subscription id |
Некорректный формат ID подписки |
invalid member role |
Передана неизвестная роль участника организации |
invalid subscription status |
Передан неизвестный статус подписки |
invalid plan status |
Передан неизвестный статус тарифного плана |
period_end must be after period_start |
Дата окончания подписки раньше даты начала |
plan name is empty |
Не передано название тарифного плана |
no fields to update |
Тело запроса не содержит полей для обновления |
401 Unauthorized — ошибки аутентификации:
detail |
Причина |
|---|---|
authentication required |
Не передан заголовок авторизации |
invalid email or password |
Неверная пара email/пароль при входе |
account is inactive |
Аккаунт деактивирован администратором |
account is not verified |
Email аккаунта не подтверждён |
your session was terminated. please login again |
Сессия отозвана — нужно войти заново |
403 Forbidden — недостаточно прав:
detail |
Причина |
|---|---|
you are not a member of this organization |
Пользователь не состоит в запрашиваемой организации |
only organization admins can add members |
Добавлять участников может только администратор организации |
only organization admins can update member roles |
Изменять роли участников может только администратор организации |
only organization admins can remove members |
Удалять участников может только администратор организации |
only organization admins can add sites |
Добавлять защищаемые сайты может только администратор организации |
only organization admins can update sites |
Редактировать сайты может только администратор организации |
only organization admins can delete sites |
Удалять сайты может только администратор организации |
only organization admins can manage rule configs |
Управлять правилами обнаружения может только администратор организации |
only organization admins can update organizations |
Редактировать организацию может только её администратор |
only organization admins can delete organizations |
Удалять организацию может только её администратор |
only organization admins can purchase a subscription |
Оформлять подписку может только администратор организации |
only organization admins can cancel a subscription |
Отменять подписку может только администратор организации |
only organization admins can renew a subscription |
Продлевать подписку может только администратор организации |
only organization admins can change a subscription plan |
Менять тарифный план может только администратор организации |
only admins can create plans |
Создавать тарифные планы может только суперадминистратор |
only admins can update plans |
Редактировать тарифные планы может только суперадминистратор |
only admins can delete plans |
Удалять тарифные планы может только суперадминистратор |
you can view only your own profile |
Просматривать чужой профиль запрещено |
you can only update your own profile |
Редактировать чужой профиль запрещено |
you are not allowed to delete users |
Удалять пользователей может только суперадминистратор |
can't delete your own account |
Удалить собственный аккаунт невозможно |
404 Not Found — запрошенный ресурс не существует:
detail |
Причина |
|---|---|
user not found |
Пользователь с указанным ID не существует |
organization not found |
Организация с указанным ID не существует |
site not found |
Сайт с указанным ID не существует |
plan not found |
Тарифный план с указанным ID не существует |
subscription not found |
Подписка с указанным ID не существует |
member not found |
Участник организации с указанным ID не найден |
rule config not found |
Конфигурация правила обнаружения не найдена |
incident not found |
Инцидент с указанным ID не найден |
avatar not found |
Аватар пользователя не найден |
409 Conflict — конфликт с уже существующими данными:
detail |
Причина |
|---|---|
user with this email already exists |
Email уже используется другим пользователем |
user with this username already exists |
Username уже занят другим пользователем |
organization with this name already exists |
У владельца уже есть организация с таким именем |
site with this domain already exists in the organization |
Такой домен уже добавлен в эту организацию |
user is already a member of this organization |
Пользователь уже состоит в этой организации |
plan with this name already exists |
Тарифный план с таким именем уже существует |
organization already has an active subscription |
У организации уже есть активная подписка |
subscription is already active |
Подписка уже находится в активном состоянии |
subscription is already canceled |
Подписка уже отменена |
422 Unprocessable Entity — бизнес-правило не позволяет выполнить операцию:
detail |
Причина |
|---|---|
cannot remove the last admin of the organization |
В организации должен оставаться хотя бы один администратор |
organization has no subscription |
Операция недоступна без активной подписки |
maxUsers cannot be negative |
Лимит пользователей в тарифном плане не может быть отрицательным |
maxProtectedResources cannot be negative |
Лимит защищаемых ресурсов не может быть отрицательным |
maxThroughput cannot be negative |
Пропускная способность в плане не может быть отрицательной |
price cannot be negative |
Цена тарифного плана не может быть отрицательной |
planPriority cannot be negative |
Приоритет тарифного плана не может быть отрицательным |
429 Too Many Requests — превышен лимит запросов. Лимиты задаются переменными HTTP_RATE_LIMIT_AUTHENTICATED_PER_MINUTE и HTTP_RATE_LIMIT_UNAUTHENTICATED_PER_MINUTE.
500 Internal Server Error — внутренняя ошибка сервера. Причина не раскрывается в ответе, записывается только в лог.
501 Not Implemented — запрошена функция, не настроенная в данном развёртывании (например, GitHub OAuth2 при отсутствии GITHUB_CLIENT_ID / GITHUB_CLIENT_SECRET).
Подробная документация: docs/3_USER_SPECS.md
.
├── cmd/ # Точки входа (main.go) для каждого сервиса
│ ├── admin/
│ ├── detector/
│ └── agent/
├── src/ # Бизнес-логика сервисов
│ ├── admin/
│ ├── detector/
│ ├── agent/
│ └── common/ # Общие пакеты
├── proto/ # Определения gRPC-протоколов (.proto)
│ ├── admin/v1/
│ ├── detector/v1/
│ └── agent/v1/
├── api/gen/ # Сгенерированный gRPC-код (не редактировать вручную)
├── migrations/ # SQL-миграции
│ ├── admin/ # Миграции для Admin DB
│ └── detector/ # Миграции для Detector DB
├── docker/ # Dockerfile'ы и docker-compose конфигурации
│ ├── docker-compose.yaml # Полный стек (все сервисы в Docker)
│ ├── docker-compose-dev.yaml # Только инфраструктура для разработки
│ ├── Admin.Dockerfile
│ ├── Detector.Dockerfile
│ ├── Agent.Dockerfile
│ └── Migrate.Dockerfile
├── nginx/ # Конфигурация Nginx
│ ├── nginx.conf # Продуктивная конфигурация
│ ├── nginx.dev.conf # Конфигурация для разработки
│ └── conf.d/ # Конфигурации виртуальных хостов
├── certs/ # mTLS-сертификаты (генерируются через make certs)
├── scripts/ # Вспомогательные скрипты (nftables, deploy, rollback)
├── docs/ # Документация проекта
├── go.mod
└── Makefile
| Сервис | Файл | HTTP-порт | gRPC-порт |
|---|---|---|---|
| Admin Service | cmd/admin/main.go | 8080 | 50051 |
| Detector Service | cmd/detector/main.go | — | 50051 |
| Agent Service | cmd/agent/main.go | — | 50051 |
Требования: Go 1.25+, Docker, Docker Compose v2, Make, OpenSSL.
cp .env.example .envДля локальной разработки значения по умолчанию уже заполнены. Обязательно задать вручную:
| Переменная | Описание |
|---|---|
JWT_SECRET |
Произвольная секретная строка для подписи JWT-токенов |
HOSTNAME |
Публичный URL приложения, например http://localhost:8080 |
GITHUB_CLIENT_ID / GITHUB_CLIENT_SECRET |
Опционально — для входа через GitHub OAuth2 |
Сертификаты нужны для защищённой связи между Admin, Detector и Agent по gRPC:
make certsСгенерированные файлы появятся в директории certs/.
Команда поднимает в Docker все инфраструктурные зависимости (PostgreSQL, MongoDB, Nginx, MinIO, Mailpit), применяет миграции и запускает Admin Service локально с флагом DEBUG=1:
make devПосле успешного запуска доступно:
| Адрес | Что |
|---|---|
| http://localhost:8080 | REST API и веб-интерфейс |
| http://localhost:8080/swagger/index.html | Swagger UI |
| http://localhost:8025 | Mailpit — перехват писем |
| http://localhost:9001 | MinIO Console |
| localhost:5433 | PostgreSQL (user: postgres, pass: postgres) |
| localhost:27017 | MongoDB |
make build-detector
./bin/detectorКлючевые переменные окружения Detector Service:
| Переменная | Значение для локальной разработки |
|---|---|
MONGO_URI |
mongodb://localhost:27017 |
MONGO_DB |
detector |
DB_HOST / DB_PORT / DB_NAME |
localhost / 5433 / detector |
ADMIN_HOST / ADMIN_PORT |
localhost / 50051 |
make downВсе сервисы и инфраструктура в контейнерах — используется docker/docker-compose.yaml:
# Первый запуск: собрать образы из исходников и запустить
make up-build
# Последующие запуски: использовать уже собранные образы
make up
# Остановка
make down| Команда | Описание |
|---|---|
make test |
Запуск тестов |
make lint |
Статический анализ кода (golangci-lint) |
make gen |
Регенерация gRPC-кода и Swagger-документации |
make build |
Сборка всех трёх бинарников в bin/ |
make certs |
Перегенерация mTLS-сертификатов |
make genтребует установленныхprotoc,protoc-gen-go,protoc-gen-go-grpcиswag.
Подробная документация: docs/4_DEPLOY.md
| Параметр | Минимум | Рекомендуется |
|---|---|---|
| CPU | 2 ядра | 4 ядра |
| RAM | 2 ГБ | 4 ГБ |
| Диск | 20 ГБ | 40 ГБ |
| Сеть | 100 Мбит/с | 1 Гбит/с |
| ОС | Linux 64-bit | Linux 64-bit |
Ограничения производительности:
- Задержка, добавляемая прокси-компонентом: не более 50 мс (p95) при нагрузке до 500 RPS.
- Пороговые правила обнаружения срабатывают не позднее 30 секунд после начала атаки.
- Статистические правила срабатывают не позднее 5 минут после отклонения от базовой модели.
- Блокировка IP применяется не позднее 2 секунд после создания инцидента.
Подробная документация: docs/5_SECURITY.md