10 KiB
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. Адрес берётся из IPv4nat_tun_ip, иначе изtun_ip. Маршруты ОС и доступ провайдера в интернет настраиваются отдельно.
- Клиент получает
[prefix:1][IP]изnat_tun->output_queue.nat_tun_outputзаменяет prefix наETCP_RT_ID_NATи передаёт исходный entry/dgram роутеру с адресатомnat_via_node_id. - Провайдер получает пакет в
nat_receive, выполняетeim_nat_egressи пишет чистый IP в NAT TUN. - Ответ/статический проброс из TUN провайдера проходит
eim_nat_ingressвnat_tun_output. Преобразованный пакет отправляется узлу изmapping->src_node_id. - Клиент принимает ответ только от своего провайдера, проверяет 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_queueTUN, 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 и остановку с активными ожиданиями.