nftables flowtable offload: ускорение маршрутизации без потери контроля firewall | AdminWiki

nftables flowtable offload: ускорение маршрутизации без потери контроля firewall

20 сентября 2026 15 мин. чтения
Содержание статьи

Что такое flowtable в nftables и какую задачу он решает

flowtable в nftables переводит уже установившиеся потоки на fast path: первый пакет соединения проходит полный набор правил и conntrack, а последующие пакеты того же потока обрабатываются по компактной записи flowtable, где нет перебора правил и повторного поиска маршрута. Фильтрация при этом сохраняется: решение пропустить или заблокировать поток принимается на первом пакете, а запись в flowtable появляется только после того, как пакет был принят правилами forward.

Причина, по которой механизм вообще понадобился, в стоимости slow path. Каждый forwarded-пакет на Linux проходит вход через интерфейс, поиск в conntrack, цепочку prerouting, решение о маршруте, цепочку forward со всей вашей политикой, postrouting и отправку в выходной интерфейс. При десятках тысяч пакетов в секунду суммарная работа CPU по этим шагам упирается в предел раньше, чем канал. Flowtable позволяет после первого пакета убрать из обработки перебор правил и routing lookup для каждого следующего пакета потока.

Прирост не одинаков для любого трафика. Он заметен на длинных потоках: выдача ISO-образа, репликация, бэкапы, потоковое видео, длинный TCP-сеанс через туннель. На наборе из коротких HTTP-запросов каждый поток состоит из нескольких пакетов, и запись в flowtable не успевает окупить расходы на своё создание. Замер на конкретном стенде занимает около 10 минут и отвечает на вопрос «сработает ли это у меня» точнее любых обобщённых цифр.

Материал опирается на общие принципы работы netfilter и nftables. Номера версий, набор доступных опций и поддержку конкретного сетевого оборудования сверяйте с документацией вашего дистрибутива и драйвера, а фактическое состояние узла проверяйте командами uname -r, nft --version, ethtool -k и dmesg. Конкретные версии ядра и nftables, в которых появились те или иные возможности flowtable, в этом материале не приводятся: перед внедрением уточняйте их по официальной документации ядра Linux и changelog nftables.

Slow path и fast path: как пакеты проходят через nftables

Slow path строится на хуках netfilter. Пакет входит в устройство, проходит defrag и conntrack в prerouting (conntrack подключён на отрицательном приоритете, поэтому его результат доступен цепочкам filter), затем ядро решает, куда пакет идёт: локально в input или транзитом в forward. Для транзитного трафика выполняется поиск маршрута, отрабатывает ваша политика forward, затем postrouting с возможным NAT и отправка. Порядок этих шагов и типовые ошибки при их смешении подробно разобраны в материале о взаимодействии nftables и таблицы маршрутизации Linux.

Fast path выглядит иначе. Пакеты приходят на ingress-хук устройства, где подключён flowtable, сопоставляются по кортежу с существующей записью и сразу отправляются в выходной интерфейс с уже вычисленным следующим узлом. Цепочки inet prerouting и forward для них не выполняются.

Что происходит с пакетомSlow pathFast path (flowtable)
Перебор правил forwardДля каждого пакетаТолько для первого пакета потока
Поиск маршрутаДля каждого пакетаОдин раз, результат хранится в записи
Проверка conntrackДля каждого пакетаПо кортежу записи flowtable
log, limit, meta markПрименяютсяК последующим пакетам не применяются
Счётчики правил nftablesРастут на каждый пакетРастут только на первом пакете

Ключевые сущности: conntrack, flowtable entry, offload

conntrack ведёт таблицу соединений: кортеж (адреса источника и назначения, порты, протокол), состояние, таймеры, результат трансляции адресов. Запись flowtable строится на основе этой информации и добавляет к ней данные, нужные для быстрой пересылки: выходной интерфейс, MAC-адрес следующего узла, признак трансляции. Проще говоря, conntrack отвечает на вопрос «это чей поток и что с ним можно делать», а flowtable entry на вопрос «куда этот пакет отправить прямо сейчас, не пересчитывая всё заново».

Offload означает перенос обработки потока на уровень, где стандартный стек обходится. Software offload делает это внутри ядра, hardware offload перекладывает часть работы на сетевую карту. Записи живут ограниченное время: их удаляет истечение таймаута, принудительная очистка flowtable или завершение соединения в conntrack.

Software и hardware offload: в чём разница и что выбрать

Software offload выполняет ядро. Вы ничего не платите за него по железу, получаете полную видимость трафика для tcpdump и диагностики, но экономите только на обходе правил и маршрутного поиска: сам пакет по-прежнему копируется и обрабатывается CPU. Hardware offload переносит пересылку потока на NIC или ASIC, пакеты части установившихся потоков могут вообще не попадать в ядро. Это даёт максимальную разгрузку CPU, но требует поддержки в драйвере и оборудовании.

Практический порядок выбора прост. Сначала включайте software offload: он работает на любой сетевой карте и на виртуальных интерфейсах. Hardware offload имеет смысл, когда software-вариант уже внедрён, CPU всё ещё упирается в обработку сети, а карта и драйвер умеют аппаратную выгрузку. На виртуализированных шлюзах и в контейнерных окружениях обычно остаётся только software.

Требования к ядру и nftables для offload

Инфраструктура flowtable развивалась постепенно: со временем в ядре добавлялись поддержка разных семейств адресов, работа с NAT и аппаратная выгрузка. Точные версии ядра и nftables, в которых появилась та или иная возможность, в этом материале не приводятся: их следует сверять по официальной документации ядра Linux (в частности, по Documentation/networking/nf_flowtable.rst) и по changelog nftables. Для рабочей эксплуатации ориентируйтесь на актуальное LTS-ядро и свежую версию nftables из вашего дистрибутива, а не на конкретные номера из сторонних обзоров.

Проверить свой узел можно так:

uname -r
nft --version
modinfo nf_flow_table
lsmod | grep -E 'nf_flow_table|nft_flow_offload'
grep -E 'CONFIG_NF_FLOW_TABLE|CONFIG_NFT_FLOW_OFFLOAD' /boot/config-$(uname -r)

Модули, за которыми стоит следить: nf_flow_table, семейные nf_flow_table_inet, nf_flow_table_ipv4, nf_flow_table_ipv6 и nft_flow_offload с реализацией выражения flow в nftables. Если modinfo не находит nf_flow_table, ядро собрано без поддержки, и подгрузить модуль вручную не получится.

Когда hardware offload не сработает

  • Драйвер карты не умеет hw-tc-offload. Проверка: ethtool -k eth0 | grep hw-tc-offload, ожидаемое значение в первой колонке - on.
  • Поток содержит трансляцию адресов, а драйвер не умеет её выгружать. Такие потоки молча остаются в software-пути.
  • Интерфейсы виртуальные: veth, bridge, tun/tap, типичные для KVM и контейнеров, аппаратной выгрузки не дают.
  • Правила используюют выражения, которые невозможно представить в терминах аппаратной таблицы: сложные match по payload, queue, tproxy, helpers.
  • В определении flowtable не указан флаг offload, и ядро даже не пытается передать поток в карту.

Провал аппаратной выгрузки не ломает сеть: поток просто продолжает идти через программный путь. Но диагностировать это по загрузке CPU легко принять за ошибку в конфигурации, поэтому смотрите dmesg на сообщения о невозможности выгрузить соединение.

Путь первого пакета и последующих пакетов потока

  1. Первый пакет нового соединения приходит на ingress-интерфейс. Записи в flowtable для этого кортежа ещё нет, пакет идёт обычным путём.
  2. Отрабатывают defrag и conntrack, создаётся запись соединения в состоянии NEW.
  3. Цепочки inet prerouting и forward применяют вашу политику. Если пакет отклонён, соединение дальше не существует, никакой записи в flowtable не будет.
  4. Пакет принят и доходит до правила с действием flow add @имя_flowtable. Ядро создаёт flowtable entry, дополняет его маршрутной информацией и связывает с записью conntrack.
  5. Следующие пакеты потока попадают на ingress-хук, находят запись по кортежу и уходят в выходной интерфейс по fast path.
  6. Обратный трафик существующего соединения обрабатывается так же: его первый пакет проходит slow path, после чего направление добавляется в запись.

Отсюда главный вывод про контроль firewall: политика проверяется на входе в соединение и при смене состояния, а не отключается целиком. Поток, который ваши правила не пропускают, в flowtable не попадёт в принципе.

Как создаётся flowtable entry

Запись создаётся не в момент появления пакета, а в момент выполнения действия flow add, то есть после того, как пакет уже прошёл правила. Условия совместимости: соединение отслеживается conntrack (пакеты не помечены notrack), поток транзитный, то есть проходит через forward, а не адресован самому серверу, и интерфейс входа присутствует в списке devices вашего flowtable. Если хотя бы одно условие нарушено, запись не появится, и трафик продолжит идти standard path с полной обработкой правил.

Из этого же следует ограничение: flowtable ускоряет только транзитный трафик. Локальные соединения самого сервера (SSH, веб-сервис, обращения мониторинга) через него не ускоряются, потому что идут в input и output, а не в forward.

Что происходит при изменении потока

Запись живёт, пока поток остаётся в предсказуемом состоянии. Завершение TCP-соединения (FIN, RST), истечение таймаута, удаление записи conntrack или смена политики приводит к удалению flowtable entry: пакеты снова идут через slow path и заново проверяются правилами. Для UDP таймауты короче, чем для TCP, поэтому записи по UDP-потокам обновляются и истекают заметно чаще, а выигрыш от offload на коротких UDP-обменах скромнее. ICMP и прочие вспомогательные протоколы ведут себя похоже: запись создаётся, но живёт недолго.

Практическое следствие: изменение правил NAT или маркировки не влияет на уже установленные потоки. Новые правила начнут применяться к потоку только после того, как запись истечёт или соединение завершится. Перед выкаткой изменений в политику полезно сбросить flowtable, чтобы не гадать, почему старый поток идёт по старым правилам.

Ограничения NAT и других функций firewall при offload

Трансляция адресов выполняется один раз, на первых пакетах соединения, а результат сохраняется в conntrack. Запись flowtable должна включать эти данные, чтобы подменять адреса и порты без обращения к таблице соединений. Software offload в общем случае рассчитан на работу с трансляцией, поэтому типовой шлюз «локалка в интернет через masquerade» продолжает работать. С hardware offload всё строже: возможность выгрузки NAT-потоков зависит от драйвера и конкретной карты, и такие потоки могут оставаться в программном пути. Точный перечень поддерживаемых сценариев NAT для вашего оборудования сверяйте с документацией драйвера. Рабочие примеры правил трансляции и типовые ошибки при их составлении собраны в руководстве по политикам маршрутизации, SNAT и DNAT в Linux.

NAT и conntrack: почему это важно для offload

Порядок цепочек определяет, что попадёт в запись. Правило masquerade в postrouting отрабатывает на первом пакете и фиксирует выбранный адрес и порт. Если после этого добавить правило трансляции в prerouting для уже установленного соединения, оно подействует только на новые потоки, потому что все остальные идут по готовой записи. Для шлюза с несколькими внешними адресами это означает: проверяйте распределение потоков сразу после изменения правил, пока записи ещё не закэшированы.

Второй момент касается статистики. Есть основания полагать, что пакеты, ушедшие на offload, не увеличивают счётчики conntrack, поэтому conntrack -S и учёт трафика по таблице соединений могут показывать заниженные значения. Это утверждение требует проверки на вашей версии ядра и nftables: перед тем как строить на conntrack лицензирование или биллинг, убедитесь, что счётчики отражают реальный объём трафика, и при необходимости используйте независимые счётчики (ethtool -S, ip -s link, отдельный counter на правиле с flow add).

Какие правила nftables мешают offload

Формулировка «мешают» здесь не совсем точна: правило flow add срабатывает независимо от того, что стоит выше него. Вопрос в другом, какие выражения перестают применяться к последующим пакетам потока. К ним относятся:

  • log и счётчики packet-level: журнал покажет только первый пакет потока.
  • limit и quota: ограничение частоты не будет проверяться на каждом пакете установленного соединения.
  • meta mark и последующий policy routing: маркировка ставится один раз, политика по метке для остальных пакетов потока не срабатывает.
  • queue и tproxy: перенаправление в userspace-обработчик для установившихся потоков не выполняется.
  • notrack: соединение без conntrack не может попасть в flowtable.
  • conntrack helpers вроде FTP или SIP: вторичные соединения зависят от разбора payload, а выгруженный поток такой разбор обходит, динамический порт может не открыться.

Отдельно про multi-WAN: если балансировка и отказоустойчивость построены на метках и ip rule, offloaded-потоки пойдут по тому маршруту, который был вычислен на первом пакете. Устройство этой схемы разобрано в статье про multi-WAN с nftables, маркировкой трафика и ip rule. Планируя offload на таком шлюзе, решите заранее, какие потоки выгрузке не подлежат.

Настройка flowtable в nftables: проверяемые команды

Ниже приведена минимальная рабочая схема для шлюза с двумя интерфейсами: eth0 смотрит в локальную сеть, eth1 в интернет. Правила создаются в семействе inet, поэтому покрывают и IPv4, и IPv6.

Создание flowtable и привязка к интерфейсам

Список devices определяет, на входе каких интерфейсов ядро будет искать записи flowtable. Для маршрутизатора перечислите оба интерфейса, иначе обратное направление потока не попадёт на fast path. Хук ingress и приоритет 0 подходят для стандартной схемы фильтрации.

nft add table inet filter
nft add flowtable inet filter f1 { hook ingress priority 0; devices = { eth0, eth1 }; }
nft list flowtable inet filter f1

Для аппаратной выгрузки в определение добавляют флаг offload. Без него ядро работает программно и не пытается отдать поток в сетевую карту:

nft add flowtable inet filter f1 { hook ingress priority 0; devices = { eth0, eth1 }; flags offload; }

Добавление правила для offload

Правило с действием flow add размещается в цепочке forward. Политику цепочки можно оставить drop: первый пакет всё равно проверяется полностью, а в flowtable попадут только принятые потоки.

nft add chain inet filter forward { type filter hook forward priority 0; policy drop; }
nft add rule inet filter forward ct state established,related accept
nft add rule inet filter forward iifname "eth0" oifname "eth1" accept
nft add rule inet filter forward meta l4proto { tcp, udp } flow add @f1 counter

Выражение meta l4proto { tcp, udp } покрывает TCP и UDP в обоих семействах адресов. Селектор flow offload применяйте осознанно, например только к доверенным подсетям, если выгрузка нужна не для всей полосы трафика.

Готовый ruleset удобно держать в файле и подключать целиком, тогда откат сводится к загрузке предыдущей версии:

nft list ruleset > /root/ruleset-backup-$(date +%F-%H%M).nft
nft -c -f /etc/nftables.conf
nft -f /etc/nftables.conf
systemctl enable --now nftables

Опция проверки синтаксиса без применения правил доступна в свежих версиях nftables. Если ваша сборка её не поддерживает, проверяйте конфигурацию на тестовом узле. Перед применением firewall-настроек на удалённом сервере держите второй канал доступа: консоль провайдера, IPMI или последовательный порт.

Как проверить, что flowtable offload работает

Просмотр статистики flowtable

Первое, что нужно убедиться: flowtable существует и привязан к нужным интерфейсам.

nft list flowtable inet filter f1
nft list ruleset | grep -A5 flow

Самый надёжный признак работающего offload - пометка в таблице соединений. У выгруженных записей conntrack появляется флаг OFFLOAD:

conntrack -L | grep -i offload
conntrack -L | grep -i -E 'tcp|udp' | head
cat /proc/net/nf_conntrack | grep -i offload
conntrack -S

Если счётчиков самого flowtable в вашей версии nftables не видно, добавьте counter к правилу с flow add, как в примере выше: он покажет, сколько первых пакетов потоков дошло до выгрузки. Пакеты, идущие по fast path, в этот счётчик не попадают, и это ожидаемое поведение, а не ошибка.

Диагностика проблем с offload

Когда offload не включается, проверяйте по порядку: версии, модули, поддержку оборудования, сообщения ядра. Полезный набор команд:

uname -r
nft --version
lsmod | grep -E 'nf_flow_table|nft_flow_offload'
ethtool -k eth1 | grep -i hw-tc-offload
ethtool -S eth1 | grep -i offload
dmesg | grep -i -E 'flowtable|flow_table|offload'
ip -s link show eth1
mpstat -P ALL 1 5

Практический тест на ускорение. Запустите iperf3 -s на узле за шлюзом, а с клиента в другой подсети - iperf3 -c с несколькими параллельными потоками и длительностью 30 секунд. Снимите mpstat в момент теста с выключенным flowtable и с включённым. Сравнивайте долю idle на ядрах, обрабатывающих сеть, и посмотрите, появились ли записи с флагом OFFLOAD. Так вы получите цифры именно для своего профиля трафика.

Если нагрузка на CPU не изменилась и offloaded-записей нет, типичные причины: соединения не доходят до правила flow add, интерфейс не указан в devices, соединение помечено notrack, либо трафик не транзитный, а адресован самому шлюзу.

Безопасный план внедрения flowtable offload

Что проверить перед включением offload

  • Версия ядра и nftables, наличие модулей nf_flow_table и nft_flow_offload.
  • Инвентаризация правил forward, NAT и маркировки: какие потоки зависят от log, limit, mark или helpers.
  • Сохранённый бэкап ruleset и доступ к консоли на случай потери SSH.
  • Понимание, какие сервисы критичны: VoIP, FTP, туннели и VPN часто требуют полной обработки пакетов.
  • План мониторинга: счётчики flowtable, conntrack -S, загрузка CPU, статистика интерфейсов.

Порядок внедрения: сначала стенд с копией конфигурации, затем один интерфейсную пару в непиковые часы, затем наблюдение в течение суток, и только после этого расширение на остальные сегменты. Аппаратную выгрузку внедряйте последней и согласуйте изменения с сетевыми инженерами, отвечающими за оборудование.

Rollback и восстановление

Откат должен быть выполним одной командой, поэтому бэкап делается до любых изменений, а не после.

nft list ruleset > /root/ruleset-preflow.nft
nft list ruleset -a | grep -n 'flow add'
nft delete flowtable inet filter f1
nft -f /root/ruleset-preflow.nft

Удаление объекта flowtable мгновенно возвращает весь трафик в slow path: соединения при этом не разрываются, потому что таблица conntrack продолжает работать. Если вы использовали flags offload, после удаления flowtable часть потоков может оставаться в аппаратной таблице карты. Надёжного универсального способа очистить её из userspace нет: в зависимости от драйвера может помочь перезагрузка модуля драйвера или узла целиком, поэтому такой сценарий стоит запланировать заранее и проверить на тестовом стенде с вашим оборудованием.

После откатов и изменений обязательно проверяйте, что фильтрация не ослабла. Достаточный минимум: с внешнего узла просканировать несколько закрытых портов и убедиться, что они по-прежнему фильтруются. Подход к построению политики deny all и точечному открытию портов описан в руководстве по настройке firewall на Linux-сервере.

Ограничения и подводные камни flowtable offload

Когда flowtable не даст ускорения

Выигрыш отсутствует там, где поток живёт несколько пакетов. Короткие HTTP-запросы, DNS, обмен с микросервисами, health-check-и: каждый из них требует создания записи, а затем немедленно завершается. Расходы на создание и удаление записи могут оказаться сопоставимы с экономией. Схожий эффект даёт высокая доля NAT и сложная политика: чем больше логики нужно выполнить на первом пакете, тем меньше доля пакетов, для которых обход успеет окупиться.

Ещё одна категория - протоколы с динамическими портами и встроенным контролем вроде FTP, SIP, TFTP. Они зависят от conntrack helpers, которые анализируют содержимое пакетов. Выгрузка основного потока в fast path обходит этот анализ, и вторичные соединения могут не открыться. Такие протоколы исключайте из flowtable явными селекторами.

Память тоже стоит учитывать. Каждая активная запись занимает память ядра, поэтому шлюз с сотнями тысяч одновременных соединений должен иметь запас по RAM, а также настроенные таймауты conntrack: чем короче время жизни записи, тем чаще потоки возвращаются на slow path.

Влияние на отладку и мониторинг

При software offload tcpdump продолжает видеть трафик на интерфейсе, но помните, что цепочки nftables для этих пакетов уже не выполняются, поэтому счётчики правил и логи перестают отражать реальный объём. При hardware offload ситуация жёстче: пакеты обрабатываются сетевой картой и могут не появляться в tcpdump вообще, а статистика conntrack по ним не растёт.

Компенсировать это можно так: считать трафик через ethtool -S и ip -s link, отслеживать записи с флагом OFFLOAD в conntrack, вести отдельный счётчик на правиле с flow add (он покажет число новых потоков, ушедших на выгрузку) и держать отдельный сегмент или отдельный интерфейс без flowtable для задач отладки и захвата трафика.

Начните с копии текущего ruleset на тестовом стенде и одного теста iperf3 с замером mpstat: этого достаточно, чтобы понять, даёт ли offload выигрыш вашей конфигурации, и только потом переносите изменение на рабочий шлюз.

Поделиться:
Сохранить гайд? В закладки браузера