fix(proxy): клиент, с которым не договорились, закрывался молча (#42) (#45)

Диагностика от @alexsagaidak в #42 показала третий случай, которого ни один
счётчик не различал. У него ноль отклонённых и живые туннели, то есть оба
показателя говорят «всё хорошо»:

    соединений 17 · туннелей 6 · DC4 · Запасной Telegram IP · сбоев 0 ·
    падений маршрутов 26 · отклонено 0

Клиент, который дошёл до прокси, но не сумел договориться, не попадал ни в
blocked, ни в ws_failures. Ошибка из handle() выбрасывалась в `let _ =`,
соединение закрывалось, и наружу это выглядело как active, дёрнувшийся вверх и
обратно. По диагностике неотличимо от клиента, который подключился и работает.

Теперь такие клиенты считает unknown_clients, а журнал называет адрес и
причину. Причин две:

MTProto-init не разбирается под текущим секретом. Почти всегда это ссылка
tg://proxy от прошлого запуска: секрет — её половина, и клиент с сохранённой
старой ссылкой попадает ровно сюда. Со стороны Telegram это и есть «прокси
настроен неверно и будет отключён» — то, с чем пришли в #37 и что до сих пор
нельзя было подтвердить со стороны прокси.

SOCKS5-приветствие не разбирается. Сюда же попадает MTProto-соединение,
ушедшее в SOCKS5-ветку по неоднозначному первому байту, если полный init не
успел прийти за PROTOCOL_PROBE_TIMEOUT. На loopback этого не бывает, а через
Wi-Fi с телефона — уже вопрос задержки.

От ws_failures отличается тем, что тот растёт после успешного рукопожатия с
клиентом: там договорились с клиентом, но не смогли с Telegram. Различать их
важно, иначе непонятно, в какую сторону смотреть.

В интерфейсе — метрика «Не опознаны» с пояснением, в строке статуса CLI —
поле «не опознано N».

Co-authored-by: by-sonic <171230345+by-sonic@users.noreply.github.com>
This commit is contained in:
Никита Sonic
2026-08-19 14:32:34 +03:00
committed by GitHub
parent 41e8040e59
commit b92403b4c9
6 changed files with 139 additions and 7 deletions
+14
View File
@@ -13,6 +13,8 @@ type Status = {
routeFailures: number;
/// Отклонено политикой «в LAN-режиме только Telegram».
blocked: number;
/// Клиенты, которые дошли, но не сумели договориться о рукопожатии.
unknownClients: number;
uptimeSeconds: number;
port: number;
/// Адрес для других устройств. Приходит только в LAN-режиме.
@@ -44,6 +46,7 @@ let status: Status = {
failures: 0,
routeFailures: 0,
blocked: 0,
unknownClients: 0,
uptimeSeconds: 0,
port: 1080,
shareAddress: null,
@@ -290,6 +293,10 @@ function renderDiagnostics(): void {
<span>Отклонено</span>
<strong>${status.blocked}</strong>
</article>
<article class="metric-card">
<span>Не опознаны</span>
<strong>${status.unknownClients}</strong>
</article>
</div>
<p class="field-hint">
@@ -305,6 +312,13 @@ function renderDiagnostics(): void {
дело в сети или брандмауэре. Какие именно адреса отклонены, видно ниже.
</p>
<p class="field-hint">
«Не опознаны» — клиенты, которые дошли до прокси, но договориться с ними
не удалось. Почти всегда это старая ссылка: секрет в Telegram остался от
прошлого запуска и больше не совпадает. Тогда Telegram пишет «прокси
настроен неверно», а адрес такого клиента появится в журнале ниже.
</p>
<div class="log-panel">
<div class="log-heading">
<span>Последние события</span>