nftables support

This commit is contained in:
bol-van
2022-02-15 17:15:36 +03:00
parent b7aa3a878c
commit 95667733a6
35 changed files with 3099 additions and 2000 deletions

View File

@@ -218,3 +218,7 @@ nfqws: ipfrag
v45
nfqws: hop-by-hop ipv6 desync and fooling
v46
big startup script refactoring to support nftables and new openwrt snapshot builds with firewall4

92
docs/nftables_notes.txt Normal file
View File

@@ -0,0 +1,92 @@
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 будет мусолить несколько секунд.
Что он делает за это время ? Тащит из ядра огромный блоб, в котором все в куче, и разбирает его, чтобы выделить искомую мелочь ?
В какой-то мере удается это сгладить, обьединяя несколько команд в единый скрипт.
Плюс N1, главный
iptables хороши, когда ими пользуется кто-то один. Иначе это проходной двор.
Когда есть система управления фаерволом, то приходится как-то к ней прикручиваться, чтобы не нарушить ее работу
и управлять правилами синхронно. Нужно уметь внести и удалить отдельные правила когда это нужно, не трогая все остальное.
Некоторые системы управления фаерволом вообще не предполагают, чтобы кто-то еще лез в iptables, и это очень сильно портит жизнь.
У iptables есть предопределенный набор хуков netfilter с фиксированным приоритетом.
В nftables хуков можно создать неограниченное количество с выбранным приоритетом, управляя ими независимо в отдельных таблицах.
Система управления фаерволом может работать в одной таблице (fw4 в случае openwrt) и не трогать все остальное.
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 работают быстрее.
Выводы
Честно говоря, лучше бы openwrt оставался на iptables.
Пусть они и старые, c недостатками, но как говорится ложка дегтя портит цистерну меда.
nftables - именно тот случай. Все хорошо, но все плохо из-за досадной особенности.
Без больших листов все почти прекрасно. Но большие ip листы убивают все. Не для домашних это роутеров.
А ipset-ы к nftables не прикрутить.
Делать нечего. Openwrt отошел от iptables. С этим придется как-то жить.
Поэтому пришлось сделать для openwrt поддержку и iptables, и nftables (только с версии openwrt 21.xx, в более старых будут проблемы).
iptables можно задействовать на любой openwrt версии.
Если используется fw3, применяется старый механизм интеграции в fw3.
Если он не используется, то правилами iptables управляем как в традиционных linux системах - то есть с возможностью
запуска и остановки, а скрипт запуска вносит в том числе и правила iptables.

View File

@@ -49,7 +49,7 @@ deal with its consequences.
3. Modification of TCP connection at the packet level. Implemented through the NFQUEUE handler and raw sockets.
For options 2 and 3, tpws and nfqws programs are implemented, respectively.
You need to run them with the necessary parameters and redirect certain traffic with iptables.
You need to run them with the necessary parameters and redirect certain traffic with iptables or nftables.
To redirect a TCP connection to a transparent proxy, the following commands are used:
@@ -110,6 +110,17 @@ In the PREROUTING DNAT chain, it is possible to any global address or to the lin
the packet came from.
NFQUEUE works without changes.
## nftables
nftables are fine except one very big problem.
nft requires tons of RAM to load large nf sets (ip lists) with subnets/intervals. Most of the home routers can't afford that.
For example, even a 256 Mb system can't load a 100K ip list. nft process will OOM.
nf sets do not support overlapping intervals and that's why nft process applies very RAM consuming algorithm to merge intervals so they don't overlap.
There're equivalents to iptables for all other functions. Interface and protocol anonymous sets allow not to write multiple similar rules.
Flow offloading is built-in into new linux kernels and nft versions.
## When it will not work
* If DNS server returns false responses. ISP can return false IP addresses or not return anything
@@ -564,6 +575,9 @@ if remote resolving causes trouble configure clients to use local name resolutio
## Ways to get a list of blocked IP
nftables can't work with ipsets. Native nf sets require lots of RAM to load large ip lists with subnets and intervals.
In case you're on a low RAM system and need large lists it may be required to fall back to iptables+ipset.
1. Enter the blocked domains to `ipset/zapret-hosts-user.txt` and run `ipset/get_user.sh`
At the output, you get `ipset/zapret-ip-user.txt` with IP addresses.
@@ -643,6 +657,12 @@ When using large regulator lists estimate the amount of RAM on the router !
The file `/opt/zapret/config` is used by various components of the system and contains basic settings.
It needs to be viewed and edited if necessary.
Which firewall type use on linux systems : `nftables` or `iptables`.
On traditional systems `nftables` is selected by default if nft is installed.
On openwrt by default `nftables` is selected on `firewall4` based systems.
`FWTYPE=iptables`
Main mode :
```
@@ -739,8 +759,9 @@ temp directory. Used by ipset/*.sh scripts for large lists processing.
/tmp by default. Can be reassigned if /tmp is tmpfs and RAM is low.
TMPDIR=/opt/zapret/tmp
ipset options :
ipset and nfset options :
`SET_MAXELEM=262144`
`IPSET_OPT="hashsize 262144 maxelem 2097152`
Kernel automatically increases hashsize if ipset is too large for the current hashsize.
@@ -770,6 +791,11 @@ In openwrt there's default network 'lan'. Only traffic coming from this network
To override this behaviour set the following variable :
`OPENWRT_LAN="lan lan2 lan3"`
The `INIT_APPLY_FW=1` parameter enables the init script to independently apply iptables rules.
With other values or if the parameter is commented out, the rules will not be applied.
This is useful if you have a firewall management system, in the settings of which you should tie the rules.
Not applicable to `OpenWRT` if used with `firewall3+iptables`.
The following settings are not relevant for openwrt :
If your system works as a router, then you need to enter the names of the internal and external interfaces:
@@ -781,10 +807,6 @@ IMPORTANT: configuring routing, masquerade, etc. not a zapret task.
Only modes that intercept transit traffic are enabled.
It's possible to specify multiple interfaces like this : `IFACE_LAN="eth0 eth1 eth2"`
The `INIT_APPLY_FW=1` parameter enables the init script to independently apply iptables rules.
With other values or if the parameter is commented out, the rules will not be applied.
This is useful if you have a firewall management system, in the settings of which you should tie the rules.
## Screwing to the firewall control system or your launch system
@@ -795,17 +817,41 @@ In this case, the rules for iptables should be screwed to your firewall separate
The following calls allow you to apply or remove iptables rules separately:
```
/opt/zapret/init.d/sysv/zapret start-fw
/opt/zapret/init.d/sysv/zapret stop-fw
/opt/zapret/init.d/sysv/zapret start_fw
/opt/zapret/init.d/sysv/zapret stop_fw
/opt/zapret/init.d/sysv/zapret restart_fw
```
And you can start or stop the demons separately from the firewall:
```
/opt/zapret/init.d/sysv/zapret start-daemons
/opt/zapret/init.d/sysv/zapret stop-daemons
/opt/zapret/init.d/sysv/zapret start_daemons
/opt/zapret/init.d/sysv/zapret stop_daemons
/opt/zapret/init.d/sysv/zapret restart_daemons
```
nftables nearly eliminate conflicts betweeen firewall control systems because they allow
separate tables and netfilter hooks. `zapret` nf table is used for zapret purposes.
If your system does not touch it everything will likely be OK.
Some additional nftables-only calls exist :
Lookup `lanif`, `wanif`, `wanif6` and `flow table` interface sets.
```
/opt/zapret/init.d/sysv/zapret list_ifsets
```
Renew `lanif`, `wanif`, `wanif6` and `flow table` interface sets.
Taken from `IFACE_LAN`, `IFACE_WAN` config variables on traditional Linux systems.
Autoselected on `OpenWRT`. `lanif` can be extended using `OPENWRT_LAN` config variable.
/opt/zapret/init.d/sysv/zapret reload_ifsets
Calls `nft -t list table inet zapret`.
```
/opt/zapret/init.d/sysv/zapret list_table
```
## Installation
### Checking ISP

View File

@@ -1,4 +1,4 @@
zapret v.45
zapret v.46
English
-------
@@ -63,7 +63,7 @@ For english version refer to docs/readme.eng.txt
Для вариантов 2 и 3 реализованы программы tpws и nfqws соответственно.
Чтобы они работали, необходимо их запустить с нужными параметрами и перенаправить на них определенный трафик
средствами iptables.
средствами iptables или nftables.
Для перенаправления tcp соединения на transparent proxy используются команды следующего вида :
@@ -149,6 +149,14 @@ DNAT на localhost (::1) возможен только в цепочке OUTPUT
NFQUEUE работает без изменений.
Особенности применения nftables
-------------------------------
Более подробно преимущества и недостатки nftables применительно к данной системе описаны в docs/nftables_notes.txt
Если коротко, то в nftables невозможно работать с большими ip листами на системах с малым количеством RAM.
Остальные рассматриваемые здесь функции могут быть перенесены на nftables.
Когда это работать не будет
---------------------------
@@ -490,6 +498,9 @@ options ip6table_raw raw_before_defrag=1
Это нужно сделать вручную, никакой автоматики в blockcheck.sh нет.
Либо можно раз и навсегда избавиться от этой проблемы, используя nftables. Там можно создать netfilter hook
с любым приоритетом. Используйте приоритет -401 и ниже.
tpws
-----
@@ -642,6 +653,10 @@ tpws полностью работает на асинхронных сокет
Способы получения списка заблокированных IP
-------------------------------------------
!!! nftables не могут работать с ipset-ами. Собственный аналогичный механизм требует огромного количество RAM
!!! для загрузки больших листов. Например, для загона 100K записей в nfset не хватает даже 256 Mb.
!!! Если вам нужны большие листы на домашних роутерах, откатывайтесь на iptables+ipset.
1) Внесите заблокированные домены в ipset/zapret-hosts-user.txt и запустите ipset/get_user.sh
На выходе получите ipset/zapret-ip-user.txt с IP адресами.
@@ -829,6 +844,11 @@ tpws и nfqws решают нужно ли применять дурение в
Файл /opt/zapret/config используется различными компонентами системы и содержит основные настройки.
Его нужно просмотреть и при необходимости отредактировать.
На linux системах можно выбрать использовать iptables или nftables.
По умолчанию на традиционных linux выбирается nftables, если установлен nft.
На openwrt по умолчанию выбирается nftables на новых версиях с firewall4.
FWTYPE=iptables
Основной режим :
tpws - tpws в режиме transparent
@@ -910,8 +930,11 @@ MDIG_THREADS=30
указать место на флэшке или диске.
TMPDIR=/opt/zapret/tmp
Опции для создания ipset-ов
Опции для создания ipset-ов и nfset-ов
SET_MAXELEM=262144
IPSET_OPT="hashsize 262144 maxelem 2097152"
ПРО РУГАНЬ в dmesg по поводу нехватки памяти.
Может так случиться, что памяти в системе достаточно, но при попытке заполнить огромный ipset
ядро начинает громко ругаться, ipset заполняется не полностью.
@@ -939,6 +962,11 @@ GZIP_LISTS=1
Но возможно задать другие сети или список сетей :
OPENWRT_LAN="lan lan2 lan3"
Параметр INIT_APPLY_FW=1 разрешает init скрипту самостоятельно применять правила iptables.
При иных значениях или если параметр закомментирован, правила применены не будут.
Это полезно, если у вас есть система управления фаерволом, в настройки которой и следует прикрутить правила.
На openwrt неприменимо при использовании firewall3+iptables.
Следующие настройки не актуальны для openwrt :
Если ваша система работает как роутер, то нужно вписать названия внутреннего и внешнего интерфейсов :
@@ -948,10 +976,6 @@ IFACE_WAN=eth1
Включаются только режимы, обеспечивающие перехват транзитного трафика.
Возможно определить несколько интерфейсов следующим образом : IFACE_LAN="eth0 eth1 eth2"
Параметр INIT_APPLY_FW=1 разрешает init скрипту самостоятельно применять правила iptables.
При иных значениях или если параметр закомментирован, правила применены не будут.
Это полезно, если у вас есть система управления фаерволом, в настройки которой и следует прикрутить правила.
Прикручивание к системе управления фаерволом или своей системе запуска
----------------------------------------------------------------------
@@ -961,13 +985,34 @@ IFACE_WAN=eth1
Следующие вызовы позволяют применить или убрать правила iptables отдельно :
/opt/zapret/init.d/sysv/zapret start-fw
/opt/zapret/init.d/sysv/zapret stop-fw
/opt/zapret/init.d/sysv/zapret start_fw
/opt/zapret/init.d/sysv/zapret stop_fw
/opt/zapret/init.d/sysv/zapret restart_fw
А так можно запустить или остановить демоны отдельно от фаервола :
/opt/zapret/init.d/sysv/zapret start-daemons
/opt/zapret/init.d/sysv/zapret stop-daemons
/opt/zapret/init.d/sysv/zapret start_daemons
/opt/zapret/init.d/sysv/zapret stop_daemons
/opt/zapret/init.d/sysv/zapret restart_daemons
nftables сводят практически на нет конфликты между разными системами управления, поскольку позволяют
использовать независимые таблицы и хуки. Используется отдельная nf-таблица "zapret".
Если ваша система ее не будет трогать, скорее всего все будет нормально.
Для nftables предусмотрено несколько дополнительных вызовов :
Посмотреть set-ы интерфейсов, относящихся к lan, wan и wan6. По ним идет завертывание трафика.
А так же таблицу flow table с именами интерфейсов ingress hook.
/opt/zapret/init.d/sysv/zapret list_ifsets
Обновить set-ы интерфейсов, относящихся к lan, wan и wan6.
Для традиционных linux список интерфейсов берется из переменных конфига IFACE_LAN, IFACE_WAN.
Для openwrt определяется автоматически. Множество lanif может быть расширено параметром OPENWRT_LAN.
Все интерфейсы lan и wan так же добавляются в ingress hook от flow table.
/opt/zapret/init.d/sysv/zapret reload_ifsets
Просмотр таблицы без содержимого set-ов. Вызывает nft -t list table inet zapret
/opt/zapret/init.d/sysv/zapret list_table
Вариант custom
--------------
@@ -980,20 +1025,22 @@ custom код вынесен в отдельный shell include
Нужно свой код вписать в функции :
zapret_custom_daemons
zapret_custom_firewall
zapret_custom_firewall_nft
В файле custom пишите ваш код, пользуясь хелперами из "functions" или "zapret".
Смотрите как там сделано добавление iptables или запуск демонов.
Используя хелпер функции, вы избавитесь от необходимости учитывать все возможные случаи
типа наличия/отсутствия ipv6, является ли система роутером, имена интерфейсов, ...
Хелперы это учитывают , вам нужно сосредоточиться лишь на фильтрах iptables и
Хелперы это учитывают , вам нужно сосредоточиться лишь на фильтрах {ip,nf}tables и
параметрах демонов.
Код для openwrt и sysv немного отличается. В sysv нужно обрабатывать и запуск, и остановку.
Код для openwrt и sysv немного отличается. В sysv нужно обрабатывать и запуск, и остановку демонов.
Запуск это или остановка передается в параметре $1 (0 или 1).
В openwrt за остановку демонов отвечает procd, а firewall вычищается при "fw3 restart",
потому нет необходимости реализовывать логику останова.
В openwrt за остановку отвечает procd.
При апгрейде нужно сохранить лишь custom, другие файлы править не надо.
Для фаервола кастом пишется отдельно для iptables и nftables. Все очень похоже, но отличается
написание фильтров и названия процедур хелперов. Если вам не нужны iptables или nftables -
можете не писать соответствующую функцию.
Готовый custom скрипт custom-tpws4http-nfqws4https позволяет применить дурение
tpws к http и nfqws к https. При этом поддерживаются установки из config.
@@ -1011,6 +1058,8 @@ tpws к http и nfqws к https. При этом поддерживаются у
apt-get update
apt-get install ipset curl dnsutils git
Если хотите использовать nftables, то нужен пакет nftables, а ipset не обязателен.
Скопировать директорию zapret в /opt или скачать через git :
cd /opt
git clone --depth 1 https://github.com/bol-van/zapret
@@ -1124,7 +1173,7 @@ git и curl по умолчанию могут присутствовать, ips
Подключить init скрипт :
ln -fs /opt/zapret/init.d/sysv/zapret /etc/init.d
ln -fs /opt/zapret/init.d/openrc/zapret /etc/init.d
rc-update add zapret
Запустить службу :
@@ -1174,8 +1223,11 @@ install_easy.sh автоматизирует описанные выше руч
Деинсталяция выполняется через uninstall_easy.sh
Ручная установка на openwrt/LEDE
--------------------------------
Ручная установка на openwrt/LEDE 15.xx-21.xx
--------------------------------------------
!!! Данная инструкция написана для систем, основанных на iptables+firewall3
!!! В новых версиях openwrt переходит на nftables+firewall4, инструкция неприменима. Пользуйтесь install_easy.sh
Установить дополнительные пакеты :
opkg update
@@ -1283,10 +1335,10 @@ Cкрипт из /etc/hotplug.d/iface перезапустит демоны по
Посмотреть через iptables -nL, ip6tables -nL или через luci вкладку "firewall" появились ли нужные правила.
ЭКОНОМИЯ МЕСТА : если его мало, то можно оставить в директории zapret лишь подкаталог ipset, файл config и init.d/openwrt.
ЭКОНОМИЯ МЕСТА : если его мало, то можно оставить в директории zapret лишь подкаталоги
ipset, common, файл config, init.d/openwrt.
Далее нужно создать подкаталоги с реально используемыми бинариками (ip2net, mdig, tpws, nfq)
и скопировать туда из binaries рабочие executables.
Рекомендуется оставить ip2net и mdig. Из tpws и nfq оставить лишь тот, что был выбран в config.
ЕСЛИ ВСЕ ПЛОХО С МЕСТОМ : откажитесь от работы со списком РКН. используйте только get_user.sh