Files
omarandClaude Opus 4.8 5f4271b747
CI / validate (push) Successful in 41s
CI / images (push) Failing after 5s
Initial implementation: proxy checker panel + subscription system
Full stack per GOAL.md / TODO.md:
- checker (Go): fetch sources, canonicalize/dedup (whitelist+sort, & fixes),
  validity check (connect+latency+speed gates), geoip by exit IP, session model
  ("only working / last completed session"), global lock, manual run/stop,
  Telegram start/finish notifications. Reuses tessero-checker dialers
  (vless/vmess/trojan/ss), upstream parser, geoip, fetcher.
- api (Go): admin auth (single operator), dashboard stats, proxies
  list/filter/export/bulk, subscriptions CRUD, sources CRUD, settings, checker
  control, and dynamic public /sub endpoints with unique_ips + plain/base64/
  clash/singbox rendering.
- frontend (React+Vite+TS+Tailwind): telemetry-console SPA — Dashboard, Proxies,
  Subscriptions, Settings.
- postgres schema, docker-compose (postgres/checker/api/web-nginx), Dockerfiles,
  Gitea Actions CI.

Verified end-to-end via Docker: pipeline, all sub formats, unique_ips collapse,
and all four panel tabs (Playwright).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014TtR4PP2JM9KadaBkhPGAE
2026-07-02 01:02:00 +03:00

18 KiB
Raw Permalink Blame History

zhguchiy_perchik — список желаний (wishlist)

Это НЕ архитектура и НЕ ТЗ. Это список того, что панель должна уметь, — «хотелки» по функционалу. Стек, схему БД, API и деплой обсуждаем отдельно позже.

Статус: [~] — под вопросом (обсуждаем), [x] — согласовано, делаем.


О проекте

Панель-чекер прокси со своей sub-системой.

Суть: постоянно тянем конфиги прокси (vless / vmess / trojan / ss) из списков-источников, проверяем каждый на валидность (по его исходящему IP), храним только рабочие, и отдаём клиентам как подписки (sub-ссылки, конфиги через \n для Happ / v2rayN и подобных).

Критерий «валидности» (что проходит чек):

  • Успешный коннект (handshake по протоколу) + удалось узнать exit IP в пределах таймаута.
  • Латенси не хуже порога (порог в настройках).
  • Скорость не хуже порога (порог в настройках) — спидтест ЯВЛЯЕТСЯ гейтом валидности, гоняется для каждого кандидата, прошедшего коннект+латенси.

Модель данных «только рабочие / только последняя сессия» (ключевой принцип)

  • В базе (для отображения и выдачи) — только рабочие прокси, и только они.
  • Работаем сессиями чека: check_session_N отчекала всё → по ней показываются прокси и вся статистика. Пока check_session_(N+1) в работе (или крашнулась — неважно), панель и подписки всегда показывают результат последней завершённой сессии.
  • Незавершённая / упавшая сессия не должна портить текущую выдачу — переключение на её результат происходит только когда она успешно завершилась.
  • Нет автоудаления по N провалам и нет «мёртвого пула» в выдаче — невалид просто не попадает в актуальную сессию и не отдаётся клиентам. (см. «Автоудаление — нет».)
  • Счётчики валид/невалид для статистики берём из результатов сессий (сколько кандидатов проверено, сколько прошло/не прошло), а не из выдаваемого списка.
  • Персистентная история по canonical URL: на каждый уникальный прокси помним first_seen, last_alive, аптайм, провалы подряд, последние метрики — даже когда он сейчас невалиден. Это внутренняя история; в панели/подписках показываем и отдаём только рабочие из последней завершённой сессии. (нужно для аптайма и «провалов подряд»)
  • Историю сессий храним ВСЮ, без чистки/ретеншена (для трендов по дням/неделям/месяцам).
  • Атрибуция source: закрепляем за прокси ПЕРВЫЙ увиденный источник (first-seen), один source на прокси.

Уникализация прокси (грамотная) — с фактами из реальных источников

Проверил живьём ~577k строк из источников (__init__.py). Что реально прилетает и как чистим:

Что нашли (реальная «грязь»):

  • Почти у КАЖДОЙ строки есть #-метка — это реклама/лейбл, не часть конфига. Примеры: 🔥Join+Telegram:@Farah_VPN🟣 (×6939), EPODONIOS, @oneclickvpnkeys::US, @meliproxyy, کانال تلگرام, флаги-эмодзи стран, t.me/….
  • Рекламные query-параметры: Telegram (×25908 у vless), note (×1887), brand, @NebulaVPNx, и даже целый URL как имя ключа: https://t.me/WangCai2🇨🇳.
  • Баг HTML-экранирования: ~3.5% строк содержат &amp; вместо & → параметры превращаются в битые amp;type, amp;security (amp;type ×15251 у vless), встречается и вариант с ведущим ; (;type) и двойной amp;;security.
  • Битые строки: два конфига слиты без переноса (…type=tcptrojan://…), недекодируемые base64-блобы, текст ошибок вида 订阅内容解析错误 («ошибка парсинга подписки»).

Правила чистки (желания):

  • Разэкранировать &amp; → & (и разобрать варианты с ;/двойным amp;) ДО парсинга.
  • Выкинуть фрагмент #… целиком (метки/реклама) — до сохранения и до чека.
  • Вайтлист query-параметров по протоколу: оставляем только реально влияющие на коннект, остальное режем (реклама отваливается сама). Черновой вайтлист:
    • vless: type, security, encryption, sni, fp, path, host, pbk, sid, flow, headerType, alpn, mode, spx, serviceName, allowInsecure/insecure, packetEncoding, authority, extra, ech, quicSecurity; новые xhttp: x_padding_bytes, pcs, pqv, fm; ws early-data: ed, eh.
    • trojan: sni, type, security, path, host, allowInsecure, fp, alpn, headerType, mode, serviceName, sid, pbk, spx, peer.
    • ss: userinfo = base64(method:password); из query по сути только plugin.
    • vmess: это base64(json) — декодируем, оставляем add, port, id, aid, net, type, host, path, tls, sni, alpn, fp, scy, v; выкидываем ps (лейбл) и мусор (name, test_name, nation, pcs, vcn, deviceID).
    • Точный вайтлист финализируем при реализации (сверяемся с v2ray URL-спекой).
  • Сортировать query-параметры по алфавиту → одинаковый прокси в разном порядке параметров даёт один и тот же канонический URL.
  • Нормализация формы: единый регистр схемы, обрезка хвостового / в host:port, нормализация percent-encoding; для vmess — переупаковать json канонично.
  • Дедуп по каноническому URL (после всей чистки). В базе/выдаче — уже чистый URL.
  • Битые/непарсящиеся строки — отклонять (не считать за прокси).
  • Показывать в панели, сколько дублей/мусора схлопнулось при импорте (сырых строк → уникальных после канонизации).

Известное ограничение:

  • [~] hysteria2 / hy2 / ssr / tuic встречаются (hysteria2 ×594 и т.д.), но Go-диалеры их не умеют — будут отсеиваться. Возможно добавим поддержку позже.

Уникализация по out_ip (кнопка unique_ips)

Две РАЗНЫЕ прокси (разный протокол/настройки/конфиг-строка) могут после подключения выходить в интернет с ОДНОГО и того же out_ip — это дубли «по точке выхода» (по конфигу они уникальны, по выходу — нет). Это отдельная от canonical-URL уникализация.

  • Кнопка/тумблер unique_ips в табах Proxies и Subscriptions. Когда включена — группа прокси с одинаковым out_ip схлопывается до ОДНОГО прокси-победителя. На выходе — список / сабка, уникальные по out_ip.
  • Рядом с кнопкой — переключатель МЕТРИКИ схлопки: по speed_test (берём с макс. Mbps) или по latency (берём с мин. мс). Победитель на каждый out_ip выбирается по ней.
  • Дефолт: метрика speed_test; тай-брейк при равной скорости — меньшая латенси. Сам unique_ips по умолчанию выключен (opt-in).
  • Это фильтр отображения/выдачи — базу не меняет. В Proxies — тумблер над таблицей; в Subscriptions — опция подписки (хранится в её настройках, влияет на sub-ссылку).

Вкладки панели

1. Dashboard (статистика по сети — максимально подробно)

  • Кол-во валид / невалид (по последней сессии), числом и в %.
  • Разбивка валид/невалид по дням / неделям / месяцам (графики-тренды).
  • Общее кол-во рабочих прокси в базе (актуальная сессия).
  • Динамика: сколько добавилось нового / сколько отвалилось за день/неделю/месяц.
  • Разбивка по протоколам (vless / vmess / trojan / ss) — кол-во и % валида.
  • Разбивка по странам (гео по exit IP) — топ стран.
  • Разбивка по источникам — какой source даёт валид, какой мусор.
  • Статистика по латенси (средняя / медиана / распределение по бакетам мс).
  • Статистика по скорости (спидтест включаем, ссылка в настройках).
  • Аптайм конкретных прокси (как долго прокси держится живым между сессиями).
  • Время последнего чека, длительность.
  • Живой прогресс текущего цикла (проверено X из Y) + статус активной сессии.

2. Proxies

  • Список прокси с фильтрами: протокол, страна, источник, латенси, скорость.
  • Поиск по прокси.
  • Выгрузка отфильтрованного списка в .txt (по \n).
  • Скопировать конкретную проксю одной кнопкой.
  • Массовые действия: удалить выбранные, пере-проверить выбранные.
  • Метаданные прокси: пинг, страна, exit IP, кол-во провалов подряд, откуда взят.
  • Кнопка unique_ips + переключатель метрики (speed_test / latency) — схлопка списка до уникальных по out_ip (см. раздел «Уникализация по out_ip»).

3. Subscriptions (подписки для клиентов)

  • Создание подписки → уникальная sub-ссылка.
  • Отдача прокси через \n (формат для Happ / v2ray и прочих).
  • Sub отдаётся ДИНАМИЧЕСКИ: каждый запрос — актуальные рабочие по фильтрам из последней завершённой сессии (без кэша/снапшота).
  • Фильтры подписки:
    • по протоколу(ам);
    • по стране(ам);
    • по статусу (только живые);
    • по латенси / скорости (не хуже порога);
    • по источнику;
    • лимит количества (топ-N).
  • Опция unique_ips + метрика (speed_test / latency) — сабка отдаёт уникальные по out_ip (см. раздел «Уникализация по out_ip»).
  • Сортировка выдачи по одному или нескольким параметрам (выбираемым) — напр. по скорости, латенси, стране.
  • Порядок формирования выдачи подписки: фильтры → (опц.) схлопка unique_ips → сортировка по выбранным параметрам → лимит топ-N. Т.е. лимит N считает УЖЕ уникальные по out_ip прокси.
  • Форматы выдачи (выбираются на подписке): plain text (\n), base64 (v2ray/Happ), Clash / Clash.Meta YAML, sing-box JSON.
  • Вкл/выкл подписки, срок действия. Если подписка выключена или истёк срок — sub-ссылка отвечает 404 / ошибкой.
  • Статистика по подписке: сколько раз дёргали, когда последний раз.

4. Settings

  • Интервал проверки прокси (как часто гоняем цикл; каждый цикл сам перефетчивает источники — отдельного интервала импорта НЕ надо).
  • Список source'ов — откуда брать прокси (добавить / удалить / вкл-выкл). Это ссылки на листы (txt / подписки).
  • Параметры чека: таймаут, кол-во воркеров, порог латенси, порог мин. скорости, интервал чека, вкл/выкл спидтест. Черновые дефолты (тюнятся в UI): интервал 12 ч, воркеры 10, таймаут 5 сек, порог латенси 1000 мс, мин. скорость 3 Mbps.
  • Ссылка для спидтеста (для замера скорости) — настраивается.
  • URL для проверки коннекта / получения exit IP — НЕ в настройках, зашит дефолтом (надёжный IP-echo сервис, желательно с фолбэком на несколько).
  • Гео-база: выбирается в настройках; дефолт — geolite2-geo-whois-asn-country (mmdb) из https://github.com/sapics/ip-location-db. Страна прокси определяется по его exit IP.
  • Ручной запуск чека / импорта кнопкой + кнопка СТОП. Активна может быть только ОДНА операция чека зараз (глобальный лок): полный цикл и ручной «пере-проверить выбранные» не идут параллельно — второй блокируется, пока первый не завершится.
  • Telegram-уведомления: в настройках задаётся ОДИН bot token + ОДИН chat_id, с чекбоксами когда слать — на НАЧАЛО чека и на КОНЕЦ (в конце — со статистикой сессии).

Явные «нет» (чтобы не делать лишнего)

  • Отдельный интервал импорта — НЕ надо (каждый перечек перефетчит источники).
  • Автоудаление прокси после N провалов — НЕ надо (храним только рабочие, см. модель выше).
  • Экспорт всей базы / бэкап — НЕ надо.
  • Уведомления «валида стало меньше обычного» — НЕ надо (телега шлёт только старт/финиш чека).

Идеи на потом (не для первой версии)

  • История циклов проверки (когда, сколько проверено, сколько прошло) — нужна.
  • [~] Поддержка hysteria2 / tuic / ssr — НЕ в первой версии (в источниках ~0.1%), возможно позже.

Что осознанно обсуждаем ОТДЕЛЬНО (не сейчас)

  • Стек (бэкенд / чекер / фронт), язык, библиотеки.
  • Схема БД, API-эндпоинты.
  • Как именно реализуем модель «последняя завершённая сессия» на уровне БД.
  • Точный финальный вайтлист параметров по протоколам.
  • Аутентификация в панель.
  • Деплой.