You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

5.5 KiB

TUN Interface (tun_if)

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

Модуль создания и управления виртуальным сетевым интерфейсом (TUN) — точкой входа/выхода всего VPN-трафика. Через TUN-интерфейс ОС отправляет IP-пакеты в uTun и получает обработанные пакеты обратно. Реализует кроссплатформенную абстракцию над платформенными механизмами: Linux (/dev/net/tun), FreeBSD (/dev/tun + TUNSIFHEAD), Windows (WinTun API).

Модель данных — две очереди:

  • output_queue — пакеты, прочитанные из TUN (ОС → uTun → routing)
  • input_queue — пакеты для записи в TUN (routing → uTun → ОС), с callback tun_input_queue_callback

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

// Инициализация из конфига (основной интерфейс VPN)
tun = tun_init(ua, config);
// или для NAT TUN с явными параметрами
nat_tun = tun_init_nat(ua, "tun_nat", "10.0.1.1", 1500, 0);

// Чтение: очередь output_queue наполняется автоматически (через uasync/epoll), 
// обработчик читает через queue_set_callback
struct ll_queue* out = tun_get_output_queue(tun);

// Запись: пакет кладётся в input_queue, callback пишет в TUN
tun_write(tun, buf, len); // прямой вызов, не через очередь

// Завершение
tun_close(tun);

Root-права: требуются на всех платформах для создания TUN-устройств и настройки IP. Тестовый режим (test_mode=1): вместо реального TUN используется socketpair(AF_UNIX, SOCK_DGRAM). Вторая сторона пары доступна через tun_get_test_fd().

Платформенные различия:

  • Linux: open("/dev/net/tun") + ioctl(TUNSETIFF) с IFF_TUN | IFF_NO_PI, неблокирующий режим через fcntl(O_NONBLOCK)
  • FreeBSD: open("/dev/tun") (cloning device), имя присваивается ядром, ioctl(TUNSIFHEAD) для multi-af (4-байтный заголовок AF), ioctl(TUNSIFMODE) для POINTOPOINT
  • Windows: WinTun API через wintun.dll, кольцевой буфер 4 MiB, отдельный read-поток (tun_read_thread_proc), пакеты передаются в main thread через uasync_post → tun_packet_handler

3. API

Структуры

  • struct tun_if — хендл интерфейса: fd (Linux/BSD файловый дескриптор), platform_handle/adapter_handle (Windows WinTun), ifname, ifindex, очереди input_queue/output_queue, пул pool для ll_entry, счётчики статистики (bytes_read/written, packets_read/written, read_errors, write_errors)
  • struct tun_packet_data — обёртка для передачи пакета из read-потока (Windows) в main thread: указатели на tun_if и ll_entry

Функции

  • tun_init(ua, config) / tun_init_nat(ua, ifname, ip, mtu, test_mode) — создают TUN-интерфейс: платформенный init, настройка IP/MTU, поднятие интерфейса, создание очередей, регистрация в uasync (Linux/BSD) или запуск read-потока (Windows). tun_init_nat — вариант для отдельного NAT TUN с явными параметрами вместо конфига
  • tun_close(tun) — остановка read-потока (Windows), удаление из uasync, слив и освобождение обеих очередей, уничтожение пула, платформенная очистка (close(fd) на Linux, SIOCIFDESTROY на FreeBSD, WintunEndSession+WintunCloseAdapter на Windows)
  • tun_write(tun, buf, len) — прямая запись в TUN (в тестовом режиме — в output_queue, иначе tun_platform_write). Пакет имеет префиксный байт, отбрасываемый при записи
  • tun_inject_packet(tun, buf, len) — инжекция пакета в output_queue (для тестов и Windows-нотификаций)
  • tun_read_packet(tun, buf, len) — тестовый helper: чтение одного пакета из input_queue
  • tun_packet_handler(arg) — callback для main thread (Windows): распаковывает tun_packet_data, кладёт ll_entry в output_queue
  • Платформенные функции (tun_linux.c / tun_freebsd.c / tun_windows.c):
    • tun_platform_init() — создание устройства, настройка IP/MTU, поднятие, получение ifindex, O_NONBLOCK
    • tun_platform_cleanup() — закрытие fd/хендлов
    • tun_platform_read() — чтение из TUN (FreeBSD: readv с отделением 4-байтного AF-заголовка)
    • tun_platform_write() — запись в TUN (FreeBSD: writev с AF-заголовком; Windows: WintunAllocateSendPacket + WintunSendPacket)
    • tun_platform_get_poll_fd() — fd для uasync (Windows возвращает -1, используется read-поток)