fix(fuzzer): eliminate fuzzer hangs, preserve DNS flags, and optimize probing performance
This commit is contained in:
+2111
-1991
File diff suppressed because it is too large
Load Diff
+2049
-1971
File diff suppressed because it is too large
Load Diff
@@ -7,8 +7,8 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: TACHYON\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2026-09-12 17:21+0300\n"
|
||||
"PO-Revision-Date: 2026-09-12 17:21+0300\n"
|
||||
"POT-Creation-Date: 2026-09-13 10:03+0300\n"
|
||||
"PO-Revision-Date: 2026-09-13 10:03+0300\n"
|
||||
"Last-Translator: Dushnilin\n"
|
||||
"Language-Team: none\n"
|
||||
"Language: ru\n"
|
||||
@@ -293,6 +293,9 @@ msgstr "Дополнительно показывать серверы по пр
|
||||
msgid "Address"
|
||||
msgstr "Адрес"
|
||||
|
||||
msgid "Address copied to clipboard"
|
||||
msgstr "Адрес скопирован в буфер обмена"
|
||||
|
||||
msgid "Administrator Chat IDs"
|
||||
msgstr "Chat ID администраторов"
|
||||
|
||||
@@ -386,8 +389,8 @@ msgstr "Все кроме выбранных"
|
||||
msgid "All Internet"
|
||||
msgstr "Весь интернет"
|
||||
|
||||
msgid "All Internet (Complete internet cutoff)"
|
||||
msgstr "Весь интернет (Полное отключение)"
|
||||
msgid "All Internet (Screen time quota or total internet cutoff)"
|
||||
msgstr "Весь интернет (квота экранного времени или полное отключение интернета)"
|
||||
|
||||
msgid "All remaining except selected"
|
||||
msgstr "Все остальные кроме выбранных"
|
||||
@@ -587,6 +590,9 @@ msgstr "Auth Digest"
|
||||
msgid "Auto"
|
||||
msgstr "Авто"
|
||||
|
||||
msgid "Auto (yields if SQM is active)"
|
||||
msgstr "Авто (уступает, если активен SQM)"
|
||||
|
||||
msgid "Auto Modes (--auto)"
|
||||
msgstr "Авто-режимы (--auto)"
|
||||
|
||||
@@ -752,12 +758,12 @@ msgstr "Заблокированные ресурсы"
|
||||
msgid "Blocked Sites"
|
||||
msgstr "Заблокированные сайты"
|
||||
|
||||
msgid "Blocked Sites (Block specified domains during scheduled hours)"
|
||||
msgstr "Заблокированные сайты (блокировка указанных доменов в часы по расписанию)"
|
||||
|
||||
msgid "Blocked Sites (Domains)"
|
||||
msgstr "Заблокированные сайты (домены)"
|
||||
|
||||
msgid "Blocked Sites (Only block domains specified below)"
|
||||
msgstr "Заблокированные сайты (Блокировать только указанные домены)"
|
||||
|
||||
msgid "Blocks access to private/LAN IP addresses (10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16, etc.) for selected users before applying routing mode."
|
||||
msgstr "Блокирует доступ к приватным/локальным IP-адресам (10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16 и др.) для указанных пользователей перед применением режима маршрутизации."
|
||||
|
||||
@@ -962,8 +968,8 @@ msgstr "Выберите, действует ли расписание круг
|
||||
msgid "Choose whether to install updates immediately when detected or at a scheduled time (e.g. maintenance window)"
|
||||
msgstr "Выберите, устанавливать ли обновления сразу при обнаружении или по расписанию (например, в ночное окно обслуживания)"
|
||||
|
||||
msgid "Choose whether to restrict the entire internet or only specific Tachyon routing sections."
|
||||
msgstr "Выберите, блокировать ли весь доступ в интернет или только определенные секции Tachyon."
|
||||
msgid "Choose whether to restrict the entire internet (with optional daily screen time quota) or only specific sites/domains (by scheduled hours). Screen time quotas can also be set per child directly in Profiles."
|
||||
msgstr "Выберите, ограничивать ли весь интернет (с возможностью суточной квоты экранного времени) или только конкретные сайты/домены (в часы по расписанию). Суточную квоту экранного времени также можно задать для каждого ребенка прямо в Профилях."
|
||||
|
||||
msgid "Choose whether to route traffic to all destinations except selected countries (Exclude) or only to selected countries (Include)."
|
||||
msgstr "Выберите, маршрутизировать ли трафик ко всем назначениям кроме выбранных стран (Исключить) или только в выбранные страны (Включить)."
|
||||
@@ -1145,12 +1151,18 @@ msgstr "Размер мусора в пакете cookie (S3)"
|
||||
msgid "Copied"
|
||||
msgstr "Скопировано"
|
||||
|
||||
msgid "Copied!"
|
||||
msgstr "Скопировано!"
|
||||
|
||||
msgid "Copy"
|
||||
msgstr "Копировать"
|
||||
|
||||
msgid "Copy address"
|
||||
msgstr "Копировать адрес"
|
||||
|
||||
msgid "Copy Address"
|
||||
msgstr "Скопировать"
|
||||
|
||||
msgid "Copy log"
|
||||
msgstr "Копировать лог"
|
||||
|
||||
@@ -1175,6 +1187,12 @@ msgstr "Страна"
|
||||
msgid "Country code (e.g. ru, us, de)"
|
||||
msgstr "Код страны (напр. ru, us, de)"
|
||||
|
||||
msgid "Credit Cards / SBP / Tinkoff Pay"
|
||||
msgstr "Карты РФ / СБП / Tinkoff Pay"
|
||||
|
||||
msgid "Cryptocurrency"
|
||||
msgstr "Криптовалюта"
|
||||
|
||||
msgid "Current Diagnosis"
|
||||
msgstr "Текущий диагноз"
|
||||
|
||||
@@ -1229,15 +1247,15 @@ msgstr "Настройте порядок и видимость вкладок
|
||||
msgid "Daily Quota"
|
||||
msgstr "Дневная квота"
|
||||
|
||||
msgid "Daily quota applies only when Target Scope is All Internet"
|
||||
msgstr "Суточная квота действует только при выборе области «Весь интернет»"
|
||||
|
||||
msgid "Daily Screen Time Quota (minutes)"
|
||||
msgstr "Дневная квота экранного времени (минуты)"
|
||||
|
||||
msgid "Daily Time Limit (minutes)"
|
||||
msgstr "Дневной лимит времени (минуты)"
|
||||
|
||||
msgid "Daily time quota (minutes)"
|
||||
msgstr "Дневной лимит времени (минуты)"
|
||||
|
||||
msgid "Daily Traffic Limit (MB)"
|
||||
msgstr "Дневной лимит трафика (МБ)"
|
||||
|
||||
@@ -1739,6 +1757,9 @@ msgstr "Включить WAN-доступ к YACD"
|
||||
msgid "Enabled"
|
||||
msgstr "Включено"
|
||||
|
||||
msgid "Enabled (always prioritize)"
|
||||
msgstr "Включено (всегда повышать приоритет)"
|
||||
|
||||
msgid "Enables the background daemon that polls Telegram for commands and sends notifications."
|
||||
msgstr "Включает фоновый демон, который опрашивает Telegram на наличие команд и отправляет уведомления."
|
||||
|
||||
@@ -1907,6 +1928,9 @@ msgstr "Не удалось закрыть подключения"
|
||||
msgid "Failed to communicate with AI provider"
|
||||
msgstr "Не удалось связаться с провайдером ИИ"
|
||||
|
||||
msgid "Failed to copy address"
|
||||
msgstr "Не удалось скопировать адрес"
|
||||
|
||||
msgid "Failed to copy report to clipboard"
|
||||
msgstr "Не удалось скопировать отчет в буфер обмена"
|
||||
|
||||
@@ -2393,6 +2417,9 @@ msgstr "Таймаут простоя"
|
||||
msgid "If one health check fails with an error, continue running other checks instead of stopping."
|
||||
msgstr "Если одна проверка завершается ошибкой, продолжать другие проверки, а не останавливаться."
|
||||
|
||||
msgid "If Tachyon powers your daily networking and keeps your connection fast and secure, consider supporting ongoing development! ☕ 🧀 🌭"
|
||||
msgstr "Если Tachyon помогает вам и делает работу в сети комфортной, вы можете поддержать проект и автора! ☕ 🧀 🌭"
|
||||
|
||||
msgid "Immediately upon release"
|
||||
msgstr "Сразу при выходе новой версии"
|
||||
|
||||
@@ -2951,9 +2978,6 @@ msgstr "Обнаружены устаревшие пути zapret, требуе
|
||||
msgid "Level name"
|
||||
msgstr "Имя уровня"
|
||||
|
||||
msgid "Limit device network usage per day. When the quota is exhausted, the device is blocked until midnight. 0 disables the limit."
|
||||
msgstr "Ограничьте использование сети устройством за день. Когда квота исчерпана, устройство блокируется до полуночи. 0 — без лимита."
|
||||
|
||||
msgid "List must be an HTTP(S) URL or a local .lst path"
|
||||
msgstr "Список должен быть HTTP(S) URL или локальным путём .lst"
|
||||
|
||||
@@ -3755,6 +3779,9 @@ msgstr "Предотвращает множественные вызовы reloa
|
||||
msgid "Primary DNS"
|
||||
msgstr "Основной DNS"
|
||||
|
||||
msgid "Prioritizes interactive DNS, VoIP/WebRTC, gaming and TCP ACK packets via DSCP marking in nftables. In Auto mode, automatically yields if OpenWrt SQM (CAKE/FQ_CoDel) is detected to prevent bufferbloat degradation."
|
||||
msgstr ""
|
||||
|
||||
msgid "Priority"
|
||||
msgstr "Приоритет"
|
||||
|
||||
@@ -3854,6 +3881,9 @@ msgstr "Публичный хост"
|
||||
msgid "Public IP Address Isolation"
|
||||
msgstr "Изоляция публичного IP-адреса"
|
||||
|
||||
msgid "QoS Priority Engine (DSCP)"
|
||||
msgstr ""
|
||||
|
||||
msgid "QR code is too large"
|
||||
msgstr "QR-код слишком большой"
|
||||
|
||||
@@ -3863,6 +3893,9 @@ msgstr "Опрос прямого подключения и исходящего
|
||||
msgid "QUIC (HTTP/3)"
|
||||
msgstr "QUIC (HTTP/3)"
|
||||
|
||||
msgid "Quick donation via Russian bank cards or SBP"
|
||||
msgstr "Быстрый перевод картами РФ или через СБП"
|
||||
|
||||
msgid "RAG Knowledge Base + Live ISP Probe Context"
|
||||
msgstr "База знаний RAG + результаты живого зондирования провайдера"
|
||||
|
||||
@@ -4862,6 +4895,12 @@ msgstr "Вс"
|
||||
msgid "Sunday"
|
||||
msgstr "Воскресенье"
|
||||
|
||||
msgid "Support Development"
|
||||
msgstr "Поддержать разработку"
|
||||
|
||||
msgid "Support on CloudTips"
|
||||
msgstr "Поддержать проект на CloudTips"
|
||||
|
||||
msgid "Sweden (se)"
|
||||
msgstr "Швеция (se)"
|
||||
|
||||
@@ -5210,6 +5249,9 @@ msgstr "TorrServer не найден"
|
||||
msgid "Total allowed network usage per day for devices in this profile. When the quota is reached, access is blocked until midnight. Enter 0 for unlimited."
|
||||
msgstr "Суммарное разрешенное время работы в сети в день для устройств этого профиля. По исчерпании лимита доступ блокируется до полуночи. Введите 0 для отсутствия ограничений."
|
||||
|
||||
msgid "Total allowed network usage per day for devices in this rule. When reached, ALL internet access is blocked until midnight (not just specific domains). Enter 0 for unlimited. Note: Applies when Target Scope is 'All Internet' (or configured in Profile)."
|
||||
msgstr "Суммарное разрешенное время работы в сети в день для устройств этого правила. По исчерпании лимита блокируется ВЕСЬ доступ в интернет до полуночи (а не только отдельные домены). Введите 0 для отсутствия ограничений. Примечание: действует при выборе области «Весь интернет» (или при настройке в Профиле)."
|
||||
|
||||
msgid "Total lines:"
|
||||
msgstr "Всего строк:"
|
||||
|
||||
@@ -5819,6 +5861,21 @@ msgstr "Правила маршрутизации sing-box для Zapret2 нас
|
||||
msgid "Zapret2 sing-box route rules are not configured"
|
||||
msgstr "Правила маршрутизации sing-box для Zapret2 не настроены"
|
||||
|
||||
msgid "All Internet (Complete internet cutoff)"
|
||||
msgstr "Весь интернет (Полное отключение)"
|
||||
|
||||
msgid "Blocked Sites (Only block domains specified below)"
|
||||
msgstr "Заблокированные сайты (Блокировать только указанные домены)"
|
||||
|
||||
msgid "Choose whether to restrict the entire internet or only specific Tachyon routing sections."
|
||||
msgstr "Выберите, блокировать ли весь доступ в интернет или только определенные секции Tachyon."
|
||||
|
||||
msgid "Daily time quota (minutes)"
|
||||
msgstr "Дневной лимит времени (минуты)"
|
||||
|
||||
msgid "Limit device network usage per day. When the quota is exhausted, the device is blocked until midnight. 0 disables the limit."
|
||||
msgstr "Ограничьте использование сети устройством за день. Когда квота исчерпана, устройство блокируется до полуночи. 0 — без лимита."
|
||||
|
||||
msgid "⚠️ CRITICAL IP LEAK: Your real public IP is exposed through the proxy outbound!"
|
||||
msgstr "⚠️ КРИТИЧЕСКАЯ УТЕЧКА IP: Ваш реальный публичный IP раскрыт через исходящий прокси!"
|
||||
|
||||
@@ -6649,33 +6706,3 @@ msgstr "Разрешить только: "
|
||||
|
||||
msgid "Block: "
|
||||
msgstr "Блокировать: "
|
||||
|
||||
msgid "Support Development"
|
||||
msgstr "Поддержать разработку"
|
||||
|
||||
msgid "If Tachyon powers your daily networking and keeps your connection fast and secure, consider supporting ongoing development! ☕ 🧀 🌭"
|
||||
msgstr "Если Tachyon помогает вам и делает работу в сети комфортной, вы можете поддержать проект и автора! ☕ 🧀 🌭"
|
||||
|
||||
msgid "Credit Cards / SBP / Tinkoff Pay"
|
||||
msgstr "Карты РФ / СБП / Tinkoff Pay"
|
||||
|
||||
msgid "Quick donation via Russian bank cards or SBP"
|
||||
msgstr "Быстрый перевод картами РФ или через СБП"
|
||||
|
||||
msgid "Support on CloudTips"
|
||||
msgstr "Поддержать проект на CloudTips"
|
||||
|
||||
msgid "Cryptocurrency"
|
||||
msgstr "Криптовалюта"
|
||||
|
||||
msgid "Copy Address"
|
||||
msgstr "Скопировать"
|
||||
|
||||
msgid "Copied!"
|
||||
msgstr "Скопировано!"
|
||||
|
||||
msgid "Address copied to clipboard"
|
||||
msgstr "Адрес скопирован в буфер обмена"
|
||||
|
||||
msgid "Failed to copy address"
|
||||
msgstr "Не удалось скопировать адрес"
|
||||
|
||||
@@ -1711,7 +1711,7 @@ export function renderStrategyFuzzerModal(ruleNames: string[] = []) {
|
||||
|
||||
const startPolling = () => {
|
||||
stopPolling();
|
||||
pollingInterval = setInterval(pollStatus, 600);
|
||||
pollingInterval = setInterval(pollStatus, 1200);
|
||||
pollStatus();
|
||||
};
|
||||
|
||||
|
||||
@@ -14297,7 +14297,7 @@ function renderStrategyFuzzerModal(ruleNames = []) {
|
||||
};
|
||||
const startPolling = () => {
|
||||
stopPolling();
|
||||
pollingInterval = setInterval(pollStatus, 600);
|
||||
pollingInterval = setInterval(pollStatus, 1200);
|
||||
pollStatus();
|
||||
};
|
||||
const stopPolling = () => {
|
||||
|
||||
@@ -917,11 +917,23 @@ function createParentalContent(section) {
|
||||
o.rawhtml = true;
|
||||
o.modalonly = false;
|
||||
o.cfgvalue = function (sectionId) {
|
||||
const target = uci.get(UCI_PACKAGE, sectionId, "target") || "domains";
|
||||
const raw =
|
||||
Number(uci.get(UCI_PACKAGE, sectionId, "daily_quota_minutes")) || 0;
|
||||
if (raw <= 0) {
|
||||
return '<span style="opacity:0.5;">' + _("None") + "</span>";
|
||||
}
|
||||
if (target !== "all") {
|
||||
return (
|
||||
'<span style="color:var(--warning-color-medium, #d69e2e);font-size:11px;" title="' +
|
||||
_("Daily quota applies only when Target Scope is All Internet") +
|
||||
'">⚠️ ' +
|
||||
raw +
|
||||
" " +
|
||||
_("min/day") +
|
||||
"</span>"
|
||||
);
|
||||
}
|
||||
return (
|
||||
'<span style="color:var(--primary-color-medium, #3182ce);font-weight:500;">⏳ ' +
|
||||
raw +
|
||||
@@ -931,9 +943,13 @@ function createParentalContent(section) {
|
||||
);
|
||||
};
|
||||
o.textvalue = function (sectionId) {
|
||||
const target = uci.get(UCI_PACKAGE, sectionId, "target") || "domains";
|
||||
const raw =
|
||||
Number(uci.get(UCI_PACKAGE, sectionId, "daily_quota_minutes")) || 0;
|
||||
return raw > 0 ? `${raw} ${_("min/day")}` : _("None");
|
||||
if (raw <= 0) return _("None");
|
||||
return target === "all"
|
||||
? `${raw} ${_("min/day")}`
|
||||
: `${raw} ${_("min/day")} (target!=all)`;
|
||||
};
|
||||
|
||||
// Blocked sites column in table
|
||||
@@ -1095,14 +1111,20 @@ function createParentalContent(section) {
|
||||
"target",
|
||||
_("Target Scope"),
|
||||
_(
|
||||
"Choose whether to restrict the entire internet or only specific Tachyon routing sections.",
|
||||
"Choose whether to restrict the entire internet (with optional daily screen time quota) or only specific sites/domains (by scheduled hours). Screen time quotas can also be set per child directly in Profiles.",
|
||||
),
|
||||
);
|
||||
o.modalonly = true;
|
||||
o.rmempty = false;
|
||||
o.default = "domains";
|
||||
o.value("domains", _("Blocked Sites (Only block domains specified below)"));
|
||||
o.value("all", _("All Internet (Complete internet cutoff)"));
|
||||
o.value(
|
||||
"domains",
|
||||
_("Blocked Sites (Block specified domains during scheduled hours)"),
|
||||
);
|
||||
o.value(
|
||||
"all",
|
||||
_("All Internet (Screen time quota or total internet cutoff)"),
|
||||
);
|
||||
o.value("sections", _("Specific Sections (Select sections below)"));
|
||||
|
||||
// Multi-select for sections
|
||||
@@ -1212,16 +1234,15 @@ function createParentalContent(section) {
|
||||
o = section.option(
|
||||
form.Value,
|
||||
"daily_quota_minutes",
|
||||
_("Daily time quota (minutes)"),
|
||||
_("Daily Screen Time Quota (minutes)"),
|
||||
_(
|
||||
"Limit device network usage per day. When the quota is exhausted, internet access is blocked until midnight. 0 disables the limit.",
|
||||
"Total allowed network usage per day for devices in this rule. When reached, ALL internet access is blocked until midnight (not just specific domains). Enter 0 for unlimited. Note: Applies when Target Scope is 'All Internet' (or configured in Profile).",
|
||||
),
|
||||
);
|
||||
o.modalonly = true;
|
||||
o.rmempty = true;
|
||||
o.default = "0";
|
||||
o.placeholder = "0";
|
||||
o.depends("target", "all");
|
||||
o.validate = function (_sectionId, value) {
|
||||
if (value === "" || value === null || value === undefined) return true;
|
||||
const n = Number(value);
|
||||
|
||||
@@ -2466,6 +2466,21 @@ function createSettingsContent(section, capabilities) {
|
||||
o.default = "0";
|
||||
o.rmempty = false;
|
||||
|
||||
o = section.taboption(
|
||||
"advanced",
|
||||
form.ListValue,
|
||||
"qos_priority_engine",
|
||||
_("QoS Priority Engine (DSCP)"),
|
||||
_(
|
||||
"Prioritizes interactive DNS, VoIP/WebRTC, gaming and TCP ACK packets via DSCP marking in nftables. In Auto mode, automatically yields if OpenWrt SQM (CAKE/FQ_CoDel) is detected to prevent bufferbloat degradation.",
|
||||
),
|
||||
);
|
||||
o.value("", _("Auto (yields if SQM is active)"));
|
||||
o.value("1", _("Enabled (always prioritize)"));
|
||||
o.value("0", _("Disabled"));
|
||||
o.default = "";
|
||||
o.rmempty = true;
|
||||
|
||||
// WARP Generator Proxy Section
|
||||
o = section.taboption(
|
||||
"advanced",
|
||||
|
||||
@@ -7,8 +7,8 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: TACHYON\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2026-09-12 17:21+0300\n"
|
||||
"PO-Revision-Date: 2026-09-12 17:21+0300\n"
|
||||
"POT-Creation-Date: 2026-09-13 10:03+0300\n"
|
||||
"PO-Revision-Date: 2026-09-13 10:03+0300\n"
|
||||
"Last-Translator: Dushnilin\n"
|
||||
"Language-Team: none\n"
|
||||
"Language: ru\n"
|
||||
@@ -293,6 +293,9 @@ msgstr "Дополнительно показывать серверы по пр
|
||||
msgid "Address"
|
||||
msgstr "Адрес"
|
||||
|
||||
msgid "Address copied to clipboard"
|
||||
msgstr "Адрес скопирован в буфер обмена"
|
||||
|
||||
msgid "Administrator Chat IDs"
|
||||
msgstr "Chat ID администраторов"
|
||||
|
||||
@@ -386,8 +389,8 @@ msgstr "Все кроме выбранных"
|
||||
msgid "All Internet"
|
||||
msgstr "Весь интернет"
|
||||
|
||||
msgid "All Internet (Complete internet cutoff)"
|
||||
msgstr "Весь интернет (Полное отключение)"
|
||||
msgid "All Internet (Screen time quota or total internet cutoff)"
|
||||
msgstr "Весь интернет (квота экранного времени или полное отключение интернета)"
|
||||
|
||||
msgid "All remaining except selected"
|
||||
msgstr "Все остальные кроме выбранных"
|
||||
@@ -587,6 +590,9 @@ msgstr "Auth Digest"
|
||||
msgid "Auto"
|
||||
msgstr "Авто"
|
||||
|
||||
msgid "Auto (yields if SQM is active)"
|
||||
msgstr "Авто (уступает, если активен SQM)"
|
||||
|
||||
msgid "Auto Modes (--auto)"
|
||||
msgstr "Авто-режимы (--auto)"
|
||||
|
||||
@@ -752,12 +758,12 @@ msgstr "Заблокированные ресурсы"
|
||||
msgid "Blocked Sites"
|
||||
msgstr "Заблокированные сайты"
|
||||
|
||||
msgid "Blocked Sites (Block specified domains during scheduled hours)"
|
||||
msgstr "Заблокированные сайты (блокировка указанных доменов в часы по расписанию)"
|
||||
|
||||
msgid "Blocked Sites (Domains)"
|
||||
msgstr "Заблокированные сайты (домены)"
|
||||
|
||||
msgid "Blocked Sites (Only block domains specified below)"
|
||||
msgstr "Заблокированные сайты (Блокировать только указанные домены)"
|
||||
|
||||
msgid "Blocks access to private/LAN IP addresses (10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16, etc.) for selected users before applying routing mode."
|
||||
msgstr "Блокирует доступ к приватным/локальным IP-адресам (10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16 и др.) для указанных пользователей перед применением режима маршрутизации."
|
||||
|
||||
@@ -962,8 +968,8 @@ msgstr "Выберите, действует ли расписание круг
|
||||
msgid "Choose whether to install updates immediately when detected or at a scheduled time (e.g. maintenance window)"
|
||||
msgstr "Выберите, устанавливать ли обновления сразу при обнаружении или по расписанию (например, в ночное окно обслуживания)"
|
||||
|
||||
msgid "Choose whether to restrict the entire internet or only specific Tachyon routing sections."
|
||||
msgstr "Выберите, блокировать ли весь доступ в интернет или только определенные секции Tachyon."
|
||||
msgid "Choose whether to restrict the entire internet (with optional daily screen time quota) or only specific sites/domains (by scheduled hours). Screen time quotas can also be set per child directly in Profiles."
|
||||
msgstr "Выберите, ограничивать ли весь интернет (с возможностью суточной квоты экранного времени) или только конкретные сайты/домены (в часы по расписанию). Суточную квоту экранного времени также можно задать для каждого ребенка прямо в Профилях."
|
||||
|
||||
msgid "Choose whether to route traffic to all destinations except selected countries (Exclude) or only to selected countries (Include)."
|
||||
msgstr "Выберите, маршрутизировать ли трафик ко всем назначениям кроме выбранных стран (Исключить) или только в выбранные страны (Включить)."
|
||||
@@ -1145,12 +1151,18 @@ msgstr "Размер мусора в пакете cookie (S3)"
|
||||
msgid "Copied"
|
||||
msgstr "Скопировано"
|
||||
|
||||
msgid "Copied!"
|
||||
msgstr "Скопировано!"
|
||||
|
||||
msgid "Copy"
|
||||
msgstr "Копировать"
|
||||
|
||||
msgid "Copy address"
|
||||
msgstr "Копировать адрес"
|
||||
|
||||
msgid "Copy Address"
|
||||
msgstr "Скопировать"
|
||||
|
||||
msgid "Copy log"
|
||||
msgstr "Копировать лог"
|
||||
|
||||
@@ -1175,6 +1187,12 @@ msgstr "Страна"
|
||||
msgid "Country code (e.g. ru, us, de)"
|
||||
msgstr "Код страны (напр. ru, us, de)"
|
||||
|
||||
msgid "Credit Cards / SBP / Tinkoff Pay"
|
||||
msgstr "Карты РФ / СБП / Tinkoff Pay"
|
||||
|
||||
msgid "Cryptocurrency"
|
||||
msgstr "Криптовалюта"
|
||||
|
||||
msgid "Current Diagnosis"
|
||||
msgstr "Текущий диагноз"
|
||||
|
||||
@@ -1229,15 +1247,15 @@ msgstr "Настройте порядок и видимость вкладок
|
||||
msgid "Daily Quota"
|
||||
msgstr "Дневная квота"
|
||||
|
||||
msgid "Daily quota applies only when Target Scope is All Internet"
|
||||
msgstr "Суточная квота действует только при выборе области «Весь интернет»"
|
||||
|
||||
msgid "Daily Screen Time Quota (minutes)"
|
||||
msgstr "Дневная квота экранного времени (минуты)"
|
||||
|
||||
msgid "Daily Time Limit (minutes)"
|
||||
msgstr "Дневной лимит времени (минуты)"
|
||||
|
||||
msgid "Daily time quota (minutes)"
|
||||
msgstr "Дневной лимит времени (минуты)"
|
||||
|
||||
msgid "Daily Traffic Limit (MB)"
|
||||
msgstr "Дневной лимит трафика (МБ)"
|
||||
|
||||
@@ -1739,6 +1757,9 @@ msgstr "Включить WAN-доступ к YACD"
|
||||
msgid "Enabled"
|
||||
msgstr "Включено"
|
||||
|
||||
msgid "Enabled (always prioritize)"
|
||||
msgstr "Включено (всегда повышать приоритет)"
|
||||
|
||||
msgid "Enables the background daemon that polls Telegram for commands and sends notifications."
|
||||
msgstr "Включает фоновый демон, который опрашивает Telegram на наличие команд и отправляет уведомления."
|
||||
|
||||
@@ -1907,6 +1928,9 @@ msgstr "Не удалось закрыть подключения"
|
||||
msgid "Failed to communicate with AI provider"
|
||||
msgstr "Не удалось связаться с провайдером ИИ"
|
||||
|
||||
msgid "Failed to copy address"
|
||||
msgstr "Не удалось скопировать адрес"
|
||||
|
||||
msgid "Failed to copy report to clipboard"
|
||||
msgstr "Не удалось скопировать отчет в буфер обмена"
|
||||
|
||||
@@ -2393,6 +2417,9 @@ msgstr "Таймаут простоя"
|
||||
msgid "If one health check fails with an error, continue running other checks instead of stopping."
|
||||
msgstr "Если одна проверка завершается ошибкой, продолжать другие проверки, а не останавливаться."
|
||||
|
||||
msgid "If Tachyon powers your daily networking and keeps your connection fast and secure, consider supporting ongoing development! ☕ 🧀 🌭"
|
||||
msgstr "Если Tachyon помогает вам и делает работу в сети комфортной, вы можете поддержать проект и автора! ☕ 🧀 🌭"
|
||||
|
||||
msgid "Immediately upon release"
|
||||
msgstr "Сразу при выходе новой версии"
|
||||
|
||||
@@ -2951,9 +2978,6 @@ msgstr "Обнаружены устаревшие пути zapret, требуе
|
||||
msgid "Level name"
|
||||
msgstr "Имя уровня"
|
||||
|
||||
msgid "Limit device network usage per day. When the quota is exhausted, the device is blocked until midnight. 0 disables the limit."
|
||||
msgstr "Ограничьте использование сети устройством за день. Когда квота исчерпана, устройство блокируется до полуночи. 0 — без лимита."
|
||||
|
||||
msgid "List must be an HTTP(S) URL or a local .lst path"
|
||||
msgstr "Список должен быть HTTP(S) URL или локальным путём .lst"
|
||||
|
||||
@@ -3755,6 +3779,9 @@ msgstr "Предотвращает множественные вызовы reloa
|
||||
msgid "Primary DNS"
|
||||
msgstr "Основной DNS"
|
||||
|
||||
msgid "Prioritizes interactive DNS, VoIP/WebRTC, gaming and TCP ACK packets via DSCP marking in nftables. In Auto mode, automatically yields if OpenWrt SQM (CAKE/FQ_CoDel) is detected to prevent bufferbloat degradation."
|
||||
msgstr ""
|
||||
|
||||
msgid "Priority"
|
||||
msgstr "Приоритет"
|
||||
|
||||
@@ -3854,6 +3881,9 @@ msgstr "Публичный хост"
|
||||
msgid "Public IP Address Isolation"
|
||||
msgstr "Изоляция публичного IP-адреса"
|
||||
|
||||
msgid "QoS Priority Engine (DSCP)"
|
||||
msgstr ""
|
||||
|
||||
msgid "QR code is too large"
|
||||
msgstr "QR-код слишком большой"
|
||||
|
||||
@@ -3863,6 +3893,9 @@ msgstr "Опрос прямого подключения и исходящего
|
||||
msgid "QUIC (HTTP/3)"
|
||||
msgstr "QUIC (HTTP/3)"
|
||||
|
||||
msgid "Quick donation via Russian bank cards or SBP"
|
||||
msgstr "Быстрый перевод картами РФ или через СБП"
|
||||
|
||||
msgid "RAG Knowledge Base + Live ISP Probe Context"
|
||||
msgstr "База знаний RAG + результаты живого зондирования провайдера"
|
||||
|
||||
@@ -4862,6 +4895,12 @@ msgstr "Вс"
|
||||
msgid "Sunday"
|
||||
msgstr "Воскресенье"
|
||||
|
||||
msgid "Support Development"
|
||||
msgstr "Поддержать разработку"
|
||||
|
||||
msgid "Support on CloudTips"
|
||||
msgstr "Поддержать проект на CloudTips"
|
||||
|
||||
msgid "Sweden (se)"
|
||||
msgstr "Швеция (se)"
|
||||
|
||||
@@ -5210,6 +5249,9 @@ msgstr "TorrServer не найден"
|
||||
msgid "Total allowed network usage per day for devices in this profile. When the quota is reached, access is blocked until midnight. Enter 0 for unlimited."
|
||||
msgstr "Суммарное разрешенное время работы в сети в день для устройств этого профиля. По исчерпании лимита доступ блокируется до полуночи. Введите 0 для отсутствия ограничений."
|
||||
|
||||
msgid "Total allowed network usage per day for devices in this rule. When reached, ALL internet access is blocked until midnight (not just specific domains). Enter 0 for unlimited. Note: Applies when Target Scope is 'All Internet' (or configured in Profile)."
|
||||
msgstr "Суммарное разрешенное время работы в сети в день для устройств этого правила. По исчерпании лимита блокируется ВЕСЬ доступ в интернет до полуночи (а не только отдельные домены). Введите 0 для отсутствия ограничений. Примечание: действует при выборе области «Весь интернет» (или при настройке в Профиле)."
|
||||
|
||||
msgid "Total lines:"
|
||||
msgstr "Всего строк:"
|
||||
|
||||
@@ -5819,6 +5861,21 @@ msgstr "Правила маршрутизации sing-box для Zapret2 нас
|
||||
msgid "Zapret2 sing-box route rules are not configured"
|
||||
msgstr "Правила маршрутизации sing-box для Zapret2 не настроены"
|
||||
|
||||
msgid "All Internet (Complete internet cutoff)"
|
||||
msgstr "Весь интернет (Полное отключение)"
|
||||
|
||||
msgid "Blocked Sites (Only block domains specified below)"
|
||||
msgstr "Заблокированные сайты (Блокировать только указанные домены)"
|
||||
|
||||
msgid "Choose whether to restrict the entire internet or only specific Tachyon routing sections."
|
||||
msgstr "Выберите, блокировать ли весь доступ в интернет или только определенные секции Tachyon."
|
||||
|
||||
msgid "Daily time quota (minutes)"
|
||||
msgstr "Дневной лимит времени (минуты)"
|
||||
|
||||
msgid "Limit device network usage per day. When the quota is exhausted, the device is blocked until midnight. 0 disables the limit."
|
||||
msgstr "Ограничьте использование сети устройством за день. Когда квота исчерпана, устройство блокируется до полуночи. 0 — без лимита."
|
||||
|
||||
msgid "⚠️ CRITICAL IP LEAK: Your real public IP is exposed through the proxy outbound!"
|
||||
msgstr "⚠️ КРИТИЧЕСКАЯ УТЕЧКА IP: Ваш реальный публичный IP раскрыт через исходящий прокси!"
|
||||
|
||||
@@ -6649,33 +6706,3 @@ msgstr "Разрешить только: "
|
||||
|
||||
msgid "Block: "
|
||||
msgstr "Блокировать: "
|
||||
|
||||
msgid "Support Development"
|
||||
msgstr "Поддержать разработку"
|
||||
|
||||
msgid "If Tachyon powers your daily networking and keeps your connection fast and secure, consider supporting ongoing development! ☕ 🧀 🌭"
|
||||
msgstr "Если Tachyon помогает вам и делает работу в сети комфортной, вы можете поддержать проект и автора! ☕ 🧀 🌭"
|
||||
|
||||
msgid "Credit Cards / SBP / Tinkoff Pay"
|
||||
msgstr "Карты РФ / СБП / Tinkoff Pay"
|
||||
|
||||
msgid "Quick donation via Russian bank cards or SBP"
|
||||
msgstr "Быстрый перевод картами РФ или через СБП"
|
||||
|
||||
msgid "Support on CloudTips"
|
||||
msgstr "Поддержать проект на CloudTips"
|
||||
|
||||
msgid "Cryptocurrency"
|
||||
msgstr "Криптовалюта"
|
||||
|
||||
msgid "Copy Address"
|
||||
msgstr "Скопировать"
|
||||
|
||||
msgid "Copied!"
|
||||
msgstr "Скопировано!"
|
||||
|
||||
msgid "Address copied to clipboard"
|
||||
msgstr "Адрес скопирован в буфер обмена"
|
||||
|
||||
msgid "Failed to copy address"
|
||||
msgstr "Не удалось скопировать адрес"
|
||||
|
||||
+2049
-1971
File diff suppressed because it is too large
Load Diff
@@ -110,6 +110,17 @@ function get_timeout_prefix(sec) {
|
||||
return _has_timeout ? sprintf("timeout %d ", sec) : "";
|
||||
}
|
||||
|
||||
function wrap_cmd_timeout(cmd, sec) {
|
||||
sec = sec || 8;
|
||||
if (_has_timeout === null) {
|
||||
_has_timeout = (system("command -v timeout >/dev/null 2>&1") == 0);
|
||||
}
|
||||
if (_has_timeout) {
|
||||
return sprintf("timeout -s KILL %d %s", sec, cmd);
|
||||
}
|
||||
return sprintf("( %s ) & p=$!; ( sleep %d; kill -9 $p 2>/dev/null ) & w=$!; wait $p 2>/dev/null; r=$?; kill -9 $w 2>/dev/null; wait $w 2>/dev/null; [ $r -ne 0 ] && printf \"\\t%%d\\n\" $r; exit $r", cmd, sec);
|
||||
}
|
||||
|
||||
let _fuzzer_curl_dns_flags = null;
|
||||
function get_fuzzer_curl_dns_flags() {
|
||||
if (_fuzzer_curl_dns_flags !== null)
|
||||
@@ -131,6 +142,82 @@ function get_fuzzer_curl_dns_flags() {
|
||||
return _fuzzer_curl_dns_flags;
|
||||
}
|
||||
|
||||
let _fuzzer_host_cache = {};
|
||||
function get_resolved_host_flags(url) {
|
||||
let m = match(url, /^https?:\/\/([^\/:]+)/);
|
||||
if (!m || !m[1]) return "";
|
||||
let host = m[1];
|
||||
if (match(host, /^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$/) || index(host, ":") >= 0) return "";
|
||||
if (exists(_fuzzer_host_cache, host))
|
||||
return _fuzzer_host_cache[host];
|
||||
|
||||
let ip = null;
|
||||
// 1. Try Cloudflare DoH JSON
|
||||
let p = fs.popen(sprintf("curl -s -m 3 --connect-timeout 2 -H 'accept: application/dns-json' 'https://1.1.1.1/dns-query?name=%s&type=A'", host), "r");
|
||||
let out = p ? p.read("all") : "";
|
||||
if (p) p.close();
|
||||
if (out && out != "") {
|
||||
try {
|
||||
let data = json(out);
|
||||
if (data && data.Answer) {
|
||||
for (let ans in data.Answer) {
|
||||
if (ans.type == 1 && ans.data && match(ans.data, /^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$/)) {
|
||||
ip = ans.data;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (e) {}
|
||||
}
|
||||
// 2. Try Google DoH JSON if Cloudflare failed
|
||||
if (!ip) {
|
||||
let gp = fs.popen(sprintf("curl -s -m 3 --connect-timeout 2 -H 'accept: application/dns-json' 'https://8.8.8.8/dns-query?name=%s&type=A'", host), "r");
|
||||
let gout = gp ? gp.read("all") : "";
|
||||
if (gp) gp.close();
|
||||
if (gout && gout != "") {
|
||||
try {
|
||||
let gdata = json(gout);
|
||||
if (gdata && gdata.Answer) {
|
||||
for (let ans in gdata.Answer) {
|
||||
if (ans.type == 1 && ans.data && match(ans.data, /^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$/)) {
|
||||
ip = ans.data;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (e) {}
|
||||
}
|
||||
}
|
||||
// 3. Fallback: nslookup via 1.1.1.1 or system
|
||||
if (!ip) {
|
||||
let np = fs.popen(sprintf("nslookup %s 1.1.1.1 2>/dev/null", host), "r");
|
||||
let nout = np ? np.read("all") : "";
|
||||
if (np) np.close();
|
||||
if (nout && nout != "") {
|
||||
let lines = split(nout, "\n");
|
||||
let name_seen = false;
|
||||
for (let line in lines) {
|
||||
if (index(line, "Name:") >= 0) { name_seen = true; continue; }
|
||||
if (name_seen) {
|
||||
let nm = match(line, /Address:[ \t]+([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)/);
|
||||
if (nm && nm[1]) {
|
||||
ip = nm[1];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (ip) {
|
||||
let flags = sprintf("--resolve %s:443:%s --resolve %s:80:%s ", host, ip, host, ip);
|
||||
_fuzzer_host_cache[host] = flags;
|
||||
return flags;
|
||||
}
|
||||
_fuzzer_host_cache[host] = "";
|
||||
return "";
|
||||
}
|
||||
|
||||
const KNOWN_BLOB_FILES = {
|
||||
tls_max: { file: "tls_clienthello_max_ru.bin", size: 654, desc: "Max.ru authentic ClientHello" },
|
||||
tls_google: { file: "tls_clienthello_www_google_com.bin", size: 681, desc: "Google authentic ClientHello" },
|
||||
@@ -550,10 +637,10 @@ const STRATEGIES_ZAPRET2 = [
|
||||
description: "Standard 2-fragment multisplit desync for compatibility."
|
||||
},
|
||||
{
|
||||
id: "z2_disorder_pos1",
|
||||
name: "Classic Multidisorder (pos=1)",
|
||||
id: "z2_disorder_pos2",
|
||||
name: "Classic Multidisorder (pos=2)",
|
||||
engine: "zapret2",
|
||||
args: "--lua-desync=multidisorder:pos=1:fooling=badseq",
|
||||
args: "--lua-desync=multidisorder:pos=2:fooling=badseq",
|
||||
description: "Sends out-of-order segment with badseq fooling."
|
||||
},
|
||||
|
||||
@@ -1091,7 +1178,7 @@ function generate_combinatorial_zapret2() {
|
||||
}
|
||||
|
||||
// 2. Multidisorder combinations
|
||||
for (let pos in [ "1", "2", "midsld", "1,midsld" ]) {
|
||||
for (let pos in [ "2", "midsld", "1,midsld" ]) {
|
||||
for (let fooling in [ "badseq", "md5sig", "badack" ]) {
|
||||
add(sprintf("Multidisorder (pos=%s, %s)", pos, fooling),
|
||||
sprintf("--lua-desync=multidisorder:pos=%s:fooling=%s", pos, fooling),
|
||||
@@ -1106,8 +1193,9 @@ function generate_combinatorial_zapret2() {
|
||||
add(sprintf("Fake PAWS (%s, rep=%d) + Multisplit (pos=%s)", blob, rep, pos),
|
||||
sprintf("--lua-desync=fake:blob=%s:repeats=%d:tcp_ts=-600000:tcp_ts_up --lua-desync=multisplit:pos=%s", blob, rep, pos),
|
||||
"PAWS ancient TCP timestamp spoofing with authentic ClientHello blob");
|
||||
add(sprintf("Fake PAWS (%s, rep=%d) + Multidisorder (pos=%s)", blob, rep, pos),
|
||||
sprintf("--lua-desync=fake:blob=%s:repeats=%d:tcp_ts=-600000:tcp_ts_up --lua-desync=multidisorder:pos=%s", blob, rep, pos),
|
||||
let dis_pos = (pos == "1") ? "2" : pos;
|
||||
add(sprintf("Fake PAWS (%s, rep=%d) + Multidisorder (pos=%s)", blob, rep, dis_pos),
|
||||
sprintf("--lua-desync=fake:blob=%s:repeats=%d:tcp_ts=-600000:tcp_ts_up --lua-desync=multidisorder:pos=%s", blob, rep, dis_pos),
|
||||
"PAWS ancient TCP timestamp spoofing with multidisorder segments");
|
||||
}
|
||||
}
|
||||
@@ -1131,8 +1219,9 @@ function generate_combinatorial_zapret2() {
|
||||
|
||||
// 5. TCP SYN Data combinations
|
||||
for (let pos in [ "1", "1,midsld", "midsld" ]) {
|
||||
add(sprintf("SYN Data + Multidisorder (pos=%s)", pos),
|
||||
sprintf("--lua-desync=syndata --lua-desync=multidisorder:pos=%s", pos),
|
||||
let dis_pos = (pos == "1") ? "2" : pos;
|
||||
add(sprintf("SYN Data + Multidisorder (pos=%s)", dis_pos),
|
||||
sprintf("--lua-desync=syndata --lua-desync=multidisorder:pos=%s", dis_pos),
|
||||
"TCP SYN data payload with out-of-order data segments");
|
||||
add(sprintf("SYN Data + Multisplit (pos=%s, seqovl=1)", pos),
|
||||
sprintf("--lua-desync=syndata --lua-desync=multisplit:pos=%s:seqovl=1:fooling=badseq", pos),
|
||||
@@ -1149,8 +1238,9 @@ function generate_combinatorial_zapret2() {
|
||||
add(sprintf("Fake (TTL=%d, %s) + Multisplit (pos=%s)", ttl, fooling, pos),
|
||||
sprintf("--lua-desync=fake:ttl=%d:fooling=%s --lua-desync=multisplit:pos=%s", ttl, fooling, pos),
|
||||
"Low-TTL fake injection followed by multisplit payload");
|
||||
add(sprintf("Fake (TTL=%d, %s) + Multidisorder (pos=%s)", ttl, fooling, pos),
|
||||
sprintf("--lua-desync=fake:ttl=%d:fooling=%s --lua-desync=multidisorder:pos=%s", ttl, fooling, pos),
|
||||
let dis_pos = (pos == "1") ? "2" : pos;
|
||||
add(sprintf("Fake (TTL=%d, %s) + Multidisorder (pos=%s)", ttl, fooling, dis_pos),
|
||||
sprintf("--lua-desync=fake:ttl=%d:fooling=%s --lua-desync=multidisorder:pos=%s", ttl, fooling, dis_pos),
|
||||
"Low-TTL fake injection followed by multidisorder payload");
|
||||
}
|
||||
}
|
||||
@@ -1161,8 +1251,9 @@ function generate_combinatorial_zapret2() {
|
||||
add(sprintf("Fakedsplit (pos=%s, badseq)", pos),
|
||||
sprintf("--lua-desync=fakedsplit:pos=%s:fooling=badseq", pos),
|
||||
"Stream splitting with embedded fake packets");
|
||||
add(sprintf("Fakeddisorder (pos=%s, badseq)", pos),
|
||||
sprintf("--lua-desync=fakeddisorder:pos=%s:fooling=badseq", pos),
|
||||
let dis_pos = (pos == "1") ? "2" : pos;
|
||||
add(sprintf("Fakeddisorder (pos=%s, badseq)", dis_pos),
|
||||
sprintf("--lua-desync=fakeddisorder:pos=%s:fooling=badseq", dis_pos),
|
||||
"Out-of-order stream with embedded fake fragments");
|
||||
add(sprintf("Hostfakesplit (pos=%s, badseq)", pos),
|
||||
sprintf("--lua-desync=hostfakesplit:pos=%s:fooling=badseq", pos),
|
||||
@@ -1710,6 +1801,26 @@ function get_fuzzer_state() {
|
||||
finished_at: 0
|
||||
};
|
||||
}
|
||||
if (state.running) {
|
||||
let is_alive = false;
|
||||
let pid_str = fs.readfile(PID_FILE);
|
||||
if (pid_str) {
|
||||
let pid = trim(as_string(pid_str));
|
||||
if (pid != "" && match(pid, /^[0-9]+$/) != null) {
|
||||
is_alive = (system(sprintf("kill -0 %s >/dev/null 2>&1", pid)) == 0);
|
||||
}
|
||||
}
|
||||
if (!is_alive) {
|
||||
state.running = false;
|
||||
if (!state.error && state.progress_pct < 100) {
|
||||
state.error = "Worker process exited unexpectedly";
|
||||
}
|
||||
if (state.finished_at == 0) {
|
||||
state.finished_at = clock()[0];
|
||||
}
|
||||
save_fuzzer_state(state);
|
||||
}
|
||||
}
|
||||
return state;
|
||||
}
|
||||
|
||||
@@ -1906,12 +2017,16 @@ function detect_dpi_type(target_key, custom_url) {
|
||||
system("nft 'add chain inet tachyon_fuzzer bypass_singbox { type route hook output priority -155 ; policy accept; }' 2>/dev/null");
|
||||
system(sprintf("nft 'add rule inet tachyon_fuzzer bypass_singbox meta l4proto tcp tcp dport { 80, 443 } meta mark set meta mark | %s counter' 2>/dev/null", FUZZER_OUTBOUND_MARK));
|
||||
|
||||
let t_pre = get_timeout_prefix(8);
|
||||
let curl_cmd = sprintf(
|
||||
"%scurl %s-so /dev/null -w '%%{http_code}\\t%%{time_appconnect}\\t%%{time_starttransfer}\\t%%{speed_download}\\t%%{size_download}' -L --connect-timeout 4 --max-time 6 %s 2>&1; printf '\\t%%d\\n' $?",
|
||||
t_pre,
|
||||
dns_flags,
|
||||
shell_quote(target_url)
|
||||
let target_flags = get_resolved_host_flags(target_url);
|
||||
if (target_flags == "") target_flags = dns_flags;
|
||||
|
||||
let curl_cmd = wrap_cmd_timeout(
|
||||
sprintf(
|
||||
"curl %s-so /dev/null -w '%%{http_code}\\t%%{time_appconnect}\\t%%{time_starttransfer}\\t%%{speed_download}\\t%%{size_download}' -L --connect-timeout 4 --max-time 6 %s 2>&1; printf '\\t%%d\\n' $?",
|
||||
target_flags,
|
||||
shell_quote(target_url)
|
||||
),
|
||||
8
|
||||
);
|
||||
let pipe = fs.popen(curl_cmd, "r");
|
||||
let output = pipe ? pipe.read("all") : "";
|
||||
@@ -1937,7 +2052,7 @@ function detect_dpi_type(target_key, custom_url) {
|
||||
let dm = match(domain, /https?:\/\/([^/]+)/);
|
||||
if (dm && dm[1]) domain = dm[1];
|
||||
|
||||
let dns_cmd = sprintf("%snslookup %s 2>&1", get_timeout_prefix(4), shell_quote(domain));
|
||||
let dns_cmd = wrap_cmd_timeout(sprintf("nslookup %s 2>&1", shell_quote(domain)), 4);
|
||||
let dns_pipe = fs.popen(dns_cmd, "r");
|
||||
let dns_out = dns_pipe ? dns_pipe.read("all") : "";
|
||||
if (dns_pipe) dns_pipe.close();
|
||||
@@ -2182,13 +2297,14 @@ function run_probe(engine, args_str, target_key, custom_url) {
|
||||
let last_http = 0;
|
||||
let last_dpi_verdict = "available";
|
||||
|
||||
let t_pre = get_timeout_prefix(8);
|
||||
for (let target_item in urls_list) {
|
||||
let curl_cmd = sprintf(
|
||||
"%scurl -x socks5h://127.0.0.1:%d -so /dev/null -w '%%{http_code}\\t%%{time_appconnect}\\t%%{time_starttransfer}\\t%%{speed_download}\\t%%{size_download}' -L --connect-timeout 4 --max-time 6 %s 2>/dev/null; printf '\\t%%d\\n' $?",
|
||||
t_pre,
|
||||
BYEDPI_PORT,
|
||||
shell_quote(target_item.url)
|
||||
let curl_cmd = wrap_cmd_timeout(
|
||||
sprintf(
|
||||
"curl -x socks5h://127.0.0.1:%d -so /dev/null -w '%%{http_code}\\t%%{time_appconnect}\\t%%{time_starttransfer}\\t%%{speed_download}\\t%%{size_download}' -L --connect-timeout 4 --max-time 6 %s 2>/dev/null; printf '\\t%%d\\n' $?",
|
||||
BYEDPI_PORT,
|
||||
shell_quote(target_item.url)
|
||||
),
|
||||
8
|
||||
);
|
||||
let pipe = fs.popen(curl_cmd, "r");
|
||||
let output = pipe ? pipe.read("all") : "";
|
||||
@@ -2329,13 +2445,17 @@ function run_probe(engine, args_str, target_key, custom_url) {
|
||||
let last_dpi_verdict = "available";
|
||||
let dns_flags = get_fuzzer_curl_dns_flags();
|
||||
|
||||
let t_pre = get_timeout_prefix(8);
|
||||
for (let target_item in urls_list) {
|
||||
let curl_cmd = sprintf(
|
||||
"%scurl %s-so /dev/null -w '%%{http_code}\\t%%{time_appconnect}\\t%%{time_starttransfer}\\t%%{speed_download}\\t%%{size_download}' -L --connect-timeout 4 --max-time 6 %s 2>/dev/null; printf '\\t%%d\\n' $?",
|
||||
t_pre,
|
||||
dns_flags,
|
||||
shell_quote(target_item.url)
|
||||
let target_flags = get_resolved_host_flags(target_item.url);
|
||||
if (target_flags == "") target_flags = dns_flags;
|
||||
|
||||
let curl_cmd = wrap_cmd_timeout(
|
||||
sprintf(
|
||||
"curl %s-so /dev/null -w '%%{http_code}\\t%%{time_appconnect}\\t%%{time_starttransfer}\\t%%{speed_download}\\t%%{size_download}' -L --connect-timeout 4 --max-time 6 %s 2>/dev/null; printf '\\t%%d\\n' $?",
|
||||
target_flags,
|
||||
shell_quote(target_item.url)
|
||||
),
|
||||
8
|
||||
);
|
||||
let pipe = fs.popen(curl_cmd, "r");
|
||||
let output = pipe ? pipe.read("all") : "";
|
||||
@@ -2360,9 +2480,6 @@ function run_probe(engine, args_str, target_key, custom_url) {
|
||||
if (last_http == 0) last_http = single_res.http_code;
|
||||
if (single_res.error && result.error == "") result.error = single_res.error;
|
||||
last_dpi_verdict = single_res.dpi_verdict || "failed";
|
||||
if (_fuzzer_curl_dns_flags != "") {
|
||||
_fuzzer_curl_dns_flags = "";
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -357,6 +357,9 @@ function failsafe_restore() {
|
||||
log("Rolling back previous Tachyon dnsmasq changes because dont_touch_dhcp is enabled", "warn");
|
||||
}
|
||||
else {
|
||||
if (!dnsmasq_has_tachyon_dns() && !dnsmasq_has_tachyon_managed_state())
|
||||
return true;
|
||||
|
||||
log("Rolling back Tachyon DNS changes in dnsmasq", "warn");
|
||||
}
|
||||
|
||||
|
||||
@@ -1477,6 +1477,15 @@ function nft_add_doh_block_marking_rules(table, interface_set, fakeip_mark) {
|
||||
return result;
|
||||
}
|
||||
|
||||
function sqm_service_enabled() {
|
||||
let queues = uci_core.section_objects("sqm", "queue");
|
||||
for (let q in queues) {
|
||||
if (q && (q.enabled == "1" || q.enabled == true))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function nft_create_runtime_base(table, localv4_set, common_set, port_set, ip_port_set, interface_set, source_interfaces, fakeip_mark, outbound_mark, fakeip_range, tproxy_port, exclude_ntp, localv6_set, common6_set, ip_port6_set, fakeip6_range, tproxy6_address, block_doh) {
|
||||
localv6_set = default_arg(localv6_set, "localv6");
|
||||
common6_set = default_arg(common6_set, "tachyon_subnets6");
|
||||
@@ -1674,17 +1683,20 @@ function nft_create_runtime_base(table, localv4_set, common_set, port_set, ip_po
|
||||
return false;
|
||||
|
||||
// QoS Low-Latency Gaming & Voice Acceleration Engine
|
||||
if (uci_settings().qos_priority_engine != "0") {
|
||||
let qos_setting = uci_settings().qos_priority_engine;
|
||||
let qos_enabled = (qos_setting == "1" || (qos_setting != "0" && !sqm_service_enabled()));
|
||||
|
||||
if (qos_enabled) {
|
||||
// Voice & Discord RTC (DSCP EF 0x2e)
|
||||
nft_add_rule(table, "mangle_forward", [ "udp", "dport", "{ 5000-5020, 3478, 19302, 50000-65535 }", "ip", "dscp", "set", "0x2e" ]);
|
||||
nft_add_rule(table, "mangle_output", [ "udp", "dport", "{ 5000-5020, 3478, 19302, 50000-65535 }", "ip", "dscp", "set", "0x2e" ]);
|
||||
nft_add_rule(table, "mangle_forward", [ "udp", "dport", "{ 5000-5020, 3478, 19302 }", "ip", "dscp", "set", "0x2e" ]);
|
||||
nft_add_rule(table, "mangle_output", [ "udp", "dport", "{ 5000-5020, 3478, 19302 }", "ip", "dscp", "set", "0x2e" ]);
|
||||
|
||||
// Gaming Traffic (Steam, CS, Dota, Valorant, Apex, PUBG, Roblox) (DSCP AF41 0x22)
|
||||
nft_add_rule(table, "mangle_forward", [ "udp", "dport", "{ 3074, 7000-9000, 27000-27050, 28960 }", "ip", "dscp", "set", "0x22" ]);
|
||||
nft_add_rule(table, "mangle_output", [ "udp", "dport", "{ 3074, 7000-9000, 27000-27050, 28960 }", "ip", "dscp", "set", "0x22" ]);
|
||||
|
||||
// TCP ACK Acceleration (DSCP CS2)
|
||||
nft_add_rule(table, "mangle_forward", [ "tcp", "flags", "&", "(fin|syn|rst|ack)", "==", "ack", "ip", "dscp", "set", "cs2" ]);
|
||||
// Pure TCP ACK Acceleration (DSCP CS2) - only small packets without payload
|
||||
nft_add_rule(table, "mangle_forward", [ "tcp", "flags", "&", "(fin|syn|rst|ack)", "==", "ack", "meta", "length", "<=", "64", "ip", "dscp", "set", "cs2" ]);
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
@@ -720,7 +720,21 @@ function controller(bus, opts) {
|
||||
}
|
||||
}
|
||||
|
||||
if (setting("qos_priority_engine", "1") == "0") return;
|
||||
let qos_pref = setting("qos_priority_engine", "");
|
||||
if (qos_pref == "0") return;
|
||||
if (qos_pref != "1") {
|
||||
let queues = uci_core.section_objects("sqm", "queue");
|
||||
let sqm_on = false;
|
||||
if (queues && length(queues) > 0) {
|
||||
for (let q in queues) {
|
||||
if (q.enabled == "1" || q.enabled == true) {
|
||||
sqm_on = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (sqm_on) return;
|
||||
}
|
||||
if ((index(out_nft, "dscp set 0x2e") < 0 && index(out_nft, "dscp set ef") < 0) ||
|
||||
(index(out_nft, "dscp set 0x22") < 0 && index(out_nft, "dscp set af41") < 0))
|
||||
bus.emit(EV.QOS_MISSING, { table: nft_table });
|
||||
|
||||
@@ -475,14 +475,18 @@ function retry_start_on_wan_up_action(runtime_running_value, service_enabled_val
|
||||
}
|
||||
|
||||
function retry_start_on_wan_up(owner_pid) {
|
||||
let running = runtime_is_running();
|
||||
let enabled = service_is_enabled();
|
||||
let action = retry_start_on_wan_up_action(
|
||||
runtime_is_running() ? "1" : "0",
|
||||
service_is_enabled() ? "1" : "0",
|
||||
running ? "1" : "0",
|
||||
enabled ? "1" : "0",
|
||||
start_retry_pending(START_RETRY_FILE) ? "1" : "0"
|
||||
);
|
||||
|
||||
if (action == "skip_running" || action == "skip_disabled") {
|
||||
clear_start_retry(START_RETRY_FILE);
|
||||
if (!running && !enabled)
|
||||
restore_dnsmasq_failsafe();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -1684,6 +1684,7 @@ function disable_service() {
|
||||
let res = command_status_from_args([ SERVICE_INIT, "disable" ]);
|
||||
uci_core.set(CONFIG_NAME, "settings", "enabled", "0");
|
||||
uci_core.commit(CONFIG_NAME);
|
||||
stop();
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
@@ -2429,7 +2429,7 @@ function view_qos(token, chat_id, msg_id) {
|
||||
let text = "🎮 <b>" + t("qos_title") + "</b>\n\n" +
|
||||
t("quiet_status") + ": <code>" + (enabled ? "🟢 " + t("qos_enabled_detail") : "⚪ " + t("qos_disabled_detail")) + "</code>\n\n" +
|
||||
"<b>" + t("qos_priority_rules") + "</b>\n" +
|
||||
"├ 🎙️ <b>Golos/Discord/RTC:</b> UDP 5000-5020, 3478, 50000-65535 ➔ <code>DSCP EF (0x2e)</code>\n" +
|
||||
"├ 🎙️ <b>Golos/Discord/RTC:</b> UDP 5000-5020, 3478, 19302 ➔ <code>DSCP EF (0x2e)</code>\n" +
|
||||
"├ 🎮 <b>Games (Steam/CS/Dota/Apex/PUBG/Roblox):</b> UDP 27000-27050, 3074 ➔ <code>DSCP AF41 (0x22)</code>\n" +
|
||||
"└ ⚡ <b>TCP ACK Acceleration:</b> малые ACK пакеты ➔ <code>High Priority</code>";
|
||||
|
||||
|
||||
Reference in New Issue
Block a user