Настройка Nftables

Файрвол

Начинающие админы часто считают, что файрвол в Linux называется iptables. Более опытные знают, что нынешняя подсистема ядра для фильтрации трафика и модификации пакетов называется NetFilter, а команда iptables всего лишь утилита для ее настройки. В этой статье я познакомлю тебя с новым инструментом, который все чаще встречается в современных дистрибутивах, — nftables.

Возможно, для тебя это будет новостью, но iptables вовсе не уникальна, есть и другие утилиты подобного рода. Собственно, настраивать ей можно только правила для пакетов IPv4 на сетевом уровне. Для IPv6 понадобится ip6tables, для канального уровня — ebtables и arptables.

Сравнение iptables Nftables

Настройка сетевых интерфейсов, маршрутов, пространств имен и прочего уже давно унифицирована в утилите ip из пакета iproute2, а зоопарк старых утилит (ifconfig, vconfig, route и прочие) поддерживается только для совместимости со старыми скриптами. Ждет ли такая же унификация межсетевой экран? До версий ядра 2.4 Linux прошел через множество реализаций межсетевых экранов в ядре и утилит для их настройки (ipfilter, ipfwadm, ipchains), но NetFilter и iptables используются уже почти двадцать лет и кажутся незыблемыми.

Как ни странно, первые попытки переосмыслить настройку МСЭ предпринимались еще в 2008 году. Проект назвали nftables, но он стал легендарным (в узких кругах) долгостроем. В 2014 году его наконец приняли в основную ветку ядра 3.13, но пользовательские утилиты какое-то время оставались почти непригодными к работе. К примеру, счетчики пакетов для правил хранились в ядре, но просмотреть их из пространства пользователя не было никакой возможности.

РЕКОМЕНДУЕМ:
Преимущества NFTables

Сейчас дело наконец меняется и дистрибутивы даже начинают использовать nftables по умолчанию. Сторонние инструменты вроде fail2ban тоже уже добавляют ее поддержку.

Несколько причин расстаться с iptables и перейти на nftables:

  • унифицированный синтаксис;
  • быстрая загрузка больших конфигов;
  • встроенная поддержка списков адресов/портов;
  • средства автоматической конвертации правил из iptables;
  • вывод правил в JSON.

В этой статье мы перенесем настройки моего VPS с iptables на nftables. Нужно отметить, что использовать сразу оба инструмента на одной машине не выйдет, так что нужно планировать одномоментную миграцию.

Документацию можно найти в вики проекта.

Проблемы iptables

Хотя NetFilter вполне хорошо справлялся со своей задачей, его настройка через iptables нередко оказывалась куда сложнее, чем могла бы быть.

К примеру, встроенный синтаксис для групп адресов и сетей в нем так и не появился. Существует отдельный инструмент для этих целей — ipset, который позволяет создать группы и ссылаться на них в правилах, вроде iptables -I FORWARD -m set --match-set TrustedHosts src -j ACCEPT.

Однако само то, что группы настраиваются отдельно от правил и с помощью другой утилиты, создает много проблем. Нужно помнить два разных синтаксиса, да еще и убедиться, что настройки ipset при загрузке применяются раньше правил iptables, — это при том, что во многих дистрибутивах Linux встроенного сервиса для ipset так и нет.

Другая надоедливая проблема — нельзя указать несколько разных действий в одном правиле.

Хотя еще больше раздражает отсутствие возможности использовать одни правила для IPv4 и IPv6. В современном мире dual stack уже стал нормой на серверах, машин с одним IPv4 все меньше, а машин с одним IPv6 нет и не предвидится, в итоге админу приходится дублировать одни и те же правила в двух разных конфигах.

Кроме того, в некоторых местах синтаксис опций iptables достаточно хрупкий. Где-то можно ставить пробел после запятой, где-то нет. Где-то можно смело поменять две опции местами, где-то это вызовет ошибку. Если правила генерируются скриптом, это особенно усложняет тестирование.

Все это приводит к тому, что iptables часто используют как своеобразный низкоуровневый «язык ассемблера», который генерируется либо фронтендами вроде shorewall или firewalld, либо пользовательскими скриптами. А цель проекта nftables — в первую очередь сделать настройку правил простой и удобной для человека. Давай посмотрим, насколько это удалось.

Настройка Nftables

Автоматическая трансляция

Авторы nftables определенно учли горький опыт многих других больших миграций и написали инструменты для автоматической трансляции правил из iptables. Можно конвертировать как отдельные команды, так и файлы для iptables-restore.

К сожалению, возможности автоматической трансляции настроек ipset там нет, в первую очередь из-за совершенно разных подходов к настройке групп, ну и из-за малой популярности ipset.

Отдельные правила транслируются с помощью утилиты iptables-translate, а наборы правил из iptables-save — с помощью iptables-restore-translate. Это только для IPv4, для правил ip6tables нужно использовать ip6tables-restore-translate и далее по аналогии.

В Debian эти утилиты находятся в пакете iptables, в Fedora — в пакете iptables-nft.

Посмотрим на трансляцию отдельных правил. Команда iptables-translate — самый простой способ изучить новый синтаксис на примерах (хотя и не заменит чтения документации!).

Как видим, стиль синтаксиса больше похож на pf и другие МСЭ из систем семейства BSD.

Но! Воспользоваться этими командами на неподготовленной системе не выйдет, и вот почему: в nftables больше нет предопределенных таблиц и цепочек.

Хуки вместо цепочек

В iptables цепочки INPUT или FORWARD находятся в таблице filter по умолчанию, так же как PREROUTING и POSTROUTING в таблице nat. В nftables не существует никаких таблиц и цепочек по умолчанию. Особое значение там есть у типов таблиц и хуков, а имена таблиц и цепочек могут быть совершенно произвольными.

В целом имена хуков повторяют старые имена специальных цепочек, но в нижнем регистре. Например, input, output, forward. Скоро мы увидим их в действии.

Перенос правила

Для экономии времени мы не будем писать правила с нуля, а воспользуемся iptables-restore-translate и творчески переработаем ее вывод.

На моем VPS стоит Fedora, поэтому все команды и расположение конфигов я даю именно для этого дистрибутива. Из сервисов: SSH, веб, почта, DNS — типичный набор.

Для начала выключим и остановим старые сервисы iptables.

Теперь посмотрим на правила ( cat /etc/sysconfig/iptables).

Кроме них, есть /etc/sysconfig/ip6tables, который отличается тремя правилами.

Теперь конвертируем этот конфиг в синтаксис nftables. Пиши:

Результат будет следующим.

Ключевое слово ct — это, конечно же, ConnTrack — механизм отслеживания состояния соединений в ядре Linux. Опция counter отсутствовала в исходных правилах iptables. Просто nftables не включает счетчики правил по умолчанию, и, если они тебе важны, нужно включить их этой опцией.

Существенный недостаток синтаксиса в стиле pf — он имеет свойство превращаться в плохо читаемую стену текста. К счастью, такой синтаксис обязателен только для команды nft. Для скриптов, которые загружаются с помощью nft -f, nftables поддерживает более читаемый синтаксис с фигурными скобками и возможностью писать несколько опций в одной строке через точку с запятой.

Самый простой способ конвертировать этот синтаксис в вариант со скобками — сохранить эти правила в файл (например, /tmp/rules.nft), применить их с помощью nft -f /tmp/rules.nft и просмотреть их командой nft list ruleset.

Команда nft list ruleset может заменить и iptables -L -nv, и iptables-save. Кроме того, она поддерживает вывод правил в JSON вместе со значениями счетчиков с помощью опции -j/--json — мечта авторов фронтендов для настройки.

Можно было бы просто сохранить конвертированные правила в один из файлов в /etc/nftables/ и ограничиться этим, но можно и немного реорганизовать конфиг с помощью новых фич nftables.

Размешение новых конфигов

В iptables не существует способов разделить конфиг на части, из-за чего многие люди и генерируют конфиги скриптами. Другое дело nftables — там есть опция include.

В Fedora есть файл /etc/sysconfig/nftables.conf, который читает скрипт сервиса nftables. Этот файл состоит из одних опций include, а в «/etc/nftables/ лежит набор заготовок конфигов. Мы поместим наши новые правила в файлinet-filter.nft`.

Перед этим нужно раскомментировать в файле /etc/sysconfig/nftables.conf строку include "/etc/nftables/inet-filter.nft".

В файле из поставки дистрибутива для нас определена таблица inet filter с цепочками, которые повторяют смысл таблицы filter в iptables по умолчанию.

/etc/nftables/inet-filter.nft

Здесь filter — произвольное название таблицы, а ключевое слово inet — ее тип. Если типы ip и ip6 ограничивают таблицу правилами для IPv4 и IPv6 соответственно, то тип inet позволяет писать правила для обоих протоколов. Если все сервисы доступны по обоим протоколам, таким способом можно избежать дублирования правил почти полностью.

Названия chain input и прочие тоже чисто информационные, назначение цепочки определяет опция type, вроде type filter hook input. Соответственно, если бы у нас был NAT, нам нужна была бы таблица с опцией type nat hook prerouting вместо правил вида iptables -t nat -I PREROUTING и так далее по аналогии.

Добавления правила

Поскольку нас интересует фильтрация входящего трафика, свои правила мы будем дописывать внутрь chain input. По сути, копируем из вывода iptables-restore-translate все после add rule ip filter INPUT и вставляем внутрь chain input.

В своих старых настройках я использовал по одному правилу на каждый порт TCP или UDP. В iptables есть опция --dports, но в nftables все еще проще: можно писать порты в фигурных скобках через запятую. Этим мы и воспользуемся и объединим все правила для каждого сервиса в одно, например dport {80, 443} для HTTP(S).

Получится что-то вроде такого:

Теперь осталось запустить сервис nftables и поставить его на загрузку:

Если работаешь на удаленной машине без доступа к консоли, не забудь запланировать перезагрузку ( shutdown -r +10) или сброс правил ( echo "nft flush ruleset | at now+10min").

Создание группы адресов

Правило про tcp dport 53 разрешает репликацию зон DNS на вторичные серверы. Если обычные запросы DNS выполняются через UDP, то репликация зон — через TCP.

Конечно, репликация доступна не всем подряд, а вполне определенным хостам, в моем случае это вторичные серверы Hurricane Electric: 216.218.133.2 и 2001:470:600::2. До миграции это ограничение было прописано в настройках самого BIND, но мы добавим его и в правила nftables, чтобы посмотреть на синтаксис переменных и групп.

Переменные определяются с помощью ключевого слова define, например define foo = 192.0.2.1. На них можно ссылаться в стиле shell с помощью $foo. Объявления переменных мы поместим в самое начало файла.

РЕКОМЕНДУЕМ:
Настройка файрвола на примере Микротика

Затем мы создадим две группы, одну для IPv4, другую для IPv6. Увы, использовать оба типа адресов в одной группе не выйдет, но зато проверка нахождения адреса в группе в nftables выполняется за время O(1).

Группы определяются с помощью ключевого слова set, и в них нужно указать тип. Когда они определены, в опциях правил на них можно ссылаться с помощью @setname.

С переменными и группами наш конфиг пример следующий вид:

Выводы

На мой взгляд, синтаксис nftables и ее подход к работе с конфигами — это значительный прогресс по сравнению с iptables и расставаться со старыми инструментами можно без сожаления.

Понравилась статья? Поделиться с друзьями:
Добавить комментарий