Files
utun2/utun.md
T
evgeny 38c9f229bc stcp: ed25519 pubkey exchange in handshake, fix instance destroy segfault, fix chat_tcp_test
- u_async.c: process immediate_queue BEFORE epoll_wait in uasync_poll
- stcp_link.c: defensive NULL etcp_conn/etcp_link in stcp_link_close
- utun_instance.c: move stcp_server_list_destroy_all to Phase J (before ETCP),
  add deferred drain in both Phase J and L
- stcp.h/c: STCP_HS_ENC_CLIENT 6→38, STCP_HS_ENC_SERVER 7→39,
  exchange ed25519_pubkey in both handshake directions
- etcp_connections.c: copy peer_ed25519 from STCP to ETCP_CONN in
  etcp_link_enter_ready_tcp; guard link->etcp in tcp_link_close_cb
- chat_sync.c: fix lk->conn NULL dereference for TCP links
- test_stcp.c: update stcp_server_create/stcp_client_connect callsites
- tools/chat_tcp_test: change transport udp→tcp
2026-08-07 00:48:27 +03:00

219 lines
9.4 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# uTun — защищённый VPN-туннель поверх UDP
uTun создаёт виртуальный TUN-интерфейс и маршрутизирует IP-трафик через зашифрованные UDP-каналы по протоколу **ETCP** (Extended TCP) — комбинация TCP-надёжности + QUIC-мультиплексирования + multi-link балансировки.
## Возможности
| Возможность | Описание |
|---|---|
| **Шифрование** | X25519 обмен ключами + AES-128-CCM с аутентификацией |
| **Целостность** | CRC32 внутри зашифрованного payload |
| **Multi-link** | Одно подключение через несколько UDP-каналов одновременно |
| **Балансировка** | Выбор канала с минимальным inflight + round-robin при равенстве |
| **Bandwidth shaping** | Ограничение полосы на каждом канале с автооценкой |
| **Inflight control** | Динамическое ограничение байт в полёте для предотвращения перегрузки |
| **Retransmission** | Адаптивный таймаут: RTT_avg × k₁ + jitter × k₂ |
| **Keepalive** | Двусторонний, с настраиваемым интервалом и таймаутом |
| **Фрагментация/сборка** | Normalizer: упаковка мелких пакетов вместе, разбиение крупных |
| **Маршрутизация** | Локальная (через TUN + системные маршруты) и распределённая (BGP-обмен) |
| **NAT-детекция** | Определение типа NAT (open/restricted) через ping-пробы |
| **Файрвол** | Белый список IP:port для трафика через туннель |
| **Control server** | TCP-сервер для мониторинга метрик в реальном времени (GUI-клиент) |
| **Горячая перезагрузка** | SIGHUP — выборочное обновление конфига (сравнение сокетов/клиентов/линков) |
| **Авто-ключи** | При первом запуске генерирует X25519-пару и node_id, записывает в конфиг |
| **Демонизация** | fork/setsid на Linux; foreground-режим `-f` для отладки |
| **Кроссплатформенность** | Linux (epoll), Windows (wintun), FreeBSD |
| **Эмуляция потерь** | `loss_rate=N` в конфиге сокета — для тестирования |
## Архитектура (кратко)
```
Приложение/ОС
↓ IP-пакеты
TUN interface (tun_if)
↓ queue
Routing (routing.c) — поиск маршрута
↓ (если удалённый)
Normalizer (pkt_normalizer.c) — фрагментация/упаковка
↓
ETCP (etcp.c) — seq/ack, retransmit, reassembly
↓
LoadBalancer (etcp_loadbalancer.c) — выбор канала
↓
Encrypt + UDP send (etcp_connections.c)
↓
Сеть (UDP)
```
## Конфигурация (INI-формат)
### CLI-запуск
```
utun -c utun.conf [-p /var/run/utun.pid] [-l utun.log] [-f] [-d "etcp:debug"]
```
- `-c` — путь к конфигу (по умолчанию `utun.conf`)
- `-p` — PID-файл
- `-l` — лог-файл (по умолчанию `utun.log`)
- `-f` — foreground (не демонизироваться)
- `-d` — отладочный конфиг на лету, формат: `"категория:уровень,..."`
### Секции конфига
#### `[global]` — основные параметры
| Ключ | Значение | По умолчанию |
|---|---|---|
| `my_node_name` | Имя узла (до 15 символов) | — |
| `my_node_id` | 64-битный ID узла (hex, 16 символов) | авто |
| `my_private_key` | Приватный ключ X25519 (64 hex символа) | авто |
| `my_public_key` | Публичный ключ X25519 (64 hex символа) | авто |
| `tun_ifname` | Имя TUN-интерфейса | `tun0` |
| `tun_ip` | IP-адрес TUN-интерфейса | — |
| `mtu` | MTU для всех подключений | `1500` |
| `keepalive_timeout` | Таймаут keepalive (мс) | `2000` |
| `keepalive_interval` | Интервал keepalive (мс) | `200` |
| `log_file` | Путь к лог-файлу | — |
| `debug_level` | Уровень отладки: `error`, `warn`, `info`, `debug`, `trace` | `error` |
| `tun_test_mode` | 1 — не создавать реальный TUN (тесты) | `0` |
| `enable_timestamp` | Метки времени в логах | `1` |
| `enable_function_names` | Имена функций в логах | `1` |
| `enable_file_lines` | Файл:строка в логах | `0` |
| `enable_colors` | ANSI-цвета в терминале | `0` |
#### `[debug]` — по-категорийные уровни (переопределяют `debug_level`)
Доступные категории:
`uasync`, `ll_queue`, `connection`, `etcp`, `crypto`, `memory`, `timing`, `config`, `tun`, `routing`, `timers`, `normalizer`, `bgp`, `socket`, `general`, `control`, `dump`, `traffic`
Пример:
```ini
[debug]
etcp=info
routing=trace
bgp=trace
crypto=error
```
#### `[server: ИМЯ]` — локальные UDP-сокеты (обязательно хотя бы один)
| Ключ | Значение | По умолчанию |
|---|---|---|
| `addr` | `IP:port` для bind | **обязателен** |
| `type` | `public`, `nat`, `private` | `unknown` |
| `mtu` | MTU для этого сокета | из `[global]` |
| `loss_rate` | % потерь пакетов (0–100) | `0` |
| `so_mark` | Linux SO_MARK для policy routing | — |
| `netif` | Привязка к интерфейсу (по имени) | — |
| `fib` | FreeBSD FIB (таблица маршрутизации) | `-1` (не задан) |
| `only_local` | 1 — только локальные соединения, без forwarding | `0` |
Пример:
```ini
[server: lan1]
addr=192.168.29.117:1333
type=public
```
#### `[client: ИМЯ]` — исходящие подключения к пиру
| Ключ | Значение | По умолчанию |
|---|---|---|
| `link` | `сервер:удалённый_IP:порт` (можно несколько) | **обязателен** |
| `peer_public_key` | Публичный ключ пира (64 hex) | **обязателен** |
| `keepalive` | 1 — включить keepalive | `1` |
Пример:
```ini
[client: aeza]
link=lan1:85.192.42.96:1333
peer_public_key=04c1cae041a8e6bfba5245f6669c73f0793d7f9929300a2ba2e123ca55260d6e47...
```
> **Важно:** в серверном конфиге секции `[client]` нет. В клиентском — есть свои ключи + `peer_public_key` каждого сервера в `[client]`.
#### `[routing]` — маршруты
| Ключ | Значение |
|---|---|
| `route_subnet` | Подсеть, доступная через этот TUN (добавляется в системную таблицу маршрутизации). Можно несколько |
| `my_subnet` | Своя подсеть, анонсируемая через BGP |
Пример:
```ini
[routing]
route_subnet=10.23.0.0/16
route_subnet=10.24.0.0/16
my_subnet=10.23.1.0/24
```
#### `[firewall]` — контроль доступа
| Ключ | Значение |
|---|---|
| `allow` | `all` — разрешить всё. Или `IP` / `IP:port` (можно несколько) |
По умолчанию: deny all (если нет allow=all).
Пример:
```ini
[firewall]
allow=192.168.1.100
allow=10.0.0.0/8:443
```
#### `[control]` — сервер мониторинга
| Ключ | Значение | По умолчанию |
|---|---|---|
| `control_ip` | IP для прослушивания | `127.0.0.1` |
| `control_port` | Порт | — |
| `control_allow` | `IP/mask` (можно несколько) | deny all |
Пример:
```ini
[control]
control_ip=192.168.29.117
control_port=9090
control_allow=192.168.0.0/16
```
#### `[allowed_keys]` — белый список публичных ключей пиров
| Ключ | Значение | По умолчанию |
|---|---|---|
| `allow_all` | 1 — разрешить все ключи | — |
| `key` | Публичный ключ (64 hex, можно несколько) | — |
Поведение:
- Секция отсутствует: разрешить все (совместимость)
- `allow_all=0` + нет ключей: запретить все
- `allow_all=0` + ключи: только перечисленные ключи
Пример:
```ini
[allowed_keys]
key=c6c8a8a9616ffa6cf44d4757e2bc9f7bd78a1d3cbbe75cffaf3cab8885ad48e7677b...
key=04c1cae041a8e6bfba5245f6669c73f0793d7f9929300a2ba2e123ca55260d6e4748...
```
### Пример минимального конфига
```ini
[global]
tun_ip=10.23.1.1
my_node_name=vmL1
my_node_id=5f75c7445af88e1f
my_private_key=d065b784a8386f9b37f07b4c16c3ab83ddce5885e78f79c5d2a6d1f9954fe441
my_public_key=c6c8a8a9616ffa6cf44d4757e2bc9f7bd78a1d3cbbe75cffaf3cab8885ad48e7677b...
[server: lan1]
addr=192.168.29.117:1333
type=public
[routing]
route_subnet=10.23.0.0/16
my_subnet=10.23.1.0/24
```