zapret-kvn/docs/UI_AND_OFFLINE_GEOIP.md
loop-uh 4d82c490cf
Some checks failed
Windows project source guards / test (push) Failing after 50s
fix: retain authenticated AWG while checking HTTPS in background
2026-09-06 15:36:10 +03:00

177 lines
17 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Главная, серверы и локальная GeoIP
Главная использует стандартные карточки qfluentwidgets и прозрачные поверхности
для Mica. Подробные графики и процессы доступны на внутренних страницах.
Нормальный размер окна сохраняется; восстановление выполняется при загрузке
состояния, а не при каждом изменении настроек. Базовый минимум — 860×560,
первый размер — 1000×720 логических пикселей с ограничением по рабочей области.
Серверы показаны через одну Fluent TableView с плоской моделью и строками 28 px. По умолчанию они сгруппированы по ID
подписки; одноимённые подписки не смешиваются. Группировку можно отключить либо
переключить на поле группы, страну или протокол. Столбец имени больше не
растягивается вслед за окном. Меню «Вид» управляет столбцами и группами;
избранное доступно через контекстное меню и меню «Ещё». Поиск скрыт до Ctrl+F.
Мышь, множественное выделение, двойной щелчок, копирование ссылок, контекстное
меню и клавиатурная навигация остаются доступны. Тонкие границы строк и колонок
рисуются только в видимой области, без создания виджета для каждого сервера.
Флаги и состояние активности обновляют только соответствующие ячейки. Пакеты
метрик пересортировывают список только при изменении текущего ключа сортировки.
Обновления метрик свёрнутых групп не отправляют уведомления представлению;
их пересортировка откладывается до раскрытия. Данные и выделение сохраняются.
Сортировка сохраняет постоянные индексы; при изменении состава списка выделение
восстанавливается по ID оставшихся серверов, а свёрнутые группы — по ключам.
## Данные и совместимость
- `Node.is_favorite` и `Node.country_override` сохраняются вместе с профилем.
Обновление подписки переносит эти поля через существующее сопоставление узлов.
- `country_code` — вычисляемое поле в памяти. Старые сохранённые предположения
о стране при загрузке игнорируются.
- Настройки вида имеют `nodes_column_layout_version = 2`, поля `nodes_group_by`,
`nodes_favorites_only`, `nodes_collapsed_groups` и сохраняемые ширины всех
столбцов. Индивидуальная видимость столбцов сохраняется при миграции.
## Сетевой контракт GeoIP
Ручной выбор страны имеет приоритет. Если в имени есть флаг-эмодзи, используется
его код страны; эмодзи убирается только из отображаемого имени и заменяется PNG.
Оригинальное имя и ссылка сохраняются. Обычные слова и буквенные коды в имени
не используются для угадывания страны.
Для серверов без флага используется локальная DB-IP Country Lite MMDB.
Оно никогда не вызывает DNS, DoH/DoT, HTTP, внешние GeoIP API, тестовые
подключения или запросы внешнего IP. Домены без уже известного IP остаются без
страны. Результаты штатного разрешения endpoint передаются пассивно;
геолокация не инициирует разрешение и не меняет routing/DNS конфигурацию ядра.
Для AWG/WireGuard используются peer endpoint, а не адрес интерфейса или
AllowedIPs. Разные страны у неоднозначных endpoint означают отсутствие
автоматического результата. Ручная страна имеет приоритет. Флаги загружаются
только из настоящих PNG; неизвестный код или недостающий файл не подменяются
полосами либо другой картинкой.
## Сборочная база
`release_windows.py` перед фиксацией исходников нового stable запускает
`prepare_geoip.py --refresh`. Скрипт получает последний доступный ежемесячный
снимок с официальной страницы DB-IP, проверяет MMDB и записывает дату и хеши
в `scripts/geoip-lock.json`. Бинарные данные остаются в `.cache/geoip`.
`build.py` включает закреплённые данные в `assets/geoip` вместе с атрибуцией.
Dev/stable gates проверяют хеш в итоговом payload. Возобновление релиза не
выбирает новую базу; несовпадение хеша или недоступность источника при подготовке
нового stable останавливают соответствующий этап. В приложении нет загрузчика
или кнопки обновления GeoIP.
Источник и лицензия: [DB-IP Country Lite](https://db-ip.com/db/download/ip-to-country-lite),
[CC BY 4.0](https://creativecommons.org/licenses/by/4.0/).
## Запуск и проверки
Splash удалён. `StartupLoader` читает состояние в рабочем потоке и передаёт
ранние параметры темы и геометрии до показа окна. Виджеты и Qt-модели остаются
в GUI-потоке. Неоткрытые страницы получают последние снимки через DeferredPage
и создаются при первом обращении. Версии ядер и пресеты подготавливаются
отдельно; геолокация не задерживает подключение.
Отмена до загрузки состояния не сохраняет пустое состояние поверх реального.
Логи запуска содержат длительность подготовки и готовности управления.
Проверки включают 10 000 узлов, устойчивость выбора и ширин, запрет сетевых
вызовов из GeoIP, отмену загрузки и проверку сборочных хешей. Проверка Mica и
фактического времени запуска Windows EXE выполняется после ручной сборки.
## DNS и первое подключение
Штатные JSON-шаблоны sing-box используют native fallback: DoH через VPN →
прямой DoH с устройства → системный DNS. Внутри каждого DoH-этапа три
резолвера проверяются параллельно с ограниченным временем ожидания. IP адреса
DoH заданы явно, сертификаты проверяются по TLS server_name. NXDOMAIN
считается ответом, а не причиной обходить настроенный resolver.
Переход на резерв отмечается WARN в логе ядра и предупреждением интерфейса.
Для системного DNS отдельно указано, что запросы могут быть видны провайдеру.
Последовательность принадлежит native JSON. Секция `dns` автоматически
перезаписывается из текущего стандартного шаблона при запуске, чтении и сохранении
активного конфига, включая изменённые пользователем копии. Остальные поля
(маршрутизация, outbounds, параметры интерфейса) сохраняются. Запись атомарная;
неизменившаяся DNS-секция не вызывает повторную запись на диск. Для движка без
DNS-секции в штатном шаблоне новая политика не придумывается.
Amnezia запускает одну ограниченную волну HTTPS-проб, которая инициирует
handshake. Подтверждение авторизации берётся из статистики собственного ядра.
После handshake уже запущенные пробы завершаются в фоне; без handshake запуск
по-прежнему завершается ошибкой. Отмена подключения отменяет наблюдение за пробами.
Hysteria использует тот же общий SOCKS/HTTPS probe, что и Amnezia. До старта
sing-box DNS пробы используют IP с исходным TLS SNI и проверкой сертификата.
Официальное событие `INFO connected to server` подтверждает завершённую
авторизацию Hysteria. После него запуск продолжается, а уже запущенная волна
HTTPS-проб завершается в фоне без новых сетевых запросов. Отказ всех проверочных
адресов вызывает одно предупреждение и запись в журнале, но не отключает
подтверждённое соединение. Успешная авторизация сама по себе не доказывает
доступность произвольных сайтов — это различие явно видно в предупреждении.
Без подтверждения авторизации и без успешной HTTPS-пробы запуск по-прежнему
завершается ошибкой. Ошибки сертификата и авторизации обрабатываются сразу.
Остановка или замена процесса отменяет наблюдение за старыми пробами; их
результаты не меняют статус новой сессии. Диагностика отдельно сохраняет
`remote_authenticated` и `https_check` в статистике Hysteria.
Штатный QUIC режим соответствует Android: ChromeParrot выключен, параметры
obfs и TLS pin из профиля сохраняются. Информационные сообщения официального
клиента попадают в журнал с удалёнными секретами. Структурированные события
разбираются до удаления секретов, но после удаления цветовых кодов терминала.
Регрессия проверяется настоящим локальным ядром Hysteria: сервер принимает
авторизацию, а тестовый TCP-адрес молча удерживает TLS ClientHello. Windows
release gates используют поставляемое ядро; на Linux тест включается через
`HYSTERIA_TEST_BINARY`. Все адреса интеграционного теста находятся на loopback.
## AWG: DNS после подтверждённого транспорта
Первый этап AWG требует подтверждённый handshake. HTTPS по IP проверяется
в фоне и не отключает туннель при отказе фиксированных проверочных адресов.
Проверка доменных адресов после запуска sing-box ставится в очередь за IP-пробами
и выполняется в фоне
общим `BackgroundHealthCheck`, который также используется Hysteria. Отказ DNS/HTTPS
по доменам записывает одно предупреждение и `front_dns_check=warning`, сохраняя
авторизованный туннель. Handshake сам по себе не доказывает работоспособность
прикладного трафика; предупреждение и поля `https_check` / `front_dns_check`
сохраняют это различие. Ошибка отдельного сайта не переводит весь VPN
в состояние ошибки. Сбой процесса, наблюдателя и исчерпание handshake остаются
фатальными; результаты отменённой сессии не влияют на следующую.
Делегирование DNS в sing-box ждёт до 15 секунд вместо 5, чтобы native fallback
успевал перейти к резерву. SOCKS CONNECT имеет отдельный бюджет 30 секунд после
авторизации, включающий DNS и TCP; завершение сессии по-прежнему отменяет запросы.
Отдельный resolver в AWG не добавляется. Локальный тест с DNS-ответом через 5,2
секунды воспроизводит отказ прежней версии и проходит после исправления.
## Кэш таблицы в памяти
`NodesGroupModel` хранит до 8192 значений ролей запрошенных ячеек в ОЗУ. Повторное
открытие вкладки и resize используют этот же кэш, пока данные не изменились.
Изменение узла инвалидирует его строку, включая скрытые строки; изменения структуры,
сортировки или темы очищают соответствующий кэш. Дисковый кэш не создаётся.
Скрытые группы не получают отрисовку или пересортировку из-за фонового пинга.
Плоские рамки рисуются тонкими прямоугольными полосами, без дорогой растеризации
скругления каждой широкой строки. Пересчёт ширин после resize объединяется в один
вызов на 16 мс; изменение только высоты не перераспределяет колонки, неизменившиеся
секции повторно не изменяются. Выбор, мультивыбор, раскрытие групп, сортировка и
контекстные действия продолжают использовать живую Qt-модель.
На локальном offscreen-стенде с 884 узлами и областью 1720×900 профиль 20 кадров
сократился примерно с 0,69 до 0,30 с. Это замер изолированной таблицы на Linux,
а не измерение Windows Mica или пользовательского компьютера.
## Проверка Android
В Android `447328b` проверен путь `VpnHealthPipeline` → `ZapretVpnService`.
Он проверяет DNS и три HTTPS-адреса через VPN, затем делает одну спасательную
попытку; отказ всех проб закрывает сессию. Это отдельный строгий gate, который
нельзя считать исправленным Windows-изменением. JVM-проверки: 336 тестов без
ошибок. ADB-устройств и туннеля 15037 при проверке не было; испытание на телефоне
и изменение Android VPN/DNS без диагностик устройства не выполнялись.