Files
utun2/src/nat_transport_doc.md
T

10 KiB
Raw Blame History

NAT Transport Layer (nat_transport)

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

Передача IPv4 между отдельным TUN и удалённым NAT-провайдером через сервис ETCP_RT_ID_NAT в группе TOPO_GROUP_UTUN. Провайдер преобразует пакеты движком eim_nat, клиент использует только транспорт. Нормативный API и правила владения описаны в nat_transport.h и eim_nat.h.

2. Конфигурация и поток данных

  • Провайдер (nat_via_node_id = 0): создаёт таблицу eim_nat. В [nat] задаются tun_ifname, tun_ip, port_start, port_end; проброс — forward=udp:node_id_hex:IPv4:internal_port:external_port.
  • Клиент: в [nat] задаётся nat_via=<ID провайдера в HEX> и параметры своего NAT TUN. Таблица eim_nat не создаётся; inst->nat.initialized=1 означает готовность транспорта. Опции секции [nat] включают NAT; параметра enabled нет.
  • Создаётся отдельный nat_tun с TUN_MTU_DEFAULT. Адрес берётся из IPv4 nat_tun_ip, иначе из tun_ip. Маршруты ОС и доступ провайдера в интернет настраиваются отдельно.
  1. Клиент получает [prefix:1][IP] из nat_tun->output_queue. nat_tun_output заменяет prefix на ETCP_RT_ID_NAT и передаёт исходный entry/dgram роутеру с адресатом nat_via_node_id.
  2. Провайдер получает пакет в nat_receive, выполняет eim_nat_egress и пишет чистый IP в NAT TUN.
  3. Ответ/статический проброс из TUN провайдера проходит eim_nat_ingress в nat_tun_output. Преобразованный пакет отправляется узлу из mapping->src_node_id.
  4. Клиент принимает ответ только от своего провайдера, проверяет IPv4 и записывает в свой NAT TUN.

Роутер добавляет source/destination и протокольные заголовки. Callback получает служебный заголовок [svc:1][src:8][dst:8][rx_flags:1][group:8][IP], размером ROUTER_SVC_HDR_SIZE=26. Это формат доставки callback, а не заголовок на проводе. CLOSE/reset без IP освобождается без трансляции. Приём ограничен группой UTUN. Повреждённые пакеты, фрагменты, неподдерживаемые протоколы и входящие пакеты провайдера без mapping отбрасываются. Ограничения проверки и преобразования — в eim_nat.h.

3. Очереди, ожидания и владение

NAT не копирует IP из TUN и не создаёт для него новый пакет. Роутер синхронно копирует payload в свою очередь и принимает владение исходным entry/dgram при любом результате отправки. После передачи роутеру NAT больше не обращается к пакету и не освобождает его повторно.

Для каждого адресата создаётся FIFO и одно отменяемое ожидание готовности router send_q. Адресаты индексируются через хеш ll_queue; выделения требуются при первом обращении к узлу. Перед передачей владения проверяется место в router send_q. При заполнении ожидается on_send_ready. Порядок пакетов одного адресата сохраняется; ожидания разных адресатов независимы.

  • NAT_PENDING_PER_PEER=64 ограничивает дополнительный буфер адресата, включая пакет в активном ожидании. Новый пакет переполненного адресата отбрасывается. Остальные адресаты продолжают обслуживаться. Счётчик потерь обновляется всегда, предупреждения о перегрузке выводятся не чаще раза в секунду.
  • NAT_PENDING_TOTAL=1024 ограничивает сумму дополнительных буферов. При достижении лимита текущий преобразованный пакет возвращается в голову output_queue TUN, callback остаётся приостановленным. Непустая очередь останавливает чтение TUN; освобождение места возобновляет callback.
  • Дополнительно существуют очереди роутера: указанные лимиты ограничивают именно NAT-буферы.
  • Адресат ответа фиксируется вместе с уже преобразованным пакетом до ожидания. Истечение/повторное использование mapping во время ожидания не меняет адресата и не запускает повторную трансляцию.

При tun_write с EAGAIN/EWOULDBLOCK удерживается один принятый пакет. nat_receive_ready запрещает доставку следующих: они остаются в router recv_q без ACK. Повтор записи назначается через 10мс; maintenance также повторяет запись. После успеха или окончательной ошибки пакет освобождается, приём NAT-каналов UTUN возобновляется. Ошибки записи диагностируются в TUN-модуле.

Провайдер дополнительно вызывает eim_nat_hold для внешнего source-порта/echo ID пакета, ожидающего записи в TUN. Удержанный mapping нельзя удалить или переиспользовать при очистке. После успешной записи eim_nat_release обновляет время активности; при ошибке/остановке снимает удержание без обновления. Это удержание относится к исходящему пакету провайдера; ожидающий обратной отправки ответ уже содержит внутренний адрес и сохранённый ID клиента.

4. Обслуживание и остановка

Таймер nat_maintenance каждые 100мс:

  • проверяет 128 слотов NAT на истечение: TCP — 7440с, UDP — 120с, ICMP Echo — 60с простоя;
  • восстанавливает ожидания, отменённые при close/reset router-канала;
  • удаляет пустые FIFO адресатов после 60с простоя;
  • повторяет ожидающую запись TUN.

Статические и удержанные mapping не истекают. Полный проход таблицы занимает около 51.2с при своевременном выполнении таймеров; очистка после timeout дополнительно зависит от задержек event loop. Полного обхода mapping на пути пакета нет. Если выделение таймера повтора TUN не удалось, ошибка логируется и повтор остаётся на maintenance; ошибка планирования maintenance также логируется.

Все вызовы выполняются в uasync-потоке ядра. init требует созданного роутера, перед повторным init нужен destroy. Остановка выполняется вне NAT callback, до освобождения роутера/uasync: сначала отменяются таймеры и binding, затем waiters и FIFO освобождают исходные TUN-пакеты, закрываются NAT router-каналы, освобождаются удержанный пакет/его mapping, TUN и таблица NAT. Освобождение пакетов предшествует уничтожению их TUN-пула. Другие router-сервисы продолжают работать.

5. API и проверки

API Назначение
nat_transport_ctx TUN, хеш адресатов, счётчик pending, глобально остановленный пакет, ожидающая запись TUN и таймеры
nat_transport_init(inst) Создать транспорт по конфигу; 0 — успех/выключенный NAT, -1 — ошибка с освобождением созданных ресурсов
nat_transport_destroy(inst) Отменить ожидания и освободить транспорт; NULL/повторный вызов допустимы

test_nat_transport проверяет обе роли через настоящий роутер и TUN в test mode: порядок и контрольные суммы, отсутствие копии исходного entry, владение при ошибке, фильтрацию источника/группы, некорректные IP, давление router send_q, оба лимита NAT, прогресс исправного клиента рядом с медленным, истечение/повторное использование mapping во время ожидания, EAGAIN TUN и остановку с активными ожиданиями.