nftables (Русский)

Ссылки по теме
iptables (Русский)
Firewalld
Состояние перевода:
На этой странице представлен перевод статьи
nftables
. Дата последней синхронизации: 11 июля 2021. Вы можете
помочь
синхронизировать перевод, если в английской версии произошли
изменения
.
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-git
AUR
.
Совет
Большинство
фронтендов
iptables не предлагают прямой или косвенной поддержки nftables, хотя подобная возможность предусмотрена
[1]
.
firewalld
— единственный графический фронтенд со встроенной поддержкой как iptables, так и nftables
[2]
.
Использование
В 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) и содержатся внутри цепочек.
Добавление правила
Совет
Утилита
iptables-translate
поможет преобразовать правила
iptables
в формат nftables.
Добавить правило в цепочку:
# 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
[
ссылка недействительна
: replaced by
iptables
]
; он содержит 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