mirror of
https://github.com/by-sonic/tglock.git
synced 2026-11-05 07:11:56 +03:00
fix: медиа и «прокси не настроен»: пакет на кадр, настоящие фронты, kwsN-1 только для медиа; beta.19 (#75)
* fix(tunnel): медиа и «прокси не настроен»: один пакет на кадр, настоящие фронты, kwsN-1 только для медиа Три причины, каждая проверена на живом Telegram запросом req_DH_params: сервер сверяет номер DC внутри него с собой и отвечает -444 на чужой. - WebSocket-фронт разбирает один пакет на входящий кадр, остаток ждёт следующего. Клиент пишет запросы пачками, TGLock слал их одним кадром, и всё, что шло вторым, застревало: текст проходил, файлы вставали. Теперь поток режется на пакеты, как в Flowseal/tg-ws-proxy. Пачка через beta.18 висит на всех DC, через эту сборку принимается на всех. - Кластер kwsN-1 отвергает обычное соединение с -444, а Telegram Desktop в ответ выключает прокси как настроенный неверно. При сбое kwsN основное соединение откатывалось именно туда. Теперь kwsN-1 только для медиа. - Адреса из списка DC не говорят на TLS ни из какой сети (проверено с чистой сети), поэтому первый маршрут каждого DC не работал никогда. Закреплены настоящие фронты, и DC1, DC3, DC5 стали доступны по WebSocket, чего не было. У CDN203 своего фронта нет: остались TCP, Worker и CF-прокси. Обрыв туннеля, через который уже шли данные, больше не ставит маршрут на паузу. Таймаут соединения 8 с, как в tg-ws-proxy. probe_proxy.mjs получил --identity и --batched: они и нашли эти баги. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * feat: журнал ошибок в диагностике, --log-file для роутеров; 2.0.0-beta.19 «Скопировать диагностику» отдавала только счётчики, и по ней нельзя было понять, какой маршрут не ответил. Теперь в отчёте есть строки сбоев туннелей, а домены Worker и CF-прокси в них заменены на <домен>. --log-file и --log-max-mb (log_file, log_max_mb в настройках), как в tg-ws-proxy: журнал идёт в файл с ротацией, а не в системный журнал роутера. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * feat(routes): запасной WebSocket на порту 80 родных адресов, включая CDN203 Родные адреса Telegram принимают WebSocket без TLS на порту 80. Измерено req_DH_params: DC определяется адресом, имя хоста не важно, а 91.105.192.100 отдаёт ключи CDN. Для CDN203, откуда часто идёт видео, это первый прямой WebSocket: на 443 фронта у него нет, и там, где провайдер закрыл только 443, до него раньше было не достать без Worker. Защита та же, что у родного TCP: внутри тот же обфусцированный MTProto. В Host идёт адрес, имени Telegram в открытом виде нет. Маршрут разрешён только до закреплённых адресов и пробуется последним. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(routes): паузы маршрутов по результатам ревью, пределы и журнал - Обрыв не наказывает маршрут, только если туннель работал и получал ответы 15 с. Одного ответа мало: маршрут, который ответил раз и умер, оставался предпочтительным навсегда. - Клиент спросил, не дождался ответа за 5 с и ушёл: маршрут считается неработающим. Иначе CDN, принявший TCP и молчащий, держал первое место, и очередь до порта 80 не доходила. - Предел пакета 2 МиБ вместо 16: чужое устройство в LAN-режиме не заставит роутер копить десятки мегабайт на соединение. - Журнал: разовая ошибка записи его больше не выключает, неудачная ротация не теряет бэкап и держит предел, права 0600 и на уже существующем файле. - В отчёт диагностики не попадает Worker, заданный адресом. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: babin <Thartewerner536e@engineer.com> Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
+21
-3
@@ -513,12 +513,29 @@ async function copyTelegramLink(): Promise<void> {
|
||||
}
|
||||
}
|
||||
|
||||
// Отчёт публикуют в issue: домен Worker'а и свой домен CF-прокси туда не идут,
|
||||
// Worker можно задать и адресом, поэтому оставляются только адреса Telegram.
|
||||
// Они и имена Telegram нужны, чтобы понять, какой маршрут не ответил.
|
||||
function publicLogLine(message: string): string {
|
||||
return message.replace(/[\w-]+(?:\.[\w-]+)+/g, (host) =>
|
||||
/^(149\.154|91\.105|91\.108)\.[\d.]+$/.test(host) || host.endsWith(".telegram.org") ? host : "<домен>");
|
||||
}
|
||||
|
||||
function failureLog(): string[] {
|
||||
const failure = /^(Не поднялся туннель|Сбой туннеля|Обрыв туннеля)/;
|
||||
const paused = /на паузе после ошибок/;
|
||||
return status.logs
|
||||
.filter(({ message }) => failure.test(message) && !paused.test(message))
|
||||
.slice(-20)
|
||||
.map(({ timestamp, message }) => `${timestamp} ${publicLogLine(message)}`);
|
||||
}
|
||||
|
||||
async function copyDiagnostics(): Promise<void> {
|
||||
try {
|
||||
// Public reports exclude proxy links, worker domains and free-form logs.
|
||||
// Public reports exclude proxy links and secrets.
|
||||
const report = {
|
||||
application: "TGLock",
|
||||
version: "2.0.0-beta.18",
|
||||
version: "2.0.0-beta.19",
|
||||
running: status.running,
|
||||
activeConnections: status.activeConnections,
|
||||
tunnels: status.tunnels,
|
||||
@@ -532,9 +549,10 @@ async function copyDiagnostics(): Promise<void> {
|
||||
uptimeSeconds: status.uptimeSeconds,
|
||||
port: status.port,
|
||||
lanMode: settings.lanMode,
|
||||
failureLog: failureLog(),
|
||||
};
|
||||
await navigator.clipboard.writeText(JSON.stringify(report, null, 2));
|
||||
showToast("Диагностика скопирована без адресов и секретов");
|
||||
showToast("Диагностика скопирована без секретов и своих доменов");
|
||||
} catch { showToast("Буфер обмена недоступен", true); }
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user