- 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.
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
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.
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
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
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)
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
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)
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).
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.
- Добавлена 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 тестов бэкенда пройдены)
- 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
- Локализация: добавлены русские переводы для всех новых элементов интерфейса
- 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