Commit Graph
30 Commits
Author SHA1 Message Date
Dushnilin 4c69a98c27 fix(singbox): fix Leadaxe (lx) version parsing regex and AWG startup on OpenWrt
- In action.uc: replace broken PCRE non-capturing regex in extract_sing_box_version_from_output with token-based field splitting. ucode POSIX regex engine threw 'Repetition not preceded by valid expression', crashing component_action during binary validation.
- In telegram.uc: replace non-capturing group (?:outbounds|server|servers) with standard capturing group for POSIX regex compatibility.
- In generator_outbounds.uc and servers.uc: enhance is_lx detection to check sing-box-version file in addition to sing-box-variant, ensuring AWG 2.0 root schema is generated even if variant file is desynced.
- In runtime.uc: add fallback recovery in sing_box_check retry loop for endpoints (auto-flattening amnezia sub-objects) and outbounds unknown fields.
2026-09-03 21:11:00 +03:00
Dushnilin 43eafd8655 fix(singbox): filter dummy subscription nodes and handle empty binary rulesets on boot 2026-09-03 06:26:39 +03:00
Dushnilin b3358f77a3 fix(stability): optimize Go memory tiers, prevent nftables degradation deadlock, harden NTP & process supervision
- singbox/runtime.uc: add dynamic 4-tier GOMEMLIMIT and GOGC limits based on RAM, enforce /etc/tachyon/mem_scale, and install managed init script across all binary variants
- service/event_controller.uc: guard probe_nftables() with recovery_bypass and native_internet_restored checks to prevent 5-minute network drop deadlock
- service/watchdog.uc: reduce Telegram worker heartbeat timeout from 900s to 300s and add nslookup fallback to Zero-RTT prefetcher
- diagnostics/runtime.uc & service/lifecycle.uc: use direct-IP NTP pool to eliminate circular DNS/TLS deadlocks, and step clock forward on cold boot if RTC desynced
- service/failover.uc & diagnostics/runtime.uc: flush conntrack states on proxy group switch so client connections immediately migrate
2026-09-03 06:13:30 +03:00
Dushnilin a2eaf25c90 fix(runtime): auto-detect listen IP via ubus interface dump on x86/64
On x86/64 the LAN interface is often named 'eth1', 'enp2s0', etc.
in UCI - not 'lan' or 'br-lan'. The two-tier probe both fail,
producing 'Failed to determine the listening IP address' on startup.

Add a third-tier fallback using ubus network.interface dump:
- is_private_ipv4(): RFC-1918 address check
- network_interface_dump_first_private_ipv4(): iterates all UCI
  interfaces, skips wan/wan6/loopback, returns first private IPv4

Workaround (no update needed):
  uci set tachyon.settings.service_listen_address='192.168.x.x'
  uci commit tachyon && /etc/init.d/tachyon restart
2026-09-02 15:16:15 +03:00
Dushnilin 0f0eb90cdc fix: add missing command_status_from_args alias in singbox/runtime.uc
Fixes crash-loop introduced in 1.3.13. The function was called on lines
494-495 (stop/disable conflicting forkop/podkop services at startup) but
the alias was never declared, unlike command_success_from_args on line 48.
This caused a 'Type error: left-hand side is not a function' crash in
configure_service(), sending Tachyon into a 75-second crash loop.

Fixes #44
2026-09-02 13:20:19 +03:00
Dushnilin c33018fe8f fix(service): подавлять конкурирующие службы Forkop/Podkop из ROM при старте 2026-09-01 12:44:29 +03:00
Dushnilin e4e2d19c6d fix(runtime): устранение сбоев запуска sing-box, исправление правил nftables и защита от гонок вочдога
- Восстановление кэша правил: восстановление .srs, .lst, .json файлов из постоянного каталога /etc/tachyon/rulesets/ при старте; защита от удаления кэша при остановке; добавление фоллбэка пустых ruleset в runtime.uc перед валидацией
- nftables: удаление невалидного auto-merge для интервальных составных сетов (ipv4_addr/ipv6_addr . inet_service)
- core/ip: исправление нормализации IPv6-адреса и порта для TPROXY без дублирования скобок
- dns block: исправление возвращаемого статуса nft_add_dns_block_rules_from_schedules при отсутствии правил блокировки
- watchdog & lifecycle: добавление флага блокировки /var/run/tachyon/starting для исключения сброса правил вочдогом во время старта
- ui & i18n: форматирование бейджей устройств в родительском контроле и обновление переводов
2026-08-21 08:52:23 +03:00
Dushnilin 364b79ee27 fix: loop unknown inbound field stripping in sing-box config check
The graceful degradation for unknown sing-box inbound fields (e.g.
prefer_ip, tolerate_time_skewness) only retried once. When an older
sing-box version doesn't support multiple new fields, the first
unknown field gets stripped and the retry fails on the second one.

Now loops the check-strip-retry cycle until either:
- sing-box check passes
- no more unknown inbound fields are detected
- no stripping occurred (break to avoid infinite loop)

Fixes: 'Generated sing-box configuration is invalid: inbounds[8].
tolerate_time_skewness: json: unknown field' on older sing-box versions.
2026-08-20 13:57:11 +03:00
Dushnilin 0964b79171 fix(ai-chat): fix AI Chat and Assistant to work with LM Studio
- Fix response parsing: check report field, not just message
- Pass user query text to LLM instead of ignoring it
- Append user question to diagnostic prompt with system context
- Increase timeout to 120s for LM Studio responses
- Add command_status_from_args to core/common.uc exports

Closes #38
2026-08-19 15:57:42 +03:00
Dushnilin fe0099a32a fix(singbox): использовать password вместо secret в объектах пользователей inbounds и расширить fallback неизвестных полей 2026-08-18 07:36:03 +03:00
Dushnilin 1437997153 fix(core): повышение стабильности, фоновый поиск MTU AWG, zero-fork проверка WAN и защита от OOM 2026-08-15 15:51:10 +03:00
Dushnilin d527b86d4c Fix procd sing-box termination timeout, watchdog backup dir creation, and telegram retry log levels 2026-08-12 13:09:05 +03:00
Dushnilin 3b1eb89124 fix: graceful fallback for unknown inbound fields in sing-box config
Older sing-box versions fail on 'close_timeout' in MTProto inbound
(added in Tachyon to fix SIGHUP hot-reload crash, issue #15).

Instead of hard-failing, runtime.uc now detects 'json: unknown field'
errors from sing-box check, strips the offending inbound field from
all inbounds in the generated JSON, and retries the check once.

This makes Tachyon forward-compatible: new fields for newer sing-box
versions degrade gracefully on older installs without requiring manual
version detection or config changes.
2026-08-10 14:11:06 +03:00
Dushnilin 6cf90e3e84 fix(updates): не выдавать успешное обновление за ошибку "Failed to execute"
Воркер компонентного действия перенаправлял stderr в тот же файл, что и
stdout (2>&1). Действие печатает результат в stdout одним JSON-объектом,
а stderr — предупреждения apk/opkg, вывод init-скрипта при рестарте —
попадал в тот же файл после JSON. Разбор всего файла падал, построчный
фолбэк не находил объекта, и finish_component_job писал синтетический
success: false с последней строкой лога в качестве сообщения.

Особенно надёжно это ломало самообновление Tachyon: install_tachyon
рестартует сервис, будучи предком воркера, поэтому вывод рестарта
гарантированно ложился поверх канала результата.

Теперь stderr пишется в отдельный <job>.out.stderr, он же используется
как источник сообщения, когда воркер действительно умер, не напечатав
результат. Файл убирается вместе с заданием и подметается orphan-очисткой.

Заодно валидация sing-box перестала судить о бинарнике по коду возврата:
popen().close() отдаёт сырой wait-статус, а command_output отбрасывал
stdout при любом ненулевом статусе. `sing-box version` печатает версию и
может завершиться ненулевым кодом или получить сигнал от остановки
сервиса перед установкой — валидация получала "", объявляла рабочий
пакет битым и откатывала установку с exit_code 129 (128+SIGHUP). Добавлен
command_output_lenient, он же чинит показ версии в дашборде.
2026-08-10 05:21:19 +03:00
Dushnilin e6e3853f05 fix(errors): перестать глотать сбои записи состояния в пустых catch
Пустых catch в кодовой базе около полусотни, и они не одинаковые. Большинство
выражает намерение: fs.unlink бросает на ENOENT, а вызывающий говорит «пусть
этого файла не будет», и отсутствующий файл это условие уже выполняет; разбор
json в цикле пропускает мусорную строку и берёт следующую. Такие места теперь
несут пояснение, почему пустое тело здесь и есть правильный ответ.

Семь мест к этому классу не относились: там сбой означал потерю состояния, а
дальше код шёл так, будто всё получилось.

Watchdog писал через пустой catch файл лока перезапуска прокси, шкалу
GOMEMLIMIT после OOM, бэкап конфига и метку keepalive. Не лёгший лок означает,
что следующий тик перезапустит прокси заново, а счётчик rate-limit об этом не
узнает; не записанная метка keepalive заставляет init.d считать watchdog мёртвым
и перезапускать его. Все четыре теперь идут через write_state_file, который
логирует отказ. Метка пишется на каждом тике uloop, поэтому безусловная строка
залила бы syslog именно при переполненной файловой системе — там, где лог нужнее
всего; вместо этого каждый путь сообщает о первом отказе и молчит до следующего
успеха, что заодно делает видимым восстановление.

Контроллер разбирал /etc/sing-box/config.json ради портов http и tproxy и при
неудаче молча брал 4534 и 4530. Watchdog после этого опрашивает не тот порт,
вечно считает прокси нерабочим и лечит его по кругу — при том, что в логе нет
ничего, что связало бы это с конфигом. Разбор вынесен в общую функцию, которая
сообщает о непарсящемся конфиге один раз на процесс.

Telegram молча терял карту callback-токенов: токен уже вшит в клавиатуру к
моменту записи, поэтому провал отдаёт пользователю кнопку, которая на нажатие
ответит «кнопка устарела». Обновление списков молча теряло маркер отложенного
применения nft — списки обновлены на диске и до nftables не доехали никогда,
а строкой выше в лог написано, что маркер сохраняется. urltest молча выкидывал
битое регулярное выражение из конфига пользователя, отчего группа тихо
подхватывала меньше outbound-ов, чем сказано в конфиге.

tests/heal_escalation.sh проверял порядок строк по литералу fs.writefile для
лока и обновлён под новый вызов.
2026-08-08 22:32:09 +03:00
Dushnilin 488bbfefd5 fix: комплексный аудит и исправление ucode кодовой базы
Критические исправления:
- safe_proxy_restart: удаление lock-файла после фонового перезапуска
  с защитой от stale lock (>300 сек)
- write_json_file: атомарная запись через tmp+mv вместо прямой
- write_reload_state: атомарная запись через tmp+mv
- state_add_list: отклонение значений с пробелами

Исправления безопасности:
- killall logread заменён на pkill -f 'logread -f'
- SIGTERM→SIGKILL для Telegram и sing-box при остановке
- Recover OOM scale: инкремент +0.05 каждые 10 минут
- nfqueue и byedpi: trap для корректного завершения дочерних процессов
- nfqueue: валидация стратегий и откат при ошибке запуска
- nfqueue: flush mangle_output перед добавлением правил
- Исправлен парсинг exit code в 14 файлах (status & 127)

Улучшения стабильности:
- init.d: trap для start_service/stop_service
- watchdog: signal traps для legacy fallback loop
- lifecycle: логирование ошибок при остановке компонентов
- singbox/priority: SIGTERM→SIGKILL при остановке
- telegram: exponential backoff (1x→300s) при ошибках API
- telegram: process_updates возвращает boolean для отслеживания успеха
- watchdog: кэш proxy port для уменьшения чтения конфига sing-box
- singbox/generator: упрощён atomic_write_json_file
- packages.uc: переупорядочивание apk_version (лёгкие запросы первыми)
- dns/apply: проверка PID sing-box перед настройкой dnsmasq
- server/service: cleanup_orphaned_server_certs перед вызовом
2026-08-06 00:03:51 +03:00
Dushnilin b7d05034c8 исправление: утечки ФД и временных файлов, переполнение ОЗУ
Проблема с FD-каскадом (зависание sing-box):
watchdog.uc открывал logread -f через popen() без O_CLOEXEC. Каждый
фоновый system('... &') порождал дочерний процесс, наследующий read-end
logread pipe. После kill watchdog — дочерний процесс держал pipe, logread
не получал SIGPIPE и оставался живым. За N перезапусков накапливалось
N orphan-процессов logread → исчерпание лимита 1024 FD → генератор
конфига sing-box не мог открыть .uc файлы → sing-box не стартовал.

Исправления FD-утечки:
- watchdog.uc: добавлена переменная logread_pipe_fd + помощник bg_system(),
  который закрывает FD logread перед запуском фоновых процессов
- watchdog.uc: killall logread перед открытием нового logread -f в
  setup_syslog_listener() для очистки orphan-процессов от предыдущих экземпляров
- watchdog.uc: все 7 вызовов system('... &') переведены на bg_system():
  restart, reload_firewall (x3), WAN ifdown/ifup, subscription_update_async (x3)
- initd.uc: killall logread в stop_service() после остановки tachyon
- nft/apply.uc: добавлены </dev/null >/dev/null 2>&1 к голому reload_firewall &
- updates.uc: добавлены редиректы к tachyon reload &
- telegram.uc: добавлен </dev/null к reload_firewall &

Проблема с утечкой временных файлов (500MB в /tmp):
При каждом tachyon restart (SIGKILL) процессы-генераторы умирали на
полуслове, оставляя /tmp/tmp.* файлы (sing-box config JSON ~3.4MB,
reload state). За 8 дней накопилось 227 файлов = 506MB в tmpfs,
что занимало 25% всего ОЗУ (519MB из 2007MB shared).

Исправления утечки временных файлов:
- temp_path() в runtime.uc и updates.uc теперь создаёт /tmp/tachyon-XXXXXX
  вместо /tmp/tmp.XXXXXX (безопасный для очистки префикс)
- nft/apply.uc и lifecycle.uc: аналогичное изменение mktemp
- lifecycle.uc start_impl(): автоматическая очистка /tmp/tachyon-* файлов
  старше 30 минут при каждом старте сервиса

Результат на роутере 192.168.2.1:
  logread после stop  = 0 (было 1+)
  logread после start = 1 (было 2+ в каскаде)
  sing-box = запущен
  /tmp shared         = 27MB (было 519MB, освобождено ~490MB)
  ОЗУ available       = 1691MB (было 1195MB)
2026-08-04 15:36:37 +03:00
Dushnilin 2c31a62e4d fix: same-release SHA prefix compare + sing-box generator error detail
- action.uc: compare release target_commitish (full 40-char SHA) with
  installed short SHA by prefix instead of exact match; fixes false
  'same release update found' when commit is actually the same
- runtime.uc: generator_failure_reason now returns the first error line
  instead of the ucode 'Near here ---^' position marker, and logs full
  generator output at debug level on failure for better diagnostics
2026-08-04 11:31:51 +03:00
Dushnilin a3f877c960 fix: file handle safety, orphan cleanup, error logging edge cases
generator.uc: try/catch around hosts cache file read with guaranteed close
hosts.uc: try/catch around parse_hosts_file with guaranteed close
migration.uc: try/catch around remove_cache_path, checked unlink in remove_legacy
runtime.uc: cleanup stale temp config files on init_config startup
lifecycle.uc: log warning on nft table delete failure in stop_main
2026-08-03 20:06:18 +03:00
Dushnilin 93516e13cd fix(updates): исправление репозитория релизов на Dushnilin/tachyon и добавление HTTP Location fallback (v1.2.29) 2026-07-26 12:47:32 +03:00
Dushnilin e32d30a8fe feat: Интеграция Tor Darknet, авто-установщик Tor (opkg/apk), поддержка sing-box lx и фикс локализаций
1. Добавлен встроенный установщик Tor через LuCI-попап с поддержкой opkg и apk.
2. Маршрутизация скрытых сетей (.onion / .i2p) интегрирована на уровень backend (route.uc, generator.uc).
3. Добавлена прозрачная поддержка форка sing-box lx: UI и генераторы теперь корректно включают 'extended' фичи для lx.
4. Проведен полный аудит и восстановление отсутствующих переводов в fe-app-tachyon и luci-app-tachyon.
2026-07-21 14:57:57 +03:00
Dushnilin 07e472d617 fix(runtime): use cached version state for lx marker 2026-07-21 10:41:57 +03:00
Dushnilin 16359d260c fix: исправление проблемы обновления Leadaxe (sing-box-lx) 2026-07-21 10:16:11 +03:00
Dushnilin 41c6a7c114 Support XHTTP in sing-box-lx and check for with_xhttp tag instead of variant marker 2026-07-20 14:39:30 +03:00
Dushnilin e0b70d6b99 feat: добавлена поддержка варианта sing-box Leadaxe (lx) 2026-07-20 08:29:56 +03:00
Dushnilin 509cf128b8 Merge: объединить изменения из upstream forkop в tachyon, разрешить конфликты и исправить тесты E2E 2026-07-15 17:56:18 +03:00
Dushnilin 46ef97fe89 Release 1.0.6: синхронизировать изменения из upstream и исправить баг фильтра URLTest/Priority 2026-07-14 08:56:31 +03:00
Dushnilin f017d01a52 Рефакторинг кода: дедупликация ucode, исправления shellcheck и глобальное улучшение install.sh 2026-07-13 22:38:24 +03:00
Dushnilin f57dac6b52 refactor(rebrand): полный ребрендинг в Tachyon и перенос служб watchdog/doctor на Ucode 2026-07-13 14:09:38 +03:00
Dushnilin e89a795566 refactor(rebrand): полный ребрендинг в Tachyon и перенос служб watchdog/doctor на Ucode 2026-07-13 14:03:31 +03:00