release v1.2.3
Release v1.2.3
Downloads
macOS (Universal) - Supports both Apple Silicon and Intel
Option 1: Installation Script (Recommended)
Install with a single command (version v1.2.3):
curl -fsSL https://raw.githubusercontent.com/Leadaxe/singbox-launcher/develop/scripts/install-macos.sh | bash -s -- v1.2.3The script will:
- Download the release archive
- Extract and install to
/Applications/ - Fix macOS quarantine attributes and permissions
- Launch the application automatically
Option 2: Manual Installation
- Download:
singbox-launcher-v1.2.3-macos.zip - Extract the ZIP file
- Remove quarantine attribute (required):
xattr -cr "singbox-launcher.app" && chmod +x "singbox-launcher.app/Contents/MacOS/singbox-launcher"
- Double-click
singbox-launcher.appto run- If macOS blocks the app, go to System Settings → Privacy & Security and click "Open Anyway"
- Alternatively, right-click the app and select "Open" (first time only)
Windows (amd64)
- Download:
singbox-launcher-v1.2.3-win64.zip - Extract the ZIP file to a folder, for example:
C:\Program Files\singbox-launcher\ - Run
singbox-launcher.exefrom that folder- You may need administrator rights to install to Program Files
- The launcher will automatically download
sing-boxandwintun.dllon first launch
Windows 7 (x86, legacy)
- Download:
singbox-launcher-v1.2.3-win7-32.zip - Extract the ZIP file to a folder and run
singbox-launcher-win7-32.exe- For Windows 7 / 32-bit or legacy compatibility only
Linux Support
Checksums
See checksums.txt for SHA256 checksums of all files.
v1.2.3 — MASQUE SNI fix, WARP registration cache
Core pinned: sing-box-lx 1.14.0-lx.5 (unchanged from v1.2.2). No config migration needed.
A WARP release: MASQUE nodes generated by the wizard came out with an empty SNI and could not pass traffic — that is fixed, and repeated «Add WARP» now reuses the registration you already have instead of enrolling a new device on every click.
EN
Highlights
- MASQUE nodes generated by the wizard now carry an SNI — without it they could not pass traffic. The MASQUE section left its SNI field empty (only a placeholder was set, so
sni.Textstayed empty and the generatedmasque://URI had nosni=), while the WireGuard section next to it has always defaulted its masquerade domain towww.google.com. With no SNI the core falls back toconsumer-masque.cloudflareclient.com: the tunnel establishes and DNS resolves, so the node looks healthy — but data never flows and the node reads as-1in the proxy list. The field is now pre-filled with a random name from the pool (🎲 still re-rolls), andRegisterMasquesubstitutes a random one if it is ever handed an empty string, so no call path can produce an SNI-less node again. Measured on one machine, same node, only the SNI changing: no SNI → timeout,sni=www.google.com→ 199 ms. (SPEC 086) - «Add WARP» reuses your existing registration; a checkbox forces new keys. Every click used to enroll a brand-new device: adding MASQUE H2 and then H3 produced two independent registrations, each with its own key and IPv6 — where LxBox on Android puts both nodes on a single one. Registrations are now cached in
state.json(warp_accounts, WG and MASQUE separately) and reused, so H2 and H3 share one key. Create new keys — unchecked by default, shown only once a cached registration exists — goes to Cloudflare for a fresh one and replaces the cached entry.
Technical / Internal
core/state: new optionalwarp_accountssection in the v6 on-disk schema (disk_v6.go→WarpAccountsSection/WarpWGAccount/WarpMasqueAccount, wired throughsave.goandload_v6.go, mirrored onState).omitempty— the key is absent for anyone who never registered WARP. No schema-version bump and no migration: an older file simply has no section, and an older launcher ignores an unknown key. The section holds the registration only (keys, addresses, token) — transport, SNI and timeouts are node parameters and stay out, which is exactly why one cached entry serves both H2 and H3.core/warp/cache.go(new): conversion betweenwarp.Account/warp.MasqueAccountand the state section. Endpoint and the AmneziaWG obfuscation fields are deliberately not cached — the UI sets them per build (preset, 🎲).core/warp/client.go: the endpoint-resolution and obfuscation-field logic was inlined inRegisterbetween two HTTP calls; extracted intoresolveEndpoint+ the exportedApplyNodeOptions, so a cached account is assembled by exactly the same rules as a freshly registered one instead of a UI-side copy that could drift.core/warp/masque.go: transport/SNI/timeout assignment extracted fromRegisterMasqueintoMasqueAccount.ApplyNodeOptions(network, sni)— the same call now serves both a fresh and a cached account.ui/configurator:WizardModel.WarpAccountsmirrors the state section (loaded inrestoreParserConfig, written back inCreateStateFromModel);warp_dialog.goreads the cache, registers only on a miss, stores the result and marks the wizard changed.- Locale:
wizard.warp.new_keys/wizard.warp.new_keys_noteadded (ru + en).wizard.warp.masque_sni_placeholderno longer says "empty = core default" — an empty SNI is no longer a reachable state.
Notes
- Existing MASQUE nodes are not rewritten. The fix applies to nodes generated from now on; a node already in Sources keeps its stored URI. To repair one, re-add it via Add WARP (or append
&sni=<name>to the source URI by hand). - The
h3transport is a separate, still-open problem. In our testing anh3MASQUE node fails to pass traffic with every SNI tried, on desktop and on Android alike, whileh2works — this release does not address that, and no launcher-side setting affects it.
RU
Основное
- MASQUE-ноды из визарда теперь получают SNI — без него они не пропускали трафик. MASQUE-секция оставляла поле SNI пустым (стоял только placeholder, поэтому
sni.Textоставался пустым и в сгенерированномmasque://URI не былоsni=), тогда как соседняя WireGuard-секция всегда подставляла домен маскировкиwww.google.comпо умолчанию. Без SNI ядро используетconsumer-masque.cloudflareclient.com: туннель встаёт и DNS резолвится — нода выглядит живой, но данные не идут, и в списке прокси она показывает-1. Теперь поле заранее заполнено случайным именем из пула (🎲 по-прежнему перевыбирает), аRegisterMasqueподставляет случайное, если ему всё же передали пустую строку — так что ни один путь вызова больше не создаст ноду без SNI. Замер на одной машине, та же нода, менялся только SNI: без SNI — таймаут,sni=www.google.com— 199 мс. (SPEC 086) - «Add WARP» переиспользует уже выданную регистрацию; галочка заставляет создать новые ключи. Раньше каждый клик регистрировал новое устройство: MASQUE H2 и следом H3 давали две независимые регистрации, каждую со своим ключом и IPv6 — тогда как LxBox на Android держит обе ноды на одной. Теперь регистрации кешируются в
state.json(секцияwarp_accounts, WG и MASQUE раздельно) и переиспользуются, поэтому H2 и H3 сидят на одном ключе. Создать новые ключи — снята по умолчанию, показывается только когда кеш уже есть — идёт в Cloudflare за свежей регистрацией и заменяет кешированную.
Техническое / Внутреннее
core/state: новая необязательная секцияwarp_accountsв v6-схеме на диске (disk_v6.go→WarpAccountsSection/WarpWGAccount/WarpMasqueAccount, проводка черезsave.goиload_v6.go, зеркало наState).omitempty— у того, кто WARP не заводил, ключа в файле нет. Версия схемы не поднята, миграция не нужна: в старом файле секции просто нет, а старый лаунчер игнорирует незнакомый ключ. В секции лежит только регистрация (ключи, адреса, токен) — транспорт, SNI и таймауты относятся к узлу и в кеш не входят, именно поэтому одна запись обслуживает и H2, и H3.core/warp/cache.go(новый): конверсия междуwarp.Account/warp.MasqueAccountи секцией состояния. Endpoint и поля обфускации AmneziaWG сознательно не кешируются — их задаёт UI на каждую сборку (пресет, 🎲).core/warp/client.go: логика резолва endpoint'а и полей обфускации жила внутриRegisterмежду двумя HTTP-вызовами; вынесена вresolveEndpoint+ экспортируемыйApplyNodeOptions, чтобы кешированный аккаунт собирался ровно теми же правилами, что и свежезарегистрированный, а не копией логики на стороне UI, которая могла разъехаться.core/warp/masque.go: проставление транспорта/SNI/таймаутов вынесено изRegisterMasqueвMasqueAccount.ApplyNodeOptions(network, sni)— теперь один и тот же вызов обслуживает и свежий, и кешированный аккаунт.ui/configurator:WizardModel.WarpAccountsзеркалит секцию состояния (читается вrestoreParserConfig, пишется обратно вCreateStateFromModel);warp_dialog.goчитает кеш, регистрируется только при промахе, сохраняет результат и помечает визард изменённым.- Локализация: добавлены
wizard.warp.new_keys/wizard.warp.new_keys_note(ru + en).wizard.warp.masque_sni_placeholderбольше не обещает «пусто = дефолт ядра» — пустой SNI перестал быть достижимым состоянием.
Примечания
- Существующие MASQUE-ноды не переписываются. Фикс действует на ноды, создаваемые начиная с этой версии; нода, уже лежащая в Sources, сохраняет свой URI. Чтобы починить — пересоздайте её через Add WARP (или допишите
&sni=<имя>в URI источника руками). - Транспорт
h3— отдельная, всё ещё открытая проблема. В наших тестах MASQUE-нода наh3не пропускает трафик ни с одним из проверенных SNI — одинаково и на десктопе, и на Android, тогда какh2работает. Этот релиз её не решает, и никакая настройка лаунчера на неё не влияет.