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

3.8 KiB

EIM NAT (Endpoint-Independent Mapping NAT)

1. Назначение

Трансляция сетевых адресов с endpoint-independent поведением: для каждого кортежа (внутренний IP, внутренний порт, протокол) выделяется уникальный внешний порт на шлюзе, не зависящий от внешнего адресата. Поддерживает TCP, UDP и ICMP Echo. Инкрементальный пересчёт контрольных сумм.

2. Как пользоваться

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.

Конфиг:

[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)