Files
QVPN/research/analysis.md
T

17 KiB
Raw Blame History

QVPN: обследование BlancVPN и проверяемые решения

Дата обследования: 4 октября 2026 года, Москва. В этом документе нет ссылки подписки, UUID, ключей Reality и адресов серверов из личной подписки.

Что подтверждено на подключённом телефоне

dumpsys package установленного com.blancvpn.app показал versionName=1.8.7, versionCode=189, minSdk=28, targetSdk=36. Запись сохранена в phone-package.txt. Основное окно на phone.png показывает установленное VPN-соединение, выбранную локацию, большой переключатель подключения, переход к локациям и режим «Российские сервисы открываются без VPN».

Из APK исследованы имена компонентов и файлов, без переноса программного кода или ресурсов в QVPN. Обнаружены XrayVpnService, AwgVpnService, Flutter-ресурсы и библиотеки libflutter.so, libapp.so, libgojni.so, libhev-socks5-tunnel.so, libam-go.so, libam-quick.so, libam.so. Это подтверждает наличие Flutter-интерфейса и отдельных нативных VPN-компонентов. Имена файлов сами по себе не устанавливают точную версию ядра Xray, его текущие настройки или причину стабильности телефонного приложения.

В APK также обнаружены названия встроенных правил ru_merged_geoip.dat, ru_merged_geosite.dat, ru_whitelist_rules_v1.json и ru_app_ids.json. Они указывают на отдельную маршрутизацию российских ресурсов. Их содержимое не используется как база правил QVPN; для Windows выбраны открытые наборы и собственные правила. Фирменные изображения, шрифты, код приложения, токены встроенных сервисов и закрытые списки BlancVPN не копируются.

Что подтверждено по подписке

Приватно полученное содержимое содержит 50 локаций VLESS с Reality поверх TCP. Парсер QVPN обработал эти 50 записей; диагностический вывод содержит только LIVE_PARSE nodes=50. Ключ не включён в исходники, тестовые фикстуры и отчёт.

Импорт ограничен HTTPS-ссылкой домена withblancvpn.online или его поддомена, маршрутом /s/…, стандартным портом, без userinfo, фрагмента и query. Отклоняются чужие домены, подмена суффикса, Unicode/punycode-подмена имени провайдера, HTTP и перенаправления HTTP. Для этой версии принимаются только проверенный формат VLESS/Reality TCP и публичные IP-адреса серверов. Локальные, loopback, private и link-local адреса не могут стать целью привилегированного VPN-процесса через подписку. Это намеренно узкая совместимость с обследованной подпиской; новые форматы провайдера требуют отдельной реализации.

Почему Happ разрывает соединение

Причина пока не установлена. В проведённой проверке Windows за семь дней среди последних 300 записей ошибок приложений не найдено подтверждённого падения Happ. Ограниченное окно журнала не доказывает отсутствие всех падений и не отличает остановку ядра, сетевую ошибку, сон, обновление маршрутов и ручное отключение. Нельзя утверждать, что найдена и устранена конкретная ошибка Happ.

Для QVPN выбран Windows Service, работающий отдельно от окна. Закрытие интерфейса не должно прекращать VPN. Доступность проверяется запросом через отдельный локальный прокси, принудительно направленный в VPN; прямой доступ российских сервисов не должен дать ложное подтверждение исправности туннеля. Восстановление после ошибки использует ограниченную задержку 2, 4, 8, 16, 32, 60 секунд и смену локации при разрешённом автоматическом переключении. Успешная единичная проверка сбрасывает серию ошибок, но не накопленный backoff. Намерение пользователя «подключено» хранится отдельно от фактического состояния.

Восстановление процесса, реальная передача данных, рестарт службы, сон/пробуждение и многочасовая стабильность — разные границы проверки. Тест алгоритма восстановления не подтверждает работу сети, а краткий успешный сетевой тест не подтверждает многочасовую стабильность. В итоговой передаче следует указывать отдельно фактически выполненные проверки.

Ядро и маршрутизация

QVPN запускает неизменённый официальный Windows x64 sing-box 1.14.2 отдельным процессом. На момент обследования это последний стабильный релиз, отмеченный upstream как Latest. Источник: официальный релиз v1.14.2.

SHA-256 архива sing-box-1.14.2-windows-amd64.zip повторно вычислен локально и совпал с digest релизного API:

c2d8bfff918755808781dfdeeb8581b6c91eb3a243d9a7b55483cfc0c0684d32.

SHA-256 распакованного sing-box.exe:

7bbef1dea9189ee12799ae834ea4b4658355da25c47a21ad8804904c0ccd9410.

Конфигурация QVPN включает TUN с IPv4/IPv6, auto_route, strict_route, перехват DNS, DoH через VPN, обход локальных IP и управляемый обход российских доменов/открытых rule-set. Официальная документация описывает TUN и ограничения Windows, VLESS, Reality/TLS, DoH и маршрутизацию. Документация публикуется для нескольких версий; допустимость созданного JSON должна проверяться именно бинарником 1.14.2.

Лицензия и исходники ядра

Upstream LICENSE для точного тега разрешает sing-box по GPL версии 3 или более поздней, сохраняет copyright и отдельно ограничивает использование имени/ассоциации производных работ: LICENSE v1.14.2. QVPN не использует имя ядра как своё название и не заявляет принадлежность к SagerNet или BlancVPN.

В пакет с ядром следует включать upstream LICENSE, полный текст GPL-3.0 и уведомление: «sing-box 1.14.2, Copyright (C) 2022 nekohasekai. Ядро распространяется без изменений. Лицензия GPL-3.0-or-later».

Точный исходный тег: SagerNet/sing-box v1.14.2; архив исходников: v1.14.2.zip. При распространении бинарников необходимо сохранить лицензионные уведомления и обеспечить соответствующий исходный код и материалы сборки по условиям GPL. Одна ссылка на репозиторий не заменяет проверку полноты исходного комплекта для выбранного способа распространения.

Автоматические проверки QVPN.Core

dotnet run --project tests/QVPN.Tests/QVPN.Tests.csproj -c Release — 16 групп проверок, 16 успешно, 0 ошибок. Внешний тестовый фреймворк не требуется.

Проверены допустимая подписка и запреты импорта, 50 синтетических записей в открытом и base64-виде, удаление дублей, очистка имён, ошибочные Reality-параметры, запрет локальных адресов, DPAPI roundtrip/замена/backup/повреждение и наследуемые ACL защищённого каталога, отсутствие открытого текста в файлах, двусторонний протокол IPC и ограничения размера, маршрутизация health-проверки, TUN/DNS, переключатель российских ресурсов и политика восстановления. DPAPI LocalMachine требует защищённого каталога службы: шифрование само по себе не ограничивает другие локальные учётные записи.

Для приватной проверки содержимого: QVPN.Tests --live-parse <private-file>. Для интеграционной проверки службы предусмотрено QVPN.Tests --client <command> --value-file <private-file>; запрос и значение ключа не выводятся, ответ содержит только публичный Status. Отчёт не является доказательством многочасовой работы VPN.

QVPN.Tests --engine-check <sing-box.exe> успешно проверил JSON официальным бинарником 1.14.2 для четырёх сочетаний TUN on/off и российского обхода on/off, все exit=0. Проверка использует только синтетический ключ и не подключается к серверу. Она подтверждает допустимость конфигурации для выбранного ядра, отдельно от сетевой работы.

После единичной ошибки загрузки в .NET проведено повторное обследование командой QVPN.Tests --download --value-file <private-file> --diagnose. Непосредственный Subscription.DownloadAsync получил 50 локаций. Диагностические запросы direct, system-proxy и IPv4-direct вернули HTTP 200 с корректной TLS-цепочкой (SslPolicyErrors.None). DNS на момент проверки вернул один IPv4 и не вернул IPv6. Ошибка не воспроизведена; изменение проверки сертификатов или принудительное отключение IPv6 этим замером не обосновано. Диагностика выводит только типы исключений, HRESULT и значения enum, без Exception.Message, URL, адресов и credentials. Устойчивость загрузки должна обеспечиваться повтором временной сетевой ошибки и сохранением последней рабочей подписки.

Проверка обработчика службы после исправлений

В review найдены и исправлены: потеря IPC-слушателя при JsonException, ожидание бесконечного соседнего цикла вместо реакции SCM на fatal, сохранение работающего ядра после ошибки записи при отключении и неограниченное ожидание TCP-измерений при остановке. Дополнительно исправлены права CreateNewInstance диагностического сервера: полный доступ получает текущая серверная учётная запись, тогда как пользовательский клиент в режиме службы SYSTEM сохраняет только клиентские права.

Реальная команда QVPN.Tests --malformed-service --evidence-file research/service-regression.json отправила восемь повреждённых JSON-фреймов с клиентским TokenImpersonationLevel.Identification в уже запущенный обработчик. Каждый запрос был закрыт, после каждого status успешно ответил; до и после оставались 50 локаций и состояние disconnected. Во время проверки ядро не было запущено, поэтому этот замер подтверждает живучесть IPC и сохранение состояния, а не непрерывность активного туннеля. Команда не запускала TUN, не меняла настройки и не перезапускала службу. Публичный JSON содержит только время, счётчики, состояния и PID.

Проверка установленного приложения, 4 октября 2026

Установленная служба LocalSystem и системный адаптер QVPN работают. HTTPS без явного прокси через системную маршрутизацию вернул 204. На рабочем ключе доступны 50 локаций.

Принудительное завершение установленного TUN-ядра: восстановление за 11.1 секунды без ввода ключа. Принудительное завершение службы: SCM восстановил службу и подключение за 11.4 секунды, дочернее ядро предыдущей службы не осталось работать. Последующий HTTPS-запрос через системный маршрут вернул 204. Свидетельство: installed-recovery-verification.json.

Старый installed-verification.json содержит ошибочный отказ теста: после завершения ядра проверка сразу прочитала предыдущий снимок connected со старым PID. Исправлено ожидание нового PID одновременно с проверенным состоянием connected. Это ошибка первоначального проверочного скрипта, а не подтвержденный отказ восстановления приложения.

В конце проверки VPN оставлен включённым, локация Цюрих, Швейцария. Отрисовка установленного интерфейса по реальному статусу — installed-live.png, не демонстрационный режим. Многосуточная эксплуатация и реальный цикл сна/пробуждения этой короткой проверкой не подтверждаются.