v1.0.1
sleep3r/mtproto.zigv1.0.1Jun 7, 2026by sleep3r
Upgrading?
AI Summary
Fixes a middleproxy mode issue where the proxy appeared healthy but clients could not connect due to stale metadata that failed to refresh frequently enough.
Key Highlights
- MiddleProxy metadata refresh period reduced from 24 hours to 1 hour.
- Reactive metadata refresh triggered immediately upon stalled handshakes.
- Metadata fetch now resilient to malformed `/etc/resolv.conf` files using a `getent` fallback.
Full Release Notes
<details open> <summary>🇷🇺 Что нового (RU)</summary> ## Что решает этот релиз `v1.0.1` — патч-релиз для middleproxy-режима (`use_middle_proxy = true`), который чинит коварный сценарий: прокси выглядит **полностью здоровым**, но клиенты не подключаются. Production-инцидент выглядел так: процесс жив, слушает `:443`, туннель в норме (свежий handshake, до DC по TCP достукивается) — но `users_total=0`, и **каждое** соединение уходит в `hs_timeout`. Клиенты проходят FakeTLS, но застревают на upstream RPC-handshake с middleproxy, который перестал отвечать. Причина: метаданные MiddleProxy (адреса DC из `getProxyConfig` + секрет из `getProxySecret`) обновлялись по таймеру **раз в 24 часа**, а Telegram ротирует их быстрее — в нашем случае `dc4` уехал `91.108.4.139 → 91.108.4.200` примерно через **10 часов** после загрузки на старте. Кэш протух, и весь middleproxy-трафик встал до ручного рестарта. `v1.0.1` обновляет метаданные **часто** (раз в час), а при первых же зависших handshake'ах — **немедленно** (реактивно), и заодно делает саму загрузку метаданных устойчивой к битому `/etc/resolv.conf`. > [!NOTE] > Менять `config.toml` не нужно — фикс работает на текущих настройках. Затрагивает только middleproxy-режим (`use_middle_proxy = true`); чисто обфусцированных / FakeTLS-без-middleproxy деплоев это не касается. > [!TIP] > Что реактивное обновление сработало, видно в логах — строка `Middle-proxy reactive refresh: ...`, а следом `Middle-proxy cache updated: dc4=... secret_len=128`. ## Что изменено ### Метаданные MiddleProxy обновляются раз в час, а не раз в сутки ([#305](https://github.com/sleep3r/mtproto.zig/pull/305)) - Период периодического обновления (`middle_proxy_update_period_ns`) сокращён с 24 часов до **1 часа**. - Telegram ротирует адреса DC и секрет в пределах суток (в инциденте — за ~10 часов), поэтому суточная частота позволяла кэшу протухнуть и обрушить весь middleproxy-трафик до рестарта. - Загрузка дешёвая и best-effort: при сетевом сбое прокси держит текущий кэш, так что дополнительные опросы стоят практически ничего. - Худший случай протухания сужен с суток до часа. ### Реактивное обновление при зависших handshake'ах ([#305](https://github.com/sleep3r/mtproto.zig/pull/305)) - Если соединение уходит в `hs_timeout`, **всё ещё находясь в RPC-handshake с middleproxy**, это прямой признак, что кэш протух — data-plane просит updater обновиться **не дожидаясь часового таймера**. - Протухший DC/секрет заменяется за ~`handshake_timeout` + одну загрузку (десятки секунд) вместо «до часа». - Дебаунс **60 секунд**: шквал падающих handshake'ов — или реальный сбой на стороне middleproxy, который свежие метаданные не починят — не устроит refresh-шторм. - Реализовано lock-free (атомарный флаг на data-plane, который читает wait-цикл updater'а); на горячий путь ретрансляции не влияет. ### Загрузка метаданных устойчива к битому `resolv.conf` ([#305](https://github.com/sleep3r/mtproto.zig/pull/305)) - Стандартный резолвер Zig кидает `ResolvConfParseFailed` на `/etc/resolv.conf` без завершающего перевода строки (SolusVM и ряд VPS-образов) — из-за чего каждая загрузка логировала `unreachable directly … retrying via tunnel`. - Теперь именно на эту ошибку загрузка делает фоллбэк на **curl** (резолв через NSS/getent, который такой файл переваривает). - Бездепендентный std-путь сохранён для здоровых хостов; для middleproxy с прямым egress на таких хостах загрузка метаданных перестаёт быть сломанной, а шум в логах уходит. ## Проверено - `zig build test` (включая новый тест предиката `MiddleProxyHandshakeStep.awaitingMiddleProxy`) и кросс-компиляция под `x86_64-linux` + `aarch64-linux` — зелёные; `zig fmt` чистый. - GitHub Actions: `Test & Build`, `E2E Integration`, `Bench (No Soak)`. - Инцидент диагностирован и восстановлен на живом деплое (`proxy.sleep3r.ru`): подтянулись свежие `dc4=91.108.4.200` + секрет, `users_total` снова растёт, `hs_timeout` пропал. </details> --- <details> <summary>🇬🇧 Release notes (EN)</summary> ## What this release addresses `v1.0.1` is a patch release for middleproxy mode (`use_middle_proxy = true`) that fixes a sneaky failure: the proxy looks **completely healthy**, yet clients can't connect. The production incident looked like this: the process is up and listening on `:443`, the tunnel is fine (fresh handshake, DCs reachable over TCP) — but `users_total=0` and **every** connection hits `hs_timeout`. Clients pass FakeTLS but then stall on the upstream RPC handshake with a middleproxy that stopped answering. Root cause: the MiddleProxy metadata (`getProxyConfig` DC addresses + `getProxySecret`) refreshed on a **24-hour** timer, but Telegram rotates it faster — here the `dc4` media-DC address moved `91.108.4.139 → 91.108.4.200` about **10 hours** after the startup fetch. The cache went stale and stalled all middleproxy traffic until a manual restart. `v1.0.1` refreshes the metadata **often** (hourly), refreshes it **immediately** (reactively) at the first stalled handshakes, and makes the fetch itself resilient to a malformed `/etc/resolv.conf`. > [!NOTE] > No `config.toml` changes needed — the fix works on your current settings. It only affects middleproxy mode (`use_middle_proxy = true`); plain-obfuscated / FakeTLS-without-middleproxy deployments are unaffected. > [!TIP] > You can see the reactive refresh fire in the logs — the line `Middle-proxy reactive refresh: ...` followed by `Middle-proxy cache updated: dc4=... secret_len=128`. ## What changed ### MiddleProxy metadata refreshes hourly, not daily ([#305](https://github.com/sleep3r/mtproto.zig/pull/305)) - The periodic refresh period (`middle_proxy_update_period_ns`) is cut from 24 hours to **1 hour**. - Telegram rotates the DC addresses and secret within a day (~10 hours in the incident), so the daily cadence let the cache go stale and stall all middleproxy traffic until a restart. - The fetch is cheap and best-effort: on a network failure the proxy keeps its current cache, so the extra polls cost effectively nothing. - Bounds the worst-case stale window from a day to an hour. ### Reactive refresh on stalled handshakes ([#305](https://github.com/sleep3r/mtproto.zig/pull/305)) - When a connection hits `hs_timeout` **while still in the RPC handshake with the middleproxy**, that's a direct sign the cache went stale — the data plane asks the updater to refresh **without waiting for the hourly timer**. - A stale DC/secret is replaced in ~`handshake_timeout` + one fetch (tens of seconds) instead of up to an hour. - Debounced by **60 seconds**: a flood of failing handshakes — or a genuine middleproxy-side outage that fresh metadata can't fix — can't cause a refresh storm. - Implemented lock-free (an atomic flag on the data plane, read by the updater's wait loop); no effect on the relay hot path. ### Metadata fetch resilient to a malformed `resolv.conf` ([#305](https://github.com/sleep3r/mtproto.zig/pull/305)) - Zig's std resolver throws `ResolvConfParseFailed` on a `/etc/resolv.conf` without a trailing newline (SolusVM and several VPS images) — which is why every fetch logged `unreachable directly … retrying via tunnel`. - On exactly that error, the fetch now falls back to **curl** (NSS/getent resolution, which tolerates that file). - The dependency-free std path is kept for healthy hosts; direct-egress middleproxy on such hosts stops being broken, and the log noise goes away. ## Verified - `zig build test` (including a new `MiddleProxyHandshakeStep.awaitingMiddleProxy` predicate test) and cross-compilation for `x86_64-linux` + `aarch64-linux` — green; `zig fmt` clean. - GitHub Actions: `Test & Build`, `E2E Integration`, `Bench (No Soak)`. - The incident was diagnosed and restored on the live deployment (`proxy.sleep3r.ru`): fresh `dc4=91.108.4.200` + secret pulled, `users_total` climbing again, `hs_timeout` gone. </details> ## Changelog * fix(middleproxy): hourly + reactive refresh, and a getent fallback on the metadata fetch ([#305](https://github.com/sleep3r/mtproto.zig/pull/305)) ([86ccf03](https://github.com/sleep3r/mtproto.zig/commit/86ccf034be72604628f9fc4632ce978d4a24eea2))
Related Repositories
lightpanda-io/browser★ 36,854
Lightpanda: the headless browser designed for AI and automation
tigerbeetle/tigerbeetle★ 17,229
The financial transactions database designed for mission critical safety and performance.
nullclaw/nullclaw★ 8,131
Fastest, smallest, and fully autonomous AI assistant infrastructure written in Zig
zml/zml★ 4,194
Any model. Any hardware. Zero compromise. Built with @ziglang / @openxla / MLIR / @bazelbuild
dmtrKovalenko/odiff★ 3,280
A very fast SIMD-first image comparison library (with nodejs API)