v0.23.0
sleep3r/mtproto.zigv0.23.0May 10, 2026by sleep3r
Upgrading?
AI Summary
Feature release introducing tunnel pool failover, allowing operators to manage multiple tunnel interfaces with automatic switching to the next healthy interface.
Key Highlights
- Ordered pool of tunnel interfaces with automatic failover
- New `pinned_interface` option for manual preference
- Dashboard updates to show pool state and per-interface health
- Added `README.ru.md` documentation
New Features
- Tunnel pool failover and management
Full Release Notes
<details open> <summary>🇷🇺 Что нового (RU)</summary> ## Что решает этот релиз `v0.23.0` - большой feature-релиз про tunnel pool failover, более честную документацию по ограничениям и нормальную русскую версию README. До этого `mtbuddy setup tunnel` фактически был рассчитан на один tunnel interface: прокси ставил `SO_MARK=200`, а host routing table 200 указывала на один настроенный `awg0`. Это работало, пока один туннель жив. Но если Telegram route через него умирал, оператору приходилось вручную менять интерфейс, перезапускать routing setup и держать в голове текущее состояние. В `v0.23.0` tunnel mode стал pool-based: `mtproto-proxy` по-прежнему использует один data-plane контракт (`SO_MARK=200 -> table 200`), а `mtbuddy` управляет ordered pool туннелей и выбирает первый живой интерфейс. Если основной туннель отваливается, новые upstream-соединения уходят через следующий здоровый tunnel. Когда приоритетный туннель возвращается, контроллер автоматически переключает table 200 обратно, если не задан manual pin. > [!NOTE] > Уже открытые TCP-соединения не мигрируют между туннелями. Failover влияет на новые upstream connections и клиентские reconnects. > [!IMPORTANT] > Telegram calls по-прежнему не поддерживаются. В Telegram они завязаны на SOCKS-поведение, которое нельзя нормально замаскировать в этой модели. Также медиа на аккаунтах без Premium требует MiddleProxy: без него такие загрузки не станут надёжно работать только за счёт tunnel pool. ## Что изменено ### Tunnel pool failover ([#250](https://github.com/sleep3r/mtproto.zig/pull/250)) - `[upstream.tunnel]` теперь поддерживает ordered pool: - `interfaces = ["awg0", "awg1", ...]`; - `pinned_interface = "awg1"` для ручного предпочтения; - старый `interface = "awg0"` остаётся совместимым fallback. - `mtbuddy` ставит `mtproto-tunnel-pool.service` и `mtproto-tunnel-pool.timer`. - `/usr/local/bin/setup_tunnel.sh` теперь: - поднимает все интерфейсы из пула; - проверяет `fwmark 200 -> table 200`; - пробует Telegram через каждый интерфейс; - переключает route через `ip -4 route replace default dev <iface> table 200`. - Selection policy - priority auto-failback: первый живой интерфейс в списке снова становится активным, когда восстанавливается. - Automatic failover не перезапускает `mtproto-proxy`. ### Настройка tunnel pool через mtbuddy ([#250](https://github.com/sleep3r/mtproto.zig/pull/250)) - Повторный `mtbuddy setup tunnel <conf|vpn://>` добавляет следующий свободный `awgN`. - Добавлен `--iface <name>`, чтобы установить или заменить конкретный участник пула. - Интерактивный wizard теперь показывает: - выбор VPN-типа (пока AmneziaWG); - текущий tunnel pool; - действие: создать новый tunnel или заменить существующий. - Конфиги сохраняются в `/etc/amnezia/amneziawg/<iface>.conf`. - Input sanitizing стал явным: удаляются `DNS`, пустые AWG assignments, добавляется `Table = off`. ### Runtime и dashboard знают про активный tunnel ([#250](https://github.com/sleep3r/mtproto.zig/pull/250)) - `Config` парсит `interfaces` и `pinned_interface` вместе с legacy `interface`. - MiddleProxy metadata refresh больше не предполагает один legacy interface: активный tunnel определяется из table 200 / pool state. - Dashboard routing card показывает ordered pool, active route, pinned interface, last switch, health reason и per-interface probe status. - Dashboard action `Set iface` переосмыслен как `Pin`: он пишет `pinned_interface`, запускает pool controller один раз и не рестартит прокси. - `/api/stats.routing` получил поля для pool/active/pinned/health state. ### Документация и UX ([#250](https://github.com/sleep3r/mtproto.zig/pull/250), [#252](https://github.com/sleep3r/mtproto.zig/pull/252)) - Добавлен `README.ru.md`. - В верхней части README появился более заметный переключатель языков EN/RU. - Docker описан честнее: контейнер полезен для тестов, упаковки и простых запусков, но основной production path проекта - native Linux host под управлением `mtbuddy`. - README теперь явно описывает tunnel pool, `pinned_interface`, dashboard monitoring/pinning и ограничения Telegram calls / non-Premium media без MiddleProxy. - `config.toml.example` обновлён под ordered tunnel pool. - `THREAT_MODEL.md` дополнен ограничениями по calls/media. ## Проверено - `python3 -m py_compile src/ctl/dashboard_assets/server.py` - `node --check src/ctl/dashboard_assets/static/app.js` - generated tunnel controller script checked with `bash -n` - `zig build test` - `zig build -Dtarget=x86_64-linux` - `git diff --check` </details> --- <details> <summary>🇬🇧 Release notes (EN)</summary> ## What this release addresses `v0.23.0` is a larger feature release for tunnel pool failover, clearer compatibility documentation, and first-class Russian README coverage. Before this release, `mtbuddy setup tunnel` was effectively designed around a single tunnel interface: the proxy marked upstream sockets with `SO_MARK=200`, and host routing table 200 pointed at one configured `awg0`. That was fine while the tunnel stayed healthy. Once that route failed, operators had to manually change the interface, rerun routing setup, and keep the current state in their head. `v0.23.0` makes tunnel mode pool-based. `mtproto-proxy` still keeps one data-plane contract (`SO_MARK=200 -> table 200`), while `mtbuddy` manages an ordered pool of tunnels and selects the first healthy interface. If the primary tunnel fails, new upstream connections use the next healthy tunnel. When the higher-priority tunnel recovers, the controller automatically points table 200 back to it unless a manual pin is set. > [!NOTE] > Existing TCP connections are not migrated between tunnels. Failover affects new upstream connections and client reconnects. > [!IMPORTANT] > Telegram calls are still unsupported. Telegram calls depend on SOCKS behavior that cannot be masked properly in this model. Media loading on non-Premium accounts also still requires MiddleProxy; the tunnel pool alone does not make that path reliable. ## What changed ### Tunnel pool failover ([#250](https://github.com/sleep3r/mtproto.zig/pull/250)) - `[upstream.tunnel]` now supports an ordered pool: - `interfaces = ["awg0", "awg1", ...]`; - `pinned_interface = "awg1"` for manual preference; - legacy `interface = "awg0"` remains a compatible fallback. - `mtbuddy` installs `mtproto-tunnel-pool.service` and `mtproto-tunnel-pool.timer`. - `/usr/local/bin/setup_tunnel.sh` now: - brings up all configured pool interfaces; - ensures `fwmark 200 -> table 200`; - probes Telegram through each interface; - switches the route with `ip -4 route replace default dev <iface> table 200`. - The selection policy is priority auto-failback: the first healthy interface in the list becomes active again when it recovers. - Automatic failover does not restart `mtproto-proxy`. ### Tunnel pool setup through mtbuddy ([#250](https://github.com/sleep3r/mtproto.zig/pull/250)) - Re-running `mtbuddy setup tunnel <conf|vpn://>` appends the next free `awgN`. - Added `--iface <name>` to install or replace a specific pool member. - The interactive wizard now shows: - VPN type selection (AmneziaWG for now); - the current tunnel pool; - an action choice: create a new tunnel or replace an existing one. - Configs are stored as `/etc/amnezia/amneziawg/<iface>.conf`. - Input sanitizing is explicit: `DNS` is removed, empty AWG assignments are removed, and `Table = off` is added. ### Runtime and dashboard know the active tunnel ([#250](https://github.com/sleep3r/mtproto.zig/pull/250)) - `Config` parses `interfaces` and `pinned_interface` alongside the legacy `interface`. - MiddleProxy metadata refresh no longer assumes one legacy interface; it resolves the active tunnel from table 200 / pool state. - The dashboard routing card shows the ordered pool, active route, pinned interface, last switch, health reason, and per-interface probe status. - Dashboard `Set iface` is now a `Pin` action: it writes `pinned_interface`, invokes the pool controller once, and does not restart the proxy. - `/api/stats.routing` now exposes pool/active/pinned/health state. ### Documentation and UX ([#250](https://github.com/sleep3r/mtproto.zig/pull/250), [#252](https://github.com/sleep3r/mtproto.zig/pull/252)) - Added `README.ru.md`. - The README language switcher near the top is now easier to spot. - Docker documentation is more explicit: containers are useful for testing, packaging, and simple runs, but the main production path is a native Linux host managed by `mtbuddy`. - README now documents the tunnel pool, `pinned_interface`, dashboard monitoring/pinning, and the Telegram calls / non-Premium media limitations without MiddleProxy. - `config.toml.example` now includes the ordered tunnel pool fields. - `THREAT_MODEL.md` documents the calls/media limitations. ## Verified - `python3 -m py_compile src/ctl/dashboard_assets/server.py` - `node --check src/ctl/dashboard_assets/static/app.js` - generated tunnel controller script checked with `bash -n` - `zig build test` - `zig build -Dtarget=x86_64-linux` - `git diff --check` </details> ## Changelog * feat: add tunnel pool failover and localized docs ([#250](https://github.com/sleep3r/mtproto.zig/pull/250)) ([6eb7dff](https://github.com/sleep3r/mtproto.zig/commit/6eb7dffa92af499793a304c69236a427027386f4)) * docs: highlight README language switcher ([#252](https://github.com/sleep3r/mtproto.zig/pull/252)) ([d0611b3](https://github.com/sleep3r/mtproto.zig/commit/d0611b3140cf343c33f973641a7c2e8402843cb3)) * chore(main): release 0.23.0 ([#251](https://github.com/sleep3r/mtproto.zig/pull/251)) ([beaa437](https://github.com/sleep3r/mtproto.zig/commit/beaa437a22aba91f91d528fa850d66be4b3bfde3))
Related Repositories
lightpanda-io/browser★ 36,855
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,195
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)