Iptables, firewalld, ufw, nftables
Настройки показанные здесь приведены на примере ОС Ubuntu и Debian, работоспособность на других дистрибутивах необходимо уточнить самостоятельно.
В этой статье мы рассмотрим, как настроить базовую защиту с использованием одного из 4х представленных firewall'ов.
UFW
UFW (Uncomplicated Firewall) - является самым простым и довольно популярным инструментарием командной строки для настройки и управления брандмауэром в дистрибутивах Ubuntu и Debian. Правильно функционирующий брандмауэр является наиболее важной частью полной безопасности системы Linux. UFW позволяет сделать базовые настройки, для более сложных настроек используйте iptables.
Установка и проверка статуса
В случае, если ufw не установлен по умолчанию используйте:
sudo apt install ufw
Проверить текущий статус и вывести все текущие правила можно с помощью следующей команды:
sudo ufw status verbose
Например, в выключенном состоянии вы увидите следующее сообщение:
Включить firewall можно с помощью следующей команды:
sudo ufw enable
В диалоговом окне необходимо ответить на вопрос, при использовании нашей инфраструктуры соединение не пропадет, если вы ранее не отключили iptables:
Command may disrupt existing ssh connections.
Proceed with operation (y|n)? y
Firewall is active and enabled on system startup
.
В результате ufw будет активен:
Если Вам потребуется отключить утилиту, то используйте команду:
sudo ufw disable
Политики по умолчанию
По умолчанию брандмауэр UFW отклоняет все входящие соединения и разрешает только исходящие подключения к серверу. Это означает, что никто не может получить доступ к вашему серверу, если только вы специально не открываете порт, а все запущенные службы или приложения на вашем сервере могут иметь доступ к внешней сети.
Политики безопасности по умолчанию находятся в файле /etc/default/ufw и могут быть изменены с помощью следующей команды:
sudo ufw default deny incoming
sudo ufw default allow outgoing
Первое правило запрещает все входящие подключения, второе разрешает исходящие.
Профили приложений
При установке программного пакета ufw с использованием диспетчера пакетов он будет включать в себя профили приложений, находящиеся в каталоге /etc/ufw/applications.d, который определяет приложение или службу и соответствующие им настройки безопасности, например открытые или закрытые порты.
Все профили создаются вручную. Посмотреть созданные профили можно следующим образом:
sudo ufw app list
На только, что созданном виртуальном сервере вы скорее всего увидите только профиль для OpenSSH:
Для просмотра детальной информации можно использовать следующую команду:
sudo ufw app info '<название_ПО>'</название_ПО>
Например:
sudo ufw app info 'OpenSSH'
Результат:
Для создания профиля приложения перейдите в директорию:
cd /etc/ufw/applications.d
Создайте текстовый файл с любым названием и вставьте в него строки следующего формата:
[<название_профиля>]
title=<заголовок>
description=<краткое описание>
ports=<список портов>/<протокол>
Например:
[App1]
title=Text editor
description=Most popular open source application for editing text.
ports=53,80,5223,16393:16472/udp
Для того, чтобы файл был виден брандмауэру, перезагрузите его:
ufw reload
Далее разрешите или запретите доступ профилю:
ufw <allow/deny> <название_профиля>
Например:
ufw allow App1
Работа с портами
Для открытия портов используется ключевое слово allow.
С помощью следующей команды можно открыть порт для входящих подключений:
sudo ufw allow <порт>/<протокол>
Например:
sudo ufw allow 1234/tcp
Также можно открывать порты по именам конкретных сервисов, например:
sudo ufw allow http
Примечание: если сервер использует порт не по умолчанию, то данное правило использовать нельзя.
ufw позволяет открывать или закрывать промежуток портов:
sudo ufw allow <портN>:<портM>/<протокол>
Например:
sudo ufw allow 5000:5003/udp
Для закрытия портов используйте ключевое слово deny. Синтаксис ufw остается прежним, только allow заменяется на deny. Например, чтобы закрыть порт используется следующая команда:
sudo ufw deny <порт>/<протокол>
Например:
sudo ufw deny 1234/tcp
Работа с IP-адресами
Чтобы разрешить соединение ко всем портам сервера с конкретного IP-адреса, используйте следующую команду:
sudo ufw allow from <IP-адрес>
К примеру:
sudo ufw allow from 111.111.111.111
Также можно разрешить подключаться к конкретному порту с определенного IP-адреса:
sudo ufw allow from <IP-адрес> to any port <порт>
Пример:
sudo ufw allow from 111.111.111.111 to any port 22
Для запрета подключения используйте ключевое слово deny:
sudo ufw deny from <IP-адрес>
Пример:
sudo ufw deny from 111.111.111.111
Работа с подсетью
С помощью утилиты ufw можно разрешить получение трафика со всей подсети с помощью нотации CIDR:
sudo ufw allow from <подсеть>
Например:
sudo ufw allow from 192.168.1.0/24
Также можно направить трафик с подсети на конкретный порт:
sudo ufw allow from <подсеть> to any port <порт>
Например:
sudo ufw allow from 192.168.1.0/24 to any port 22
Примечание: для запрета данных правил используйте ключевое слово deny.
Работа с сетевым интерфейсом
С помощью ufw можно настроить подключение к конкретному порту определенного интерфейса:
sudo ufw allow in on <имя интерфейса> to any port <порт>
Например:
sudo ufw allow in on eth2 to any port 22
Примечание: имена всех интерфейсов сервера можно просмотреть с помощью команды ifconfig -a.
Удаление правил
Для удаления правил выведете нумерованный список текущих правил:
sudo ufw status numbered
Удалите правила под нужным номером:
sudo ufw delete <номер_правила>
Пример:
sudo ufw delete 1
Также можно удалить правило с помощью ключевого слова delete, например:
sudo ufw delete allow 443
Iptables
Iptables - чрезвычайно гибкая утилита межсетевого экрана, предназначенная для операционных систем Linux. Iptables основана на правилах (rules), которые контролируют входящие и исходящие пакеты, а также использует цепочки правил для разрешения или блокировки трафика. По умолчанию никакие правила не установлены, пользователь может создавать, добавлять и редактировать правила.
iptables почти всегда предустановлена на любом дистрибутиве Linux. Чтобы обновить или установить, просто загрузите пакет iptables с помощью пакетного менеджера, например apt-get:
sudo apt-get install iptables
Необходимо быть предельно осторожным при настройке правил iptables, особенно если вы используете ssh на сервере, потому что одна неправильная команда может заблокировать подключение по ssh.
Основные конфигурационные файлы:
/etc/init.d/iptables – скрипт инициализации для запуска, остановки, перезапуск и сохранения наборов правил;
/etc/sysconfig/iptables – файл, в который сохраняются правила;
/sbin/iptables – бинарный файл, в котором находится утилита.
В структуре iptables существует 4 таблицы:
Filter - таблица по умолчанию;
NAT - предназначена для преобразования сетевых адресов;
Mangle - предназначена для внесения специализированных изменений в пакеты;
Raw - предназначена для конфигурационных исключений.
Filter
Filter - это таблица по умолчанию для iptables. Если вы не определяете собственную таблицу, то будет использоваться эта таблица правил. Таблица Filter использует три разные цепочки: INPUT, FORWARD и OUTPUT.
NAT
Таблица NAT имеет следующие встроенные цепочки: PREROUTING, POSTROUTING, OUTPUT.
Правила
Правила содержат критерии и цель.
Если критерии сопоставляются, то действия применяются к целевому объекту.
Если критерии не сопоставляются, то происходит переход к следующему правилу.
Ниже приведены возможные целевые объекты:
Для того, чтобы посмотреть текущую конфигурацию iptables, выполните следующую команду:
iptables --list
Вывод:
Здесь:
target - специальная целевая переменная, как видно из вывода, это может быть собственное значение, первые два правила ссылаются на собственные цепочки;
prot - протоколы;
opt - специальные опции;
source - исходный ip-адрес;
destination - ip-адрес назначения.
Примечание: по умолчанию правила попадают в таблицу filter.
Чтобы посмотреть правила конкретной таблицы используйте следующую команду:
iptables -t <имя_таблицы> --list
Например:
iptables -t filter --list
Чтобы вывести правила с нумерацией используется дополнительный ключ --line-numbers:
iptables -L --line-numbers
Для создания собственной цепочки используйте команду:
iptables -N <имя_цепочки>
Например:
iptables -N MY_CHAIN
Блокировка ip-адресов
Часто возникает задача блокирования ip-адресов. Например, вы заметили, что IP 11.22.121.122 постоянно пытается атаковать ваш сервер, и вы хотите его заблокировать. Нужно просто заблокировать все входящие пакеты с этого IP-адреса. Чтобы это сделать, нужно добавить следующее правило в цепочку INPUT таблицы filter. В примере имя таблицы указано явно, без использования ключа t правило попадает в таблицу по умолчанию:
iptables -t filter -A INPUT -s 11.22.121.122 -j REJECT
Здесь:
t - указывает, в какую таблицу будет входить правило;
A - указывает на добавление (Append) правила в цепочку INPUT;
s - указывает источник;
j - указывает iptables на отклонение трафика с помощью цели REJECT.
Также можете блокировать диапазоны IP-адресов, используя CIDR-нотацию. Если необходимо заблокировать все IP-адреса от 11.22.121.0 до 11.22.121.255, это можно сделать с помощью команды:
iptables -A INPUT -s 11.22.121.0/24 -j REJECT
Если необходимо заблокировать исходящий трафик на конкретный ip, используется цепочка OUTPUT и флаг -d для указания ip-адреса назначения:
iptables -A OUTPUT -d 31.13.78.35 -j DROP
Удаление правил
Теперь, скажем, вы заблокировали IP-адрес 11.22.121.0/24 по ошибке. Чтобы удалить существующее правило используйте команду:
iptables -D INPUT -s 11.22.121.0/24 -j REJECT
Здесь ключ -D (Drop) означает удаление правила из цепочки.
Также можно удалять правила по номерам строк. Если вы хотите удалить второе правило из цепочки INPUT, команда будет следующей:
iptables -D INPUT 2
Примечание: при удалении правил нумерация изменяется.
Также возможно удалить все правила цепочки - с помощью опции F:
iptables -F INPUT
Вставка и замена правил
Поскольку iptables обрабатывает правила в цепочках одно за другим, возможно вставить правила в определенное место в цепочке. Например, следующая команда вставляет блокировку указанного ip-адреса на первое место:
iptables -I INPUT 1 -s 11.22.121.10 -j ACCEPT
Для замены правила стоящем на определенном месте, необходимо использовать ключ -R. Следующая команда заменит правило стоящее на 1 месте:
iptables -R INPUT 1 -s 11.22.121.11 -j ACCEPT
Протоколы, модули, интерфейсы
Например, чтобы заблокировать весь входящий TCP-трафик, нужно с помощью ключа -p указать протокол следующим образом:
iptables -A INPUT -p tcp -j DROP
Более полезный пример - блокировка доступа по ssh для диапазона ip-адресов. Для начала необходимо сопоставить трафик TCP, как в примере выше. Затем нужно проверить предназначен ли трафик для SSH порта, используя --dport. Таким образом, вся команда будет:
iptables -A INPUT -p tcp --dport 22 -s 11.22.121.0/24 -j DROP
Для того, чтобы заблокировать доступ одновременно и к SSH и VNC для диапазона адресов, нужно использовать модуль multiport и ключ --dports. Команда:
iptables -A INPUT -p tcp -m multiport --dports 22,5901 -s 59.45.175.0/24 -j DROP
Чтобы открыть порт, например 80, для подключения по http, используйте команду:
iptables -A INPUT -p tcp --dport 80 -j ACCEPT
Для разрешения всех входящих соединений с адаптера, например с eth1, используйте следующее правило:
iptables -A INPUT -i eth1 -j ACCEPT
Пример перенаправления портов
Довольно часто возникает необходимость перенаправления портов и ip-адресов в целях безопасности в локальной сети. Например, чтобы перенаправить трафик с порта 80 сервера, который имеет выход в глобальную сеть, на 85 порт локальной машины.
Для перенаправления необходимо выполнить следующий набор правил:
iptables -t nat -A PREROUTING -d <внешний_ip-адрес> -p tcp -m tcp --dport <порт_подключения> -j DNAT --to-destination <целевой_внутренний_ip-адрес>:<целевой_порт>
iptables -t nat -A POSTROUTING -d <целевой_внутренний_ip-адрес> -p tcp -m tcp --dport <целевой_порт> -j SNAT --to-source <внутренний_ip-адрес_шлюза>
iptables -t nat -A OUTPUT -d <внешний_ip-адрес> -p tcp -m tcp --dport <целевой_порт> -j DNAT --to-destination <целевой_внутренний_ip-адрес>
iptables -I FORWARD 1 -i <внешний_ip-адрес> -o <внутренний_ip-адрес_шлюза> -d <целевой_внутренний_ip-адрес> -p tcp -m tcp --dport <целевой_порт> -j ACCEPT
Например:
iptables -t nat -A PREROUTING -d 11.22.121.10 -p tcp -m tcp --dport 80 -j DNAT --to-destination 10.0.1.2:85
iptables -t nat -A POSTROUTING -d 10.0.1.2 -p tcp -m tcp --dport 85 -j SNAT --to-source 10.0.1.1
iptables -t nat -A OUTPUT -d 11.22.121.10 -p tcp -m tcp --dport 80 -j DNAT --to-destination 10.0.1.2
iptables -I FORWARD 1 -i 11.22.121.10 -o 10.0.1.1 -d 10.0.1.2 -p tcp -m tcp --dport 85 -j ACCEPT
Минимальная конфигурация firewall
Конкретные правила фаервола зависят от сервисов, используемых на вашем сервере. Ниже приведен пример правил, подразумевающих использование вами веб-сервера. Прежде, чем применять правила iptables, спланируйте их исходя из вашей вашей конфигурации.
Примечание: восклицательный знак `!` используется для инверсии правил.
Для начала разрешите все входящие подключения:
iptables --policy INPUT ACCEPT
Затем необходимо очистить все правила Iptables:
iptables -F
Чтобы не потерять соединение по SSH, откройте 22 порт:
iptables -A INPUT -p tcp --dport 22 -m state --state NEW -j ACCEPT
Следующие правила зависят от ваших потребностей: Разрешить весь трафик c loopback (lo0):
iptables -A INPUT -i lo -j ACCEPT
Перенаправить трафик на localhost, который исходит не из lo0.
iptables -A INPUT ! -i lo -s 127.0.0.0/8 -j REJECT
Разрешить ping:
iptables -A INPUT -p icmp -m state --state NEW --icmp-type 8 -j ACCEPT
Разрешить соединения HTTP и HTTPS:
iptables -A INPUT -p tcp --dport 80 -m state --state NEW -j ACCEPT
iptables -A INPUT -p tcp --dport 443 -m state --state NEW -j ACCEPT
Разрешить входящий трафик из установленных соединений:
iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
Отклонить все остальные входящие пакеты:
iptables -A INPUT -j REJECT
Сохранение правил
После перезагрузки системы правила iptables очищаются, поэтому после их применения их необходимо сохранить.
На операционных системах Ubuntu и Debian можно использовать утилиту netfilter-persistent (или iptables-persistent):
apt-get install iptables-persistent
Сохранить правила:
sudo netfilter-persistent save
Примечание: если у Вас включен uwf, необходимо его отключить:
sudo ufw disable
Для сохранения правил на серверах Centos используйте команду:
service iptables save
Примечание: если при использовании этой команды на Centos у вас возникает следующая ошибка:
То необходимо отключить firewalld, который введен для управления iptables, установить пакет iptables-services и запустить его:
systemctl stop firewalld
systemctl mask firewalld
yum install iptables-services
systemctl enable iptables
systemctl start iptables
service iptables save
Firewalld
Firewalld запускается как демон, новые правила добавляются без перезапуска и без сброса установленного файрвола. Изменения в конфигурации могут быть сделаны в любое время и применяются мгновенно: сохранять или применять изменения не требуется. Поддерживается IPv4, IPv6, автоматическая загрузка модулей ядра и сетевые зоны, определяющие уровень доверия соединений. Предоставляется простой интерфейс добавления правил для служб и приложений, белый список приложений, имеющих право менять правила. В настоящее время такую возможность поддерживает libvirt, Docker, fail2ban, Puppet, скрипт установки Virtuozzo и многие другие проекты. В репозитории YUM уже есть пакеты fail2ban-firewalld и puppet-firewalld, поэтому подключить их можно одной командой.
Firewalld предоставляет информацию о текущих настройках брандмауэра через D-Bus API, а также принимает изменения через D-Bus с использованием методов аутентификации PolicyKit. В качестве бэкенда используются iptables, ip6tables, ebtables, ipset и планируется nftables. Но сами правила, созданные непосредственно этими утилитами, firewalld не может разобрать, поэтому оба метода использовать нельзя.
Управление производится при помощи утилит командной строки firewall-cmd или графической firewall-config, позволяющей настроить все правила в удобной среде. Для помощи в миграции текущих правил iptables на firewalld используется утилита firewall-offline-cmd, по умолчанию считывающая /etc/sysconfig/system-config-firewall
. В последних релизах появилась утилита firewallctl, имеющая простой синтаксис и позволяющая получать информацию о состоянии службы, конфигурации брандмауэра и изменять правила.
Смотрим статус:
Разрешить соединение на определенный порт очень просто:
Чтобы любые изменения вступили в силу, всегда после правок должна быть запущена команда
Для удаления порта из правил используется параметр --remove-port
:
Вообще, многие команды --add-*
имеют значения для проверки статуса --query-*
, --list-*
— список, изменения --change-*
или удаления --remove
соответствующего значения. Для краткости на этом не будем дальше заострять внимание. После релоада правил проверяем:
В firewalld предусмотрен режим, позволяющий одной командой заблокировать все соединения:
Для проверки, в каком режиме находится файрвол, есть специальный ключ:
Отключается panic mode:
В firewalld необязательно знать, какой порт привязан к сервису, достаточно указать название сервиса. Все остальное утилита возьмет на себя.
После установки firewalld знает настройки более 50 сервисов, получаем их список.
Разрешим подключение к HTTP:
Используя фигурные скобки, можно задавать сразу несколько сервисов. Информация по настройкам сервисов доступна при помощи
Firewalld хранит все настройки в XML-файлах в каталогах в /usr/lib/firewalld. В частности, сервисы лежат в services. Внутри файла описание: название, протокол и порт.
Это каталог системный, и менять там ничего нельзя. Если нужно переопределить настройки или создать свой сервис, то копируем любой файл в качестве шаблона в /etc/firewalld/services
, правим под свои условия и применяем настройки.
Для настройки ICMP используется отдельный набор правил. Получаем список поддерживаемых типов ICMP:
Проверяем статус:
Управление зонами
Для определения уровня доверия сетевому соединению в firewalld используются зоны. Зона может содержать несколько сетевых подключений, но сетевое соединение может входить только в одну зону. Список всех зон получаем командой firewall-cmd --get-zones
.
После установки создается девять зон, в зависимости от назначения может быть использована одна или несколько зон:
trusted — все сетевые соединения разрешены;
work/home/internal — зоны похожи по настройкам, отличаются назначением. Устанавливается максимальное доверие к компьютерам в сети, разрешается устанавливать только конкретные входящие соединения (по умолчанию SSH и DHCPv6 client, в home и internal плюс MDNS и Samba client);
dmz — для компьютеров, находящихся в демилитаризованной зоне, доступные из Сети и с ограниченным доступом к внутренней сети. Разрешаются только указанные входящие соединения (по умолчанию SSH);
external — правило, подходящее для роутеров, для использования во внешних сетях с разрешенным маскарадингом, с максимальным недоверием и четко установленными разрешенными входящими соединениями (по умолчанию SSH);
public — для использования в общественных местах, с максимальным недоверием к другим компьютерам, разрешены только конкретные входящие соединения (по умолчанию SSH и DHCPv6 client);
block — входящие сетевые соединения отклоняются с icmp-host-prohibited сообщением, разрешены только соединения, инициированные в этой системе;
drop — разрешаются только исходящие соединения, все входящие блокируются.
Описания зон также представлены в XML-файлах в /usr/lib/firewalld/zones
.
После установки системы обычно используется зона public. Если имеющихся зон недостаточно, то можно создавать новые зоны при помощи
Все пакеты, не попадающие под определенные зоны, обрабатываются в зоне по умолчанию.
Теперь — какие зоны сейчас активны и какие интерфейсы к ним привязаны.
Также можем получить обратную информацию — к какой зоне привязан интерфейс.
Смотрим настройки зоны (сервисы, порты, протоколы...).
Если параметр пуст, то это значит, что настройки не установлены. При необходимости переназначаем интерфейс зоне:
Если сейчас проверить вывод firewall-cmd --zone=public --list-all
, то увидим, что из списка установок пропал сетевой интерфейс. Разрешим подключение сервиса:
Удаляется он так же:
К зонам можно привязывать и другие источники, определяемые по MAC, отдельному IP или адресу сети. Пакет, пришедший из такого источника, будет обрабатываться по правилам зоны.
Список всех source смотрим при помощи --zone=trusted --list-sources
. NAT, позволяющий нескольким компьютерам подключаться к сети, в firewalld включается одной командой. Смотрим текущие настройки маскарадинга:
Если в ответ получим no
, то включаем:
Это все. Для доступа извне настроим форвардинг порта в один из компьютеров. Например, нам нужен доступ по SSH к внутреннему серверу:
Проверяем:
Удаляется правило форвардинга при помощи --remove-forward-port
.
Сложные правила
Для отдельного ПК или небольших сетей базовых возможностей вполне хватает, для настройки сложных правил в firewalld изначально предлагался так называемый direct-синтаксис, чуть позже появился собственный язык Rich Language. В первом варианте достаточно знать синтаксис iptables, рекомендуется использовать в крайнем случае, так как правила не сохраняются после перезагрузки.
Синтаксис direct правила такой:
Позиция полностью совпадает с синтаксисом iptables. Получаем текущие установки:
Добавляем правило, разрешающее соединение по 25-му порту:
Пробросим соединение по 22-му на другой сервер:
Проверяем:
Rich Language позволяет записывать сложные правила в более удобном для понимания виде. В правиле можно указывать любые параметры, характеризующие пакет: источник, назначение, сервис, порт, протокол, маскарадинг, журналирование, аудит и действие. Например, разрешим подсети соединяться по HTTP и добавляем аудит:
Большой плюс Rich Language в том, что все параметры можно описать в XML в файле зоны. Формат файла очень простой и повторяет названия параметров:
Настройка файрвола — дело привычки. Часто удобнее вбить команду, которой пользуешься уже не один год, чем осваивать новую утилиту. Поэтому иногда все-таки хочется вернуть классический инструмент. Это не проблема. Iptables в CentOS 7 не ставится, поэтому его нужно вернуть:
Чтобы не настраивать все повторно, лучше сохранить текущие правила, сгенерированные firewalld.
Останавливаем firewalld и запускаем iptables:
Проверяем текущие правила:
Запрещаем автозапуск firewalld при загрузке ОС:
Nftables
Чем не устраивает iptables?
Проект netfilter/iptables был основан в 1998 году и с версии ядра 2.4 используется по умолчанию. Команда разработчиков сохранила основную идею, заложенную еще в ipfwadm, — список правил, состоящих из критериев и действия, которое выполняется, если пакет соответствует критериям. Netfilter разрешал подключать дополнительные модули (ранее архитектура ядра такой возможности не предоставляла). Это позволило очень просто развивать подсистему фильтрации, и со временем появилось большое количество новых функций и модулей. Полноценная поддержка IPv6 появилась только в 2011 году, что, правда, потребовало редизайна netfilter. В результате модуль NAT разделили на два независимых компонента, один из которых включает в себя ядро подсистемы NAT, а второй реализует поддержку протокола третьего уровня. Помимо фильтрации, модули обеспечивают классификацию трафика (вплоть до седьмого уровня OSI), балансировку нагрузки, манипуляцию с пакетами, маршрутизацию и прочее.
Со временем накапливались проблемы на функциональном уровне и в дизайне. Код ядра дублировался, становилось все сложнее его поддерживать и добавлять новые возможности. Обработка некоторых параметров жестко вшита в ядро, модуль нередко обслуживает только свой протокол. Например, за извлечение номера порта UDP и TCP отвечают два разных модуля. Для реализации любой функции в userspace требуется поддержка модулем ядра, это затрудняет разработку, и без пересборки часто не обойтись. Правила загружаются как один большой дамп, в случае изменения правила выгружаются, меняются, и весь набор отправляется обратно. Без учета дополнительных расширений количество опций конфигурирования в ядре уже давно перевалило за сотню.
Еще один важный мотив — необходимость сбросить текущий ABI (Application Binary Interface), представляющий собор набор соглашений между программами, библиотеками и ОС, обеспечивающими их взаимодействие на низком уровне. В iptables ABI жестко прописаны специфические для протоколов поля, поэтому расширить его сложно. Как результат, приходится сразу запускать iptables, arptables и ebtables, по существу выполняющие одну работу, но каждый на своем уровне. По общим оценкам дублируется 10 000 строк кода. Учитывая, что все защитные механизмы и цепочки (даже пустые) грузятся изначально и активны, iptables потребляет больше ресурсов, чем реально необходимо.
Пользователям и администраторам управлять большим количеством правил довольно тяжело, трудно с ходу разобраться, что делают все цепочки, правила начинают повторяться, их становится сложно обслуживать и обновлять. Чтобы настроить два разных действия (вроде MARK и ACCEPT), правила приходится дублировать. Каждое расширение имеет свой синтаксис, одни поддерживают диапазоны, отрицание, префиксы, другие — нет.
Журналирование в nftables
Для регистрации событий используется Netfilter, при помощи модулей xt_LOG (регистрирует в syslog) и/или nfnetlink_log. Последний использует демон сбора информации ulogd2, вышедший примерно полтора года назад и способный накапливать данные на уровне отдельных пакетов или потоков и сохранять их, в том числе и в БД.
Механизм журналирования для каждого протокола настраивается через /proc.
Под номером 2 у нас скрывается IPv4. Меняем на nfnetlink_log:
Назначение nftables
Об nftables впервые заговорили в октябре 2008 года на конференции Netfilter Workshop. Задача проекта — заменить подсистемы iptables, ip6table, arptables и ebtables одним решением. Разработкой новой подсистемы пакетной фильтрации стала заниматься та же команда, только под руководством Патрика Мак-Харди (Patrick McHardy). Альфа-версия была представлена в марте 2009 года, хотя до 2012 года проект практически спал.
Дерево патчей состояло из более 100 патчей, которые в конце октября 2013-го были объединены в 17. В стандартную ветку Linux nftables включен с версии 3.13, хотя высокоуровневые инструменты все еще находятся в разработке, а документация, ориентированная на пользователя, отсутствует. Старая и новая подсистемы будут некоторое время сосуществовать рядом, так как nftables еще требует доработки и тестирования. Для обеспечения обратной совместимости предоставляется специальная прослойка, позволяющая использовать iptables/ip6tables поверх инфраструктуры nftables.
В nftables реализована идея, схожая с BPF (Berkeley Packet Filters): правила фильтрации в пространстве пользователя компилируются в байт-код, а затем через Netlink API передаются в ядро. После этого для принятия решения по дальнейшим действиям с пакетом они выполняются с использованием так называемого конечного автомата (pseudo-state machine), который представляет собой простейшую виртуальную машину, выполняющую байт-код.
Виртуальная машина способна манипулировать наборами данных (как правило, IP-адреса), позволяя заменить несколько операций сравнения единым набором поиска. Для принятия решений на основе этих данных могут быть использованы арифметика, битовые операторы и операторы сравнения. Возможен и обратный процесс декомпиляции объектов, позволяющий воссоздать текущую конфигурацию в ядре.
Использование userspace значительно упрощает код ядра и позволяет гораздо проще анализировать и принимать решения по отдельным протоколам. Отсутствует дублирование кода, особенности каждого протокола уже не встраиваются.
Все операции по определению условий и связанных с ними действий выполняются в пространстве пользователя, в ядре производится только базовый набор операций, таких как чтение данных из пакета, сравнение данных. Присутствует поддержка словарного маппинга и поиск по наборам правил (sets), работа которых реализована через хеши и rb-деревья. При этом элементы наборов могут быть заданы в виде диапазонов значений (можно определять подсети).
В качестве базовых блоков по-прежнему используются компоненты netfilter, в том числе существующие хуки, система отслеживания состояния соединений, компоненты организации очередей и подсистема ведения лога. Хотя работа в userspace позволяет получать больше отчетов об ошибках.
Отличается и алгоритм работы фильтра, он сделан более универсальным, теперь разборкой пакета занимаются операторы (expression). Специальный механизм payload expression загружает данные из пакета в один из регистров общего назначения. Базовое смещение, специфичное для протокола, берется из структуры nft_pktinfo и модулей netfilter (IPv4, ARP и так далее). То есть уже нельзя сказать: «сравни IP источника с IP 192.168.0.1», — теперь фильтр «знает», что нужно извлечь определенную часть заголовка, помещает ее в переменную и затем сравнивает с нужным адресом. Обработка пакета несколькими правилами за счет введения так называемого verdict register стала значительно проще. Также легко пропустить ненужные операции, вроде счетчиков, если в них нет необходимости, меньше ресурсов требует поиск и сопоставление с диапазоном.
В итоге простое правило iptables в памяти занимает 112 байта, аналогичное nftables — 24 байта. Проверка пинга "-d 192.168.0.1 -p icmp –icmp-type echo-request" — 152 и 96 байт соответственно.
Улучшенный API позволяет производить инкрементные обновления правил или атомарную замену правила, гарантирующие эффективность и согласованность, без выгрузки/загрузки всего набора в пределах одной транзакции Netlink.
Для взаимодействия kernel <-> userspace nftables API использует особый компонент ядра Netlink, позволяющий через обычный сокет передавать и принимать сообщения, сформированные особым образом. При этом сам Netlink позволяет:
получать уведомления об изменении сетевых интерфейсов, таблиц маршрутизации и состоянии пакетного фильтра;
управлять параметрами сетевых интерфейсов, таблицами маршрутизации и параметрами netfilter;
управлять ARP-таблицей;
взаимодействовать со своим модулем в ядре.
Именно через Netlink работает утилита iproute2, пришедшая на смену ifconfig и route.
Собственно взаимодействие с кодом, работающим на уровне ядра, возложено на интерфейсные библиотеки libmnl (Netlink), libnftables (userspace Netlink API) и построенный поверх фронтенд, работающий на уровне пользователя. Для формирования правил фильтрации в nftables подготовлена утилита nft, которая проверяет корректность правил и транслирует их в байт-код. Утилита iptables-nftable позволяет использовать правила iptables.
Правила
Конечно, писать низкоуровневые правила пользователи не будут, доступен понятный язык описания. Новый синтаксис правил непохож на iptables, главное отличие — использование иерархических блочных структур вместо линейной схемы. Группировка позволяет легко составлять, читать и понимать настройки без особых пояснений. Синтаксис при этом чем-то напоминает ipfw из FreeBSD.
Язык классификации правил основан на реальной грамматике, при обработке которой используется парсер bison. К сожалению, документация в этом вопросе мало помогает, она просто еще не готова. О возможностях можно судить только по исходному коду nftables и обрывкам информации в специализированных мейл-листах.
Правила могут содержать:
таблицы — контейнеры для одного семейства протоколов, поддержка мультипротокола не реализована в netfilter, хотя в будущем, вероятно, что-то изменится;
цепочки (chains) — контейнеры для правил, могут использоваться в действии перехода (jump), но в отличие от iptables цепи не содержат счетчики;
базовые цепочки (base chains) — особый тип цепи, регистрируются с хуками netfilter, обеспечивая отправную точку для таблиц. Регистрируются при вставке первого правила;
правила (rules) — атомарная единица, содержащая expressions.
Сами правила выглядят следующим образом. Разрешаем ping (ICMP-сообщения echo-request):
Теперь разрешаем доступ с подсети 192.168.1.0/24 и IP 192.168.0.10 по SSH, блокируем для всех доступ по 80-му порту и разрешаем все пакеты уже установленного соединения (connection tracking).
Счетчики — необязательный элемент в правилах, и, если он нужен, его необходимо активировать. Теперь в одном правиле можно указать сразу несколько действий. Например, подсчитаем количество пакетов, отправленных на 192.168.0.1, и заблокируем соединение:
Вместо IP в правилах возможно использование доменного имени:
Фильтр интерфейса позволяет указывать правило для конкретного сетевого интерфейса (сетевуха должна присутствовать в системе, иначе правило не будет активным):
Еще один нюанс. Утилита nft может работать в трех режимах, чем-то напоминая управление в Cisco. Например, все настройки можно указать в файле и затем просто скормить конфиг nft, это очень удобно для переноса рулесетов на несколько ПК. В каталоге files/nftables
с исходными текстами уже имеется ряд шаблонов, перед началом использования nftables необходимо выбрать нужные и активировать:
Также есть режим командной строки, когда нужная настройка указывается сразу, и интерактивный режим CLI. Перейти в CLI просто:
Теперь можем последовательно давать команды или считывать настройки. Единичные правила группируются в таблице, образуя иерархическую блочную структуру, напоминающую pf и npf.
Правило можно вставить в нужную позицию (handle), здесь работают две директивы — add и insert. Первая добавляет правило после указанной позиции, а вторая — перед. Например, чтобы вставить правило перед handle 8, пишем:
Удаляются правила в цепочке при помощи параметра delete:
Если не указывать номер правила, то будет очищена вся цепочка. При помощи flush сбрасывается вся таблица:
Настройка NAT не сложнее, вначале необходимо загрузить модули:
Создаем цепочку:
И добавляем в нее правила:
Первое активирует NAT для всего трафика с 192.168.1.0/24 на интерфейсе eth0, второе перенаправляет весь DNS-трафик на 8.8.8.8.
WWW
Сайт nftables: netfilter.org/projects/nftables
Установка nftables в Ubuntu
На данный момент единственный выход изучить новинку — это установить nftables самостоятельно. Нам потребуются библиотеки и стандартный набор для сборки ПО:
Библиотеку можно поставить из сырцов, но пока версии, доступной в репозитории, вполне достаточно. Копируем код libnftables и nftables.
Сборка в том и другом случае стандартна, переходим в каталог и даем команды:
В некоторых системах (в Ubuntu, например) при конфигурировании nftables следует активировать ряд функций:
Далее вводим make oldconfig
, переходим в Core Netfilter Configuration, где находим специфичные для nftables настройки (их, кстати, на порядок меньше, чем для iptables), собираем ядро.
Пакетный фильтр FF
Джефри Мерки (Jeffrey Merkey) представил в списке рассылки разработчиков ядра Linux код нового специализированного пакетного фильтра FF, предназначенного для блокирования большого числа IP-адресов в сетях с интенсивным трафиком. FF состоит из модуля Linux-ядра и утилиты для управления пакетным фильтром. Представленный пакетный фильтр не отличается такой гибкостью, как iptables, но опережает последний по производительности и потребляет значительно меньше памяти в расчете на один IP.
От ipset новая система отличается тем, что поддерживает блокирование на уровне драйвера e1000. Набор утилит, работающий на уровне пользователя, обеспечивает сохранение БД-адресов на диске с кешированием базы в памяти ядра.
Главная задача FF — защита от DoS/DDoS-атак, блокирование различного флуда и паразитного трафика. В качестве примера представлен код для интеграции разработки с Postfix с целью борьбы с роботами спамеров, выступающий в роли более жесткой системы блокирования для серых списков и RBL-систем.
INFO
До появления iptables для обеспечения возможностей межсетевого экрана в Linux использовались проекты ipchains в Linux 2.2 и ipfwadm в Linux 2.0 (основанный на ipfw из BSD).
Last updated