nftables (Русский)
nftables — проект netfilter, разработанный для замены существующего фреймворка {ip,ip6,arp,eb}tables. Предоставляет новую систему фильтрации пакетов, пользовательскую утилиту ntf, а также слой совместимости с {ip,ip6}tables. nftables использует существующие хуки, отслеживание соединений, очереди в пространстве пользователя и подсистему логирования netfilter.
nftables состоит из трёх основных частей: низкоуровневая реализация в ядре, библиотека libnl, которая обеспечивает netlink-взаимодействие, и пользовательский фронтенд nftables. Ядро предоставляет интерфейс настройки netlink, а также занимается runtime-выполнением наборов правил. Библиотека libnl содержит низкоуровневые функции для взаимодействия с ядром. Фронтенд nftables — то, с чем пользователь взаимодействует утилитой nft.
Подробную информацию о nftables можно найти на вики-странице проекта.
Установка
Установите пакет nftables или git-версию nftables-gitAUR.
Использование
В nftables не различаются временные правила, добавленные из командной строки, и постоянные, загруженные из файла или сохранённые в файл.
Все правила должны создаваться или загружаться утилитой nft
. Подробнее о работе с ней см. раздел #Настройка.
Текущий набор правил можно узнать командой:
# nft list ruleset
Простой межсетевой экран
В пакет nftables входит простая и надёжная конфигурация экрана, сохранённая в файле /etc/nftables.conf
.
Служба nftables.service
загрузит эти правила при запуске или включении.
Настройка
Утилита nft выполняет большую часть обработки правил перед передачей их ядру. Правила объединяются в цепочки, которые, в свою очередь, входят в состав таблиц. В последующих разделах описано создание и модифицирование этих структур.
Прочитать правила из файла можно с помощью опции -f
/--file
:
# nft --file имя-файла
Обратите внимание, что уже загруженные на этот момент правила не будут при этом автоматически стёрты.
Полный список команд можно найти в руководстве nft(8).
Таблицы
Таблицы содержат #Цепочки. В отличие от iptables, в nftables отсутствуют встроенные таблицы. Количество таблиц и их имена определяется пользователем. Тем не менее, каждая таблица имеет только одно семейство адресации и применяется к пакетам только этого семейства. Таблицы могут относиться к одному из пяти семейств.
семейство nftables | утилита iptables |
---|---|
ip | iptables |
ip6 | ip6tables |
inet | iptables и ip6tables |
arp | arptables |
bridge | ebtables |
ip
(т.е. IPv4) — семейство по умолчанию; используется, если семейство не было указано.
Семейство inet
объединяет протоколы IPv4 и IPv6, что позволяет унифицировать семейства ip
и ip6
и упростить создание правил.
Описание остальных семейств адресации вы найдёте в руководстве nft(8) § ADDRESS FAMILIES.
В командах ниже параметр семейство
будет указываться не всегда; если его нет, то подразумевается семейство ip
.
Создание таблицы
Добавить новую таблицу:
# nft add table семейство таблица
Просмотр таблиц
Вывести список таблиц:
# nft list tables
Просмотр цепочек и правил в таблице
Вывести цепочки и правила выбранной таблицы:
# nft list table семейство таблица
Например, чтобы вывести на экран правила таблицы my_table
семейства inet
, выполните команду:
# nft list table inet my_table
Удаление таблицы
Удалить таблицу со всеми цепочками:
# nft delete table семейство таблица
Очистка таблицы
Стереть все правила в таблице:
# nft flush table семейство таблица
Цепочки
Цепочка содержит #Правила. В отличие от iptables, в nftables отсутствуют встроенные цепочки. Соответственно, если опрелённые типы или хуки фреймворка netfilter не задействованы ни в одной цепочке, то проходящие через эти цепочки пакеты обрабатываться не будут (в отличие от iptables).
Есть два типа цепочек. Базовая цепочка является точкой входа для пакетов из сетевого стека; в ней указывается хук. Обычная цепочка может использоваться в качестве цели перехода и используется для лучшей организации правил.
В командах ниже параметр семейство
будет указываться не всегда; если его нет, то подразумевается семейство ip
.
Создание цепочки
Обычная цепочка
Добавить обычную цепочку цепочка
в таблицу таблица
:
# nft add chain семейство таблица цепочка
Например, чтобы добавить обычную цепочку my_tcp_chain
к таблице my_table
семейства адресации inet
, выполните:
# nft add chain inet my_table my_tcp_chain
Базовая цепочка
Чтобы добавить базовую цепочку, укажите хук и значение приоритета:
# nft add chain семейство таблица цепочка '{ type тип hook хук priority приоритет ; }'
тип
может принимать значения filter
, route
или nat
.
Для семейств адресации IPv4/IPv6/Inet хук
может принимать значения prerouting
, input
, forward
, output
или postrouting
. Описание других возможных хуков вы найдёте в руководстве nft(8) § ADDRESS FAMILIES.
Параметр приоритет
задаётся названием приоритета или его численным значением (подробнее см. nft(8) § CHAINS). Цепочки с более низкими значениями обрабатываются раньше. Значение приоритета может быть отрицательным [3].
Например, добавим базовую цепочку для фильтрации входящих пакетов:
# nft add chain inet my_table my_chain '{ type filter hook input priority 0; }'
Если заменить команду add
на create
в любом из правил выше, то цепочка тоже будет создана, но если цепочка с таким названием уже существует, то вы получите сообщение об ошибке.
Просмотр правил
Следующая команда выводит на экран все правила в цепочке:
# nft list chain семейство таблица цепочка
Например, следующая команда выведет правила цепочки my_output
таблицы my_table
семейства inet
:
# nft list chain inet my_table my_output
Изменение цепочки
Для редактирования цепочки укажите её название и правила, которые нужно изменить:
# nft chain семейство таблица цепочка '{ [ type тип hook хук device устройство priority приоритет ; policy политика ; ] }'
Например, для изменения политики обработки входящих пакетов цепочки исходной таблицы с accept
на drop
выполните команду:
# nft chain inet my_table my_input '{ policy drop ; }'
Удаление цепочки
Удалить цепочку:
# nft delete chain семейство таблица цепочка
Цепочка должна быть пустой (не содержащей правил) и не должна быть целью перехода из другой цепочки.
Очистка цепочки
Стереть все правила в цепочке:
# nft flush chain семейство таблица цепочка
Правила
Правила конструируются из выражений (expressions) и операторов (statements) и содержатся внутри цепочек.
Добавление правила
Добавить правило в цепочку:
# nft add rule семейство таблица цепочка handle маркер оператор
Правило будет прикреплено после маркер
, который можно не указывать. Если маркер (handle) не задать, то правило добавится в конец цепочки.
Чтобы добавить правило перед определённой позицией, выполните
# nft insert rule семейство таблица цепочка handle маркер оператор
Если маркер
не указан, то правило добавится в начало цепочки.
Выражения
Обычно оператор
включает некоторое выражение для сравнения и вынесения решения. Решениями могут быть accept
, drop
, queue
, continue
, return
, jump цепочка
и goto цепочка
. Возможны и другие операторы помимо решений, подробнее смотрите nft(8).
В nftables доступен ряд выражений, по большей части совпадающий с аналогичными в iptables. Наиболее важное отличие заключается в том, что здесь нет обобщённых или неявных параметров. Обобщённый параметр (generic match) обычно доступен для всех правил, например, параметры --protocol
или --source
. Неявные правила (implicit matches) относятся к конкретному протоколу, как параметр --sport
для пакетов TCP.
Ниже представлен неполный список возможных параметров:
- meta (метасущности, напр. интерфейсы)
- icmp (протокол ICMP)
- icmpv6 (протокол ICMPv6)
- ip (протокол IP)
- ip6 (протокол IPv6)
- tcp (протокол TCP)
- udp (протокол UDP)
- sctp (протокол SCTP)
- ct (отслеживание соединений)
Ниже приведён неполный список аргументов для параметров (подробнее см. nft(8)):
meta: oif <интерфейс-отправитель НОМЕР> iif <интерфейс-получатель НОМЕР> oifname <интерфейс-отправитель ИМЯ> iifname <интерфейс-получатель ИМЯ> (параметры oif и iif принимают строковые значения, которые конвертируются в номер) (параметры oifname и iifname более гибкие, но они медленнее из-за необходимости выполнять сравнение строк) icmp: type <тип icmp> icmpv6: type <тип icmpv6> ip: protocol <протокол> daddr <адрес получателя> saddr <адрес отправителя> ip6: daddr <адрес получателя> saddr <адрес отправителя> tcp: dport <порт получателя> sport <порт отправителя> udp: dport <порт получателя> sport <порт отправителя> sctp: dport <порт получателя> sport <порт отправителя> ct: state <new | established | related | invalid>
Удаление
Отдельные правила могут быть удалены только с помощью маркера. Команда nft --handle list
выведет список маркеров.
Ниже приведён пример правила с маркером и команда для его удаления. Аргумент --numeric
позволяет выводить IP-адреса в численном виде.
# nft --handle --numeric list chain inet my_table my_input
table inet my_table { chain my_input { type filter hook input priority 0; ip saddr 127.0.0.1 accept # handle 10 } }
# nft delete rule inet my_table my_input handle 10
Стирание всех цепочек таблицы выполняется командой nft flush table
. Отдельные цепочки могут быть стёрты командами nft flush chain
или nft delete rule
.
# nft flush table таблица # nft flush chain семейство таблица цепочка # nft delete rule семейство таблица цепочка
Первая команда стирает все цепочки в ip-таблице таблица
. Вторая очищает цепочку цепочка
в таблице таблица
семейства семейство
. Третья удаляет все правила в цепочке цепочка
в таблице таблица
семейства семейство
.
Множества
Множества бывают именованные и анонимные. Множество объявляется фигурными скобками, в которых перечислены разделённые запятыми элементы. Анонимные множества "встраиваются" в правило и не могут быть изменены отдельно от него. Если множество необходимо модифицировать, то придётся удалить правило целиком и добавить его заново. Так, не получится удалить "http" из множества dport'ов в следующем правиле:
# nft add rule ip6 filter input tcp dport {telnet, http, https} accept
Именованное множество можно изменить, а также присвоить ему тип и установить флаги. sshguard использует именованные множества для хранения адресов блокированных хостов.
table ip sshguard { set attackers { type ipv4_addr flags interval elements = { 1.2.3.4 } }
Команды для добавления и удаления элементов из множества:
# nft add element ip sshguard attackers { 5.6.7.8/32 } # nft delete element ip sshguard attackers { 1.2.3.4/32 }
Если множество имеет тип ipv4_addr, то помимо адреса можно указать маску сети (маска "/32" в примере не обязательна, но указана для большей ясности). Обращение к множеству из примера выше ("TABLE ip sshguard { SET attackers }") производится по имени ip sshguard attackers
.
Полная перезагрузка правил
Создать файл для новых правил:
# echo "flush ruleset" > /tmp/nftables
Сбросить дамп правил в новый файл:
# nft -s list ruleset >> /tmp/nftables
Теперь можно редактировать файл /tmp/nftables
, создавая и изменяя правила. Применить изменения можно командой:
# nft -f /tmp/nftables
Примеры
Рабочая станция
/etc/nftables.conf
flush ruleset table inet my_table { set LANv4 { type ipv4_addr flags interval elements = { 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16, 169.254.0.0/16 } } set LANv6 { type ipv6_addr flags interval elements = { fd00::/8, fe80::/10 } } chain my_input_lan { udp sport 1900 udp dport >= 1024 meta pkttype unicast limit rate 4/second burst 20 packets accept comment "Accept UPnP IGD port mapping reply" udp sport netbios-ns udp dport >= 1024 meta pkttype unicast accept comment "Accept Samba Workgroup browsing replies" } chain my_input { type filter hook input priority filter; policy drop; iif lo accept comment "Accept any localhost traffic" ct state invalid drop comment "Drop invalid connections" ct state established,related accept comment "Accept traffic originated from us" meta l4proto ipv6-icmp icmpv6 type { destination-unreachable, packet-too-big, time-exceeded, parameter-problem, mld-listener-query, mld-listener-report, mld-listener-reduction, nd-router-solicit, nd-router-advert, nd-neighbor-solicit, nd-neighbor-advert, ind-neighbor-solicit, ind-neighbor-advert, mld2-listener-report } accept comment "Accept ICMPv6" meta l4proto icmp icmp type { destination-unreachable, router-solicitation, router-advertisement, time-exceeded, parameter-problem } accept comment "Accept ICMP" ip protocol igmp accept comment "Accept IGMP" udp dport mdns ip6 daddr ff02::fb accept comment "Accept mDNS" udp dport mdns ip daddr 224.0.0.251 accept comment "Accept mDNS" ip6 saddr @LANv6 jump my_input_lan comment "Connections from private IP address ranges" ip saddr @LANv4 jump my_input_lan comment "Connections from private IP address ranges" counter comment "Count any other traffic" } chain my_forward { type filter hook forward priority filter; policy drop; # Drop everything forwarded to us. We do not forward. That is routers job. } chain my_output { type filter hook output priority filter; policy accept; # Accept every outbound connection } }
Сервер
/etc/nftables.conf
flush ruleset table inet my_table { set LANv4 { type ipv4_addr flags interval elements = { 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16, 169.254.0.0/16 } } set LANv6 { type ipv6_addr flags interval elements = { fd00::/8, fe80::/10 } } chain my_input_lan { meta l4proto { tcp, udp } th dport 2049 accept comment "Accept NFS" udp dport netbios-ns accept comment "Accept NetBIOS Name Service (nmbd)" udp dport netbios-dgm accept comment "Accept NetBIOS Datagram Service (nmbd)" tcp dport netbios-ssn accept comment "Accept NetBIOS Session Service (smbd)" tcp dport microsoft-ds accept comment "Accept Microsoft Directory Service (smbd)" udp sport { bootpc, 4011 } udp dport { bootps, 4011 } accept comment "Accept PXE" udp dport tftp accept comment "Accept TFTP" } chain my_input { type filter hook input priority filter; policy drop; iif lo accept comment "Accept any localhost traffic" ct state invalid drop comment "Drop invalid connections" ct state established,related accept comment "Accept traffic originated from us" meta l4proto ipv6-icmp icmpv6 type { destination-unreachable, packet-too-big, time-exceeded, parameter-problem, mld-listener-query, mld-listener-report, mld-listener-reduction, nd-router-solicit, nd-router-advert, nd-neighbor-solicit, nd-neighbor-advert, ind-neighbor-solicit, ind-neighbor-advert, mld2-listener-report } accept comment "Accept ICMPv6" meta l4proto icmp icmp type { destination-unreachable, router-solicitation, router-advertisement, time-exceeded, parameter-problem } accept comment "Accept ICMP" ip protocol igmp accept comment "Accept IGMP" udp dport mdns ip6 daddr ff02::fb accept comment "Accept mDNS" udp dport mdns ip daddr 224.0.0.251 accept comment "Accept mDNS" ip6 saddr @LANv6 jump my_input_lan comment "Connections from private IP address ranges" ip saddr @LANv4 jump my_input_lan comment "Connections from private IP address ranges" tcp dport ssh accept comment "Accept SSH on port 22" tcp dport ipp accept comment "Accept IPP/IPPS on port 631" tcp dport { http, https, 8008, 8080 } accept comment "Accept HTTP (ports 80, 443, 8008, 8080)" udp sport bootpc udp dport bootps ip saddr 0.0.0.0 ip daddr 255.255.255.255 accept comment "Accept DHCPDISCOVER (for DHCP-Proxy)" } chain my_forward { type filter hook forward priority filter; policy drop; # Drop everything forwarded to us. We do not forward. That is routers job. } chain my_output { type filter hook output priority filter; policy accept; # Accept every outbound connection } }
Ограничение скорости передачи
table inet my_table { chain my_input { type filter hook input priority filter; policy drop; iif lo accept comment "Accept any localhost traffic" ct state invalid drop comment "Drop invalid connections" meta l4proto icmp icmp type echo-request limit rate over 10/second burst 4 packets drop comment "No ping floods" meta l4proto ipv6-icmp icmpv6 type echo-request limit rate over 10/second burst 4 packets drop comment "No ping floods" ct state established,related accept comment "Accept traffic originated from us" meta l4proto ipv6-icmp icmpv6 type { destination-unreachable, packet-too-big, time-exceeded, parameter-problem, mld-listener-query, mld-listener-report, mld-listener-reduction, nd-router-solicit, nd-router-advert, nd-neighbor-solicit, nd-neighbor-advert, ind-neighbor-solicit, ind-neighbor-advert, mld2-listener-report } accept comment "Accept ICMPv6" meta l4proto icmp icmp type { destination-unreachable, router-solicitation, router-advertisement, time-exceeded, parameter-problem } accept comment "Accept ICMP" ip protocol igmp accept comment "Accept IGMP" tcp dport ssh ct state new limit rate 15/minute accept comment "Avoid brute force on SSH" } }
Переход
Если вы используете переходы (jumps), то целевая цепочка должна быть описана до перехода. Иначе будет получена ошибка Error: Could not process rule: No such file or directory
.
table inet my_table { chain web { tcp dport http accept tcp dport 8080 accept } chain my_input { type filter hook input priority filter; ip saddr 10.0.2.0/24 jump web drop } }
Несколько сетевых интерфейсов с разными правилами
Если у вашей системы несколько сетевых интерфейсов и вы хотите использовать для них разные наборы правил, то создайте фильтрующую цепочку-диспетчер, а после неё опишите цепочки для сетевых интерфейсов. Например, пусть ваша машина выступает в качестве домашнего маршрутизатора и вы желаете запустить веб-сервер, доступный по локальной сети (интерфейс enp3s0
), но не из публичного интернета (интерфейс enp2s0
). Создайте таблицу вроде этой:
table inet my_table { chain my_input { # this chain serves as a dispatcher type filter hook input priority filter; iif lo accept # always accept loopback iifname enp2s0 jump my_input_public iifname enp3s0 jump my_input_private reject with icmpx type port-unreachable # refuse traffic from all other interfaces } chain my_input_public { # rules applicable to public interface interface ct state {established,related} accept ct state invalid drop udp dport bootpc accept tcp dport bootpc accept reject with icmpx type port-unreachable # all other traffic } chain my_input_private { ct state {established,related} accept ct state invalid drop udp dport bootpc accept tcp dport bootpc accept tcp port http accept tcp port https accept reject with icmpx type port-unreachable # all other traffic } chain my_output { # we let everything out type filter hook output priority filter; accept } }
Можно поступить иначе - задать только одну строку iifname
, например для интерфейса веб-сервера, а правила для остальных интерфейсов вместо диспетчеризации описать в одном месте.
Маскарадинг
В nftables есть специальное ключевое слово masquerade
, "позволяющее автоматически изменять адрес источника на адрес интерфейса-отправителя" [4]. Это особенно удобно в ситуациях, когда IP-адрес интерфейса непредсказуем или нестабилен — например, исходящий интерфейс маршрутизатора, подключённого к нескольким интернет-провайдерам. Маскарадинг позволяет не переписывать правила межсетевого экрана для трансляции сетевых адресов (NAT) при каждом изменении IP-адреса интерфейса.
Правила работы маскарадинга:
- опция
masquerading
в ядре Linux должна быть включена (в стандартном ядре она включена по умолчанию); в противном случае задайте параметр ядраCONFIG_NFT_MASQ=m
. - ключевое слово
masquerade
может использоваться только в цепочке типаnat
. - masquerading является подвидом SNAT, поэтому работает только для исходящих пакетов.
Пример правил межсетевого экрана для машины с двумя интерфейсами, локальным enp3s0
и публичным enp2s0
:
table inet my_nat { chain my_masquerade { type nat hook postrouting priority srcnat; oifname "enp2s0" masquerade } }
Поскольку таблица выше относится к типу inet
, то маскарадингу подвергаются пакеты и IPv4, и IPv6. Чтобы ограничить маскарадинг только IPv4-пакетами (т.к. у IPv6 большое пространство адресов и NAT не требуется) либо добавьте выражение meta nfproto ipv4
перед oifname "enp2s0" masquerade
, либо измените тип таблицы на ip
.
NAT с пробросом портов
Ниже приведён пример проброса портов 22 и 80 на адрес ip-адрес_получателя
. Необходимо предварительно с помощью sysctl установить параметры net.ipv4.ip_forward
и net.ipv4.conf.wan_интерфейс.forwarding
на 1
.
table ip my_nat { chain my_prerouting { type nat hook prerouting priority dstnat; tcp dport { ssh, http } dnat to destination_ip } chain my_postrouting { type nat hook postrouting priority srcnat; ip daddr destination_ip masquerade } }
Счётчик новых соединений
Следующий сниппет позволяет считать открытые HTTPS-соединения:
/etc/nftables.conf
table inet filter { set https { type ipv4_addr; flags dynamic; size 65536; timeout 60m; } chain input { type filter hook input priority filter; ct state new tcp dport 443 update @https { ip saddr counter } } }
Текущее значение счётчика можно вывести командой nft list set inet filter https
.
Динамическая блокировка
Следующий сниппет позволяет в течение минуты отклонять все HTTPS-соединения от адресов, которые превысили лимит в 10 запросов на соединение в секунду:
/etc/nftables.conf
table inet dev { set blackhole { type ipv4_addr; flags dynamic, timeout; size 65536; } chain input { ct state new tcp dport 443 \ meter flood size 128000 { ip saddr timeout 10s limit rate over 10/second } \ add @blackhole { ip saddr timeout 1m } ip saddr @blackhole counter drop } }
Для вывода заблокированных адресов выполните nft list set inet dev blackhole
.
Советы и рекомендации
Сохранение текущего набора правил
Вывод команды nft list ruleset
можно использовать в качестве входных данных для других команд. Текущий набор правил можно сохранить в файл, а позже — загрузить их из него.
# nft -s list ruleset | tee название_файла
nft list
не выводит определения переменных. Если в файле /etc/nftables.conf
есть какие-либо переменные, то в выводе команды вы их не увидите — все переменные будут заменены на значения.
Настройка межсетевого экрана
См. также Настройка межсетевого экрана.
Одиночная машина
Сотрите текущий набор правил:
# nft flush ruleset
Добавьте таблицу:
# nft add table inet my_table
Добавьте базовые цепочки input, forward и output. Политика для входящих и пересылаемых пакетов должна быть drop. Политика для исходящих пакетов — accept.
# nft add chain inet my_table my_input '{ type filter hook input priority 0 ; policy drop ; }' # nft add chain inet my_table my_forward '{ type filter hook forward priority 0 ; policy drop ; }' # nft add chain inet my_table my_output '{ type filter hook output priority 0 ; policy accept ; }'
Добавьте две обычные цепочки, которые будут обрабатывать пакеты протоколов TCP и UDP:
# nft add chain inet my_table my_tcp_chain # nft add chain inet my_table my_udp_chain
Разрешите related и established трафик:
# nft add rule inet my_table my_input ct state related,established accept
Разрешите трафик на петлевой интерфейс:
# nft add rule inet my_table my_input iif lo accept
Заблокируйте invalid трафик:
# nft add rule inet my_table my_input ct state invalid drop
Разрешите пакеты ICMP и IGMP:
# nft add rule inet my_table my_input meta l4proto ipv6-icmp icmpv6 type '{ destination-unreachable, packet-too-big, time-exceeded, parameter-problem, mld-listener-query, mld-listener-report, mld-listener-reduction, nd-router-solicit, nd-router-advert, nd-neighbor-solicit, nd-neighbor-advert, ind-neighbor-solicit, ind-neighbor-advert, mld2-listener-report }' accept # nft add rule inet my_table my_input meta l4proto icmp icmp type '{ destination-unreachable, router-solicitation, router-advertisement, time-exceeded, parameter-problem }' accept # nft add rule inet my_table my_input ip protocol igmp accept
Новый UDP-трафик будет передаваться цепочке my_udp_chain
:
# nft add rule inet my_table my_input meta l4proto udp ct state new jump my_udp_chain
Новый TCP-трафик будет передаваться цепочке my_tcp_chain
:
# nft add rule inet my_table my_input 'meta l4proto tcp tcp flags & (fin|syn|rst|ack) == syn ct state new jump my_tcp_chain'
Заблокировать весь трафик, который не обрабатывается другими правилами:
# nft add rule inet my_table my_input meta l4proto udp reject # nft add rule inet my_table my_input meta l4proto tcp reject with tcp reset # nft add rule inet my_table my_input counter reject with icmpx type port-unreachable
В этом месте необходимо выбрать, какие порты будут оставаться открытыми для входящих соединений, обрабатываемых цепочками my_tcp_chain
и my_udp_chain
. Например, открыть соединения для веб-сервера:
# nft add rule inet my_table my_tcp_chain tcp dport 80 accept
Разрешить HTTPS-соединения для веб-сервера на порте 443:
# nft add rule inet my_table my_tcp_chain tcp dport 443 accept
Разрешить SSH-трафик на порт 22:
# nft add rule inet my_table my_tcp_chain tcp dport 22 accept
Разрешить входящие DNS-запросы:
# nft add rule inet my_table my_tcp_chain tcp dport 53 accept # nft add rule inet my_table my_udp_chain udp dport 53 accept
В конце не забудьте сохранить набор правил, чтобы они стали постоянными.
Предотвращение атак перебором
Sshguard может обнаруживать атаки перебором и модифицировать сетевые экраны, временно помещая IP-адреса в чёрный список. Описание настройки nftables для работы с sshguard можно найти в статье Sshguard#nftables.
Журналирование трафика
Действие log
позволяет вести журнал пакетов. Простейшее правило для сохранения информации обо всём поступающем трафике:
# nft add rule inet filter input log
Подробнее см. nftables wiki.
Решение проблем
Работа с Docker
nftables может создавать помехи сетевой работе контейнеров Docker (возможно, и другим средствам виртуализации тоже). В частности, политика drop
цепочки forward
блокирует пакеты, источником которых является docker. Если вы не хотите удалять эту цепочку, то сделайте следующее:
- Установите пакет iptables-nft; он содержит iptables-совместимый интерфейс nftables, который docker сможет использовать.
- Модифицируйте цепочку
forward
таблицыinet
:chain forward { type filter hook forward priority security; policy drop; mark 1 accept }
- Добавьте цепочку DOCKER-USER в таблицу
ip filter
, чтобы помечать (mark) пакеты docker:table ip filter { chain DOCKER-USER { mark set 1 } }
Теперь сгенерированные контейнером docker пакеты будут маркироваться и пересылаться дальше, поскольку docker уже их отфильтровал (цепочка forward
в docker использует политику drop
).
Смотрите также
- netfilter nftables — документация от разработчиков проекта netfilter
- debian:nftables — статья на Debian-wiki
- gentoo:nftables — статья на Gentoo-wiki
- First release of nftables — выход nftables (2009)
- nftables quick howto — советы и подсказки
- The return of nftables — обновление nftables (2013)
- What comes after "iptables"? — nftables со временем заменит iptables