github Leadaxe/LxBox v2.20.5
LxBox v2.20.5

latest releases: v2.25.20, v2.25.19, v2.25.19-rc.3...
3 months ago

L×Box v2.20.5

Two fixes for old Android, both from the same user's reports: importing a
config from a file failed even with a file manager installed, and nodes with
real TLS would not connect at all. Plus a core update that stops connections
through a dead path from hanging for two minutes in silence.

Два исправления для старых Android, оба по репортам одного пользователя: импорт
конфига из файла не работал при установленном файловом менеджере, а узлы с
настоящим TLS не подключались вовсе. Плюс обновление ядра, после которого
соединения через мёртвый путь перестают висеть две минуты в тишине.

🇬🇧 English

🐛 Fixed

Importing a file did nothing, even with a file manager installed. The app
asks the system whether a file picker exists before opening one — without that
check the import button is simply mute on devices that have none. But it asked
about one kind of picker only: the Storage Access Framework, which is answered
by apps that publish documents. Old-school file managers — Total Commander and
its kin, still the norm on Android 7.x — register for a different, older
request and stay silent on that question. The result was the worst of both
worlds: the app confidently reported "no file manager on this device" while a
perfectly good one sat in the launcher, and importing from a file was closed
off entirely.

Both kinds are now checked. The modern one is still preferred where available —
it grants lasting access to the file — and the older one is used when it is all
there is. Selection, reading and the extension filter for the older path had to
be written by hand: the picker plugin builds only the modern request and offers
no way to change it.

If a file is picked but cannot be used — wrong extension, or unreadable — the
app now says so instead of returning silently, which was indistinguishable from
a broken button.

Nodes with real TLS did not connect on old Android. The set of root
certificates that vouches for servers is baked into the firmware. On Android
7.1 it was last updated in 2016, and it never learned about Let's Encrypt: the
ISRG Root X1 root is absent, and the older bridge through DST Root CA X3
expired on 30 September 2021. So the identity check failed for most modern
servers, and only nodes with verification switched off would work — which is
where affected users ended up on their own, giving up server authentication
entirely.

VPN Settings → Core now has a Certificate store setting: system (the
firmware set, as before), mozilla, or chrome. The Mozilla and Chrome sets
are already compiled into the core, so nothing is downloaded, nothing is
fetched from Google, and the app does not grow. One setting fixes every node at
once.

Deliberately not offered: the option to use no roots at all. The core supports
it, but it makes every TLS node unusable and serves no one who is not editing
JSON by hand — where it remains available, in the config editor.

🔌 Core

Connections through a dead path hung for two minutes in silence.
Connections that run inside a tunnel — WireGuard and AmneziaWG nodes, MASQUE,
OpenVPN, OpenConnect, Tailscale — had no time limit of their own. As long as
the path was merely silent rather than actively refusing, nothing gave up: the
attempt kept waiting roughly 127 seconds before failing, and for a domain
name that repeated for every address it resolved to.

This is what a silently broken path looks like in practice: WiFi that stops
passing the tunnel's traffic, a node that goes off the air, a radio that fell
asleep. The app looks frozen — nothing loads and nothing errors out. Worse, the
group of nodes has no failure to react to, so it keeps sending traffic to the
same dead node while apps time out on their own and retry straight back into
it.

Every such connection now gives up after 15 seconds. The limit applies only
while a connection is being established, never to one already carrying data, so
downloads and long-lived streams are untouched. UDP is deliberately left alone:
it has no connect step to limit, and the protocols above it carry their own
timers. Measured on the bench: 2m07s before, 15.05s after, with normal and
waking-from-sleep connections unaffected.

Core pin: v1.14.0-lx.20-rc.8 → v1.14.0-lx.21. The core's Java surface is
byte-for-byte identical across the bump — 226 classes, 3131 signature lines, no
differences — so no app-side changes were required.

✅ Tests

flutter analyze clean across the project, 2952 tests passing, all four
localization checkers green. The file picker fix is device-verified on an
Android TV emulator with a test manager registered for the older request only,
with no regression on the modern path; the certificate setting is
device-verified on an API 34 emulator, including that the choice survives a
cold start and reaches the core. Both fixes still await confirmation on real
Android 7.1.1 hardware — that image exists only for x86 and will not run on
Apple Silicon.

🇷🇺 Русский

🐛 Исправлено

Импорт файла не работал при установленном файловом менеджере. Перед тем
как открыть выбор файла, приложение спрашивает систему, есть ли вообще чем его
открыть — без этой проверки на устройствах без менеджера кнопка импорта просто
немая. Но спрашивало оно лишь про один вид выбора: Storage Access Framework, на
который отвечают приложения-поставщики документов. Файловые менеджеры старой
школы — Total Commander и ему подобные, на Android 7.x до сих пор норма —
регистрируются на другой, более старый запрос и на этот вопрос молчат. Итог
получился худшим из возможных: приложение уверенно сообщало «на этом устройстве
нет файлового менеджера», пока вполне рабочий лежал в лаунчере, и импорт из
файла был закрыт наглухо.

Теперь опрашиваются оба вида. Современный по-прежнему в приоритете там, где он
есть — он даёт постоянный доступ к файлу, — а старый используется, когда
другого нет. Выбор, чтение и фильтр по расширению для старого пути пришлось
написать самим: плагин выбора файлов умеет строить только современный запрос и
сменить его не позволяет.

Если файл выбран, но использовать его нельзя — не то расширение или не
читается, — приложение теперь об этом говорит, а не возвращается молча: молчание
было неотличимо от сломанной кнопки.

Узлы с настоящим TLS не подключались на старых Android. Набор корневых
сертификатов, которыми удостоверяются серверы, вшит в прошивку. На Android 7.1
он последний раз обновлялся в 2016 году и про Let's Encrypt так и не узнал:
корня ISRG Root X1 в нём нет, а более старый мост через DST Root CA X3 истёк
30 сентября 2021 года. Проверка подлинности не проходила для большинства
современных серверов, и работали только узлы с отключённой проверкой — к чему
затронутые пользователи приходили сами, отказываясь от удостоверения сервера
целиком.

В Настройках VPN → Core появился пункт Certificate store: system
(набор из прошивки, как раньше), mozilla или chrome. Наборы Mozilla и
Chrome уже вкомпилированы в ядро — ничего не скачивается, ничего не тянется из
Google, приложение не растёт в размере. Одна настройка чинит все узлы разом.

Намеренно не предлагается вариант «без корневых сертификатов вовсе». Ядро его
поддерживает, но он делает неработоспособными все TLS-узлы и не нужен никому,
кроме тех, кто правит JSON руками, — там, в редакторе конфига, он и остаётся
доступен.

🔌 Ядро

Соединения через мёртвый путь висели две минуты в тишине. У соединений,
идущих внутри туннеля — узлы WireGuard и AmneziaWG, MASQUE, OpenVPN,
OpenConnect, Tailscale — не было собственного ограничения по времени. Пока путь
просто молчал, а не отвечал отказом, сдаваться было нечему: попытка ждала около
127 секунд до отказа, а для доменного имени это повторялось для каждого его
адреса.

Именно так выглядит тихо сломанный путь: Wi-Fi перестал пропускать трафик
туннеля, узел ушёл из эфира, радиомодуль заснул. Приложение выглядит зависшим —
ничего не грузится и ничего не сообщает об ошибке. Хуже того, группе узлов не
на что реагировать, поэтому она продолжает слать трафик в тот же мёртвый узел,
а приложения отваливаются по своим таймаутам и ретраятся туда же.

Теперь каждое такое соединение сдаётся через 15 секунд. Ограничение действует
только на время установки соединения и никогда — на уже установленное, так что
загрузки и долгоживущие потоки не затронуты. UDP сознательно не тронут: у него
нет фазы установки, которую можно ограничить, а протоколы над ним несут
собственные таймеры. Замерено на стенде: было 2м07с, стало 15.05с; обычные
соединения и соединения через просыпающийся узел не затронуты.

Пин ядра: v1.14.0-lx.20-rc.8 → v1.14.0-lx.21. Java-поверхность ядра при
бампе не изменилась ни на байт — 226 классов, 3131 строка сигнатур, ноль
расхождений, — поэтому правок в приложении не потребовалось.

✅ Тесты

flutter analyze чист по всему проекту, 2952 теста проходят, все четыре
l10n-чекера зелёные. Фикс выбора файла проверен на устройстве — эмулятор
Android TV с тестовым менеджером, зарегистрированным только на старый запрос, —
регрессии на современном пути нет; настройка сертификатов проверена на
эмуляторе API 34, включая то, что выбор переживает холодный старт и доезжает до
ядра. Оба исправления ждут подтверждения на реальном железе с Android 7.1.1:
образ этой версии существует только под x86 и на Apple Silicon не запускается.


Install / Установка

adb install -r LxBox-v2.20.5-arm64-v8a.apk

Без uninstall! Поверх существующей установки. Настройки и подписки сохранятся.

No uninstall needed — install over the existing one. Settings and
subscriptions are preserved.


Previous release / Предыдущий релиз: v2.20.4.

Don't miss a new LxBox release

NewReleases is sending notifications on new releases.