Release v1.2.7
Downloads
macOS (Universal) - Supports both Apple Silicon and Intel
Option 1: Installation Script (Recommended)
Install with a single command (version v1.2.7):
curl -fsSL https://raw.githubusercontent.com/Leadaxe/singbox-launcher/develop/scripts/install-macos.sh | bash -s -- v1.2.7The 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.7-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.7-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.7-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
⚠️ Linux build temporarily unavailable - мы ищем тестировщика для ручного тестирования перед включением автоматической сборки.
Checksums
See checksums.txt for SHA256 checksums of all files.
v1.2.7 — одна нода с fp=HelloChrome_120 больше не роняет весь конфиг
Core pinned: sing-box-lx 1.14.0-lx.5 (unchanged from v1.2.6). No config migration needed.
A one-bug release. If any node in your subscription carried a raw uTLS identifier in fp=, sing-box refused to start at all — not just that node, the entire config. Nothing connected, and the log said unknown uTLS fingerprint.
EN
Highlights
-
A single node with an unknown
fp=value no longer takes down the whole config. Some lists ship the uTLS library's Go identifier —fp=HelloChrome_120— instead of the short name sing-box expects. The launcher only lowercased it, sohellochrome_120landed inconfig.jsonverbatim. sing-box validates that field against a fixed set and aborts on anything else:FATAL create service: initialize outbound[26]: unknown uTLS fingerprint: hellochrome_120That is a config-load failure, not a per-node one: outbound #26 being bad meant outbounds #0–25 never started either. The value is now checked against the set sing-box actually accepts, and raw uTLS identifiers are mapped onto their browser family (
HelloChrome_120→chrome,HelloFirefox_Auto→firefox, and so on). -
Unrecognised fingerprints degrade the node instead of poisoning the config. Anything that cannot be mapped is dropped, and the node falls back to a valid fingerprint rather than carrying junk into
config.json. Same policy as the REALITYpbkvalidation in v1.1.7 and the malformed?ed=handling in v1.2.6.
Technical / Internal
- The accepted set was taken from sing-box's own source, not from memory.
uTLSClientHelloIDincommon/tls/utls_client.goacceptschrome,firefox,edge,safari,360,qq,ios,android,random,randomized,""— plus five Chrome ClientHello variants that are easy to overlook:chrome_psk,chrome_psk_shuffle,chrome_padding_psk_shuffle,chrome_pq,chrome_pq_psk. Guessing the list would have silently broken nodes that legitimately use those. - Alias matching ignores separators.
_,-and spaces are stripped before the prefix match, soHelloChrome_120,hellochrome-106andHelloChrome 120all resolve tochrome. Ordering matters:hellorandomizedis tested beforehellorandom, otherwiseHelloRandomizedwould collapse intorandom. - The emitter needed its own fix.
GenerateNodeJSONre-normalises the fingerprint, but previously would have written"fingerprint":""for a rejected value. It now omits the key entirely, letting sing-box fall back to its default Chrome hello. This matters for templates: atls.utlsblock placed by hand or seeded intowizard_template.jsonnever passes through a parser, so the emitter is the only gate it meets. - Verified against sing-box's validator rather than by assertion. Every value the normaliser can emit was run through a verbatim copy of the upstream switch, confirming all outputs are accepted — and that the original
hellochrome_120really was rejected, so the check proves something. - Tests: 5 new cases — a normaliser table (sing-box names, Chrome variants, raw uTLS identifiers, junk), two parser regressions, and two emitter regressions. The existing
QQcasing test from issue #45 still passes.
Notes
sing-box checkdid catch this one — unlike the?ed=bug in v1.2.6, the failure was loud and at config-load time. The launcher surfaced it asRebuildConfigIfDirty: sing-box check failed, retrying every few seconds.- Nothing else changed. If no node in your subscription carries an unusual
fp=value, this release is a no-op for you.
RU
Основное
-
Одна нода с неизвестным
fp=больше не роняет весь конфиг. Некоторые списки кладут вfp=Go-идентификатор из библиотеки uTLS —fp=HelloChrome_120— вместо короткого имени, которое ждёт sing-box. Лаунчер только приводил строку к нижнему регистру, иhellochrome_120уезжал вconfig.jsonкак есть. sing-box сверяет это поле с фиксированным набором и на всём остальном прекращает загрузку:FATAL create service: initialize outbound[26]: unknown uTLS fingerprint: hellochrome_120Это отказ загрузки всего конфига, а не одной ноды: из-за битого outbound #26 не поднимались и outbound'ы #0–25. Теперь значение проверяется по набору, который sing-box действительно принимает, а сырые uTLS-идентификаторы отображаются на своё семейство браузера (
HelloChrome_120→chrome,HelloFirefox_Auto→firefoxи т.д.). -
Нераспознанный fingerprint деградирует ноду, а не портит конфиг. Всё, что не удалось сопоставить, отбрасывается, и нода откатывается на валидный fingerprint вместо того, чтобы тащить мусор в
config.json. Та же политика, что при валидации REALITYpbkв v1.1.7 и при разборе битого?ed=в v1.2.6.
Техническое / Внутреннее
- Набор допустимых значений взят из исходников sing-box, а не по памяти.
uTLSClientHelloIDвcommon/tls/utls_client.goпринимаетchrome,firefox,edge,safari,360,qq,ios,android,random,randomized,""— плюс пять вариантов Chrome ClientHello, которые легко пропустить:chrome_psk,chrome_psk_shuffle,chrome_padding_psk_shuffle,chrome_pq,chrome_pq_psk. Угадывание списка молча сломало бы ноды, которые их законно используют. - Сопоставление алиасов игнорирует разделители.
_,-и пробелы вычищаются перед сравнением префикса, поэтомуHelloChrome_120,hellochrome-106иHelloChrome 120одинаково даютchrome. Порядок важен:hellorandomizedпроверяется доhellorandom, иначеHelloRandomizedсхлопнулся бы вrandom. - Эмиттеру потребовалась отдельная правка.
GenerateNodeJSONперенормализует fingerprint, но раньше на отклонённом значении записал бы"fingerprint":"". Теперь ключ не пишется вовсе, и sing-box берёт свой Chrome-hello по умолчанию. Это важно для шаблонов: блокtls.utls, положенный руками или засеянный вwizard_template.json, не проходит через парсер вообще — эмиттер для него единственный барьер. - Проверено против валидатора sing-box, а не на слово. Все значения, которые может вернуть нормализатор, прогнаны через дословную копию upstream-switch: подтверждено, что ядро принимает каждое — и что исходный
hellochrome_120действительно отвергался, иначе проверка ничего не доказывала бы. - Тесты: 5 новых кейсов — таблица нормализатора (имена sing-box, варианты Chrome, сырые uTLS-идентификаторы, мусор), две регрессии парсера и две регрессии эмиттера. Старый тест на регистр
QQиз issue #45 продолжает проходить.
Примечания
sing-box checkэту проблему как раз ловил — в отличие от бага с?ed=из v1.2.6, отказ был громким и на этапе загрузки конфига. Лаунчер показывал его какRebuildConfigIfDirty: sing-box check failedи повторял попытку каждые несколько секунд.- Больше ничего не изменилось. Если ни в одной вашей ноде нет необычного
fp=, этот релиз для вас пустой.