Release v2.4.0
Downloads
macOS (Universal) - Supports both Apple Silicon and Intel
Option 1: Installation Script (Recommended)
Install with a single command (version v2.4.0):
curl -fsSL https://raw.githubusercontent.com/Leadaxe/singbox-launcher/develop/scripts/install-macos.sh | bash -s -- v2.4.0The script will:
- Download the release archive
- Extract and install to
/Applications/ - Fix macOS quarantine attributes and permissions
- Launch the application automatically
Option 2: Homebrew (stable releases only, available a few hours after the release)
brew install --cask leadaxe/tap/singbox-launcherUpdate later with brew upgrade --cask singbox-launcher. The Cask installs the latest stable release, not a pre-release.
Option 3: Manual Installation
- Download:
singbox-launcher-v2.4.0-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)
Option 1: Installer (Recommended)
- Download:
singbox-launcher-v2.4.0-win64-setup.exe - Run it and confirm the administrator prompt once. The launcher goes to
C:\Program Files\singbox-launcher, your data to%LOCALAPPDATA%\singbox-launcher;sing-box.exe,wintun.dll, the config template and Mesa3D are included, nothing is downloaded on first launch- Tasks: desktop shortcut, Start with Windows, software OpenGL (Mesa3D) for RDP / VMs without a GPU
- Installing over a previous version keeps your data; uninstall from Settings → Apps asks whether to remove the data too
- The installer is not code-signed yet: if SmartScreen shows "Windows protected your PC", click More info → Run anyway
Option 2: Portable ZIP
- Download:
singbox-launcher-v2.4.0-win64.zip- or
singbox-launcher-v2.4.0-win64-full.zip— full bundle:sing-box.exe,wintun.dll, the config template and Mesa3D (mesa3d/, used only when no hardware OpenGL — RDP, VMs) are already inside, nothing is downloaded on first launch
- or
- Extract the ZIP file to a folder your account can write to, for example
D:\Tools\singbox-launcher\— settings stay next to the program (portable.txt)- Under
C:\Program Files\the launcher keeps its data in%LOCALAPPDATA%\singbox-launcherinstead
- Under
- Run
singbox-launcher.exefrom that folder — no administrator rights, no UAC prompt- TUN needs administrator rights: Start offers Restart as administrator or Switch to proxy mode
- The regular archive downloads
sing-boxandwintun.dllon first launch
Windows 7 (x86, legacy)
- Download:
singbox-launcher-v2.4.0-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
- Runs as administrator (UAC prompt on every start), settings stay next to the program (
portable.txt); no installer and no daemon service
Linux Support
⚠️ Linux build temporarily unavailable - мы ищем тестировщика для ручного тестирования перед включением автоматической сборки.
Checksums
See checksums.txt for SHA256 checksums of all files.
Release notes — v2.4.0 (2026-10-16)
EN
A minor release after v2.3.10. Core sing-box-lx 1.14.3-lx.21 (was 1.14.3-lx.18), contract 1.1.130 (was 1.1.119).
New
- Tunnel ingress protection. A client tunnel is a two-way channel: the server on the other side of a WireGuard/AWG, OpenVPN or OpenConnect node could open connections to your router, your LAN or the internet through you, because the core's userspace stack accepts packets for any address. The new Tunnel ingress preset (on by default, added once to existing setups, placed right after the locked head of the rules) rejects every connection arriving from such a tunnel, except what the node allows: the node window of these types gets Allow access to this device (services on the tunnel address; they see the peer as
127.0.0.1), Expose local network (private networks) and Allow as gateway (anything). The preset form has just three settings: what happens to the rest (Incoming from tunnels,rejectby default, ordrop, or an outbound), where allowed device/LAN traffic goes (direct-out) and where gateway traffic goes (proxy-out). While the rest is rejected, peers that are not gateways also get their DNS queries rejected. Tailscale is not covered: tailnet peers are your own devices and already follow Tailscale ACLs and what you announce withadvertise_routes/advertise_exit_node. Contract 1.1.126 / 1.1.129,TEMPLATE_LANG§6.5.2, decisions D-134, D-136. - DNS follows the rule. The window of your own rule (domains, processes or SRS) has a DNS tab: Send DNS to a dedicated server sends DNS queries that match the rule to the chosen server, Force IPv4 (drop AAAA) answers AAAA for them with an empty reply. The build derives the DNS rules from the routing rule and places them before the first library preset with a later position; the DNS tab shows them as read-only 📎 rows, the Rules list marks the rule. Unavailable for rules with ports, protocols or network and for IP-only rules. A disabled DNS server the rule needs stays in the config (📎 in the server list); a deleted one drops the DNS rule with a warning in the build report. The option is the same as in LxBox and now travels in backups both ways — before, the launcher dropped it on import and on save. Contract 1.1.130,
TEMPLATE_LANG§6.11, decision D-137 (#140). - Add server: forms for VLESS, Hysteria2, Trojan, WireGuard (AWG), Naive and MASQUE. VLESS: security None / TLS / Reality, uTLS fingerprint, transports ws, gRPC, HTTP, HTTPUpgrade, XHTTP. Hysteria2: obfuscation and port hopping. WireGuard (AWG): a collapsed AmneziaWG block (
jc…i5). SOCKS5, HTTP and WireGuard moved to the same registry-driven form. The type list is VLESS · Hysteria2 · Trojan · WireGuard (AWG) · Naive · MASQUE · SOCKS5 · HTTP · OpenConnect (SSL VPN) · Tailscale · Source. The same form edits an existing node of these types in the node window. The WireGuard form no longer has a DNS field: tunnel DNS was never applied (the launcher's DNS is global). - OpenConnect (FortiGate, Cisco AnyConnect, GlobalProtect, F5, Pulse, Juniper NC). A form in Add server and in the node editor: gateway type, server, username and password, server certificate check (system CAs / pinned fingerprint / do not verify), SNI and group, and an Advanced block (TCP only, User-Agent, Hostcheck for FortiGate, MTU, DPD interval, reconnect timeout, disable IPv6, legacy crypto). An empty field writes no key. In the server list the node is labelled like
openconnect·fortinet. - OpenConnect second factor and browser (SAML) sign-in — daemon mode (lxd) and remote machines only. When the gateway asks for a code, a dialog shows the gateway's own form fields; "Not now" closes it and sends nothing, "Request a new code" asks the gateway again. FortiGate browser sign-in works through a link and a temporary local callback on 127.0.0.1 (port from the gateway's answer, or 8020). In classic mode the node shows a hint that code prompts are unavailable. SSO that returns a cookie (AnyConnect) is not supported yet.
- Sources: Add with an empty field opens the Add server form; the field's hint names OpenVPN among accepted inputs.
- DNS servers: the server form covers DoQ (
quic, port 853) and DoH3 (h3, port 443, with path) alongside UDP/TCP/DoT/DoH, as in LxBox. - Detour picker is a two-level tree: "(none — direct)" on top and expandable Directions and Nodes branches; the branch with the current choice opens by itself. A chosen target that is no longer in the config stays visible with a ⚠ (missing) mark.
- Template language: short
#ifform.{"#if": [cond, value, else]}is now the canonical spelling; the long{"#and": […], "#value": …, "#else": …}form is still read indefinitely, and the stock template is rewritten to the short form with byte-identical output. A#dooperation in a node loop can be conditional:{"#if": [cond, {"#append": "@node"}]}skips nodes where the condition is false. Contract 1.1.125,TEMPLATE_LANG§4.1 / §6.7.1, decision D-133. - Core builds for linux/386 and linux/riscv64. "Download core" now finds them for a machine whose daemon has not reported its platform yet,
riscv64is offered in the machine and Target architecture lists (Target also gainsmips/mipsle), and a Linux machine on 386 or riscv64 without a passport defaults to the procd service recipe, as these builds target OpenWrt. A machine whose daemon reportspacked(core 1.14.3-lx.21+, the running core is UPX-packed) gets the.upx.tar.gzcopy from "Download core", saved as…-upxbeside the plain one; if the release has no packed copy, the plain binary is downloaded with a warning that it is 4–5 times larger. - Homebrew on macOS:
brew install --cask leadaxe/tap/singbox-launcher. The Cask lives in Leadaxe/homebrew-tap and follows stable releases on its own; the install script stays the recommended option. - Compact JSON in the Preset tab. The preset window's Preset tab shows short constructs on one line (
{"#if": ["@node.allow_local", {"#append": "@node"}]},"#in": [...]) instead of spreading them over five to eight lines; objects and arrays up to 100 characters stay on one line.
Changed
- "Skip presets" is now "Skip Tailscale presets". The node field
skip_presetsbecameskip_tailscale_presets, is shown for Tailscale nodes only and affects only thetailscalepreset — it can no longer switch off the tunnel protection. Oldstate.jsonfiles and backups withskip_presetsare read as before; only the new key is written. - Your SRS rules keep their place in the rule order. In the built config an SRS rule ignored its position and went above every other rule of yours and every library preset, so a rule shown below it in Rules could never match first. It now stands where the list puts it. If you relied on the old order, check the rules list after updating.
- The "Split all traffic 50/50" preset is gone. It was no longer relevant; a saved rule that referenced it is kept disabled with a warning rather than lost.
Fixed
- DNS rule editor no longer drops
rule_setreferences. Opening "Edit DNS Rule" rebuilt the JSON from the form, whose picker held one value from a fixed list, so"rule_set": ["user:custom", "user:dpi"]came back as nothing (or as its first tag). The picker is now a multi-select, keeps tags that are not in the list (a disabled rule, a hand-written tag) and a server that is not enabled, and edits made in the JSON tab carry over to the form instead of being overwritten. Fields of the other rule type are cleared only when you switch the type yourself (#140). - A preset's DNS rule now appears where its routing rule stands. Routing rules live on a numbered axis, DNS rules are ordered by hand, and a newly enabled preset's DNS rule used to be appended after every DNS rule you already had. For the new Tunnel ingress preset that meant its DNS reject landed behind the FakeIP catch-all (
A/AAAA → fakeip) on existing setups, so closed tunnel peers still had their DNS answered although their connections were rejected. A preset's DNS rule is now inserted in front of the first preset DNS rule with a higher routing number (late defaults, presets enabled from the library, backups that lack the entry, the Debug API and a build that runs before the first save alike); your own DNS rules and the rules already in the list are not moved. Fresh installs are unchanged. Contract 1.1.127,TEMPLATE_LANG§6.10, decision D-135. - OpenConnect nodes added as sing-box JSON (
"type": "openconnect") land inendpoints[], where the core expects them. Before, they went tooutbounds[]and the core rejected the whole config withunknown outbound type: openconnect. On a core built withoutwith_openconnectthe node is dropped with a build-report warning instead. - A node whose body the core cannot even decode (for example an old MASQUE body with
network) is turned off automatically like any other node the core rejects, and the config is rebuilt. Before, this error named no tag, the safety net stayed silent and the VPN did not start. - DNS rules: the "SRS (existing rule_set)" picker lists the rule sets of your own SRS rules (
user:<name>,user:<name>:2, …), not only those of enabled library presets (#140). - Detour picker and rule/DNS target lists no longer offer template Direction stubs you deleted (
vpn ①,vpn ②), andblock-outis no longer offered as a detour. - Tailscale: the "Keep local network reachable while using the exit node" checkbox is gone from Add server and the node's Settings block — it had no effect (LAN traffic bypasses the exit node through the "Private IPs" rule preset).
exit_node_allow_lan_accessis still accepted from JSON. - macOS release ZIPs keep the executable bit. The launcher binary was packed as
0644, so an app extracted by hand did not start withoutchmod +x.
Core
sing-box-lx 1.14.3-lx.21(was 1.14.3-lx.18). lx.19:lxd updatefrom the launcher no longer rolls back withTUNSETIFF: device or resource busy(the updater no longer inherits the core's TUN descriptor). From lx.17/lx.18 the first update needs one manual step: stop the core, press Update, start the core — or runsing-box lxd updateover SSH once; later updates work with the core running. lx.20:lxd updateprints download progress, shown in the Service window.- lx.21: router builds for
linux-386(SSE2) andlinux-riscv64; UPX-packed copies forlinux-arm64andlinux-mipsle-softfloat(~17 MB on flash instead of 75–90 MB, at the cost of RAM and a slower start).lxd updatekeeps a packed core packed and checks free space against the new binary before writing; the daemon reportspacked, which the launcher's "Download core" uses. The core also gains an experimentaltrusttunneloutbound/inbound (AdGuard TrustTunnel); the launcher does not offer it yet.
Technical / Internal
- Contract 1.1.120–1.1.124:
openconnectas a known endpoint type; the core's decode-error form names the node by index; wildcard*in the registry, theformattribute and thevariantrole (fields_uncheckedremoved); forms on scheme ref fields and sharedtls/transportsfields,form.fixed,form.implies,exclude_fields/exclude_variants, array element[0]in form paths, active choice by the longest match; an empty described object is dropped, an empty pass-through object is kept. Corpuscorpus/form/*_form.json. - Fyne 2.8.1 → 2.8.2 (#142); GLFW 3.4 on the tagged
pre.2. - golangci-lint CI takes Go from
go.mod, golangci-lint 2.14.0, action v9; 36 errcheck/unused/bodyclose findings fixed. internal/jsonfmt.FormatCompact— order-preserving compact JSON printer (one-line containers up to 100 characters, number literals as written, no HTML escaping);bin/wizard_template.jsonis kept in this form (go run ./tools/tplfmt -w|-check, guarded byTestWizardTemplateFormatted), 2250 → 1383 lines with the same content.- The
#ifbody is parsed in one place (core/template/if_form.go); map-spread, array-element,EvalIfScalar,default_value, the load validator and#doall go through it. Corpus: 28 new cases (short_*,do_if_*), paired with the long form. - Rule DNS mirror:
state.Rule.DNS(RuleDNS, record keydns),build.RuleDNSMirrorMatch(matcher and gate from the registry allowlistsrule_dns_mirror_match/rule_dns_mirror_gate, shared by the build and the rule window),build.RuleDNSMirrorIndex(placement, shared by the build and the DNS tab); mirrors are inserted inMergePresetsIntoDNSand never stored instate.DNS.Rules. TestTestRuleDNSMirror(backup →state.json→ export round trip and the builtdnssection). state.PresetDNSSlotIndexis the single place that computes where a new preset DNS slot goes;SyncDNSOptionsWithActivePresets, the DNS tab'sReconcileDNSRuleOrderandResolveDNS(which now walks a synced copy ofdns.rulesinstead of appending unlisted presets at the end) all use it. One named test:TestLatePresetDNSRuleTakesAxisPosition.- Node record fields travel as one
configtypes.NodeRecordFlags(state → emission → build cache →template.PresetNode.Record→@node.<field>), instead of a per-field map. Corpus:for_each_node*cases renamed toskip_tailscale_presets, newtunnel_ingress_mixed/tunnel_ingress_no_nodes.
RU
Минорный релиз после v2.3.10. Ядро sing-box-lx 1.14.3-lx.21 (было 1.14.3-lx.18), контракт 1.1.130 (было 1.1.119).
Новое
- Защита от входящих из туннеля. Клиентский туннель — двусторонний канал: сервер на той стороне узла WireGuard/AWG, OpenVPN или OpenConnect мог открыть соединение к роутеру, в вашу LAN или в интернет через вас — userspace-стек ядра принимает пакеты на любой адрес. Новый пресет Tunnel ingress (включён по умолчанию, у существующих настроек появляется один раз, стоит сразу после запертой головы правил) отклоняет всё, что приходит из такого туннеля, кроме разрешённого узлом: в окне узла этих типов переключатели Allow access to this device (сервисы на туннельном адресе; пира они видят как
127.0.0.1), Expose local network (частные сети) и Allow as gateway (всё). В форме пресета всего три настройки: что делать с остальным (Incoming from tunnels, по умолчаниюreject, либоdrop, либо outbound), куда идёт разрешённое к устройству и LAN (direct-out) и куда — трафик шлюза (proxy-out). Пока остальное отклоняется, пирам, которые не шлюз, отклоняются и DNS-запросы. Tailscale пресет не трогает: пиры tailnet — ваши же устройства, их ограничивают ACL Tailscale и то, что вы анонсируете черезadvertise_routes/advertise_exit_node. Контракт 1.1.126 / 1.1.129,TEMPLATE_LANG§6.5.2, решения D-134, D-136. - DNS следует за правилом. В окне своего правила (домены, процессы или SRS) появилась вкладка DNS: Send DNS to a dedicated server отправляет DNS-запросы, подходящие под правило, на выбранный сервер, Force IPv4 (drop AAAA) отвечает на их AAAA пустым ответом. Сборка выводит DNS-правила из маршрутного и ставит их перед первым пресетом библиотеки с более поздней позицией; во вкладке DNS они видны строками 📎 только для чтения, в списке Rules правило помечено. Недоступно для правил с портами, протоколами или network и для правил только по IP. Выключенный DNS-сервер, нужный правилу, остаётся в конфиге (📎 в списке серверов); удалённый — DNS-правило не выпускается, в отчёте сборки предупреждение. Опция та же, что в LxBox, и теперь ездит в бэкапах в обе стороны — раньше лаунчер терял её при импорте и сохранении. Контракт 1.1.130,
TEMPLATE_LANG§6.11, решение D-137 (#140). - «Add server»: формы для VLESS, Hysteria2, Trojan, WireGuard (AWG), Naive и MASQUE. VLESS: безопасность None / TLS / Reality, отпечаток uTLS, транспорты ws, gRPC, HTTP, HTTPUpgrade, XHTTP. Hysteria2: обфускация и port hopping. WireGuard (AWG): свёрнутый блок AmneziaWG (
jc…i5). SOCKS5, HTTP и WireGuard переведены на ту же форму по реестру. Список типов: VLESS · Hysteria2 · Trojan · WireGuard (AWG) · Naive · MASQUE · SOCKS5 · HTTP · OpenConnect (SSL VPN) · Tailscale · Source. Та же форма правит готовый узел этих типов в окне узла. В форме WireGuard больше нет поля DNS: DNS туннеля и раньше не применялся (DNS у лаунчера общий). - OpenConnect (FortiGate, Cisco AnyConnect, GlobalProtect, F5, Pulse, Juniper NC). Форма в «Add server» и в правке узла: тип шлюза, сервер, логин и пароль, проверка сертификата сервера (системные CA / отпечаток / без проверки), SNI и группа, блок Advanced (TCP only, User-Agent, Hostcheck для FortiGate, MTU, DPD, reconnect timeout, отключение IPv6, legacy crypto). Пустое поле ключ не пишет. В списке серверов узел подписан как
openconnect·fortinet. - OpenConnect: второй фактор и вход через браузер (SAML) — только в daemon-режиме (lxd) и на удалённых машинах. Если шлюз просит код, открывается диалог с полями, которые отдал сам шлюз; «Not now» закрывает его и ничего не шлёт, «Request a new code» запрашивает код заново. Браузерный вход для FortiGate идёт через ссылку и временный локальный callback на 127.0.0.1 (порт из ответа шлюза или 8020). В классическом режиме на узле подсказка, что запрос кода недоступен. SSO через cookie (AnyConnect) пока не поддерживается.
- Sources: Add при пустом поле открывает форму «Add server»; подсказка поля называет OpenVPN среди принимаемых форматов.
- DNS-серверы: форма сервера умеет DoQ (
quic, порт 853) и DoH3 (h3, порт 443, с путём) наряду с UDP/TCP/DoT/DoH — как в LxBox. - Выбор detour — двухуровневое дерево: сверху «(нет — напрямую)», под ним раскрываемые ветки «Направления» и «Узлы»; ветка с текущим выбором раскрыта сразу. Выбранная цель, которой больше нет в конфиге, остаётся видна с пометкой ⚠ (нет в конфиге).
- Язык шаблонов: короткая форма
#if.{"#if": [cond, value, else]}— теперь канон; длинная{"#and": […], "#value": …, "#else": …}читается бессрочно, штатный шаблон переписан на короткую форму с байт-в-байт тем же конфигом. Операция#doобхода узлов может быть условной:{"#if": [cond, {"#append": "@node"}]}пропускает узлы, где условие ложно. Контракт 1.1.125,TEMPLATE_LANG§4.1 / §6.7.1, решение D-133. - Сборки ядра linux/386 и linux/riscv64. «Download core» находит их и для машины, чей демон ещё не сообщил платформу;
riscv64есть в выборе архитектуры машины и вкладки Target (там же добавленыmips/mipsle); Linux-машина на 386 или riscv64 без паспорта по умолчанию получает рецепт службы procd — эти сборки под OpenWrt. Машина, чей демон сообщаетpacked(ядро 1.14.3-lx.21+, работающее ядро сжато UPX), получает в «Download core» копию.upx.tar.gz— файл с суффиксом-upxрядом с обычным; если сжатой копии в релизе нет, качается обычный бинарь с предупреждением, что он в 4–5 раз крупнее. - Homebrew на macOS:
brew install --cask leadaxe/tap/singbox-launcher. Cask живёт в Leadaxe/homebrew-tap и сам следует за стабильными релизами; install-скрипт остаётся рекомендуемым способом. - Компактный JSON на вкладке Preset. Вкладка Preset окна пресета показывает короткие конструкции в строку (
{"#if": ["@node.allow_local", {"#append": "@node"}]},"#in": [...]), а не на пяти–восьми строках; объекты и массивы до 100 символов остаются в одной строке.
Изменено
- «Skip presets» стал «Skip Tailscale presets». Поле узла
skip_presetsпереименовано вskip_tailscale_presets, показывается только у узлов Tailscale и действует только на пресетtailscale— выключить им защиту туннеля больше нельзя. Старыеstate.jsonи бэкапы сskip_presetsчитаются как раньше, пишется только новый ключ. - Собственные SRS-правила стоят на своём месте в порядке правил. В собранном конфиге SRS-правило не учитывало свою позицию и вставало выше всех остальных ваших правил и пресетов библиотеки, так что правило, стоящее в Rules под ним, не могло сработать первым. Теперь оно стоит там, где его ставит список. Если вы полагались на прежний порядок, проверьте список правил после обновления.
- Пресет «Split all traffic 50/50» снят. Он потерял актуальность; сохранённое правило с ссылкой на него остаётся выключенным с предупреждением, а не теряется.
Исправлено
- Редактор DNS-правил больше не теряет ссылки
rule_set. «Edit DNS Rule» при открытии пересобирал JSON из формы, где выбор набора был одним значением из фиксированного списка, и"rule_set": ["user:custom", "user:dpi"]превращался в пустоту (или в первый тег). Теперь выбор множественный, теги не из списка (выключенное правило, ручной ввод) и невключённый сервер сохраняются, а правки на вкладке JSON переносятся в форму, а не затираются ею. Поля другого типа правила вычищаются только при ручной смене типа (#140). - DNS-правило пресета появляется там, где стоит его маршрутное правило. Маршрутные правила живут на нумерованной оси, DNS-правила упорядочены вручную, и DNS-правило только что включённого пресета дописывалось после всех ваших DNS-правил. Для нового пресета Tunnel ingress это означало, что его DNS-reject у существующих настроек вставал за «ловящим всё» правилом FakeIP (
A/AAAA → fakeip): закрытым пирам туннеля всё ещё отвечал DNS, хотя их соединения отклонялись. Теперь DNS-правило пресета вставляется перед первым DNS-правилом пресета с бо́льшим номером маршрута (поздние дефолты, включение из Library, бэкап без такой записи, Debug API и сборка до первого сохранения — одинаково); ваши DNS-правила и уже стоящие в списке не двигаются. Чистая установка не меняется. Контракт 1.1.127,TEMPLATE_LANG§6.10, решение D-135. - Узлы OpenConnect, добавленные как sing-box JSON (
"type": "openconnect"), попадают вendpoints[], где их ждёт ядро. Раньше они уходили вoutbounds[], и ядро отвергало весь конфиг сunknown outbound type: openconnect. На ядре безwith_openconnectузел снимается с предупреждением в отчёте сборки. - Узел, тело которого ядро не может даже декодировать (например, старое тело MASQUE с
network), выключается автоматически, как любой узел, отвергнутый ядром, и конфиг пересобирается. Раньше в такой ошибке не было тега, страховка молчала, и VPN не поднимался. - DNS-правила: в выборе «SRS (existing rule_set)» есть наборы ваших собственных SRS-правил (
user:<имя>,user:<имя>:2, …), а не только наборы включённых пресетов библиотеки (#140). - Выбор detour и списки целей правил/DNS больше не предлагают удалённые заготовки Направлений шаблона (
vpn ①,vpn ②), аblock-outбольше не предлагается как detour. - Tailscale: из «Add server» и блока узла в Settings убрана галка «Keep local network reachable while using the exit node» — она ничего не делала (локальную сеть мимо exit node пускает пресет «Private IPs»). Поле
exit_node_allow_lan_accessпо-прежнему принимается из JSON. - В macOS-архивах релиза у бинаря есть бит исполнения. Бинарь лаунчера упаковывался как
0644, и распакованное вручную приложение не запускалось безchmod +x.
Ядро
sing-box-lx 1.14.3-lx.21(было 1.14.3-lx.18). lx.19:lxd updateиз лаунчера больше не откатывается сTUNSETIFF: device or resource busy(апдейтер больше не наследует TUN-дескриптор ядра). С lx.17/lx.18 первое обновление требует одного ручного шага: остановить ядро, нажать Update, запустить ядро — либо один разsing-box lxd updateпо SSH; дальше обновление работает при работающем ядре. lx.20:lxd updateпоказывает прогресс скачивания, он виден в окне Service.- lx.21: роутерные сборки
linux-386(нужен SSE2) иlinux-riscv64; копииlinux-arm64иlinux-mipsle-softfloat, сжатые UPX (~17 МБ на флеше вместо 75–90 МБ ценой RAM и более долгого старта).lxd updateоставляет сжатое ядро сжатым и до записи проверяет место под новый бинарь; демон сообщаетpacked, по нему «Download core» в лаунчере выбирает сжатую копию. В ядре также появились экспериментальные outbound/inboundtrusttunnel(AdGuard TrustTunnel); в лаунчере их пока нет.
Техническое / Внутреннее
- Контракт 1.1.120–1.1.124:
openconnectкак известный тип endpoint; ошибка декодирования ядра называет узел по индексу; wildcard*в реестре, атрибутformи рольvariant(fields_uncheckedснят); формы у ref-полей схем и у полей общихtls/transports,form.fixed,form.implies,exclude_fields/exclude_variants, элемент массива[0]в путях формы, активный вариант по самому длинному совпадению; пустой описанный объект снимается, пустой сквозной — остаётся. Корпусcorpus/form/*_form.json. - Fyne 2.8.1 → 2.8.2 (#142); GLFW 3.4 на теге
pre.2. - CI golangci-lint берёт Go из
go.mod, golangci-lint 2.14.0, action v9; исправлены 36 замечаний errcheck/unused/bodyclose. internal/jsonfmt.FormatCompact— компактный печатник JSON с сохранением порядка ключей (контейнер в строку до 100 символов, литералы чисел как в исходнике, без HTML-экранирования);bin/wizard_template.jsonдержится в этом виде (go run ./tools/tplfmt -w|-check, стережётTestWizardTemplateFormatted), 2250 → 1383 строки при том же содержимом.- Тело
#ifразбирается в одном месте (core/template/if_form.go); map-spread, элемент массива,EvalIfScalar,default_value, валидатор загрузки и#doидут через него. Корпус: 28 новых кейсов (short_*,do_if_*), парных с длинной формой. - DNS-зеркало правила:
state.Rule.DNS(RuleDNS, ключ записиdns),build.RuleDNSMirrorMatch(матчер и гейт по спискам реестраrule_dns_mirror_match/rule_dns_mirror_gate, общий для сборки и окна правила),build.RuleDNSMirrorIndex(место, общее для сборки и вкладки DNS); зеркала вставляются вMergePresetsIntoDNSи вstate.DNS.Rulesне хранятся. ТестTestRuleDNSMirror(круг бэкап →state.json→ экспорт и собранная секцияdns). state.PresetDNSSlotIndex— единственное место, где считается позиция нового DNS-слота пресета; им пользуютсяSyncDNSOptionsWithActivePresets,ReconcileDNSRuleOrderDNS-вкладки иResolveDNS(теперь обходит синхронизированную копиюdns.rules, а не дописывает неучтённые пресеты в конец). Один именованный тест:TestLatePresetDNSRuleTakesAxisPosition.- Поля записи узла едут одной структурой
configtypes.NodeRecordFlags(состояние → эмиссия → кэш сборки →template.PresetNode.Record→@node.<поле>) вместо карты на каждое поле. Корпус: кейсыfor_each_node*наskip_tailscale_presets, новыеtunnel_ingress_mixed/tunnel_ingress_no_nodes.