- 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
48 lines
3.8 KiB
Markdown
48 lines
3.8 KiB
Markdown
# EIM NAT (Endpoint-Independent Mapping NAT)
|
|
|
|
## 1. Назначение
|
|
Трансляция сетевых адресов с endpoint-independent поведением: для каждого кортежа `(внутренний IP, внутренний порт, протокол)` выделяется уникальный внешний порт на шлюзе, не зависящий от внешнего адресата. Поддерживает TCP, UDP и ICMP Echo. Инкрементальный пересчёт контрольных сумм.
|
|
|
|
## 2. Как пользоваться
|
|
```c
|
|
struct eim_nat_ctx nat;
|
|
eim_nat_init_ctx(&nat, &global_cfg); // таблица 64K записей
|
|
eim_nat_egress(&nat, pkt, len, node_id, conn); // src IP/port -> внешние
|
|
eim_nat_ingress(&nat, pkt, len, &entry); // dst IP/port -> внутренние
|
|
eim_nat_add_forward(&nat, proto, ip, port, ext_port); // статический проброс
|
|
eim_nat_destroy_ctx(&nat);
|
|
```
|
|
|
|
**Таблица:** 64K записей, индексируется по внешнему порту (внешний порт == индекс в таблице).
|
|
|
|
**eim_nat_egress:** выделяет внешний порт (аллоцирует из циклического пула `next_port`), заменяет src IP на шлюзовой и src порт на внешний, корректирует IP- и транспортную контрольные суммы. Фрагментированные пакеты пропускаются без обработки.
|
|
|
|
**eim_nat_ingress:** ищет запись по внешнему dst-порту в таблице, заменяет dst IP на внутренний и dst порт на внутренний, корректирует контрольные суммы. Возвращает `out_entry` — указатель на запись (содержит `src_node_id` и `src_conn` для маршрутизации ответа).
|
|
|
|
**eim_nat_add_forward:** добавляет статическую запись (`EIM_NAT_ENTRY_STATIC`), которая не вытесняется динамическими.
|
|
|
|
**Контрольные суммы:** пересчитываются инкрементально через `csum_update_n()` — старые значения вычитаются из ~csum, новые прибавляются. Это работает для TCP pseudo-header checksum и UDP.
|
|
|
|
**Конфиг:**
|
|
```ini
|
|
[nat]
|
|
enabled = 1
|
|
tun_ip = 10.0.0.1
|
|
port_start = 10000
|
|
port_end = 20000
|
|
[nat_forward]
|
|
rule = tcp 192.168.1.2:80 :8080
|
|
```
|
|
|
|
## 3. API
|
|
|
|
| Функция/Структура | Описание |
|
|
|---|---|
|
|
| `struct eim_nat_entry` | Запись: internal_ip, internal_port, proto, state (FREE/ACTIVE/STATIC), src_node_id, src_conn, last_seen |
|
|
| `struct eim_nat_ctx` | Контекст: gateway_ip, port_start/end, next_port (циклический аллокатор), table[64K], initialized |
|
|
| `eim_nat_init_ctx(ctx, cfg)` | Инициализация таблицы, загрузка статических пробросов из конфига |
|
|
| `eim_nat_destroy_ctx(ctx)` | Освобождение таблицы, обнуление |
|
|
| `eim_nat_egress(ctx, ip_data, ip_len, src_node_id, src_conn)` | Трансляция исходящего пакета: src IP/port → шлюзовые. Создаёт динамическую запись при первом проходе |
|
|
| `eim_nat_ingress(ctx, ip_data, ip_len, out_entry)` | Обратная трансляция входящего пакета: dst IP/port → внутренние. Заполняет out_entry для маршрутизации |
|
|
| `eim_nat_add_forward(ctx, proto, ip_host, port_net, ext_port)` | Добавление статического проброса (runtime API) |
|