v1.1.0

sleep3r/mtproto.zigv1.1.0Jun 8, 2026by sleep3r

Upgrading?

AI Summary

Focuses on evasion, access control, and operability by adding new evasion knobs, per-user connection limits, and a one-command network diagnostic tool. The release also enhances the dashboard with tunnel quality metrics and expands installer support to Ubuntu 20.04.

Key Highlights

  • New evasion settings: `unknown_sni_action` and `idle_timeout_jitter_pct`
  • Per-user access limits: max connections and expiration dates
  • Diagnostic command: `mtbuddy config doctor --network`
  • Tunnel Quality dashboard panel with RTT and packet loss metrics
  • Ubuntu 20.04 installer support with minisign fallback

New Features

  • Configurable SNI handling (mask/reject/drop)
  • Per-user connection limits
  • Network diagnostic tool
  • Tunnel Quality dashboard
  • Ubuntu 20.04 support

Full Release Notes

<details open>
<summary>🇷🇺 Что нового (RU)</summary>

## Что решает этот релиз

`v1.1.0` — релиз про **обход, контроль доступа и эксплуатацию**. Он добавляет новые evasion-ручки, пользовательские лимиты для шеринга, диагностику «меня заблокировали?» в одну команду, панель качества туннеля в дашборде и широкое покрытие установщика — включая **Ubuntu 20.04**.

> [!NOTE]
> Все новые настройки **по умолчанию сохраняют текущее поведение** — обновление безопасно, ничего менять в `config.toml` не нужно. Новые возможности включаются явно.

## Обход (evasion)

### `unknown_sni_action` (`[censorship]`, по умолчанию `mask`)
На TLS ClientHello с SNI, не совпадающим с `tls_domain`:
- `mask` — форвардить на маскирующий бэкенд (текущее поведение, защита от активного зондирования);
- `reject` — отдать **фатальный TLS-alert** (`handshake_failure`), как сервер, отклоняющий handshake, и закрыть;
- `drop` — молча закрыть.
Соединения с **правильным** SNI, но провалившие валидацию/replay, по-прежнему маскируются — действие касается только реально чужого SNI.

### `idle_timeout_jitter_pct` (`[server]`, по умолчанию 15)
Константный idle-таймаут сам по себе сигнатура поведения — теперь у каждого соединения он со случайным джиттером ±%, посчитанным один раз при подключении (с полом, чтобы джиттер никогда не делал таймаут патологически коротким).

## Контроль доступа (для шеринга)

- **`[access.user_max_conns]`** — лимит одновременных соединений на пользователя (атомарный приём, без гонок между воркерами).
- **`[access.user_expirations]`** — дата истечения доступа `"YYYY-MM-DD"` на пользователя (включительно по концу дня, строгая валидация календаря).
Удобно раздавать прокси семье/друзьям, не давая одному устройству забить весь канал. Читаются при старте.

## Эксплуатация и UX

- **`mtbuddy config doctor --network` → «меня заблокировали?»**: пробит прямую достижимость DC Telegram (SYN-timeout vs connect отличает L3 IP-блэкхол — текущий RU-блок — но не падает на нём жёстко: вердикт выносит fetch метаданных), пробит Telegram через каждый туннель-интерфейс с RTT, и проверяет наличие tg://-ссылки. «Прокси перестал работать — посмотри» превращается в одну команду с вердиктом.
- **Карта «Tunnel Quality» в дашборде** (`GET /api/egress`, под существующей авторизацией): на каждый туннель-интерфейс — up/down, возраст последнего WG/AWG-handshake, RTT и потери до DC, с подсветкой «узкое место». Высоколатентный туннель теперь **видно**, а не угадываешь. Двуязычно EN/RU.

## Установщик

- **Поддержка Ubuntu 20.04 (focal)**: в focal нет пакета `minisign` в apt, из-за чего установка падала на проверке подписи. Теперь и bootstrap (`curl | bash`), и `mtbuddy install` ставят minisign отдельно: сперва apt, при отсутствии — **закреплённый, проверенный по SHA-256** upstream-бинарь. Fail-closed: без проверяемого minisign установка не идёт (если не `--insecure`).
- **installer-e2e расширен с 2 до 5 ОС**: debian 11/12, ubuntu 20.04/22.04/24.04 — на каждый прогон полная установка + проверка подписи релиза + nfqws + туннель-роутинг.

## Под капотом

- Две идеи из обзора конкурентов **сознательно отброшены** как неверные для нашей архитектуры: ALPN-echo в plaintext-ServerHello (в TLS 1.3 ALPN едет в зашифрованном EncryptedExtensions — plaintext-эхо было бы регрессом-сигнатурой) и app-level ME-keepalive (фича пула соединений; наши per-client ME-соединения уже под TCP-keepalive). Обе — в будущий трек ME-пула.
- Установщик-фоллбэк закалён против гонки в `/tmp` (приватный `mktemp -d`, 0700), найденной адверсариал-обзором.

## Проверено

- `zig build test`, кросс-сборка `x86_64-linux` + `aarch64-linux`, `zig fmt` — зелёные.
- GitHub Actions: `Test & Build`, `E2E Integration`, `Bench`, и **installer-e2e на 5 ОС** (включая ubuntu:20.04 — проверяет minisign-фоллбэк на x86_64).
- Локально (Colima, arm64): сквозная установка на ubuntu:20.04, debian:11, ubuntu:24.04 — проверяет тот же фоллбэк на arm64.
- Два прохода адверсариал-обзора (десятки агентов, find-then-verify) по бандлу и по установщику; подтверждённые находки исправлены.

</details>

---

<details>
<summary>🇬🇧 Release notes (EN)</summary>

## What this release addresses

`v1.1.0` is an **evasion, access-control, and operability** release: new evasion knobs, per-user limits for sharing, a one-command "am I blocked?" diagnostic, a tunnel-quality dashboard panel, and broad installer coverage — including **Ubuntu 20.04**.

> [!NOTE]
> Every new setting **defaults to current behavior** — upgrading is safe and needs no `config.toml` change. New features are opt-in.

## Evasion

### `unknown_sni_action` (`[censorship]`, default `mask`)
For a TLS ClientHello whose SNI doesn't match `tls_domain`:
- `mask` — forward to the masking backend (current behavior; active-probe defense);
- `reject` — send a **fatal `handshake_failure` TLS alert** (like a server refusing the handshake), then close;
- `drop` — close silently.
Connections with the **right** SNI that fail validation/replay still mask — the action only covers a genuinely unknown SNI.

### `idle_timeout_jitter_pct` (`[server]`, default 15)
A constant idle timeout is itself a behavioral signature; each connection now gets a ±% jittered timeout computed once at setup (floored so jitter never shortens it pathologically).

## Access control (for sharing)

- **`[access.user_max_conns]`** — per-user concurrent-connection cap (atomic admission, no cross-worker overshoot).
- **`[access.user_expirations]`** — per-user `"YYYY-MM-DD"` expiry (end-of-day inclusive, strict calendar validation).
Handy for sharing one proxy with family/friends without one device hogging the link. Read at startup.

## Operability & UX

- **`mtbuddy config doctor --network` → "am I blocked?"**: probes direct Telegram-DC reachability (a SYN timeout vs connect distinguishes an L3 IP-blackhole — the current RU block — but doesn't hard-fail on it; the metadata fetch arbitrates), probes Telegram via each tunnel interface with an RTT, and reports tg:// link availability. Turns "the proxy stopped working — check it" into one command with a verdict.
- **Dashboard "Tunnel Quality" card** (`GET /api/egress`, behind the existing auth): per tunnel interface — up/down, last WG/AWG handshake age, RTT and packet loss to a DC, with a bottleneck hint. A high-latency tunnel is now *visible*, not guessed. Bilingual EN/RU.

## Installer

- **Ubuntu 20.04 (focal) support**: focal ships no `minisign` apt package, so installs aborted at signature verification. Now both the bootstrap (`curl | bash`) and `mtbuddy install` acquire minisign separately: apt first, then a **pinned, SHA-256-verified** upstream binary if apt has none. Fails closed: no verifiable minisign → no install (unless `--insecure`).
- **installer-e2e expanded 2 → 5 OSes**: debian 11/12, ubuntu 20.04/22.04/24.04 — each run does a full install + release-signature verification + nfqws + tunnel routing.

## Under the hood

- Two ideas from the competitor survey were **deliberately dropped** as wrong for our architecture: plaintext-ServerHello ALPN echo (TLS 1.3 carries ALPN in the encrypted EncryptedExtensions — a plaintext echo would be a fingerprint regression) and app-level ME keepalive (a connection-pool feature; our per-client middleproxy connections already have tuned TCP keepalive). Both belong with a future ME connection pool.
- The installer fallback was hardened against a `/tmp` TOCTOU (private `mktemp -d`, 0700) caught by adversarial review.

## Verified

- `zig build test`, cross-compilation for `x86_64-linux` + `aarch64-linux`, `zig fmt` — green.
- GitHub Actions: `Test & Build`, `E2E Integration`, `Bench`, and the **5-OS installer-e2e** (incl. ubuntu:20.04 — exercises the minisign fallback on x86_64).
- Locally (Colima, arm64): end-to-end install on ubuntu:20.04, debian:11, ubuntu:24.04 — exercises the same fallback on arm64.
- Two adversarial-review passes (dozens of agents, find-then-verify) over the bundle and the installer; confirmed findings fixed.

</details>

## Changelog

* feat: evasion + robustness + UX bundle (+ Ubuntu 20.04 installer fix) ([#316](https://github.com/sleep3r/mtproto.zig/pull/316)) ([a837d89](https://github.com/sleep3r/mtproto.zig/commit/a837d89))
* test(installer): cover Ubuntu 20.04 + more OSes; minisign fallback in install.zig ([#318](https://github.com/sleep3r/mtproto.zig/pull/318)) ([5806953](https://github.com/sleep3r/mtproto.zig/commit/5806953))

Related Repositories