Commit Graph
2097 Commits
Author SHA1 Message Date
Dushnilin 963185569e fix(fuzzer): support .lua.gz scripts and correct zapret2 desync function names 2026-09-02 19:37:13 +03:00
Dushnilin fd629555c7 feat(dns): recommend multiple diverse servers for primary DoH, bootstrap, and fallback DNS 2026-09-02 18:38:30 +03:00
Dushnilin 5f4bfc7caf fix(dns): optimize benchmark probing with host caching and strict timeouts 2026-09-02 18:19:37 +03:00
Dushnilin de691c61ab feat(dns): prioritize encrypted DoH as primary DNS with verified UDP bootstrap resolution 2026-09-02 17:29:51 +03:00
Dushnilin 4a46d78e60 fix(singbox): restore strict unusable outbounds rejection while preserving country filter fallback 2026-09-02 16:52:00 +03:00
Dushnilin e8932d3f2d fix(core): prevent ruleset download_detour crash, resilient selector fallback, and clean legacy migration 2026-09-02 16:49:10 +03:00
Dushnilin ad960a173a fix(dns): two-phase cascade benchmark with verified bootstrap DNS resolution 2026-09-02 16:25:58 +03:00
Dushnilin d72e381018 fix(dns): probe DoH with RFC 8484 wireformat and direct IP resolution 2026-09-02 16:18:31 +03:00
Dushnilin 2e094a5c15 fix(tests): update applied_migrations expected fixtures in config_migration.sh 2026-09-02 15:58:07 +03:00
Dushnilin fa38422260 fix(tests): supply isolated cache dirs in config_migration dns tests 2026-09-02 15:54:30 +03:00
Dushnilin de61450e91 ci: include luci-app-tachyon and locales in backend-ci triggers 2026-09-02 15:45:03 +03:00
Dushnilin 8e1d613959 chore(locales): synchronize source and packaged Russian PO catalogs 2026-09-02 15:42:08 +03:00
Dushnilin f3b1feba31 chore(release): bump version to 1.3.14 2026-09-02 15:38:47 +03:00
Dushnilin 6b92b12135 fix(singbox): supply default /dns-query path and SNI for DoH/DoT IP addresses
- When users configure plain IP addresses (e.g. 8.8.8.8, 1.1.1.1, 77.88.8.8) with DoH (https in sing-box), sing-box requires a non-empty HTTP path (defaulting to /dns-query) and proper TLS SNI (server_name) matching the provider certificate.
- Added default /dns-query path fallback in server_from_options().
- Added KNOWN_DNS_SERVER_NAMES mapping for Google, Cloudflare, Yandex, Quad9, AdGuard, Mullvad, Control D, AliDNS, OpenDNS, DNS.SB to provide correct TLS SNI when connecting to raw DNS IPs.
- Added comprehensive DoH/DoT unit tests in tests/dns_failover.sh.
2026-09-02 15:34:27 +03:00
Dushnilin 84658d84dc feat(dns): add intelligent DNS Benchmark, Auto-Tuner & clean defaults
- Implement ucode module dns/benchmark.uc:
  * Probes major DNS servers (Yandex, Cloudflare, Google, Quad9, AdGuard, Comss, Mullvad, Control D) across UDP 53 and DoH.
  * Measures latency, packet loss, and detects ISP DNS poisoning/hijacking.
  * Intelligent recommendation engine computes optimal primary DNS (prefers encrypted DoH if fast), bootstrap plain UDP, fallback plain UDP from independent provider, and upstream mode (sequential/parallel).
  * Supports CLI execution (tachyon dns_benchmark, tachyon dns_autotune --apply) and background async worker mode for LuCI UI.
- LuCI Web UI modal (renderDnsBenchmarkModal.ts):
  * Real-time progress bar, responsive results table with latency rating badges.
  * Recommendation summary card with one-click 'Apply Recommended DNS' action.
  * Added '⚡ Auto-Tune & Benchmark DNS' button in Settings -> DNS tab.
- Added comprehensive unit tests in vitest (538/538 passed) and tests/dns_benchmark.sh.
- Added Russian PO translations.
2026-09-02 15:28:23 +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 557058c772 fix(ui): reject DoH URLs and path-style DoH in dns_fallback_server field
Mirror the backend validator.uc checks in the LuCI settings UI.
Previously the validate function used validateDNS() which accepts
DoH path format (e.g. 'cloudflare-dns.com/dns-query'); now we gate
before that call with explicit checks matching the backend:
  - '://' → DoH/DoT URL (e.g. 'https://cloudflare-dns.com/...')
  - '/'   → path-style DoH (e.g. 'cloudflare-dns.com/dns-query')

Also add Russian translations for both new error messages.
2026-09-02 14:20:33 +03:00
Dushnilin 6b8e143d0b fix(validator): also reject path-style DoH in dns_fallback_server
A value like 'cloudflare-dns.com/dns-query' is the sing-box DoH
path format. The previous check only caught 'https://' URLs.
dns_server_value_valid() accepts it because it validates only the
host part — so 'cloudflare-dns.com' passed as a valid hostname.

Fallback servers are plain UDP only; any '/' in the value is the
DoH path separator and must be rejected.

Changes:
- validator.uc: add index(value, '/') >= 0 check before the
  dns_server_value_valid call
- config_validator_runtime.sh: add regression test for path-style
  DoH ('cloudflare-dns.com/dns-query') in dns_fallback_server
2026-09-02 14:18:32 +03:00
Dushnilin 6e45ecab6a fix(validator): validate dns_fallback_server entries, reject URL schemes
Fallback servers must be plain UDP (IP or IP:port). Before this fix a
user could accidentally enter a DoH URL (https://...) as a fallback
server — the validator passed it through, and it silently failed at
runtime because dns_failover treats all fallback entries as UDP.

Changes:
- validator.uc: after main/bootstrap validation, check all
  dns_fallback_server values: reject entries containing '://'
  (protocol URL scheme) with a clear error, then validate each
  with dns_server_value_valid for format correctness
- config_validator_runtime.sh: assert_rejects for a DoH URL in
  dns_fallback_server
2026-09-02 14:09:28 +03:00
Dushnilin b82a151c87 fix: inject DNS defaults on forkop->tachyon migration, add LuCI E2E check
Fixes Tachyon startup abort when migrated config has no dns_server or
bootstrap_dns_server (forkop/podkop did not require these fields).

Changes:
- migration.uc: add ensure_dns_server_defaults migration that injects
  77.88.8.8 as fallback when either dns list is empty
- default config: pre-mark orphan_section_interface_cleanup and
  ensure_dns_server_defaults as applied so fresh installs skip them
- tests/config_migration.sh: regression tests for both missing-DNS cases
  and stable named-marker assertion for the new migration
- tests/package_contract.sh: enforce that default config ships both new
  migration IDs in applied_migrations
- tests/docker_e2e_test.sh: also install luci-app-tachyon and verify
  menu.d + acl.d files are present after install (LuCI menu bug class)
2026-09-02 14:00:54 +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 60cd0d155a fix(subscription): eliminate forward-reference crashes in runtime_cache_missing
Remove helper functions section_cache_has_outbounds and section_has_source_cache
which called source_json_path (line 513), subscription_cache_is_usable (line 507)
and object_key_count (line 1115) — all defined AFTER their call site at line 334.
ucode has no function hoisting, so these caused 'left-hand side is not a function'.

Inline the logic directly in runtime_cache_missing using only primitives
available before line 334:
- read_json (line 59)
- object_or_empty, fs.stat, source_id (line 251)
- subscription_source_count (line 300)
- TMP_SUBSCRIPTION_FOLDER (line 30)
- for-in loop to check empty object (no object_key_count needed)
2026-09-02 08:09:37 +03:00
Dushnilin b03f4d8d5c fix(subscription): fix read_json_file -> read_json in section_cache_has_outbounds
Incorrect function name caused a Type error crash in CI:
  'left-hand side is not a function'

Also replace for-in early-return trick with object_key_count() which
already exists in this file (see line 1145).
2026-09-02 08:05:19 +03:00
Dushnilin 6dc6ed9486 fix(subscription): rebuild sing-box when section-cache empty but source data available
When a new subscription section is added that shares the same URL as an
existing section, the following race occurs:

1. Sing-box config is generated — source cache doesn't exist yet for the
   new section, so it is added with zero outbounds; section-cache file is
   written (empty outboundMetadata.names).
2. Background subscription download runs — content is identical to the
   existing section, so result is 'unchanged' (return 2), updated=0.
3. reload-service is triggered — runtime_cache_missing returns false
   because the section-cache file exists, so sing-box is NOT reloaded.
4. Servers from the new section never appear in the UI.

Fix: runtime_cache_missing now also returns true when a section-cache file
exists but contains no outbounds (names={}) while the source subscription
cache is already available in TMP_SUBSCRIPTION_FOLDER. This causes the
next reload cycle to regenerate sing-box config with the actual servers.
2026-09-02 08:01:38 +03:00
Dushnilin cc4ad5855a feat(dns): expand DNS server presets for UDP, DoH, DoT, DoQ and Bootstrap 2026-09-01 22:00:04 +03:00
Dushnilin 8b3c3e365f feat(dns): upstream mode (sequential/parallel) & explicit fallback DNS servers, bump 1.3.13 2026-09-01 20:49:21 +03:00
Dushnilin f55f37f804 fix(ui): добавить load() в EntryPoint — UCI не загружался до render(), tab_order всегда был default 2026-09-01 19:36:44 +03:00
Dushnilin 79a4d477db fix(ui): заменить input[checkbox] на button-тогл в виджете порядка вкладок (починить кликабельность) 2026-09-01 19:21:06 +03:00
Dushnilin 416a15a805 fix(parental): не устанавливать cron-джоб если нет расписаний с квотами (убирает cron.err spam) 2026-09-01 18:50:13 +03:00
Dushnilin 324569aa53 fix(ui): исправить чекбоксы виджета порядка вкладок (DummyValue→renderWidget) 2026-09-01 18:46:07 +03:00
Dushnilin a610c8fe2a chore: bump version to 1.3.12 2026-09-01 18:34:16 +03:00
Dushnilin 943ee1321d feat(ui): добавить управление порядком, видимостью и стартовой вкладкой меню в Настройки 2026-09-01 18:31:31 +03:00
Dushnilin 2d551bd2d1 fix(service): исправить fs.stat в lifecycle.uc, очистку кэша LuCI и перезапуск rpcd/uhttpd 2026-09-01 15:15:42 +03:00
Dushnilin a1563708c1 fix(ci): устранить падение тестов в CI runner (права доступа /usr/bin и исключение ucode_syntax_lint из xargs) 2026-09-01 12:48:37 +03:00
Dushnilin c33018fe8f fix(service): подавлять конкурирующие службы Forkop/Podkop из ROM при старте 2026-09-01 12:44:29 +03:00
Dushnilin c432220af5 feat(updates): добавить локальный бэкап и оффлайн-откат компонентов 2026-09-01 12:24:58 +03:00
Dushnilin 23aae78147 feat(migration): 1.3.11 - CLI команда import_settings и исправление миграции Forkop
- Добавлена CLI команда tachyon import_settings [файл] (и алиас import-settings) для автоматического сканирования и бесшовного импорта настроек из Forkop, Forkop Plus, Podkop, Netshift или резервных копий
- Поддержка in-place миграции прямо из активного /etc/config/tachyon при обнаружении унаследованных правил config rule
- Расширенное сканирование резервных копий и файлов конфигураций в /etc/config/, /root/ и /tmp/
- Исправлен режим миграции Forkop в Makefile, build.sh и install.sh (использование migrate-podkop для корректного преобразования старых секций config rule в config section)
- Добавлен интеграционный тест tests/import_settings.sh (119 тестов бэкенда пройдены)
2026-09-01 12:15:00 +03:00
Dushnilin 84cdf9d2f8 feat(updates): 1.3.10 - Автоматическое обновление компонентов (сразу при выходе и по расписанию)
- Backend: реализован запуск автоматического обновления компонентов в фоновом режиме (trigger_component_auto_update, component_auto_update_apply)
- Cron: поддержка окна обслуживания (schedule mode) с регистрацией задачи в crontab по заданному времени (HH:MM)
- UCI: новые опции component_auto_update_enabled, component_auto_update_mode, component_auto_update_time, component_auto_update_targets
- Web UI: элементы управления во вкладке настроек «Обновления» (чекбокс включения, переключатель режима, время и мультиселект разрешенных компонентов)
- Тесты: добавлен интеграционный тест component_auto_update.sh, обновлены cron-тесты updates_due.sh, все 118 тестов успешно пройдены в Docker
- Локализация: добавлены русские переводы для всех новых элементов интерфейса
2026-09-01 10:58:46 +03:00
Dushnilin f553352e25 release: 1.3.9 - Оптимизация кодовой базы (Ponytail Audit), очистка мертвого кода и ускорение Telegram-бота
- Frontend: полное удаление неиспользуемого renderAdvancedSettings.ts (-1354 строки), очистка каталогов локализации от фантомных ключей, инкапсуляция внутренних экспортов в runtimeTags и singBoxVariant
- Backend: удаление неиспользуемого singbox/dns_prefetch.uc (-243 строки) и его вызова в lifecycle.uc, удаление устаревших заглушек Forkop-эпохи в service_check.uc
- Telegram Bot: внедрение in-memory кэша cb_map_cache для устранения избыточных дисковых чтений/записей JSON при рендеринге inline-кнопок
- Версия: bump версии до 1.3.9 в package.json и package-lock.json
2026-09-01 08:48:29 +03:00
Dushnilin 706b35328c feat(ruleset): auto-assign download_detour for remote rulesets & add watchdog self-heal for ruleset DNS stalls 2026-08-30 21:22:23 +03:00
Dushnilin dfb32722bf release: 1.3.8 - OpenWrt network interfaces for WARP generator, DoH doctor URL normalization & doctor lock fixes 2026-08-30 20:05:16 +03:00
Dushnilin b3e0a73b2d fix(fuzzer): ensure direct outbound routing and robust zapret2 strategy testing 2026-08-30 10:21:52 +03:00
Dushnilin 123f5e6ccf release: 1.3.7 - Telegram alert deduplication & rate limiting, DNS detour deadlock resolution, ucode fs.opendir fixes 2026-08-29 21:28:41 +03:00
Dushnilin 939d9418a2 release: 1.3.6 - Family Profiles, Mobile Responsiveness, Mixed Proxy fix & AI Doctor Fuzzer improvements 2026-08-29 13:57:17 +03:00
Dushnilin 6248452e79 chore(i18n): sync fe-app-tachyon locales with luci-app-tachyon catalogs 2026-08-29 08:34:58 +03:00
Dushnilin 3c04a62479 feat(server): support per-user LAN isolation with auth_user and custom route rules 2026-08-29 08:33:24 +03:00
Dushnilin 3960660b9d fix(components): move core_url_module_or_null to top and fix same-release update lifecycle 2026-08-29 08:16:33 +03:00
Dushnilin 5543a6ce46 fix(updates): prevent premature self-update completion while background job is running 2026-08-29 07:55:36 +03:00
Dushnilin 404db8ae05 fix(dpi-bypass): TCP keepalive + conntrack tuning + nfqueue watchdog
- sysctl: tcp_keepalive=60/10/3, conntrack_established=600s (was 5 days)
- nfqws/nfqws2: --ctrack-timeouts=30,30,600,30,30,30,30,30 in default strategy
- watchdog: probe_nfqueue checks nfqws/nfqws2 process health every 300s
- watchdog: heal_nfqueue_stopped restarts tachyon if DPI bypass processes die

This eliminates the need for manual DNS flush + device restart when DPI
starts blocking connections. Dead connections are now detected in ~90s
instead of hours, and stale conntrack entries expire in 10 min instead
of 5 days.
2026-08-28 20:05:03 +03:00
Dushnilin 16ffc9f91f fix(diagnostics): check both ca-certificates.crt and ca-bundle.crt paths
On apk-based OpenWrt the file is ca-certificates.crt, not ca-bundle.crt.
Check both paths so the CA bundle detection works on opkg and apk.
2026-08-28 10:41:32 +03:00