# PR: Интеграция backend-автопоиска SNI в страницу доменов ## Контекст и цель Этот PR объединяет рабочий SNI-checker с интерфейсом 3dp так, чтобы пользователь мог: - запускать поиск кандидатов SNI прямо из страницы `Домены`, - просматривать найденные домены в предварительном списке, - вручную отбраковывать лишние записи, - импортировать только проверенный набор в основной whitelist. Ключевая идея: сетево- и CPU-нагруженный скан остаётся на backend (в контейнере), а frontend отвечает за удобный, безопасный и понятный пользовательский сценарий. ## Почему это сделано именно так - Полноценный low-level скан (TLS/socket-поведение) недоступен обычному веб-frontend в браузере из-за ограничений платформы. - Backend-контур позволяет использовать нативный бинарник сканера и системные утилиты без усложнения пользовательской среды. - Такой подход снимает необходимость в ручном внешнем пайплайне “запуск скрипта отдельно + ручной импорт”, и делает процесс единым внутри UI 3dp. ## Что сделано ## 1) Backend: подключен scanner-сервис и API - Добавлен отдельный сервис для запуска сканера и парсинга результатов. - Добавлены API-эндпоинты: - `GET /api/domains/scan/capabilities` — проверка доступности сканера и `timeout` в контейнере. - `POST /api/domains/scan/start` — запуск скана с параметрами (`addr`, `scanSeconds`, `thread`, `timeout`). - Добавлена защита от параллельных запусков (одновременно разрешён только один активный скан на инстанс backend). - Реализован корректный сбор доменов из потока логов сканера, включая обработку “разрезанных” строк между чанками stdout. - Добавлена нормализация/фильтрация найденных доменов перед отдачей во frontend. ## 2) Docker backend: сборка и доставка RealiTLScanner в контейнер - Добавлен отдельный multi-stage этап сборки бинарника из репозитория RealiTLScanner. - Сборка привязана к фиксированному commit hash (reproducible build). - Готовый бинарник копируется в runtime-образ backend и делается исполняемым. - В runtime-образ добавлены утилиты, необходимые для сценария сканирования и проверки (`bash`, `curl`, `python3`, `gawk`, `coreutils`, `procps`, `ca-certificates` и др.). ## 3) Frontend `/domains`: полный UX-сценарий автопоиска - Добавлен блок **«Автопоиск SNI (backend scanner)»** как аккордеон. - Блок показывается только когда backend сообщает, что scanner реально доступен. - Состояние аккордеона запоминается (по умолчанию при первом открытии — свернут). - Добавлены параметры запуска скана: - IP/домен VPS, - время скана, - число потоков, - таймаут проверки. - Добавлен предварительный список найденных доменов: - домены кликабельны (можно открыть и проверить вручную), - можно удалять отдельные записи из предварительного списка, - можно импортировать в основной whitelist только финальный отобранный набор. - Добавлены кнопки очистки и экспорта: - экспорт найденного предварительного списка, - экспорт основного whitelist. - Сохранение scanner-state в `localStorage`: - сохраняются введённые параметры, - сохраняется предварительный список, - сохраняется последний результат скана, - после F5 пользователь продолжает с того же места. - При первом запуске и после очистки добавлена попытка авто-подстановки адреса (из settings/runtime host) в поле `IP/домен VPS`. ## 4) Улучшение валидации доменов (основной список) - Усилен серверный normalize/validate для одиночного добавления и пакетного импорта. - Поддержаны практические случаи входных данных: - wildcard-формат (`*.domain.com`) нормализуется в `domain.com`, - удаляются лишние кавычки/обрамления/схемы URL/пути/порты, - обрабатываются комментарии и мусорные строки в файлах импорта, - устранено дублирование с учётом регистра (`LOWER(...)`). - В результате поведение ручного добавления и импорта приведено к единым правилам. ## 5) UI-полировка существующего блока whitelist - Основной авторский блок управления whitelist визуально оформлен в общей стилистике страницы. - Элементы списка сделаны ссылками на `https://...` для быстрой ручной проверки. - Добавлена подсветка строк по hover в стиле интерфейса. ## Что это даёт пользователю - Единый встроенный workflow “поиск → ручная проверка → импорт” без внешних скриптов и копипаста. - Меньше ошибок за счёт предварительного списка и точечного удаления лишних доменов. - Меньше потери контекста: состояние поиска сохраняется между перезагрузками страницы. - Более предсказуемая и чистая загрузка доменов из файлов. ## Ограничения и осознанные решения - Скан выполняется на backend (в контейнере), а не в браузере клиента: это осознанный компромисс в пользу технической реализуемости и стабильности. - Выход `timeout` в режиме ограниченного времени скана интерпретируется как нормальный сценарий поиска, а не как критическая ошибка. - Для предотвращения перегрузки включено ограничение на параллельные запуски сканера. ## Проверка и валидация Локально проверены сценарии: - старт/остановка скана и получение кандидатов, - удаление отдельных записей из предварительного списка, - импорт найденных доменов в основной whitelist, - очистка предварительного списка, - восстановление состояния после F5, - ручное добавление и импорт “сложного” списка с комментариями/wildcard/обрамлениями, - экспорт предварительного и основного списков. Отдельно просмотрены логи контейнеров (`server`, `frontend`, `postgres`) — критичных ошибок не зафиксировано, стек работает штатно. ## Совместимость и риск - Изменения локализованы в модуле `domains` и соответствующей странице frontend. - Обратная совместимость API базового управления доменами сохранена. - Риски регрессии умеренные и в основном касаются UX/валидации в доменном модуле; критичных инфраструктурных изменений вне этих зон нет.