mirror of
https://github.com/by-sonic/tglock.git
synced 2026-11-05 15:21:55 +03:00
8ce9355243
* 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>
82 lines
4.1 KiB
Markdown
82 lines
4.1 KiB
Markdown
# Manual protocol probe
|
|
|
|
`scripts/probe_proxy.mjs` uses only Node.js built-ins and is independent of the
|
|
Rust transport helpers. It connects to an already running TGLock listener at
|
|
`127.0.0.1`, sends one unauthenticated `req_pq_multi` through a secret-protected
|
|
obfuscated2 padded-intermediate stream, and validates the returned `resPQ`, its
|
|
request nonce, and the lengths of its TL fields. It stops before creating an
|
|
authorization key. No Telegram account, API ID, API hash or login is needed.
|
|
|
|
The secret is read from an explicitly supplied file and is never printed. Use
|
|
the same secret file as the running CLI. Do not paste proxy links or secret
|
|
values into public logs.
|
|
|
|
```sh
|
|
# Offline validation first: no network access.
|
|
node scripts/probe_proxy.mjs --self-test
|
|
|
|
# Start a local CLI separately, using a persistent secret file.
|
|
tglock-cli --port 18080 --secret-file /private/path/tglock-secret
|
|
|
|
# Ordinary DC, media route, and CDN route; run each explicitly.
|
|
node scripts/probe_proxy.mjs --port 18080 --secret-file /private/path/tglock-secret --dc 2
|
|
node scripts/probe_proxy.mjs --port 18080 --secret-file /private/path/tglock-secret --dc -4 --fragment-size 7
|
|
node scripts/probe_proxy.mjs --port 18080 --secret-file /private/path/tglock-secret --dc 203
|
|
```
|
|
|
|
On Windows, supply the downloaded CLI executable and a Windows file path in the
|
|
same commands. Supported DC values are `1` through `5` and `203`; a negative
|
|
value requests a media route. `--timeout-ms` defaults to 15000 and is bounded at
|
|
120000. The response is bounded at 2 MiB. `--fragment-size 7` sends small writes
|
|
with 2 ms gaps to exercise stream fragmentation; TCP can still combine writes.
|
|
|
|
A successful JSON report contains `response: "resPQ"`, `nonceMatches: true`, the
|
|
requested DC, the public RSA fingerprint count, and elapsed time. Exit status 1
|
|
means connection, timeout, decryption/framing or response validation failed.
|
|
The ordinary CI suite does not run this live probe.
|
|
|
|
Success demonstrates a correctly relayed protocol exchange. It does **not**
|
|
authenticate the responding server, prove its DC identity, log into an account,
|
|
or verify message sending, media downloads or Android lifecycle. In particular,
|
|
`requestedDc` describes the request, not an independently confirmed backend.
|
|
|
|
## Confirm which data centre answers
|
|
|
|
`--identity` continues the handshake with `req_DH_params`. The DC number sealed
|
|
inside it is checked by the server against itself, and a mismatch is answered
|
|
with transport error `-444`, so this does prove the backend. `resPQ` alone proves
|
|
nothing here: every server answers it for any DC in the header. The handshake
|
|
stops before an authorization key exists. CDN DC203 uses its own RSA keys, so
|
|
the report says `identity: "skipped: CDN keys"` for it.
|
|
|
|
`--batched` implies `--identity` and sends `req_DH_params` glued behind another
|
|
packet in one write, the way real clients batch requests. A WebSocket frontend
|
|
reads one packet per frame, so a proxy that forwards the write as a single frame
|
|
times out here while a lone request still passes. Run it before every release:
|
|
|
|
```sh
|
|
for dc in 1 2 -2 3 4 -4 5 203; do
|
|
node scripts/probe_proxy.mjs --port 18080 --secret-file /private/path/tglock-secret --dc $dc --batched
|
|
done
|
|
```
|
|
|
|
## Isolate CDN transport failures
|
|
|
|
To distinguish an unavailable CDN WebSocket endpoint from an unavailable CDN
|
|
TCP connection, explicitly run:
|
|
|
|
```sh
|
|
node scripts/probe_proxy.mjs --direct-cdn --dc 203
|
|
```
|
|
|
|
This optional mode bypasses local TGLock and connects **only** to the pinned
|
|
Telegram CDN address `91.105.192.100:443`, using raw obfuscated2 TCP without a
|
|
proxy secret or TLS. It supports no arbitrary host. It performs the same single
|
|
unauthenticated exchange and still does not prove account or media operation.
|
|
The parser accepts trailing bytes after the complete `resPQ` TL object because
|
|
live CDN replies can include random padding in the declared message length.
|
|
|
|
Protocol references: [handshake initiation](https://core.telegram.org/mtproto/auth_key),
|
|
[obfuscated transports](https://core.telegram.org/mtproto/mtproto-transports),
|
|
and [unencrypted messages](https://core.telegram.org/mtproto/description#unencrypted-message).
|