14 KiB
Вступление
nftables
- это технология, пришедшая на замену iptables
.
В ней собрали все, что относилось к различным iptables
. А их немало. iptables
, ip6tables
, ebtables
, arptables
, ipset
.
Весь код из разрозненных, но похожих компонент, собрали в одно целое с единым синтаксисом.
Добавили различные конструкции языка, позволяющие писать правила более лаконично, не повторяя одни и те же команды с небольшими различиями.
На nftables
можно сделать почти все, что можно было сделать на iptables
. Есть то, что можно сделать на nftables
, но нельзя на iptables
.
Есть и наоборот.
Минусы
К сожалению, не обошлось и без боли.
Главная боль №1
Очень серьезная, актуальная для OpenWrt, и решения не видно.
ipset-ы позволяли загонять пересекающиеся интервалы IP адресов или подсетей.
nftables sets это не позволяют. Любое пересечение вызывает ошибку.
Есть auto-merge, но это работает только в user mode в процессе nft
, при условии, что весь блок адресов загоняется одной командой
и нет пересечений с уже имеющимся контентом в set.
Это не было бы критической проблемой, поскольку скрипты zapret
и так загоняют ipset целиком.
Проблема в катастрофическом расходе памяти при операции загона больших интервальных листов, то есть с подсетями и диапазонами.
Чтобы загнать 100000 IPv4 записей, едва хватает 300 Mb памяти устройства.
При успехе операции в ядре список столько не занимает, но суть дела это не меняет.
Для традиционных Linux систем это не проблема, но почти все роутеры загнутся.
Приемлемого решения не просматривается.
Сделать записи непересекающимися в листах - задача непростая.
Потребуется переписать алгоритм auto-merge из nft
, но с пониженным расходом памяти.
Загонять записи по одному отдельными вызовами nft
, игнорируя ошибки, займет вечность.
Загонять блоком отдельных команд, игнорируя ошибки, - nft
такого не умеет. Похоже, при любой ошибке происходит откат всего скрипта.
К тому же при таком подходе будут неточности в итоговом результате.
Swap позволяет немного сгладить проблему, но лишь незначительно.
Скажем, если вдруг list загоняется без ошибок с 300 Mb памяти и с падением на 256 MB, то swap спасает.
Если памяти становится 200 MB, то swap уже не спасет.
Все равно вызывается OOM killer, заодно убивая и другие процессы, кроме nft
, а это уже совсем плохо. Может быть убито что-то важное.
Боль №2
Не смертельная, но тоже не айс.
Какие-то нерациональные алгоритмы разбора таблиц в nft
.
Например, есть 1 большой set на 100000 элементов и 1 маленький на 2 элемента.
Чтобы просто пролистать мелкий set или добавить туда еще что-то nft
будет мусолить несколько секунд.
Что он делает за это время? Тащит из ядра огромный блоб, в котором все в куче, и разбирает его, чтобы выделить искомую мелочь?
В какой-то мере удается это сгладить, объединяя несколько команд в единый скрипт.
Боль №3
Система nftables
построена на виртуальной машине. Правила, которые вы пишите, переводятся в псевдокод VM.
Чтобы потом их показать, nft
декомпилирует код и переводит в читаемый язык.
Это довольно сложно, и регулярно случаются баги, связанные с неверным отображением.
Кроме этого, часто встречаются и баги парсера.
Например, все версии nft
вплоть до 1.0.1 имеют баг, который не разрешает названия интерфейсов в кавычках в определении flowtable.
Без кавычек нельзя вставить интерфейсы, имя которых начинается с цифры.
OpenWrt решает эту проблему отдельным патчем в snapshot версии, но на традиционных системах и в OpenWrt 21.x- его нет.
Почему бы не наплевать на интерфейсы, начинающиеся с цифры? Потому что для OpenWrt 6to4-6to4, 6in4-he-net - обычное явление.
На текущий момент этой проблемы в OpenWrt уже нет, если использовать актуальную версию.
Но тем не менее, хоть nft
и давно перешел отметку 1.0, всякая мелочь, особенно на не совсем стандартных правилах, регулярно всплывает.
Потому чем новее у вас будет версия nft
, тем больше там выловлено проблем.
Здесь обновления важны, чтобы потом не мучиться из-за давно исправленного велосипеда.
Боль №4
Невозможно, не копаясь в других таблицах и хуках, ничего не зная об их содержании, предотвратить DROP или REJECT.
Нельзя написать такое правило, которое что-то важное ACCEPT нет, игнорируя остальные хуки во всех таблицах.
Если у вас есть какой-то фаервол, и он что-то дропает, то как от этого отказаться, если надо временно что-то принять?
Это особенность netfilter
, он так работает, но в iptables
есть лишь стандартные таблицы с их хуками, куда можно вставить ACCEPT.
Здесь хуков может быть сколько угодно в каких угодно таблицах.
Эта проблема частично ломает кайф от независимого управления таблицами.
Плюсы
Плюс №1, главный
iptables
хороши, когда ими пользуется кто-то один. Иначе это проходной двор.
Когда есть система управления фаерволом, то приходится как-то к ней прикручиваться, чтобы не нарушить ее работу
и управлять правилами синхронно. Нужно уметь внести и удалить отдельные правила когда это нужно, не трогая все остальное.
Некоторые системы управления фаерволом вообще не предполагают, чтобы кто-то еще лез в iptables
, и это очень сильно портит жизнь.
У iptables
есть предопределенный набор хуков netfilter
с фиксированным приоритетом.
В nftables
хуков можно создать неограниченное количество с выбранным приоритетом, управляя ими независимо в отдельных таблицах.
Система управления фаерволом может работать в одной таблице (fw4
в случае OpenWrt) и не трогать все остальное.
zapret
может работать в другой таблице и не трогать систему управления фаерволом. Они друг другу не мешают.
Это снимает множество боли.
Но есть и исключение. nfset
-ы - аналог ipset
-ов - нельзя использовать из другой таблицы.
Потому если вам нужен ipset
, создаваемый zapret
скриптами, вам понадобится писать правила в той же таблице.
Но нет никакой необходимости влезать в цепочки zapret
.
Создаете свои цепочки и хуки и делаете в них что угодно.
Плюс №2
Возможность выбора приоритета хука позволяет легко решить проблему хаотической и принудительной дефрагментацией L3 IPv6, без танцев с загрузкой модулей ядра со специальными параметрами или перекомпиляцией nftables-nft
.
Это же позволяет перехватить трафик после SNAT/MASQUERADE, что на iptables
невозможно.
Атаки на проходящий трафик, ломающие NAT, крайне затруднены на iptables
.
Плюс №3
Наличие множеств (anonymous/named sets) позволяет не писать кучу однообразных правил там, где в iptables
их пришлось бы написать.
Плюс №4
Если у вас есть nftables
, то там наверняка есть уже все или почти все.
Нет кучи разных модулей ядра и .so плагинов для iptables
user-mode процесса.
Отдельные модули ядра есть, но их меньше, чем в iptables
, и OpenWrt их делит на меньшее число пакетов, большинство из которых
и так ставятся по умолчанию. user-mode процесс nft
и вовсе неделим. EXE-шник + lib.
Плюс №5
Пишут, что nftables
работают быстрее. Но это не точно и зависит от много чего.
В целом - чем меньше правил, тем выше скорость. Но в nftables
правил можно писать меньше, значит скорость тоже может быть выше.
У разработчиков есть идея перевести backend nftables
на BPF, а это наверняка будет существенно быстрее.
Выводы
Без больших листов все почти прекрасно. Но большие ip листы убивают все. Не для домашних это роутеров.
А ipset-ы к nftables
не прикрутить.
Зато есть возможность задействовать более продвинутые атаки, конфликтующие с NAT, которые на iptables
могут быть невозможны.
Делать нечего. Openwrt отошел от iptables
. С этим придется как-то жить.
Поэтому пришлось сделать для OpenWrt поддержку и iptables
, и nftables
(только с версии OpenWrt 21.xx, в более старых будут проблемы).
iptables
можно задействовать на любой OpenWrt версии.
Если используется fw3
, применяется старый механизм интеграции в fw3
.
Если он не используется, то правилами iptables
управляем как в традиционных Linux системах - то есть с возможностью
запуска и остановки, а скрипт запуска вносит в том числе и правила iptables
.
На новых OpenWrt возможно снести nftables
и firewall4
и установить firewall3
и iptables
.
Если вам никак без больших IP листов на слабой системе, это может быть единственным спасением.