AES-NI в OpenSSL или вынос в ядро: что вам нужно?
Отделите поддержку инструкций CPU от места обработки пакетов: проверьте криптографический бэкенд, согласованный шифр и активный путь перед настройкой.
Два ярлыка используются так, будто это одно и то же: аппаратно ускорено и вынесено в ядро. Первый описывает, какие инструкции выполняет процедура AES библиотеки, второй — где происходит обработка пакетов. У VPN может быть первый без второго, второй без первого или оба сразу. Любое решение о производительности должно начинаться с того, что вы назовёте, какой из двух вы действительно меняете.
Две оси, а не одна оценка
Первая ось — реализация: направляется ли код, выполняющий AES-256-GCM, в версию, использующую специальные инструкции процессора, или в переносимую процедуру, которая выполняет их как обычную арифметику. Этот выбор живёт внутри криптографической библиотеки и делается при её инициализации.
Вторая ось — размещение: проходит ли пакет через путь преобразования ядра или демон в пользовательском пространстве читает из туннельного устройства, шифрует и записывает обратно.
Ни одна ось не ограничивает другую. VPN в пользовательском пространстве на процессоре с инструкциями AES может использовать их всё время, а путь через ядро на процессоре без них возвращается к программной реализации. Ярлыки в материалах поставщиков редко делают это различие, и поэтому советы по настройке, скопированные между двумя ситуациями, так часто не дают ничего.
Ось первая: какой код выполняет шифрование
OpenSSL определяет особенности процессора при инициализации и использует результат для выбора оптимизированных путей кода, как описывает документация о возможностях x86. AES-NI — одна из задокументированных возможностей за этим распределением. Ничто из этого не требует, чтобы библиотека стала компонентом ядра.
Убедитесь, что особенность видна процессу, прежде чем предполагать, что используется быстрый путь. В Linux источником служит поле flags в /proc/cpuinfo, а внутри гостя оно отражает то, что предоставляет гипервизор, а не имя модели физического хоста.
grep -m1 '^flags' /proc/cpuinfo | grep -o '\baes\b'
openssl list -providers -verboseВторая команда называет поставщиков, загруженных в этой сборке. Она не сообщает, с какой библиотекой связан сервис VPN, и один хост может нести две установки OpenSSL, тогда как работающий процесс использует только одну из них.
Ось вторая: где работает путь пакетов
Размещение в ядре означает, что преобразование происходит в собственном механизме IPsec ядра или в туннельном драйвере внутри ядра, поэтому пакетам не нужен путь туда и обратно через процесс в пользовательском пространстве для каждой порции. Это может сократить копирования и переключения контекста и распределить работу по ядрам так, как не может однопоточный демон. Это также переносит счётчики и трассировки, которые вы будете читать при падении пропускной способности, потому что работа теперь идёт по другую сторону границы, которую вы не контролируете. Считайте это затратами на отладку, а не только решением о производительности.
Оно не создаёт поддержку инструкций, не настраивает шифр и не заставляет существующий маршрут работать.
Виртуализация добавляет складку и на этой оси. Гостю могут дать маскированную модель процессора, скрывающую особенности, которые есть у хоста, а вложенный гость может видеть ещё меньше. Читайте представление о возможностях изнутри среды, где VPN действительно работает, а не из консоли гипервизора.
Что покупает каждый выбор и чего он не может
Практический вопрос — куда уходит время. Если пропускную способность ограничивают один занятый поток, повторяющиеся копии буфера или системный вызов на каждый пакет, перенос преобразования на путь, устраняющий эти затраты, может помочь, при условии что ядро реализует нужное вам преобразование.
Если предел — перегруженный восходящий канал, путь с потерями, долгое время кругового обхода, насыщенный целевой сервис или один поток, прикреплённый к одному ядру, размещение не меняет ничего важного. То же относится к выбору инструкций: AES на специальном оборудовании не исправит отсутствующий маршрут и не поможет, если туннель простаивает из-за сбоя разрешения имён.
Там, где действуют оба, они складываются. Путь через ядро может использовать то же распределение на уровне инструкций внутри криптографического API ядра, а путь в пользовательском пространстве с хорошо выбранной библиотекой уже использует его. Решение не в том, что быстрее в абстракции, а в том, для какой затраты у вас есть доказательства.
Запишите четыре факта, прежде чем что-либо менять
Запишите бинарный файл сервиса и криптографическую библиотеку, с которой он связан, потому что они определяют первую ось. Затем зафиксируйте согласованную защиту данных, потому что шифр без выделенного пути инструкций ведёт себя иначе, чем с ним, а набор выбирают обе стороны.
Далее — представление о возможностях изнутри работающей среды и, наконец, активный путь пакетов с доказательством того, что режим, который вы считаете включённым, действительно включён. Загруженный модуль не доказывает, что профиль его использует, а строка конфигурации не доказывает, что ядро её приняло.
Измените одну вещь и сравните с ровной нагрузкой при тех же конечных точках и том же направлении передачи. Утверждение о скорости, которое вы не измерили, стоит меньше, чем заметка о том, что бэкенд никогда не был под сомнением.