diff --git a/debug.md b/debug.md deleted file mode 100644 index 6f121d0..0000000 --- a/debug.md +++ /dev/null @@ -1,93 +0,0 @@ -# Локальная отладка 3dp-manager - -## Порты локального стенда -- frontend: `http://localhost:8080` -- backend API: `http://localhost:3100/api` -- postgres: `localhost:15432` - -## Запуск/перезапуск -```powershell -# полный запуск -docker compose -f docker-compose.local.yml up -d --build - -# частичный перезапуск только фронта -docker compose -f docker-compose.local.yml up -d --build --no-deps frontend - -# частичный перезапуск только бэка -docker compose -f docker-compose.local.yml up -d --build --no-deps server - -# статус контейнеров -docker compose -f docker-compose.local.yml ps -``` - -## Что уже встроено -- Backend scanner (RealiTLScanner) собирается в `server/Dockerfile` и кладется в контейнер backend. -- Блок `Автопоиск SNI (backend scanner)` показывается только если бинарник сканера доступен в контейнере. -- Во время сканирования UI получает статус с backend (`/api/domains/scan/status`) и показывает реальный countdown. -- Если обновить страницу во время скана, UI подхватывает активный запуск по backend-статусу и продолжает отсчет. -- После завершения скана результат можно получить из backend (`/api/domains/scan/last-result`) даже если исходный запрос был прерван (например, после F5). -- Предварительный список сканера: - - ручная проверка ссылками, - - удаление позиций, - - очистка, - - экспорт в `.txt`, - - сохранение состояния после F5. -- Основной список: - - ссылки на домены, - - hover-подсветка строк, - - экспорт полного списка в `.txt`. - -## Нормализация доменов (импорт и ручное добавление) -- Единые правила применяются и для загрузки файла, и для добавления по одному. -- `*.domain.com` нормализуется в `domain.com`. -- Комментарии и мусор отбрасываются (`#`, `;`, `//`, URL/пути/порты и т.п.). -- Дубликаты убираются без учета регистра. -- Явно некорректные значения отклоняются. - -## Тестовый "больной" список -- Файл для проверки импорта: `checker/domains-import-fuzz.txt` - -## Быстрые проверки -```powershell -Invoke-WebRequest -UseBasicParsing http://localhost:8080 -Invoke-WebRequest -UseBasicParsing http://localhost:3100/api -``` - -## Остановка -```powershell -docker compose -f docker-compose.local.yml down -``` - -## Перед PR -```powershell -git status --short -git diff --name-only -``` - -Проверяем, что в PR идут только целевые изменения фичи. - -## Обновление production (кастомная ветка) -Для сервера, где `bash <(curl ...)` не работает из-за `/dev/fd`, используем пайп: - -```bash -curl -fsSL https://raw.githubusercontent.com/iqubik/3dp-manager/dp-fix/update-custom.sh | bash -s -- -r https://github.com/iqubik/3dp-manager.git -b dp-fix -``` - -Что делает команда: -- подтягивает исходники из `iqubik/3dp-manager` ветки `dp-fix` в `/opt/3dp-manager-src`, -- собирает `backend/frontend` из этих исходников, -- поднимает контейнеры через `docker-compose.custom.yml` поверх текущей установки в `/opt/3dp-manager`. - -Проверка после обновления: - -```bash -cd /opt/3dp-manager -docker compose -f docker-compose.yml -f docker-compose.custom.yml ps -docker compose -f docker-compose.yml -f docker-compose.custom.yml logs --tail 120 backend -docker compose -f docker-compose.yml -f docker-compose.custom.yml logs --tail 120 frontend -``` - -Ожидаемо и нормально в логах frontend: -- `can not modify /etc/nginx/conf.d/default.conf (read-only file system?)` - -Это штатно при `:ro`-монтировании nginx-конфига. diff --git a/pub.md b/pub.md deleted file mode 100644 index a2dcdf0..0000000 --- a/pub.md +++ /dev/null @@ -1,99 +0,0 @@ -# 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/валидации в доменном модуле; критичных инфраструктурных изменений вне этих зон нет. diff --git a/update-custom.sh b/update-custom.sh deleted file mode 100644 index 979e475..0000000 --- a/update-custom.sh +++ /dev/null @@ -1,159 +0,0 @@ -#!/usr/bin/env bash -set -euo pipefail - -trap 'echo -e "\033[1;31m[ERROR]\033[0m Ошибка в строке $LINENO"; exit 1' ERR - -log() { echo -e "\033[1;32m[INFO]\033[0m $1"; } -warn() { echo -e "\033[1;33m[WARN]\033[0m $1"; } -die() { echo -e "\033[1;31m[ERROR]\033[0m $1"; exit 1; } - -usage() { - cat <<'EOF' -Использование: - update-custom.sh -r -b [-p ] [-s ] - -Параметры: - -r Git URL вашего форка (обязательно), например: - https://github.com//3dp-manager.git - -b Ветка с вашими правками (обязательно), например: - dp-fix - -p Папка установленного 3dp-manager (по умолчанию /opt/3dp-manager) - -s Папка исходников для сборки (по умолчанию /opt/3dp-manager-src) - -h Показать эту справку - -Пример: - ./update-custom.sh -r https://github.com/me/3dp-manager.git -b dp-fix -EOF -} - -need_root() { - [[ $EUID -eq 0 ]] || die "Запускать только от root" -} - -ensure_nginx_api_timeouts() { - local nginx_conf="$1" - [[ -f "$nginx_conf" ]] || return 0 - - local tmp_file - tmp_file="$(mktemp)" - - awk ' - BEGIN { in_api = 0; injected = 0 } - { - line = $0 - - if (line ~ /^[[:space:]]*location[[:space:]]+\/api\/[[:space:]]*\{/) { - in_api = 1 - injected = 0 - } - - if (in_api && line ~ /proxy_(connect|send|read)_timeout[[:space:]]+[0-9]+s;/) { - next - } - - print line - - if (in_api && line ~ /proxy_set_header[[:space:]]+X-Forwarded-For[[:space:]]+/ && injected == 0) { - print " proxy_connect_timeout 10s;" - print " proxy_send_timeout 650s;" - print " proxy_read_timeout 650s;" - injected = 1 - } - - if (in_api && line ~ /^[[:space:]]*}/) { - in_api = 0 - injected = 0 - } - } - ' "$nginx_conf" > "$tmp_file" - - mv "$tmp_file" "$nginx_conf" -} - -REPO_URL="" -BRANCH="" -PROJECT_DIR="/opt/3dp-manager" -SOURCE_DIR="/opt/3dp-manager-src" - -while getopts ":r:b:p:s:h" opt; do - case "$opt" in - r) REPO_URL="$OPTARG" ;; - b) BRANCH="$OPTARG" ;; - p) PROJECT_DIR="$OPTARG" ;; - s) SOURCE_DIR="$OPTARG" ;; - h) - usage - exit 0 - ;; - :) - die "Параметр -$OPTARG требует значение" - ;; - \?) - die "Неизвестный параметр: -$OPTARG" - ;; - esac -done - -[[ -n "$REPO_URL" ]] || { usage; die "Укажите -r "; } -[[ -n "$BRANCH" ]] || { usage; die "Укажите -b "; } - -need_root - -[[ -d "$PROJECT_DIR" ]] || die "Папка проекта не найдена: $PROJECT_DIR" -[[ -f "$PROJECT_DIR/docker-compose.yml" ]] || die "Не найден docker-compose.yml в $PROJECT_DIR" - -command -v git >/dev/null 2>&1 || die "git не установлен" -command -v docker >/dev/null 2>&1 || die "docker не установлен" -docker compose version >/dev/null 2>&1 || die "docker compose v2 недоступен" - -log "Подготовка исходников в $SOURCE_DIR" -if [[ ! -d "$SOURCE_DIR/.git" ]]; then - if [[ -e "$SOURCE_DIR" ]]; then - die "Путь $SOURCE_DIR существует, но это не git-репозиторий. Укажите другой -s или подготовьте папку вручную." - fi - git clone --single-branch --branch "$BRANCH" "$REPO_URL" "$SOURCE_DIR" -else - cd "$SOURCE_DIR" - git remote set-url origin "$REPO_URL" - git fetch origin "$BRANCH" - - if git show-ref --verify --quiet "refs/heads/$BRANCH"; then - git checkout "$BRANCH" - else - git checkout -b "$BRANCH" --track "origin/$BRANCH" - fi - - # Обновляем только fast-forward, чтобы не переписывать локальные ручные правки. - git merge --ff-only "origin/$BRANCH" || die "Не удалось fast-forward merge. Проверьте локальные изменения в $SOURCE_DIR." -fi - -COMPOSE_OVERRIDE="$PROJECT_DIR/docker-compose.custom.yml" -cat > "$COMPOSE_OVERRIDE" </dev/null"; then - log "Scanner binary найден в backend-контейнере" -else - warn "Scanner binary не найден в backend-контейнере" -fi - -log "Готово: VPS обновлен на ваш fork/branch"