L×Box v2.24.4
A one-fix patch. Opening the JSON tab of a DNS server that comes from a
template or a preset showed “This section failed” instead of the server
(#143). It is a regression of
v2.24.0: the storage format moved to records 1.0 and the model lost its direct
serialization, but this tab still encoded the model as is. Servers you added
yourself were not affected. Nothing else changed since v2.24.3; the v2.24.3 notes are included below, since that release has no page of its own.
Патч с одним исправлением. Вкладка JSON у DNS-сервера из шаблона или
пресета показывала «В этом разделе произошла ошибка» вместо содержимого
(#143). Это регрессия v2.24.0:
формат хранения перешёл на записи 1.0, у модели не осталось прямой
сериализации, а вкладка по-прежнему кодировала модель как есть. Серверы,
добавленные вручную, затронуты не были. Больше с v2.24.3 ничего не менялось; описание v2.24.3 приведено ниже — своей страницы у того релиза нет.
🇬🇧 English
🩹 JSON tab of a template/preset DNS server (#143, docs/spec/tasks/458)
- Was: for a DNS server of kind template or preset the JSON tab failed on
open withConverting object to an encodable object failed: Instance of 'DnsServerTemplate'in Debug → Logs. The tab's “storage shape” block handed
the controller's snapshot straight to the JSON encoder; since v2.24.0 the
model has notoJson, the storage record is produced by a codec. The
sibling tab of the rule editor was moved to the codec back then, this one
was missed. Affected: v2.24.0 through v2.24.3. - Now: the block is built by the same codec and shows the record exactly as
it sits inlxbox_settings.json(kind/tag/varsfor a template,
kind/reffor a preset). The resolved body preview below it and the
editable JSON of an inline server are unchanged.
🧪 Tests
- A widget test of the tab for both kinds; it is red without the fix.
flutter analyzeclean over the whole project, the full test suite, four
l10n checkers and the docs parity check green.
🇷🇺 Русский
🩹 Вкладка JSON у DNS-сервера из шаблона или пресета (#143, docs/spec/tasks/458)
- Было: у DNS-сервера вида template или preset вкладка JSON падала при
открытии, в Отладка → Логи:Converting object to an encodable object failed: Instance of 'DnsServerTemplate'. Блок «storage shape» вкладки
отдавал снимок контроллера прямо в JSON-кодировщик; с v2.24.0 у модели нет
toJson, запись хранения строит кодек. Парную вкладку редактора правил
тогда перевели на кодек, эту пропустили. Затронуты v2.24.0 – v2.24.3. - Стало: блок строится тем же кодеком и показывает запись в том виде, в
каком она лежит вlxbox_settings.json(kind/tag/varsу шаблона,
kind/refу пресета). Превью отрезолвленного тела ниже и редактируемый
JSON inline-сервера не менялись.
🧪 Тесты
- Виджет-тест вкладки для обоих видов; без фикса красный.
flutter analyzeчист по всему проекту, полный набор тестов, четыре
l10n-чекера и проверка паритета доков зелёные.
Also in this build: v2.24.3 / В этой сборке также: v2.24.3
v2.24.3 (17.09.2026) was tagged and shipped to Google Play, but its GitHub
release page was never published: the asset upload to GitHub failed on every
attempt. v2.24.4 is built on top of it, so everything below is in these APKs.
v2.24.3 (17.09.2026) получил тег и ушёл в Google Play, но страница релиза на The node editor stops losing what you type. A NaïveProxy node with its own Редактор узла перестал терять то, что вы вписали. Узел NaïveProxy со своим
GitHub так и не была опубликована: загрузка файлов на GitHub падала при каждой
попытке. v2.24.4 собран поверх него, поэтому всё ниже есть в этих APK.
v2.24.3 — release notes / описание релиза
root certificate in tls.certificate used to lose that field on Save, because
the TLS model knew six fields and dropped the rest (#140).
Now the model carries every TLS key the core knows, and the editor itself is
rebuilt around the source: the Source tab is the node's original text and the
only place you edit, the JSON tab shows what the core will receive. A node
whose source is a sing-box JSON object goes to the core verbatim, checked by the
core on Save. WireGuard .conf files are stored as files again, tag aside. The
core moves to v1.14.1-lx.4: TLS fragmentation finally applies to REALITY, and
REALITY gets a per-node key_share choice between the hybrid post-quantum
ClientHello and the classical one.
корневым сертификатом в tls.certificate терял это поле на Save: модель TLS знала
шесть полей, остальное отбрасывала (#140).
Теперь модель несёт все TLS-ключи ядра, а сам редактор перестроен вокруг
источника: вкладка Source — исходный текст узла и единственное место правки,
вкладка JSON — то, что получит ядро. Узел, чей источник — sing-box JSON,
уходит в ядро дословно, с проверкой ядром при сохранении. WireGuard .conf
снова хранится как файл, тег отдельно. Ядро поднято до v1.14.1-lx.4:
TLS-фрагментация наконец действует на REALITY, а у REALITY появился по-узловой
выбор key_share между гибридным постквантовым ClientHello и классическим.
🇬🇧 English
🔐 TLS fields survive the node editor (#140, docs/spec/tasks/454)
server_name, alpn, insecure, utls,
reality and the public-key pin. Anything else in a node's tls block —
certificate, certificate_path, min_version, cipher_suites,
client_certificate, fragment — was dropped silently on Save, for every
protocol. NaïveProxy was trimmed further, to enabled + server_name, so a
self-signed server could not be reached at all: insecure is rejected by
the core on naive.
OutboundTLSOptions of the core. Keys the app
does not reason about pass through in the form they arrived — a string stays
a string, an array stays an array. Naive keeps certificate and
certificate_path on top of the two it had; everything the core rejects on
naive is still trimmed. The pin certificate_public_key_sha256 is now read
from sing-box JSON too. A value of the wrong type drops the field, not the
node. Nodes without the new fields emit byte-for-byte as before. The
allowlist is shared with the launcher (contract TASKS_LXBOX §22).
cannot carry when moved into a folder or copied as a link — it was rebuilt
through toUri(). It now keeps its own outbound object as its source.
📝 Node editor: Source and JSON tabs (docs/spec/tasks/455)
that copy over the original. Whatever the model did not know was gone.
or a sing-box JSON object — and the only place you edit; Save writes it as
is (the Tag field goes into the link's fragment or the JSON body). JSON
is read-only: what the core will receive. A node whose source is a JSON
object goes into the config verbatim, including keys the app does not know;
the core validates it on Save (Libbox.checkConfig), a rejected body is not
stored and the core's message is shown. Edit JSON replaces the source
with the shown JSON after a warning and takes you to Source; there is no way
back to a link. Storage is unchanged: the kind of the source is derived from
the text, there is no flag — the same rule the launcher applies to a manual
object.
📄 WireGuard
.conf is stored as the file (docs/spec/tasks/456)
wg://…#name link and
that link was stored as the source — comments and line order were lost, the
record kind was uri.
wg_ini
(as in the launcher) and the tag is a record field applied on read. The
initial name comes from the comment right under [Peer] (Proton writes
# CH-FREE#11 there), else the file name, else WireGuard. An Amnezia
vpn:// link gives each node its own INI. Records made earlier keep reading
as before.
nodes, and a Tailscale node lost its body when moved into a folder.
⚙️ Core
v1.14.1-lx.4 and REALITY key_share (docs/spec/tasks/457)
tls.fragment and tls.record_fragment now apply to REALITY nodes (core
SPEC 088). Before, the REALITY client built its handshake on the bare socket
and skipped both, including the automatic record_fragment the core enables
under a detour; the global fragmentation toggle looked on and did nothing
there. Nothing changed in the app — the toggle simply works now.
tls.reality.key_share (core SPEC 089). hybrid
requires X25519MLKEM768: the ClientHello grows to ~1.5–1.9 KB and leaves
in two TCP segments — Xray servers from v26.9.8 demand it. classical
strips the hybrid from key_share and supported_groups: ~0.5 KB, one
segment — for older servers and for networks that drop the big handshake.
Unset means whatever the fingerprint carries, as before. Set it in sing-box
JSON or as key_share= in a vless/anytls share link; a value outside the
pair is dropped silently and the node stays alive, because the core would
reject the whole config on it. The URI parameter name is shared with the
launcher.
identical to lx.3 (javap over all 253 classes — empty diff).
🔧 TCP keep-alive per node (docs/spec/tasks/453)
disable_tcp_keep_alive, tcp_keep_alive and
tcp_keep_alive_interval since 1.13, but the app did not know them and
dropped them on Save.
stored and shared in — sing-box JSON, share-URI and Xray JSON (sockopt,
whole seconds; a negative value means keep-alive off). Nine carriers, the
protocols that dial over TCP; QUIC/UDP nodes have no socket to apply them
to. A value that is not a Go duration is dropped on input. Nodes without the
fields emit byte-for-byte as before. No form fields — the JSON tab and
import only.
🧪 Tests
flutter analyze clean over the whole project, four l10n
checkers and the docs parity check at zero.
types, ech, byte parity, QUIC), verbatim body in the build, the core check
payload, INI name from the [Peer] comment, wg_ini records with a tag,
key_share round-trips and guards.
string inside the built APK (1.14.1-lx.4).
key_share is
still pending — please report on the issue if something does not behave.
🇷🇺 Русский
🔐 TLS-поля переживают редактор узла (#140, docs/spec/tasks/454)
server_name, alpn, insecure, utls,
reality и пин публичного ключа. Всё остальное в блоке tls узла —
certificate, certificate_path, min_version, cipher_suites,
client_certificate, fragment — молча отбрасывалось на Save, для любого
протокола. NaïveProxy резался ещё сильнее, до enabled + server_name, и
до сервера с самоподписанным сертификатом было не достучаться: insecure
ядро на naive отвергает.
OutboundTLSOptions ядра. Ключи, о которых
приложение не рассуждает, проходят насквозь в форме прибытия — строка
остаётся строкой, массив массивом. Naive пропускает certificate и
certificate_path в дополнение к двум прежним; всё, что ядро на naive
отвергает, по-прежнему режется. Пин certificate_public_key_sha256 теперь
читается и из sing-box JSON. Значение не того типа отбрасывает поле, а не
узел. Узлы без новых полей эмитятся байт в байт прежними. Allowlist общий с
лаунчером (контракт TASKS_LXBOX §22).
папку и в «Copy link» — его пересобирали через toUri(). Теперь он хранит
свой объект outbound'а как источник.
📝 Редактор узла: вкладки Source и JSON (docs/spec/tasks/455)
копию поверх оригинала. Чего модель не знала, то пропадало.
sing-box JSON) и единственное место правки; Save пишет его как есть (поле
Tag уходит во фрагмент ссылки или в тело JSON). JSON — только чтение: то,
что получит ядро. Узел, чей источник — JSON-объект, идёт в конфиг дословно,
включая ключи, которых приложение не знает; ядро проверяет его при
сохранении (Libbox.checkConfig), отвергнутое тело не сохраняется, ошибка
показывается словами ядра. Edit JSON после предупреждения заменяет
источник показанным JSON и уводит в Source; обратно в ссылку узел не
превращается. Хранение не менялось: вид источника выводится из текста,
флага нет — то же правило, что у лаунчера для ручного объекта.
📄 WireGuard
.conf хранится как файл (docs/spec/tasks/456)
wg://…#имя,
и источником хранилась она — комментарии и порядок строк терялись, вид
записи был uri.
wg_ini (как у
лаунчера), тег — поле записи и применяется при чтении. Начальное имя —
комментарий сразу под [Peer] (Proton пишет туда # CH-FREE#11), иначе имя
файла, иначе WireGuard. Ссылка Amnezia vpn:// даёт каждому узлу свой
INI. Старые записи читаются как раньше.
авто-эмодзи, а узел Tailscale терял тело при переезде в папку.
⚙️ Ядро
v1.14.1-lx.4 и key_share у REALITY (docs/spec/tasks/457)
tls.fragment и tls.record_fragment теперь действуют на REALITY-узлы
(ядро SPEC 088). Раньше REALITY-клиент строил рукопожатие на голом сокете и
оба пропускал, включая авто-record_fragment, который ядро включает под
detour; глобальный тумблер фрагментации выглядел включённым и ничего там
не делал. В приложении ничего не менялось — тумблер просто заработал.
tls.reality.key_share (ядро SPEC 089). hybrid
требует X25519MLKEM768: ClientHello вырастает до ~1,5–1,9 КБ и уезжает
двумя TCP-сегментами — этого требуют Xray-серверы от v26.9.8. classical
вырезает гибрид из key_share и supported_groups: ~0,5 КБ и один сегмент
— для серверов постарше и для сетей, которые большое рукопожатие роняют.
Без поля — как несёт отпечаток, прежнее поведение. Задаётся в sing-box JSON
или как key_share= в share-ссылке vless/anytls; значение вне пары
отбрасывается молча, узел остаётся жив, потому что ядро на нём отвергло бы
весь конфиг. Имя URI-параметра общее с лаунчером.
с lx.3 (javap по всем 253 классам — дифф пуст).
🔧 TCP keep-alive на узле (docs/spec/tasks/453)
disable_tcp_keep_alive, tcp_keep_alive и
tcp_keep_alive_interval с 1.13, но приложение их не знало и теряло на
Save.
и передаётся: sing-box JSON, share-URI и Xray JSON (sockopt, целые секунды;
отрицательное значение — keep-alive выключен). Носителей девять — протоколы с
TCP-дозвоном; QUIC/UDP-узлам поля не к чему применить. Значение не в формате
Go-duration отбрасывается на входе. Узлы без полей эмитятся байт в байт
прежними. Полей в форме нет — только JSON-вкладка и импорт.
🧪 Тесты
flutter analyze чист по всему проекту, четыре
l10n-чекера и проверка паритета доков на нуле.
типы, ech, байт-паритет, QUIC), дословное тело в сборке, нагрузка проверки
ядром, имя INI из комментария [Peer], записи wg_ini с тегом, round-trip
и guard'ы key_share.
собранного APK (1.14.1-lx.4).
key_share ещё не
сделана — если что-то ведёт себя не так, напишите в issue.
Install / Установка
adb install -r LxBox-v2.24.4-arm64-v8a.apkБез uninstall! Поверх существующей установки. Настройки и подписки сохранятся.
No uninstall needed — install over the existing one. Settings and subscriptions
are preserved.
Previous release / Предыдущий релиз: v2.24.3.