mirror of
https://github.com/bol-van/zapret.git
synced 2025-04-30 19:02:59 +03:00
143 lines
14 KiB
Markdown
143 lines
14 KiB
Markdown
- [Вступление](#вступление)
|
||
- [Минусы](#минусы)
|
||
- [Главная боль №1](#главная-боль-1)
|
||
- [Боль №2](#боль-2)
|
||
- [Боль №3](#боль-3)
|
||
- [Боль №4](#боль-4)
|
||
- [Плюсы](#плюсы)
|
||
- [Плюс №1, главный](#плюс-1-главный)
|
||
- [Плюс №2](#плюс-2)
|
||
- [Плюс №3](#плюс-3)
|
||
- [Плюс №4](#плюс-4)
|
||
- [Плюс №5](#плюс-5)
|
||
- [Выводы](#выводы)
|
||
|
||
# Вступление
|
||
|
||
`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 листов на слабой системе, это может быть единственным спасением.
|