zapret/docs/nftables_notes.txt
2023-10-12 12:35:06 +03:00

105 lines
11 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

nftables - это технология, пришедшая на замену iptables.
В ней собрали все, что относилось к различным iptables. А их немало. iptables, ip6tables, ebtables, arptables, ipset.
Весь код из разрозненных, но похожих компонент, собрали в одно целое с единым синтаксисом.
Добавили различные конструкции языка, позволяющие писать правила более лаконично, не повторяя одни и те же команды с небольшими различиями.
На nftables можно сделать почти все, что можно было сделать на iptables. Есть то, что можно сделать на nftables, но нельзя на iptables.
Удобно, красиво.
К сожалению, не обошлось и без боли. 10 лет развития nftables казалось бы должны были вылизать все. Но не тут то было.
Главная боль N1. Очень серьезная, актуальная для 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,
а это уже совсем плохо. Может быть убито что-то важное.
Боль N2, но не такая смертельная.
10 лет вылизывания кода, но при загоне больших листов в set-ы то и дело при вызовах nft list происходят seg faults.
Например, падать может nft -t list ruleset, но nft -t list table inet zapret может не падать.
Вроде это не влияет на функционал, но все равно создается неудобство.
Боль N3, не смертельная, но тоже не айс.
Какие-то нерациональные алгоритмы разбора таблиц в nft.
Например, есть 1 большой set на 100000 элементов и 1 маленький на 2 элемента.
Чтобы просто пролистать мелкий set или добавить туда еще что-то nft будет мусолить несколько секунд.
Что он делает за это время ? Тащит из ядра огромный блоб, в котором все в куче, и разбирает его, чтобы выделить искомую мелочь ?
В какой-то мере удается это сгладить, обьединяя несколько команд в единый скрипт.
Боль N4
Все версии nft вплоть до 1.0.1 имеют баг, который не разрешает названия интерфейсов в кавычках в
определении flowtable. Без кавычек нельзя вставить интерфейсы , имя которых начинается с цифры.
OpenWRT решает эту проблему отдельным патчем в snapshot версии, но на традиционных системах и в openwrt 21.x- его нет.
Почему бы не наплевать на интерфейсы, начинающиеся с цифры ? Потому что для openwrt 6to4-6to4, 6in4-he-net - обычное явление.
Плюс N1, главный
iptables хороши, когда ими пользуется кто-то один. Иначе это проходной двор.
Когда есть система управления фаерволом, то приходится как-то к ней прикручиваться, чтобы не нарушить ее работу
и управлять правилами синхронно. Нужно уметь внести и удалить отдельные правила когда это нужно, не трогая все остальное.
Некоторые системы управления фаерволом вообще не предполагают, чтобы кто-то еще лез в iptables, и это очень сильно портит жизнь.
У iptables есть предопределенный набор хуков netfilter с фиксированным приоритетом.
В nftables хуков можно создать неограниченное количество с выбранным приоритетом, управляя ими независимо в отдельных таблицах.
Система управления фаерволом может работать в одной таблице (fw4 в случае openwrt) и не трогать все остальное.
zapret может работать в другой таблице и не трогать систему управления фаерволом. Они друг другу не мешают.
Это снимает множество боли.
Но есть и исключение. nfset-ы - аналог ipset-ов - нельзя использовать из другой таблицы. Потому если вам нужен ipset,
создаваемый zapret скриптами, вам понадобится писать правила в той же таблице. Но нет никакой необходимости влезать в цепочки zapret.
Создаете свои цепочки и хуки и делаете в них что угодно.
Плюс N2
Возможность выбора приоритета хука позволяет легко решить проблему хаотической и принудительной дефрагментацией L3 ipv6,
без танцев с загрузкой модулей ядра со специальными параметрами или перекомпиляцией nftables-nft.
Плюс N3
Наличие множеств (anonymous/named sets) позволяет не писать кучу однообразных правил там, где в iptables их пришлось бы написать.
Плюс N4
Если у вас есть nftables, то там наверняка есть уже все или почти все.
Нет кучи разных модулей ядра и .so плагинов для iptables user-mode процесса.
Отдельные модули ядра есть, но их меньше, чем в iptables, и openwrt их делит на меньшее число пакетов, большинство из которых
и так ставятся по умолчанию. user-mode процесс nft и вовсе неделим. EXE-шник + lib.
Плюс N5
Пишут, что nftables работают быстрее. Но это не точно и зависит от много чего.
В целом - чем меньше правил, тем выше скорость. Но в nftables правил можно писать меньше, значит скрость тоже может быть выше.
У разработчиков есть идея перевести backend nftables на BPF, а это наверняка будет существенно быстрее.
Выводы
Честно говоря, лучше бы openwrt оставался на iptables.
Пусть они и старые, c недостатками, но как говорится ложка дегтя портит цистерну меда.
nftables - именно тот случай. Все хорошо, но все плохо из-за досадной особенности.
Без больших листов все почти прекрасно. Но большие ip листы убивают все. Не для домашних это роутеров.
А ipset-ы к nftables не прикрутить.
Делать нечего. Openwrt отошел от iptables. С этим придется как-то жить.
Поэтому пришлось сделать для openwrt поддержку и iptables, и nftables (только с версии openwrt 21.xx, в более старых будут проблемы).
iptables можно задействовать на любой openwrt версии.
Если используется fw3, применяется старый механизм интеграции в fw3.
Если он не используется, то правилами iptables управляем как в традиционных linux системах - то есть с возможностью
запуска и остановки, а скрипт запуска вносит в том числе и правила iptables.