Files
utun2/USER_MANUAL.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

785 lines
26 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 — Руководство пользователя
uTun — децентрализованная VPN-система с шифрованием, надёжной доставкой данных, поддержкой mesh-сетей и встроенным TCP-прокси. Работает поверх UDP (основной транспорт) и TCP (STCP-резерв). Всё шифруется через X25519 + AES-128-CCM. Топология узлов обменивается автоматически (BGP-подобный протокол).
---
## 1. Быстрый старт
### 1.1. Сборка
```bash
git clone <репозиторий> && cd utun3
./build.sh --full -j4 # autoreconf + configure + make
```
Зависимости: `gcc`, `make`, `autotools` (autoconf/automake/libtool), `OpenSSL` (libssl-dev).
### 1.2. Генерация ключей
Ключи генерируются автоматически, если их нет в конфиге. Достаточно указать `my_node_name` — `config_updater` создаст пару X25519 и node_id:
```ini
[global]
my_node_name=my-first-node
```
После первого запуска ключи пропишутся в конфиг автоматически.
### 1.3. Первый запуск
```bash
sudo ./src/utun -f -c myconfig.conf
```
- `-f` — foreground (без демонизации, видно логи в консоли)
- `-c myconfig.conf` — путь к конфигу
- `-p /var/run/utun.pid` — PID-файл
- `-l /var/log/utun.log` — лог-файл
Без `-f` процесс уходит в демон (`fork` + `setsid`).
### 1.4. Проверка работы
```bash
ip addr show tun3 # TUN-интерфейс создан?
ping 10.23.1.1 # пингуем TUN-IP узла
ss -uln | grep 1333 # UDP-сокет слушает?
```
---
## 2. Архитектура (кратко)
uTun — **однопоточная асинхронная** система. Один event loop (`epoll`/`poll`) на поток. Никаких `sleep()`, никакого блокирующего I/O.
**Стек протоколов (5 уровней):**
| Уровень | Назначение |
|---------|------------|
| 1. UDP/TUN/STCP | Физический транспорт: UDP-сокеты, TUN-интерфейс, TCP-резерв |
| 2. secure_channel | X25519 ECDH + AES-128-CCM шифрование + Ed25519 подписи |
| 3. ETCP | Надёжный транспорт (inflight, ACK, ретрансмиссии, BBR congestion control) |
| 4. LoadBalancer | Multi-link балансировка (min inflight + round-robin) |
| 5. etcp_router | Сервисная маршрутизация (seq, dedup, reorder, transit forwarding) |
Два уровня надёжности:
- **ETCP** — per-connection, RTT-based ретрансмиссии
- **etcp_router** — per-service, 300ms ретрансмиссии с 17 попытками (~5 сек)
Node identity: `SHA256(private_key)` → первые 8 байт → 63-bit `node_id`.
---
## 3. Конфигурация
Формат: INI-style. Секции `[section]`, строки `key=value`, комментарии `#`.
### 3.1. `[global]` — Идентичность и базовые настройки
```ini
[global]
my_node_name=home-server # имя узла (человекочитаемое)
my_node_id=5f75c7445af88e1f # ID узла (авто-генерируется)
my_private_key=d065b784...4fe441 # X25519 приватный ключ (hex, 64 символа)
my_public_key=86b51a8b...6a2d19 # X25519 публичный ключ (hex, 64 символа)
tun_enabled=yes # создавать TUN-интерфейс (по умолчанию yes)
tun_ifname=tun3 # имя TUN (по умолчанию tun0)
tun_ip=10.23.1.1 # IP на TUN-интерфейсе
mtu=1500 # MTU для всех соединений
debug_level=error # глобальный уровень отладки (none/error/warn/info/debug/trace)
log_file=/var/log/utun.log # путь к лог-файлу
```
### 3.2. `[server:NAME]` — Локальные UDP-сокеты
```ini
[server: lan1]
addr=192.168.1.10:1333 # IP:порт для приёма входящих
type=public # public / nat / private / local
transport=udp # udp (по умолчанию) или tcp (STCP)
mtu=1400 # MTU для этого канала
so_mark=100 # SO_MARK для policy routing
netif=eth0 # привязка к интерфейсу
only_local=0 # 1 = только локальные подключения
```
Типы адресов:
- `public` — узел на публичном IP (прямая связь)
- `nat` — узел за NAT (нужен NAT traversal)
- `private` — локальная сеть (только соседи в том же сегменте)
- `local` — только loopback/локальные подключения
### 3.3. `[client:NAME]` — Подключение к удалённым узлам
```ini
[client: aeza]
link=lan1:85.192.42.96:1333 # server_name:ip:port (можно несколько link=)
link=lan1:85.192.42.96:1433 # второй канал к тому же узлу
peer_public_key=0206dbee...fbcc16 # публичный ключ удалённого узла
keepalive=1 # интервал keepalive (сек)
```
Формат `link`: `локальный_сервер:удалённый_ip:удалённый_порт`. Серверная секция должна быть объявлена выше по файлу.
### 3.4. `[routing]` — Маршруты
```ini
[routing]
my_subnet=10.23.1.0/24 # своя подсеть — анонсируется соседям через BGP
route_subnet=10.23.0.0/16 # добавляется в системную таблицу маршрутов через TUN
route_subnet=fd00:1234::/32 # IPv6-подсеть
```
### 3.5. `[debug]` — Настройка отладки
Формат: `категория=уровень`. Уровни: `none`, `error`, `warn`, `info`, `debug`, `trace`.
```ini
[debug]
etcp=trace # всё про ETCP
crypto=info # криптографические операции
bgp=info # обмен топологией
connection=info # сокеты и линки
general=info # общая информация
```
Основные категории (всего 26): `uasync`, `ll_queue`, `connection`, `etcp`, `crypto`, `memory`, `timing`, `config`, `tun`, `routing`, `timers`, `normalizer`, `bgp`, `socket`, `control`, `dump`, `traffic`, `debug`, `general`, `nat`, `keepalive`, `etcпroute`, `bbr`, `etcp_dump`.
### 3.6. `[firewall]` — Правила фильтрации
```ini
[firewall]
allow=all # разрешить всё (bypass)
allow=192.168.1.0/24 # разрешить подсеть
allow=10.0.0.1:80 # разрешить конкретный IP:порт
```
### 3.7. `[nat]` — EIM NAT
```ini
[nat]
nat_enabled=yes
nat_tun_ifname=tun_external # внешний TUN (выход в интернет)
nat_via=gateway_ip # шлюз
port_start=10000
port_end=20000
forward=tcp:10.0.0.5:80:8080 # проброс: протокол:ip:внутр_порт:внеш_порт
```
### 3.8. `[tcp_proxy_client]` / `[tcp_proxy_server]` — TCP-прокси
**Клиент (выход через exit-узел):**
```ini
[tcp_proxy_client]
enabled=yes
tun_name=tun_proxy # имя TUN для прокси-трафика
tun_ip=10.200.30.1 # IP клиентского TUN
via_node=50e9e88658e91977 # node_id exit-узла
socks_enabled=yes # встроенный SOCKS5-прокси
socks_addr=127.0.0.1:1082 # слушать SOCKS5 здесь
http_proxy_enabled=yes # встроенный HTTP CONNECT-прокси
http_proxy_addr=127.0.0.1:8080
```
**Exit-узел (сервер):**
```ini
[tcp_proxy_server]
enabled=yes
```
Клиент настраивает браузер на SOCKS5 `127.0.0.1:1082` — весь TCP-трафик идёт через exit-узел.
### 3.9. `[control]` — Сервер мониторинга
```ini
[control]
control_ip=192.168.29.117 # IP для приёма подключений etcpmon
control_port=9090
control_allow=192.168.0.0/16 # разрешённые подсети (можно несколько)
```
### 3.10. `[allowed_keys]` — Ограничение подключений
```ini
[allowed_keys]
allow_all=1 # разрешить все ключи
# key=86b51a8b...6a2d19 # разрешить конкретный pubkey
```
### 3.11. `[ntp]` — Синхронизация времени
```ini
[ntp]
enabled=yes
server=pool.ntp.org
server=time.google.com
interval=3600 # интервал синхронизации (сек)
```
### 3.12. `[network:NAME]` — Именованные сети
```ini
[network: mynet]
id=5f75c7445af88e1f # 56-bit ID сети
pubkey=86b51a8b...6a2d19 # публичный ключ сети
signing_key=d065b784...4fe441 # ключ подписи (Ed25519)
```
### 3.13. Серверный vs клиентский конфиг
| Параметр | Сервер | Клиент |
|----------|--------|--------|
| `[server]` секция | Обязательна (свои сокеты) | Обязательна (свои сокеты) |
| `[client]` секция | Нет | Обязательна (к кому подключаться) |
| `peer_public_key` | Нет | Обязателен в `[client]` |
| `my_private_key` | Свой | Свой |
| `my_public_key` | Свой | Свой |
Важно: `[server]` обязателен в **обоих** случаях — это рабочий сокет узла. Клиент дополнительно указывает `[client]` с `peer_public_key` и `link`.
---
## 4. Сценарии использования
### 4.1. VPN между двумя узлами
**Сервер** (публичный IP `85.192.42.96`):
```ini
[global]
my_node_name=server
my_private_key=<hex>
my_public_key=<hex>
tun_ip=10.23.1.1
[server: main]
addr=85.192.42.96:1333
type=public
[routing]
my_subnet=10.23.1.0/24
```
**Клиент** (за NAT, подключается к серверу):
```ini
[global]
my_node_name=client
my_private_key=<hex>
my_public_key=<hex>
tun_ip=10.23.2.1
[server: uplink]
addr=0.0.0.0:1333 # можно 0.0.0.0 — клиенту не нужен фиксированный порт
type=nat
[client: server]
link=uplink:85.192.42.96:1333
peer_public_key=<pubkey_сервера>
keepalive=1
[routing]
my_subnet=10.23.2.0/24
```
**Проверка связности:**
```bash
# На сервере
ping 10.23.2.1
# На клиенте
ping 10.23.1.1
```
### 4.2. Mesh-сеть из нескольких узлов
Каждый узел = сервер (свои сокеты) + клиент (подключения к соседям). Пример для узла B, который подключается к A и C:
```ini
[global]
my_node_name=node-b
my_private_key=<hex>
my_public_key=<hex>
tun_ip=10.23.2.1
[server: main]
addr=0.0.0.0:1333
type=public
[client: node-a]
link=main:85.192.42.96:1333
peer_public_key=<pubkey_A>
[client: node-c]
link=main:203.0.113.10:1333
peer_public_key=<pubkey_C>
[routing]
my_subnet=10.23.2.0/24
```
Что происходит автоматически:
1. B устанавливает ETCP-соединения с A и C
2. Через BGP A узнаёт о подсетях C (и наоборот)
3. Узел A может отправлять пакеты к подсети C через B (transit forwarding)
4. `etcp_router` обеспечивает надёжную маршрутизацию через промежуточные узлы
### 4.3. Exit-прокси (выход в интернет через удалённый узел)
**Exit-узел** (с прямым выходом в интернет):
```ini
[global]
my_node_name=exit-node
my_private_key=<hex>
my_public_key=<hex>
[server: main]
addr=85.192.42.96:1333
type=public
[tcp_proxy_server]
enabled=yes
```
**Клиент** (выходит в интернет через exit-узел):
```ini
[global]
my_node_name=client
my_private_key=<hex>
my_public_key=<hex>
[server: main]
addr=0.0.0.0:1333
[client: exit]
link=main:85.192.42.96:1333
peer_public_key=<pubkey_exit>
[tcp_proxy_client]
enabled=yes
tun_name=tun_proxy
tun_ip=10.200.30.1
via_node=<node_id_exit>
socks_enabled=yes
socks_addr=127.0.0.1:1082
```
Настройка браузера: SOCKS5 proxy `127.0.0.1:1082`. TCP-трафик идёт: браузер → SOCKS5 → lwIP → ETCP → exit-узел → интернет.
### 4.4. EIM NAT (раздача интернета через NAT)
```ini
[nat]
nat_enabled=yes
nat_tun_ifname=eth0 # внешний интерфейс
port_start=20000
port_end=30000
forward=tcp:192.168.1.100:80:8080 # проброс порта 8080 → 192.168.1.100:80
forward=udp:192.168.1.100:53:53 # проброс DNS
```
### 4.5. Чат (chatgui)
Chatgui — десктопный GUI-чат (Qt 6) со встроенным uTun-узлом. Вся связь — напрямую между узлами (P2P), без центральных серверов.
**Сборка:**
```bash
sudo apt install librlottie-dev zlib1g-dev qt6-base-dev
cd tools/chatgui && mkdir -p build && cd build
cmake .. && make -j4
./chatgui
```
**Запуск:**
```bash
setsid env DISPLAY=:1.0 QT_ACCESSIBILITY=1 ./chatgui & disown
```
Chatgui работает в двух потоках:
- **GUI-поток** — Qt, отрисовка, чтение из SQLite
- **uasync-поток** — uTun-узел, сеть, криптография, ETCP, запись в SQLite
**Основные возможности:**
- Создание каналов и групп
- Обмен сообщениями с анимированными эмодзи (TGS)
- Invite-ссылки (`utun://...`) с QR-кодами
- P2P синхронизация через Merkle-деревья
- Авто-подключение к известным узлам из БД
---
## 5. Топология сети
### 5.1. Типы адресов
| Тип | Описание | Пример |
|-----|----------|--------|
| `INTERFACE` | Адрес на сетевом интерфейсе | `eth0: 192.168.1.10` |
| `NAT` | Внешний адрес после NAT (детектируется) | `85.192.42.96:54321` |
| `REAL` | Публичный адрес (совпадает interface == NAT) | `85.192.42.96:1333` |
### 5.2. Как узлы находят друг друга
1. **Прямое подключение** — через `[client]` секцию с явным IP:портом
2. **BGP-обмен** — при подключении к одному узлу, узнаёшь о всех его соседях
3. **Локальное сканирование** — `conn_mgr` периодически сканирует локальную сеть
4. **Invite-ссылки** — `utun://` ссылки с закодированными адресами и ключами
### 5.3. NAT traversal
`conn_mgr` реализует трёхфазное подключение:
1. **DIRECT** (5 сек) — прямое INIT-рукопожатие со всеми известными адресами
2. **REVERSE** (15 сек) — если клиент за NAT, сервер с прямым IP: клиент шлёт свои адреса через BGP, сервер подключается сам
3. **INDIRECT** (15 сек) — оба за NAT: выбираются общие кандидаты-посредники по min RTT, трафик идёт через `etcp_router`
Типы NAT, которые определяет uTun:
- **EIM** (Endpoint-Independent Mapping) — один внешний порт для всех назначений
- **Strict** (Address/Restricted/Symmetric) — разные порты
### 5.4. Группы
Два типа групп:
- **UTUN** (`group_id=0x8000000000000000`) — VPN-сеть: обмен подсетями, маршруты
- **CHAT** — чат-группа: только узлы, без подсетей, персистентность в SQLite
Узлы разных групп изолированы.
---
## 6. Мониторинг и отладка
### 6.1. Уровни отладки
```
none < error < warn < info < debug < trace
```
Настройка через `-d` в CLI (имеет приоритет) или секцию `[debug]` в конфиге:
```bash
./src/utun -f -c myconfig.conf -d "etcp=trace,crypto=info"
```
Или эквивалент в конфиге:
```ini
[debug]
etcp=trace
crypto=info
bgp=info
```
### 6.2. Категории отладки (26 шт)
| Категория | Что логирует |
|-----------|-------------|
| `etcp` | Протокол ETCP: очереди, retrans, ACK, RTT |
| `crypto` | Шифрование/дешифрование, ключи, nonce |
| `connection` | Сокеты, линки, INIT handshake, keepalive |
| `bgp` | Обмен топологией (NODEINFO, WITHDRAW) |
| `routing` | Таблица маршрутов, поиск путей |
| `tun` | TUN-интерфейс: чтение/запись |
| `traffic` | Данные трафика |
| `general` | Общая информация |
| `bbr` | BBR congestion control |
| `keepalive` | Адаптивный keepalive |
| `memory` | Выделение/освобождение памяти |
| `dump` | Hex-дампы пакетов |
| `etcp_dump` | Декодирование ETCP-пакетов |
### 6.3. etcpmon — Windows GUI монитор
Подключается к `control_server` узла по TCP (порт из `control_port`). Показывает:
- Список соединений и их состояние
- RTT, потери, inflight
- Графики метрик
- Дамп пакетов
### 6.4. control_server — TCP API
```ini
[control]
control_ip=0.0.0.0
control_port=9090
control_allow=192.168.0.0/16
```
Любой TCP-клиент может подключиться и получать события в реальном времени (JSON-подобный формат).
### 6.5. Логи и дампы
Лог-файл указывается через `-l`:
```bash
./src/utun -f -c myconfig.conf -l /tmp/utun.log
```
Hex-дамп пакетов включается категорией `dump=trace`:
```ini
[debug]
dump=trace
```
---
## 7. NAT и Firewall
### 7.1. Как uTun определяет тип NAT
1. Клиент подключается к серверу
2. Сервер видит внешний IP:порт клиента (из UDP-пакета)
3. Сервер через **третий узел** (посредник) пингует клиента на этот внешний IP:порт
4. Если клиент ответил — NAT EIM (один mapping для всех)
5. Если нет — NAT Strict
Результат сохраняется в `link->nat_type` и broadcast-ится всем соседям через BGP.
### 7.2. Firewall
```ini
[firewall]
allow=all # всё разрешено
allow=10.0.0.0/8 # разрешить подсеть
allow=192.168.1.5:22 # разрешить IP:порт
```
По умолчанию без секции `[firewall]` — фильтрация выключена.
### 7.3. Проброс портов
```ini
[nat]
forward=tcp:192.168.1.100:80:8080 # входящий порт 8080 → 192.168.1.100:80
forward=udp:10.0.0.53:53:53 # DNS
```
---
## 8. Устранение неполадок
### 8.1. Нет связи — проверка INIT handshake
Включите:
```ini
[debug]
connection=debug
crypto=debug
```
В логах ищите:
- `INIT_REQUEST sent to ...` / `INIT_RESPONSE received from ...` — handshake
- `session_ready=1` — ключи согласованы, шифрование работает
- `ETCP_KEEPALIVE` — keepalive-пакеты идут
- Если нет — проверьте firewall на портах, доступность IP
### 8.2. Пакеты теряются — проверка метрик
```bash
# В логах с etcp=debug смотрите:
grep "retrans" /tmp/utun.log # ретрансмиссии
grep "rtt=" /tmp/utun.log # задержки
grep "lost" /tmp/utun.log # потери
```
Каждые 10 минут пишутся гистограммы метрик с RTT-бакетами и loss-бакетами.
### 8.3. Высокая задержка — keepalive
Адаптивный keepalive: период растёт от 200ms до 10s при отсутствии трафика, сбрасывается к 200ms при появлении. Таймаут = период × 10.
Проверьте:
```ini
[debug]
keepalive=debug
```
### 8.4. Утечки памяти — проверка пулов
```ini
[debug]
memory=debug
```
При завершении `u_report_unfreed_blocks()` показывает все неосвобождённые блоки.
### 8.5. Дамп состояния
ETCP предоставляет функцию `etcp_dump_all_conns()` для вывода полного состояния всех соединений (очереди, inflight, счётчики). Включается через `etcp_dump=trace`.
### 8.6. ASAN-сборка (поиск повреждений памяти)
```bash
./build.sh --asan -j4
ASAN_OPTIONS=detect_leaks=0:halt_on_error=0 ./src/utun -f -c myconfig.conf
```
Краш-логи ASAN пишутся в `/tmp/utun_asan.<pid>`.
---
## 9. Производительность
### 9.1. BBR congestion control
BBR работает per-link. Основные настройки:
```ini
[global]
bbr_max_cwnd=1048576 # максимум окна перегрузки (1MB по умолчанию)
```
BBR автоматически измеряет пропускную способность через burst-измерения (12 пакетов пачкой, замер inter-packet gap). Периодичность burst — не чаще 500ms.
### 9.2. Memory pools
Три пула в `UTUN_INSTANCE`:
- `data_pool` — данные пакетов (payload)
- `pkt_pool` — `struct ETCP_DGRAM` (сетевые пакеты)
- `ack_pool` — `struct ACK_PACKET` (подтверждения)
Пулы аллоцируются upfront при старте. Статистику можно посмотреть через control_server.
### 9.3. Multi-link балансировка
LoadBalancer выбирает линк с минимальным inflight, с round-robin для равных. Traffic shaper ограничивает отправку до `optimal_inflight`:
```
timeout = (rtt_avg_10 * 32 + jitter * 32) / 16
```
Оптимальное окно: `optimal_inflight = sum(inflight_lim_bytes)`
### 9.4. Keepalive
Адаптивный режим:
- Начальный период = `keepalive` из `[client]` (сек)
- При трафике → сброс к начальному
- Без трафика → растёт ×1.05 до 10 секунд
- Таймаут = период × 10
---
## 10. CLI-справка
```
utun [опции]
Опции:
-f Foreground (без демонизации)
-c FILE Конфигурационный файл (по умолчанию: utun.conf)
-p FILE PID-файл (по умолчанию: /var/run/utun.pid)
-l FILE Лог-файл (по умолчанию: utun.log)
-d CONFIG Отладка: категория=уровень,... (переопределяет конфиг)
-h Справка
```
**Сигналы:**
- `SIGTERM` / `SIGINT` — graceful shutdown (закрытие соединений, освобождение ресурсов)
- `SIGHUP` — reload конфига (селективный: меняются только изменённые сокеты/клиенты; полный — при изменении ключей или TUN)
---
## 11. Типовые конфигурации
### Минимальный сервер
```ini
[global]
my_node_name=server
tun_ip=10.23.1.1
[server: main]
addr=0.0.0.0:1333
```
### Минимальный клиент
```ini
[global]
my_node_name=client
tun_ip=10.23.2.1
[server: main]
addr=0.0.0.0:1333
[client: server]
link=main:85.192.42.96:1333
peer_public_key=<pubkey_сервера>
```
### Mesh-узел с несколькими пирами
```ini
[global]
my_node_name=mesh-node-3
tun_ip=10.23.3.1
[server: main]
addr=0.0.0.0:1333
[client: node-1]
link=main:10.0.0.1:1333
peer_public_key=<pubkey_1>
[client: node-2]
link=main:10.0.0.2:1333
peer_public_key=<pubkey_2>
[routing]
my_subnet=10.23.3.0/24
```
### Exit-узел с TCP-прокси
```ini
[global]
my_node_name=exit-eu
tun_ip=10.23.100.1
[server: main]
addr=85.192.42.96:1333
type=public
[tcp_proxy_server]
enabled=yes
[routing]
my_subnet=10.23.100.0/24
```
### Клиент с SOCKS5-прокси
```ini
[global]
my_node_name=home-laptop
[server: main]
addr=0.0.0.0:1333
[client: exit]
link=main:85.192.42.96:1333
peer_public_key=<pubkey_exit>
[tcp_proxy_client]
enabled=yes
socks_enabled=yes
socks_addr=127.0.0.1:1082
via_node=<node_id_exit>
```