singbox-launcher 2.2.0

Demonis

Новичок
singbox-launcher - Кросс-платформенный десктоп-клиент (Windows, macOS, Linux), который оборачивает sing-box и добавляет вокруг него всю поверхность управления: визуальный конфигуратор, работу с несколькими подписками, переключение серверов с пингом, сетевую observability, декларативную маршрутизацию через preset bundles, локальный HTTP API и self-healing supervision. Четыре слоя, которые вместе определяют продукт:
  • Пользовательский слой — старт/стоп одной кнопкой, поток «subscription URL → работающий VPN», переключение серверов с пингом, правила маршрутизации через чекбоксы, окно Traffic Profiler с per-process атрибуцией.
  • Power-слой — Configurator с полной семантикой правил sing-box (CIDR, regex доменов, process matching, sniff, GeoIP/Geosite через SRS), preset bundles с условиями if / if_or, выбор DNS-серверов с условными правилами.
  • Флот-слой — вкладка Удалённые управляет другими машинами (роутер, VPS, другой Mac), где ядро работает демоном: у каждой свой профиль визарда и собранный конфиг, свои Start/Stop и Deploy, свой профайлер трафика и окно телеметрии хоста.
  • Headless-слой — bearer-auth Debug API на 127.0.0.1, ~30 локальных эндпоинтов: чтение и запись state, action-триггеры, управление capture трафика, snapshot endpoint для support workflows.
2.0.0 — начало единой экосистемы с LxBox: один контракт данных (contract/registry + corpus), разбор ссылок / Xray JSON / wg-quick .conf и сборка share-ссылок идут общим движком от таблиц реестра, одинаковое поведение на одних и тех же подписках. Это начало сближения, не завершение: LxBox v2.25.0 выходит на контракте 1.1.37, лаунчер на 1.1.46, разница аддитивная.

Основное
  • 2.0.0 — один контракт с LxBox. Десктоп и телефон читают одни таблицы протоколов: подписка, разобранная здесь, даёт те же тела узлов, коды предупреждений и share-ссылки, что LxBox на том же входе. Изменилось не количество фич, а конец параллельных копий правил, которые разъезжались.
  • Узел попадает в конфиг одной дорогой: откуда бы он ни пришёл — ссылкой, вставленным JSON-объектом, подпиской, бэкапом или .conf WireGuard, — его проверяет один набор правил протокола и записывает один эмиттер. Раньше эти правила жили в трёх разошедшихся копиях, и один и тот же битый узел ссылкой принимался, а объектом — нет.
  • Если у узла что-то сняли, он об этом говорит. Поля, которые ядро отвергает, снимаются с названной причиной на самом узле (⚠ в списках, подробности в карточке) вместо молчаливого исчезновения. Прежде подписка «обновлялась», у узла молча срезали обфускацию или сертификат, и увидеть это было негде. Три новых кода предупреждений называют, что снято: неизвестный параметр ссылки (uri_param_unknown), неизвестное поле JSON (json_field_unknown) или пустой пароль (password_empty).
  • Порт Shadowsocks по умолчанию — 8388 (был 443), как в каноне схемы и в LxBox.
  • Список Servers можно сузить без бесконечной прокрутки: окно фильтра отбирает по regex имени, протоколу, транспорту, источнику и порогу пинга, с чипами-эмодзи у имён Направлений.
  • Пока ядро работает, окно Core показывает статус Tailscale tailnet — подключённые пиры, свой адрес и задействован ли удалённый state_directory.
  • Один негодный сервер больше не стоит вам всего VPN. Ядро проверяет конфиг целиком и отказывается стартовать на первом же узле, который не принимает, — одна строка в одном узле подписки оставляла без связи вовсе. Теперь такой узел выключается сам, конфиг пересобирается и проверяется заново, а VPN поднимается на всех остальных. Каждый выключенный так сервер объясняет причину словами ядра (✖ в его строке, текст в карточке), а config.json заменяется только тем конфигом, который ядро приняло: отвергнутая сборка оставляет на диске предыдущий рабочий. Вернуть сервер — его же чекбоксом, следующая сборка проверит узел заново. О выключенных сообщает плашка на вкладке Local, она же открывает полный список; если их набралось десять, приложение спросит, проверять дальше или остановиться. Та же проверка идёт на последнем шаге Конфигуратора до Save и при записи конфига удалённой машины; в daemon-режиме на macOS отказ реального старта тоже называет узел и повторяет apply. Плашку после перезапуска приложения не восстанавливаем — на самом узле значок и причина остаются.
Исправления
  • Копирование ссылки узла теперь пишет её так, как её читают другие клиенты. Ссылка собирается по тем же правилам протокола, по которым читается, и узел со своей ссылкой больше не расходятся. Пять потерь исправлены: настройки keep-alive, имена полей XHTTP в написании Xray, флаг zero-RTT у tuic, пробелы в путях ( , а не + — на него серверы отвечали 404) и узел hysteria2 с пустым паролем, которым прежде нельзя было поделиться вовсе. TLS у ссылок vless/trojan/anytls теперь указывается явно, а флаг «не проверять сертификат» пишется тем именем, которое читают клиенты каждого протокола.
  • Ссылка Xray со старым написанием транспорта XHTTP (type=splithttp) больше не приезжает голым TCP-узлом без объяснений — транспорт и все его настройки сохраняются.
  • Ссылка tuic с пустым паролем принимается с пометкой, а не отбраковывается. Сервер её, скорее всего, отклонит — и теперь узел об этом говорит, а не выглядит сломанным без причины.
  • Ссылка с приватным ключом узла копируется только после подтверждения. У SSH-узла со встроенным ключом и у WireGuard/AmneziaWG в ссылке лежит ключ, по которому подключиться от вашего имени сможет любой, поэтому «Копировать ссылку сервера», «Копировать ссылку узла-перехода» и массовый экспорт сначала спрашивают — один раз на операцию, а не на каждый узел. Ссылки, где есть только пароль или uuid, копируются как раньше. У SSH-узла, где ключ задан ПУТЁМ к файлу, ключа в ссылке нет — его это не касается.
  • SSH-узел со встроенным приватным ключом вообще стало можно скопировать ссылкой. Раньше он отбивался сообщением «этот outbound нельзя преобразовать в share-ссылку»; теперь ключ пишется как ?private_key= — в той же форме, что пишет мобильное приложение и что этот лаунчер уже умеет читать обратно.
  • macOS: «Скрыть из Dock» переживает перезапуск. Переключатель в трее сохраняется в bin/settings.json (hide_app_from_dock) и применяется при следующем запуске до показа окна. Скрывается только иконка Dock: главное окно при старте открывается как обычно (запуск без окна — флагом -tray).
  • Ядро закреплено на sing-box-lx 1.14.1-lx.8: REALITY short_id длиннее 16 hex больше не роняет ядро паникой (теперь ошибка конфигурации), неизвестный tuic.udp_relay_mode отвергается при загрузке, а не молча становится native, MASQUE-профиль standard без uri получает одну понятную ошибку, ошибки ядра называют тип и тег узла (initialize outbound[0] vless[proxy-de-1]: …), а gRPC-service_name, начинающийся с «/», понимается как готовый путь запроса.
  • gRPC: serviceName в Xray-форме «абсолютного пути» (/my-service/Tun, /a/b/Tun, /a/Stream) теперь приходит на сервер ровно этим путём, и узел, отвечавший 404 Not Found, работает (issue #130). Ведущий «/» разбирает само ядро, экранируя каждый сегмент по отдельности; лаунчер значение не трогает. Без ведущего «/» ничего не меняется — это имя сервиса, и ядро дописывает /Tun как раньше.
  • vmess: набор шифров канала сверен с ядром — aes-128-ctr, которого ядро не знало и который валил весь конфиг, убран; aes-128-cfb принимается вместо молчаливого отката к auto.
  • xhttp: значения mode, seq_placement, session_placement, uplink_data_placement, x_padding_placement и x_padding_method вне набора ядра снимаются с кодом xhttp_param_reset, а не уезжают в конфиг, роняя его целиком.
  • Ручной JSON-объект больше не копируется в конфиг дословно. Опечатка в имени ключа валила весь конфиг — человек оставался вообще без VPN и без подсказки, какой узел виноват; теперь неизвестный ключ снимается, а узел объясняет почему.
  • Несколько форм узла, которые ядро отвергает сразу, до конфига больше не доходят: пустой адрес сервера, WireGuard с jmin без jmax, путь WebSocket/HTTP с битым percent-кодированием и naive с TLS-полями, которых naive не читает. Каждая из них роняла конфиг целиком.
  • Обфускация AmneziaWG больше не теряется: магические заголовки h1–h4, поля размеров пакетов и тройка reserved у WARP пишутся в числовой форме, которую ждёт ядро, и AWG-узел сохраняет настроенную обфускацию.
  • Поля, которых не знает ваше ядро (сейчас это tls.reality.key_share, ему нужно 1.14.1-lx.4), при сборке конфига опускаются, и узел продолжает работать без них. Сам узел не меняется, так что поле вернётся сразу после обновления ядра.
  • Длинные, но валидные ссылки снова принимаются: собственный предел лаунчера в 8 КБ заменён контрактными 64 КБ — теми же, что давно у мобильного приложения. Ссылки Amnezia и MASQUE с полным ключевым материалом отбивались на десктопе и принимались на телефоне.
  • Узлы shadowsocks на старых шифрах, которые ядро по-прежнему принимает (rc4-md5, aes-128/192/256-cfb и -ctr, chacha20-ietf, xchacha20), больше не выбрасываются. Девять рабочих шифров отбивались вместе с узлом — человек не получал ни узла, ни объяснения; теперь они подключаются с пометкой, что шифр устарел.
  • Ссылка, написавшая параметр иначе, больше не теряет его: insecure во всех девяти написаниях, которыми пользуются панели, полоса hysteria2 и как up_mbps/down_mbps, и как upmbps/downmbps. Таблица имён берётся из контракта, поэтому обе программы читают одну ссылку одинаково.
  • naive+https://secret@host читает единственный кредентиал как пароль — как велит спека, как читает мобильное приложение и как этот же лаунчер такие ссылки выписывает. Ссылка, отданная отсюда, прежде читалась обратно с кредентиалом не в том поле.
  • Параметр ech= формата Xray снимается с названной причиной, а не исчезает молча: он несёт ключ чужого клиента, и рукопожатие с ним не состоится. Блок tls.ech из конфигурации sing-box не затрагивается и продолжает работать.
  • Мусорный публичный ключ REALITY теперь называется, а не снимается молча, и ключи, которые лишь ПОХОЖИ на base64 (enabled, true), больше не проходят: ключ проверяется на 32 байта после декода — ровно так, как проверяет ядро.
  • Ссылки socks4:// и socks4a:// снова работают — версия протокола несётся в имени схемы, а не угадывается по порту.
  • Windows: иконка в трее снова чёткая — Fyne брал 16-цветный слой-миниатюру вместо полноцветной (#83).
  • Прыжки по портам больше не стоят всего VPN. Провайдер, записавший адрес и список портов одним значением (mport=198.51.100.24:443,20000-30000), укладывал имя хоста внутрь списка портов, и ядро отказывалось загрузить весь конфиг с «bad port range». Теперь такая запись снимается с названной причиной, а диапазоны, записанные правильно, продолжают работать. С негодной записью ALPN — так же.
  • Ключ REALITY, записанный другим алфавитом base64, теперь работает. Байты ключа в обоих написаниях одни и те же, но ядро декодирует именно это поле в одном написании и отвечало «decode public_key: illegal base64 data», отвергая конфиг целиком. Написание приводится к одному на входе.
  • Подписка, у которой диапазоны портов записаны И в адресе, и в mport= (host:443,20000-30000?mport=40000-50000), больше не теряет половину: прыжки по портам шли только по одному из двух списков, причём молча — узел подключался и выглядел исправным.
  • Подписка, упакованная в base64 ДВАЖДЫ, теперь читается. Прежде из неё не получалось ни одного узла и не появлялось ни одной ошибки: лаунчер принимал внутренний слой за текст и складывал всю подписку в один нечитаемый элемент.
  • Файл подписки или .conf, сохранённый с меткой BOM (так пишет, например, «Блокнот» Windows), читается как обычно. Невидимый символ в начале сбивал распознавание формата, и конфигурация превращалась в список несуществующих ссылок.
  • Xray-подписки с фрагментацией TLS ClientHello через freedom-outbound (dialerProxy → fragment) больше не теряют серверы: узел сохраняется с tls.fragment вместо отбраковки как битый хоп цепочки.
Техническое / Внутреннее
  • Контракт 1.1.46: движок linkmap по реестру (SPEC 133), страховка узла (SPEC 132), вычитка текстов предупреждений в warnings.json — самодостаточные подзаголовки в списке узлов, согласованные params, обновлённые служебные go.
  • Linux-сборка теперь получает пути к заголовкам Wayland через pkg-config и использует X11 при неполном наборе опциональных Wayland/EGL-файлов разработки, исправляя локальную сборку в openSUSE (PR #128, issue #127).
  • Новый docs/TROUBLESHOOTING.ru.md: известные проблемы по платформам со ссылками на решения (первая запись — повторные запросы пароля systemd-resolved на Linux, issue #126).
  • Тело узла делают Sanitize + Emit по реестру контракта (contract/registry/**): per-scheme цепочка эмиттера, allowlist-ы полей TLS и транспорта и частный фильтр naive сняты. Новое поле протокола — правка реестра, а не четырёх мест в коде.
  • Полевой гейт ядра стал табличным (min_core/platform реестра) вместо пробы на каждое поле; RealityKeyShareSupportProbe и её кэш удалены. Узловые гейты (naive/chain/tailscale/AWG3) не тронуты — они выбрасывают узел, и реестром это не выражается.
  • warnings разово досчитываются при загрузке у узлов, сохранённых до конвейера. Тело переписывается, только если санитайзер реально что-то снял или привёл, и каждая такая перезапись — строка WARN с тегом узла и кодами.
  • Корпус контракта сверяет тело, которое лаунчер СОХРАНЯЕТ, а не вывод старого эмиттера; добавлен тест, который собирает все кейсы корпуса в один конфиг и прогоняет check ядром пина.
  • Share-ссылки собирает тот же движок реестра, что их читает — эмиттеры shareuri_*.go ушли вместе с рукописными парсерами.
  • Парсеры схем стали мапперами: переводят диалект ссылки в пути sing-box и не решают ничего о значениях. 21 правило значения снято как дубль реестра, 6 перенесено в реестр (base64_32, hex_only, условный advisory, requires+equals, default_when), 14 осталось настоящим переводом диалекта. Пер-схемные парсеры ужались до экрана каждый.
  • Правила, лежавшие в трёх-четырёх копиях, стали одним: набор написаний insecure (шесть копий), подсказка об отпечатке REALITY (четыре), дефолт полосы hysteria v1 (три), список шифров shadowsocks (три). Ссылка и тот же узел объектом дают одинаковые тела И одинаковые коды с одинаковыми путями — это сверяет пара корпуса vless/junk_pair_with_body.
  • Сторожевой тест реестра перестал врать: грепа parse_warnings.go после переезда кодов хватило бы, чтобы объявить дюжину живых правил мёртвыми. Встречная проверка требует, чтобы у каждого кода полей узла был производитель — константа Go или правило реестра.
  • Конструкция Go 1.21+ в общем коде теперь ловится на каждом pull request, а не на выпуске. Новый страж tools/win7guard красит джобу тестов на импорт slices/maps, builtin min/max/clear, range по целому и Request.PathValue — то, что не собирает тулчейн Go 1.20 сборки Windows 7. Он смотрит AST и build-теги, поэтому min в комментарии, метод с именем clear и файлы-близнецы за go1.22 его не интересуют; тот же шаг стоит и в build-win7. Выгрузка покрытия переехала на codecov-action@v5 (входа file у него нет, файл отчёта называется в files), а раннер Ubuntu пригвождён к ubuntu-24.04 вместо плавающей метки.
  • Снят мёртвый легаси после перевода разбора на реестр: осиротевшие транспортные хелперы URI, uri_params.go, node_ref.go, detour_topo.go, эмиттер transport в outbound_jsonbuilder.go; адреса в LEGACY_AUDIT пересажены на живые файлы.
  • Контракт 1.1.43–1.1.46: merge: append у записей реестра исполняется слиянием списков (дельта D133-41), двойная оболочка base64 раскрывается до объявленного предела (D133-42), BOM снимается на входе определения вида источника (D133-43), порядок замен label.value_map и цепочка источников on_len_gt приведены к норме (D133-44). Встречная задача LxBox — contract/TASKS_LXBOX.md §39
Патч-релиз поверх v2.0.0. Ядро sing-box-lx 1.14.1-lx.8, контракт без изменений.

Исправлено
  • Вкладка Servers: сортировка сразу меняет порядок видимых строк при активном фильтре. Отфильтрованный срез кэшировался без учёта порядка, и новый порядок появлялся только после клика по серверу.
  • Удалённые машины: Save больше не оставляет прошлую сборку config.json. Локальная проверка не могла принять конфиг удалённой машины — пути rule_set[].path ведут в её файловую систему, — файл молча не заменялся, лог и диалог сообщали «wrote», а Deploy уносил на машину старую сборку.
  • Удалённые машины: страховка «ядро отвергло узел» теперь работает и для конфига удалённой машины (на время проверки пути наборов правил подменяются локальными). Отказ ядра «не про узел» показывается ошибкой с текстом ядра, а не сообщением «Remote config exported».
Минорный релиз поверх v2.1.0. Ядро sing-box-lx 1.14.2-lx.2 (было 1.14.1-lx.12), контракт 1.1.53 (было 1.1.52). Релиз про Windows. Лаунчер больше не работает от имени администратора (issue #99): режиму прокси права не нужны, TUN запрашивает их один раз. Новый установщик кладёт программу в Program Files, а данные — в %LOCALAPPDATA%. Daemon-режим, до сих пор только на macOS, приходит на Windows со службой sing-box-lxd: она держит VPN без прав у лаунчера и до входа в систему. Сборка для Windows 7 остаётся в прежней модели.

Основное

Windows: установщик (SPEC 140)
  • Новый ассет singbox-launcher-<version>-win64-setup.exe (Inno Setup, Windows 10/11 x64): один запрос прав администратора, программа — в C:\Program Files\singbox-launcher, данные — в %LOCALAPPDATA%\singbox-launcher; ядро, wintun.dll, шаблон и Mesa3D внутри, первый запуск ничего не качает. Ярлык в «Пуске», строка в «Параметры → Приложения»; по желанию — ярлык на рабочем столе, «Запускать вместе с Windows» и программный OpenGL (Mesa3D) для RDP / ВМ без видеокарты.
  • Установка новой версии поверх сохраняет данные и штатно закрывает работающий лаунчер (VPN останавливается, системный прокси снимается). Удаление спрашивает, удалять ли данные текущего пользователя Windows.
  • Установщик пока не подписан — SmartScreen может попросить «Подробнее → Выполнить в любом случае». Zip-архивы остаются как были и теперь описаны как portable: распаковывать в папку с правом записи, а не в Program Files.
Windows: без прав администратора (SPEC 139, #99)
  • Без запроса UAC на каждом старте. Лаунчер теперь работает без прав администратора. Режиму прокси они не нужны, TUN — нужны: Start без прав показывает диалог — Перезапустить от имени администратора (один запрос UAC, лаунчер перезапускается с правами и теми же данными и поднимает VPN; в заголовке окна — (Администратор)) или Перейти в режим прокси (TUN выключен, включён локальный прокси с системным). Под обычной учётной записью Windows спросит пароль администратора.
  • TUN по умолчанию работает под администратором. При включённом TUN лаунчер запрашивает права администратора сразу при старте (один запрос UAC) и перезапускается с правами и теми же флагами — запущенный в трее при входе остаётся в трее. Отказ — старт без прав, и при Start появится диалог выше. Выключается в Settings → Connection → Запрашивать права администратора при старте, если включён TUN (по умолчанию включено, elevate_on_start_for_tun в settings.json); в daemon-режиме не применяется.
  • Автозапуск. Settings → Connection → Запускать вместе с Windows запускает лаунчер в трее при входе, Подключать VPN при входе заодно поднимает VPN. В окне, повышенном через UAC, недоступно; установщику — -autostart=on|off. Remove all data (и -purge-data) удаляет запись, если она указывает на эту копию.
  • Распаковывайте zip в папку, куда вы можете писать. Под Program Files (и на любой ОС — там, куда пишет только администратор) portable.txt теперь не учитывается: данные живут в системной папке (%LOCALAPPDATA%\singbox-launcher), данные старой версии рядом с программой при первом запуске копируются туда, а Storage → Mode показывает «portable.txt не учитывается». Лаунчер с правами и без видит одни и те же данные.
Windows: daemon-режим со службой sing-box-lxd (SPEC 141)
  • Служба sing-box-lxd (ядро 1.14.2-lx.2+) держит VPN без прав у лаунчера и до входа в систему. Установить службу в диалоге «Для TUN нужны права администратора» ставит её одним запросом UAC, сопрягается сама и переключает движок на daemon.
  • Лаунчер проверяет службу без прав (SCM, защищённая копия в Program Files с владельцем SYSTEM/Administrators, те же файлы ядра) и предлагает Выполнить от имени администратора для установки, запуска, свежего приглашения, удаления и после обновления ядра.
  • Системный прокси в daemon-режиме ставит лаунчер в профиле пользователя и снимает при Stop.
  • Лаунчер с правами запускает ядро только из этой защищённой копии (без службы — --service=copy), его лог — C:\ProgramData\sing-box-lxd\logs\classic.log.
Windows 7 (win7-32)
  • Legacy-сборка остаётся в прежней модели. Она вшивает app.win7.manifest (requireAdministrator): запрос UAC при каждом запуске, всё работает от имени администратора, TUN — сразу, без диалога «Для TUN нужны права администратора». Только portable — portable.txt из zip учитывается везде, куда может писать администратор, включая Program Files, а переключатель Portable в Settings → Storage скрыт; без установщика, службы и автозапуска (-autostart завершается с кодом 2).
Визард и Remote
  • Открыть настройки из старой папки. В диалоге Загрузить (Read) конфигуратора — Открыть файл…: выберите state.json (или снапшот) из другой папки данных — например, из старой portable-копии, которую установщик не видит, — и он загрузится так же, как при Clone from (текущее состояние сперва уходит в снапшот, на диск пишет Save). Диалог теперь открывается, даже если в этой папке ещё нет сохранённых состояний.
  • Импорт из файла… в окне + Добавить на вкладке Remote добавляет машины из remote-daemons.json другой папки вместе с клиентскими ключами и настройками; машины с уже известным адресом пропускаются.
Исправления
  • Windows: за файловыми диалогами больше не висит окно консоли PowerShell.
  • Remote: окно ресурсов машины (RES) показывает подсказки, а его сообщения об ошибках и подтверждение удаления открываются поверх этого окна, а не главного.
  • Конфигуратор: выключенное Направление, отмеченное у другого Направления в Дополнительные опции в списке выбора, больше не предлагается целью правила — в config.json его нет.
  • Share-ссылки: ссылка VLESS REALITY теперь несёт security=reality — клиенты на Xray читают ссылку без него как узел без TLS.
  • Ссылки: servername / serverName читается именем сервера, когда нет ни sni, ни peer. В ссылках vless packet-encoding читается кодировкой пакетов, а gRPC-параметр Xray authority (у sing-box такой настройки нет) и кэш-бастеры подписок (_t, __rand, seq, nonce) пропускаются без пометки о неизвестном параметре.
  • Ссылки vmess: настройки TCP keep-alive из JSON-формы читаются обратно (записывались, но терялись на обратном пути), а транспорт h2 без своего host берёт адрес сервера.
  • Конфиги Xray: отрицательный tcpKeepAliveInterval сам по себе — так Xray выключает keep-alive — теперь выключает его, а не теряется молча.
Техническое / Внутреннее
  • Сторож зависания UI. Фоновая горутина раз в 10 с проверяет главный цикл Fyne; если он не отвечает около 30 с, лаунчер пишет стеки всех горутин в logs/ui-freeze-<yyyymmdd-hhmmss>.txt (версия, ОС/архитектура, время последнего ответа UI, число горутин; хранятся 3 последних файла) и WARN с путём в лог, а когда окно снова отвечает — INFO. Раньше зависшее окно не оставляло в логе ничего, а снять стеки на Windows нечем (SIGQUIT нет).
  • Пин ядра sing-box-lx 1.14.2-lx.2 (было 1.14.1-lx.12). Добавляет Windows-службу sing-box-lxd (--service=install|copy|status|uninstall, SPEC 103 форка; panic обработчиков пишутся в lxd.log). Синк с апстримом sing-box 1.14.2 поверх lx.13: корневой блок lx (ключи сна WireGuard под lx.wg.*, lx.masque.idle_timeout) и тихий лог рукопожатий WireGuard (шум повторов GSO). Миграции конфига и состояния нет (SPEC 138). (Для приёмки на Windows использовались пререлизы rc.1–rc.3.)
  • Готовность к корневому блоку lx ядра (SPEC 138). Ядро lx.13 переносит ключи сна WireGuard из route.lx_idle_* в lx.wg.*. Лаунчер их никогда не писал: десктопные сборки ядра собраны без сна WG и отвергают эти ключи на старте. Поэтому бамп пина не требует миграции конфига и состояния. Корневой блок lx из шаблона (например, lx.masque.idle_timeout) уходит в config.json как есть, теперь это закреплено тестом.
  • Манифест Windows asInvoker (win64; манифест остаётся вшитым — против UAC-виртуализации файлов; win7-32 вшивает app.win7.manifest с requireAdministrator). platform.IsElevated (TokenElevation или членство в Administrators), platform.RunElevated — ShellExecuteExW runas с дескриптором процесса и Wait (им же пользуются команды службы SPEC 141), platform.WaitForProcessExit. Повышенный экземпляр получает раскладку родителя флагом -handoff=<pid>|<mode>|<data>|<logs> и ждёт выхода родителя (до 25 с), прежде чем открыть логи, порт Debug API и трей. Первая WARN-строка старта теперь содержит elevated=yes|no (SPEC 139).
  • Всё, что требует админа, без прав за гейтом (SPEC 139 §6): очистка NLA, призрачных адаптеров и правил брандмауэра при старте и после Stop пропускается одной строкой INFO; Remove all data / -purge-data пропускают сетевую очистку (CLI печатает команду для консоли администратора) и остатки в защищённой папке программы («Нужны права администратора», код выхода 0) — диалог предупреждает, что такая старая копия остаётся и при следующем запуске снова переносится в папку данных; Kill ядра, запущенного лаунчером с правами, показывает сообщение с перезапуском от имени администратора, а не делает вид, что ядро остановлено; переключатель Portable недоступен в окне, повышенном через UAC, и в защищённой папке программы.
  • paths.AppDirUserWritable: проба записи и, на Windows, не под ProgramFiles/ProgramFiles(x86)/ProgramW6432/SystemRoot. Им пользуются правила portable.txt и legacy, Windows-фоллбэк, SystemDefault, переключатель Portable и проба записи для Mesa3D. portable.txt в папке только для чтения больше не роняет старт и на Linux.
  • Обвязка установщика (SPEC 140). Лаунчер создаёт мьютексы Local\ / Global\SingboxLauncher.Instance и слушает событие Local\SingboxLauncher.Quit (Windows, только GUI-режим) — по ним установщик находит лаунчер и просит его выйти через GracefulExit. Набор win64-full готовит один скрипт build/installer/stage_win64_full.sh и для zip, и для установщика; новая job CI build-windows-installer компилирует его ISCC (Inno Setup 6.4+, VersionInfoVersion из git describe), job release публикует со строкой в checksums.txt. Проверка OpenGL при старте больше не предлагает ставить Mesa3D в закрытую для записи папку программы и подсказывает задачу установщика.
  • Внутренности daemon-режима на Windows (SPEC 141). SCM опрашивается без прав (только BinaryPathName); классификатор проверяет набор защищённой копии (exe + libcronet.dll, sidecar, остатки) тем же allowlist SID владельцев, что и ядро; операции службы идут через runas с сопряжением через файл приглашения; системный прокси пользователя ставится через WinINet; папка состояния tailscale переезжает в состояние службы; classic.log получает явный DACL.
  • Код daemon-движка разделён по платформам (SPEC 141). Общий daemon-код (движок, классификатор, сопряжение, сборка команд, гейт привилегированного старта classic) собирается для macOS и Windows x64/arm64 (darwin || (windows && !386)); только-macOS части — в *_darwin.go, только-Windows — в *_windows.go; на Linux и win7-32 — заглушки.
  • Линтер реестра: пустой словарь detect предикатом не является (SPEC 133). json: {} / ini: {} / text: {} — явный или оставшийся после того, как загрузчик молча выбросил опечатанное имя поля (has_key вместо required_keys), — верен на любом элементе, и первая форма или секция с ним забирала бы элементы, ради которых написаны следующие. Detect.IsZero теперь считает такой словарь пустым, а линтер реестра обходит все секции-мапперы и формы (включая вложенные not/all/any), а не только виды источника. Семантика движка на обеих сторонах контракта не менялась.
  • Контракт 1.1.53 (SPEC 133, ревизия зеркала реестра LxBox): пункты о ссылках из «Исправлений»; ссылки Shadowsocks пишутся без =-паддинга (как в SIP002), а контейнер vmess v2rayN — в порядке ключей v2rayN и с aid строкой "0" — обе формы по-прежнему читаются; disable_sni у TUIC снимает и server_name, взятый из sni; секции mappers.singbox ещё для 13 схем; новые кейсы корпуса
Полное описание -ЗДЕСЬ-
Почитать от автора -ЗДЕСЬ-
Скачать можно с репозитария -ЗДЕСЬ-

2026-9-8 21-34-53.jpg
 
Последнее редактирование:

Demonis

Новичок
Свежее обновление до версии 2.2.0 - изменения под спойлером ...
 

Последние темы

Верх