v0.26.0

sleep3r/mtproto.zigv0.26.0Jun 5, 2026by sleep3r

Upgrading?

AI Summary

Adds an in-process handshake flood guard to block noisy source IPs before allocating connection slots, complementing the existing subnet rate limiter.

Key Highlights

  • New exact-IP handshake flood guard that counts bad events and temporarily denies noisy IPs.
  • New hot-reloadable settings for the guard in the `[server]` configuration section.
  • New metrics `mtproto_drops_flood_guard_total` to monitor guard activity.
  • Logs now expose top noisy source IPs when the guard is active.

New Features

  • Handshake flood guard

Full Release Notes

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

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

`v0.26.0` — feature-релиз для операторов, у которых прокси выглядит «залипшим» из-за входящего handshake flood, хотя tunnel/upstream остаются живыми.

Последний production-инцидент оказался не повтором проблемы с tunnel pool: маршрут через `awg0` был здоров, `core.telegram.org` отвечал, а прокси продолжал принимать TCP. Реальная нагрузка шла снаружи: шумные источники набивали `hs_inflight`, упирали процесс в `hs_budget` и генерировали handshake timeouts. Ручной restart помогал только потому, что очищал накопленное runtime-состояние, но следующий наплыв мог снова привести к той же картине.

`v0.26.0` добавляет in-process handshake flood guard: прокси теперь запоминает плохие handshake-related события по точному source IP и временно отклоняет слишком шумные адреса ещё до выделения connection slot. Это дополняет subnet rate limiter: один агрессивный IP можно притормозить без наказания всего /24 или /48 провайдера.

> [!NOTE]
> Для существующих `config.toml` новые настройки не обязательны: если ключей нет, используются безопасные defaults. При желании их можно добавить вручную в `[server]` и применить через reload/restart.

> [!TIP]
> Если снова видите рост `hs_inflight`, `hs_budget` или `hs_timeout`, смотрите periodic stats: новый лог `flood_guard: ... top{...}` покажет top source IP и смесь событий.

## Что изменено

### Exact-IP handshake flood guard перед slot allocation ([#295](https://github.com/sleep3r/mtproto.zig/pull/295))

- Добавлен новый guard, который считает плохие события по точному client IP.
- В guard попадают:
  - subnet rate-limit drops;
  - handshake-budget drops;
  - handshake timeouts.
- Если IP набирает threshold в заданном окне, он временно блокируется.
- Уже заблокированные IP закрываются сразу после `accept`, до `TCP_NODELAY`, handshake accounting и выделения slot.
- Guard не управляет `iptables`/firewall и не пишет ban state на диск: состояние хранится в памяти процесса и сбрасывается при restart.

### Новые hot-reloadable настройки в `[server]` ([#295](https://github.com/sleep3r/mtproto.zig/pull/295))

```toml
handshake_flood_guard_enabled = true
handshake_flood_guard_threshold = 20
handshake_flood_guard_window_sec = 30
handshake_flood_guard_block_sec = 120
```

- `enabled` включает/выключает guard.
- `threshold` задаёт число плохих событий с одного IP до временного deny.
- `window_sec` задаёт rolling window для подсчёта.
- `block_sec` задаёт длительность временного deny.
- Все значения применяются через текущий config reload path.

### Логи и метрики теперь показывают источник проблемы ([#295](https://github.com/sleep3r/mtproto.zig/pull/295))

- Periodic stats получили новый counter `flood_guard+=...` в строке drops.
- При активности guard логируется top offenders, например:

```text
flood_guard: blocked+=7 top{203.0.113.10=total:42/rate:3/budget:9/timeout:30/blocked:91s}
```

- Prometheus endpoint получил новый counter:

```text
mtproto_drops_flood_guard_total
```

Это помогает быстро отличить upstream/tunnel деградацию от входящего handshake flood.

### Документация и mtbuddy знают новые параметры ([#295](https://github.com/sleep3r/mtproto.zig/pull/295))

- Обновлены `README.md` и `README.ru.md`.
- `mtbuddy install` теперь генерирует config с новыми defaults.
- `mtbuddy config print-effective` показывает текущие значения flood guard.

## Проверено

- `zig build test --summary all` — 161/161 tests passed.
- `zig build -Dtarget=x86_64-linux-gnu --summary all` — 8/8 steps succeeded.
- GitHub Actions:
  - `Test & Build`
  - `Bench (No Soak)`
  - `E2E Integration`
  - installer e2e: `debian:12`
  - installer e2e: `ubuntu:24.04`

</details>

---

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

## What this release addresses

`v0.26.0` is a feature release for operators whose proxy can appear “stuck” under inbound handshake flood even while tunnel/upstream connectivity is healthy.

The latest production incident was not another tunnel pool failure: routing through `awg0` was healthy, `core.telegram.org` responded, and the proxy was still accepting TCP. The pressure came from inbound noisy sources piling up `hs_inflight`, exhausting the handshake budget, and producing handshake timeouts. A manual restart helped only because it cleared runtime state; it did not protect the proxy from the next wave.

`v0.26.0` adds an in-process handshake flood guard: the proxy now tracks bad handshake-related events by exact source IP and temporarily denies noisy addresses before allocating a connection slot. This complements the subnet rate limiter: one aggressive IP can be slowed down without penalizing the entire provider /24 or /48.

> [!NOTE]
> Existing `config.toml` files do not need to be edited immediately: missing keys use safe defaults. Add the new `[server]` keys only if you want to tune the behavior, then reload or restart the service.

> [!TIP]
> If `hs_inflight`, `hs_budget`, or `hs_timeout` rises again, check periodic stats: the new `flood_guard: ... top{...}` line shows the top source IPs and event mix.

## What changed

### Exact-IP handshake flood guard before slot allocation ([#295](https://github.com/sleep3r/mtproto.zig/pull/295))

- Added a new guard that counts bad events per exact client IP.
- The guard records:
  - subnet rate-limit drops;
  - handshake-budget drops;
  - handshake timeouts.
- When an IP crosses the threshold inside the configured window, it is temporarily denied.
- Already denied IPs are closed immediately after `accept`, before `TCP_NODELAY`, handshake accounting, or slot allocation.
- The guard does not manage `iptables`/firewall rules and does not persist ban state to disk: state is in memory and resets on process restart.

### New hot-reloadable `[server]` settings ([#295](https://github.com/sleep3r/mtproto.zig/pull/295))

```toml
handshake_flood_guard_enabled = true
handshake_flood_guard_threshold = 20
handshake_flood_guard_window_sec = 30
handshake_flood_guard_block_sec = 120
```

- `enabled` turns the guard on or off.
- `threshold` controls how many bad events from one IP trigger a temporary deny.
- `window_sec` controls the rolling counting window.
- `block_sec` controls the temporary deny duration.
- All values are applied through the existing config reload path.

### Logs and metrics now expose the noisy source ([#295](https://github.com/sleep3r/mtproto.zig/pull/295))

- Periodic stats now include `flood_guard+=...` in the drops line.
- When the guard is active, top offenders are logged, for example:

```text
flood_guard: blocked+=7 top{203.0.113.10=total:42/rate:3/budget:9/timeout:30/blocked:91s}
```

- The Prometheus endpoint now exports:

```text
mtproto_drops_flood_guard_total
```

This makes it easier to distinguish upstream/tunnel degradation from inbound handshake flood.

### Docs and mtbuddy know the new knobs ([#295](https://github.com/sleep3r/mtproto.zig/pull/295))

- Updated `README.md` and `README.ru.md`.
- `mtbuddy install` now generates configs with the new defaults.
- `mtbuddy config print-effective` now prints the current flood guard values.

## Verified

- `zig build test --summary all` — 161/161 tests passed.
- `zig build -Dtarget=x86_64-linux-gnu --summary all` — 8/8 steps succeeded.
- GitHub Actions:
  - `Test & Build`
  - `Bench (No Soak)`
  - `E2E Integration`
  - installer e2e: `debian:12`
  - installer e2e: `ubuntu:24.04`

</details>

## Changelog

* feat: add handshake flood guard ([#295](https://github.com/sleep3r/mtproto.zig/pull/295)) ([0630632](https://github.com/sleep3r/mtproto.zig/commit/0630632cf3ab67fdd8a3f6e75c2677c8bb744acc))
* chore(main): release 0.26.0 ([#296](https://github.com/sleep3r/mtproto.zig/pull/296)) ([88494ec](https://github.com/sleep3r/mtproto.zig/commit/88494ecfdc796b107224c15ab71c68e5213937c6))

Related Repositories