Протокол защиты транспортного уровня TLS 1.3 является фундаментом криптографической безопасности современного интернета. В архитектурах виртуальных частных сетей (VPN), граничных ретрансляторов и инкапсулированных защитных туннелей (таких как DNS-over-HTTPS или потоковые мультиплексоры) шифрование предотвращает перехват и модификацию трафика.
Однако классические библиотеки TLS пространства пользователя (userspace), включая OpenSSL, BoringSSL и Rustls, сталкиваются с фундаментальными ограничениями производительности на высоконагруженных сетевых узлах. В традиционной схеме каждый пакет, проходящий через защищенный узел, вынужден многократно копироваться между буферами сокетов ядра и памятью пользовательского процесса, требуя постоянных переключений контекста.
При переходе на интерфейсы со скоростями 40GbE, 100GbE и плотным потоком пакетов подобные операции истощают процессорный кэш, перегружают системную шину памяти и снижают общую пропускную способность.
Чтобы исключить лишнее дублирование данных в оперативной памяти и перенести симметричные криптографические операции непосредственно на сетевые адаптеры, в ядро Linux был внедрен механизм Kernel TLS (kTLS, CONFIG_TLS) в сочетании с аппаратной разгрузкой SmartNIC.
+--------------------------------------------------------------------------+
| СРАВНЕНИЕ ПЕРЕДАЧИ ДАННЫХ: USERSPACE TLS И LINUX KTLS |
+--------------------------------------------------------------------------+
| |
| [ КЛАССИЧЕСКАЯ РЕТРАНСЛЯЦИЯ TLS В ПРОСТРАНСТВЕ ПОЛЬЗОВАТЕЛЯ ] |
| |
| Вход с NIC ──> sk_buff ──(Копирование 1)──> Память Userspace |
| │ |
| CPU дешифрует и шифрует |
| (Сброс кэшей L1/L2) |
| v |
| Выход в NIC <── sk_buff <──(Копирование 2)── Память Userspace |
| (Требует 4 копирования и 2 переключения контекста на цикл) |
| |
| ---------------------------------------------------------------------- |
| |
| [ РЕТРАНСЛЯЦИЯ LINUX KTLS ZERO-COPY С АППАРАТНОЙ РАЗГРУЗКОЙ ] |
| |
| Вход с NIC (DMA) |
| │ |
| v (Буфер страниц ядра / sk_buff) |
| +-------------------------------------------------------------+ |
| | СЕТЕВОЙ СТЕК ЯДРА LINUX | |
| | | |
| | Модуль kTLS (CONFIG_TLS) / Маршрутизация eBPF Sockmap | |
| | - Полное отсутствие копирования в Userspace | |
| | - Прямая пересылка внутри ядра через splice() | |
| +-------------------------------------------------------------+ |
| │ |
| v (Передача Zero-Copy через DMA) |
| Аппаратный криптопроцессор на сетевой карте (Mellanox / Intel) |
| │ |
| v |
| Зашифрованный трафик на оптической линии (Скорость 100GbE) |
| |
+--------------------------------------------------------------------------+
Узкие места обработки трафика в пространстве пользователя
В архитектуре стандартных сетевых демонов ретрансляция защищенного трафика создает существенные вычислительные издержки:
- Частота системных вызовов: постоянное выполнение функций
read()илиSSL_read()провоцирует непрерывные переходы процессора между пространством пользователя и ядром. - Двойное копирование памяти: входящие сетевые фреймы из буферов ядра передаются в оперативную память процесса. После логической обработки вызовы
write()илиSSL_write()копируют данные обратно в буферы сокетов ядра. - Вытеснение процессорного кэша: интенсивное выполнение симметричного блочного шифрования (AES-GCM или ChaCha20-Poly1305) переполняет кэш-память уровней L1 и L2, вызывая задержки при обработке миллионов пакетов в секунду.
На серверах с портами 100GbE это архитектурное ограничение сдерживает производительность одного процессорного ядра на уровне 18–25 Гбит/с независимо от аппаратных ресурсов платформы.
Архитектура Linux kTLS: разделение фаз рукопожатия и передачи
Подсистема Kernel TLS устраняет указанные недостатки путем строгого разграничения задач:
- Плоскость управления в Userspace: сложные протокольные сценарии с управлением состоянием (валидация цепочек сертификатов X.509, согласование ALPN и асимметричный обмен ключами ECDHE или постквантовыми алгоритмами) по-прежнему исполняются библиотеками пространства пользователя (OpenSSL, GnuTLS).
- Плоскость данных в Ядре: как только сессионные симметричные ключи согласованы, пользовательское приложение передает их в сокетный уровень ядра с помощью вызова
setsockopt().
С этого момента ядро Linux берет на себя формирование записей TLS, контроль порядковых номеров (sequence numbers), а также шифрование и проверку целостности данных непосредственно при вызовах tcp_sendmsg и tcp_recvmsg.
+--------------------------------------------------------------------------+
| СХЕМА ИНИЦИАЛИЗАЦИИ KTLS В ЯДРЕ LINUX |
+--------------------------------------------------------------------------+
| |
| 1. Установление соединения TCP (Стандартный сокет) |
| |
| 2. Рукопожатие TLS 1.3 на уровне Userspace (OpenSSL / BoringSSL) |
| - Выбор шифра: TLS_AES_256_GCM_SHA384 |
| - Вычисление симметричных ключей и векторов инициализации (IV) |
| |
| 3. Активация kTLS через системный вызов: |
| setsockopt(fd, SOL_TCP, TCP_ULP, "tls", sizeof("tls")); |
| |
| 4. Передача криптографических параметров в ядро: |
| setsockopt(fd, SOL_TLS, TLS_TX, &crypto_info, sizeof(info)); |
| setsockopt(fd, SOL_TLS, TLS_RX, &crypto_info, sizeof(info)); |
| |
| 5. Прямой ввод-вывод на уровне ядра: |
| Ядро самостоятельно упаковывает и шифрует фреймы |
| Приложения используют splice(), sendfile() и MSG_ZEROCOPY |
| |
+--------------------------------------------------------------------------+
Настройка kTLS в приложениях на C / Rust
Пример инициализации kTLS через библиотеку OpenSSL 3.0+:
#include <sys/socket.h>
#include <netinet/tcp.h>
#include <linux/tls.h>
#include <openssl/ssl.h>
int enable_ktls_session(SSL *ssl, int socket_fd) {
/* Шаг 1: Активация поддержки kTLS в OpenSSL */
SSL_set_options(ssl, SSL_OP_ENABLE_KTLS);
/* Шаг 2: Завершение стандартного рукопожатия TLS 1.3 */
if (SSL_accept(ssl) <= 0) {
return -1;
}
/* Шаг 3: Проверка успешного включения kTLS на отправку и прием */
if (BIO_get_ktls_send(SSL_get_wbio(ssl))) {
/* Ядро отвечает за формирование записей и шифрование исходящих данных */
}
if (BIO_get_ktls_recv(SSL_get_rbio(ssl))) {
/* Ядро берет на себя проверку подлинности и дешифрацию входящих данных */
}
return 0;
}
Пересылка данных Zero-Copy через splice() и sendfile()
Главное эксплуатационное достоинство kTLS заключается в поддержке примитивов zero-copy для зашифрованных сетевых соединений.
В стандартном TLS вызов splice() не применим, так как открытые данные должны быть зашифрованы перед отправкой в стек. Благодаря kTLS трафик пересылается между двумя сокетами без транзита в память процесса:
/* Пересылка zero-copy между входящим сокетом и исходящим туннелем */
int pipefd[2];
pipe(pipefd);
while (1) {
/* Перемещение расшифрованных данных из сокета в кольцевой буфер ядра */
ssize_t bytes = splice(inbound_fd, NULL, pipefd[1], NULL, 65536, SPLICE_F_MOVE);
if (bytes <= 0) break;
/* Пересылка данных в исходящий сокет с шифрованием kTLS */
splice(pipefd[0], NULL, outbound_fd, NULL, bytes, SPLICE_F_MOVE);
}
Данная схема полностью освобождает шину оперативной памяти хоста от повторной передачи байтов.
Аппаратная разгрузка: делегирование криптографии SmartNIC
Помимо программной реализации kTLS на процессоре, сетевые контроллеры корпоративного класса (NVIDIA Mellanox ConnectX-6 Dx / BlueField и Intel Ethernet 800) поддерживают аппаратный режим kTLS Device Offload.
Сравнение режимов работы kTLS
Ядро Linux поддерживает три уровня интеграции kTLS:
+--------------------------------------------------------------------------+
| РЕЖИМЫ РАБОТЫ ТЕХНОЛОГИИ KTLS |
+--------------------------------------------------------------------------+
| Режим | Исполнительный блок | Нагрузка CPU | Поток 100GbE|
+---------------------+-----------------------+--------------+-------------+
| Программный Userspace| Процессор (Процесс) | 100% | Ограничен |
| Программный kTLS | Процессор (Ядро ASM) | 35-50% | Достижим |
| kTLS Device Offload | Аппаратный ASIC карты | <2% | Полная линия|
+--------------------------------------------------------------------------+
При включении аппаратной разгрузки:
- Ядро связывает дескриптор
sk_buffс криптографическим контекстом без изменения содержимого пакета. - Контроллер DMA сетевой карты считывает открытый текст из памяти хоста.
- Аппаратный блок AES на сетевом адаптере выполняет шифрование непосредственно перед модуляцией сигнала в оптическом кабеле.
Проверка и включение аппаратной разгрузки:
# Проверка возможностей сетевого интерфейса
ethtool -k eth0 | grep tls-hw
# Включение аппаратного шифрования и дешифрации
ethtool -K eth0 tls-hw-tx-offload on
ethtool -K eth0 tls-hw-rx-offload on
Интеграция с eBPF Sockmap для маршрутизации внутри ядра
Для максимальной производительности kTLS объединяется с технологией eBPF sockmap (BPF_MAP_TYPE_SOCKMAP и BPF_PROG_TYPE_SK_MSG).
Программа eBPF считывает расшифрованные записи непосредственно в очереди сокета ядра, анализирует заголовки L7 и перенаправляет поток в исходящий туннельный сокет через bpf_msg_redirect_map() без пробуждения рабочих потоков пользовательского пространства:
Входной NIC ──> kTLS Дешифрация ──> Фильтр eBPF sk_msg ──> kTLS Шифрование ──> Выходной NIC
[ Полная обработка внутри ядра без переключения контекста ]
Практические преимущества для RiceGuard и VPNRice
В инфраструктуре сервиса VPNRice связка kTLS и аппаратной криптографии обеспечивает ключевые технологические преимущества:
- Масштабируемость пограничных узлов: серверы, обслуживающие протоколы DoH и DoT, обрабатывают сотни тысяч параллельных запросов на один узел с задержкой менее одной миллисекунды.
- Энергоэффективность и снижение тепловыделения: перенос операций AES-GCM на аппаратные контроллеры снижает нагрузку на центральные процессоры до 80%, предотвращая троттлинг на плотных серверных стойках.
- Безопасность пользовательских данных: расшифрованный трафик циркулирует исключительно в очередях ядра, не сохраняясь в динамической памяти пользовательских процессов.
Эксплуатационные требования
При проектировании промышленных систем с поддержкой kTLS рекомендуется:
- Версия ядра: использовать Linux 5.15 LTS и новее, а для аппаратной разгрузки SmartNIC — ядра 6.1+.
- Привилегии процессов: предоставить права на установку сокетных протоколов ULP или назначить возможность
CAP_NET_ADMIN. - Наборы шифров: отдавать предпочтение алгоритмам
TLS_AES_128_GCM_SHA256иTLS_AES_256_GCM_SHA384, так как аппаратные блоки NIC оптимизированы под AES-GCM.
Объединение Linux kTLS, передачи zero-copy и аппаратных возможностей SmartNIC формирует надежный стандарт для современных защищенных шлюзов VPN.



