Iptables и другие
Проект iptables, разработанный Расти Расселом (Rusty Russell) в 1999 году для управления netfilter и заменивший в ядре 2.4 ipchains и ряд других инструментов вроде ipnatctl, предлагает более расширяемый способ фильтрации пакетов, обеспечивающий сисадмину больший контроль при упрощении самих правил. Так, в ipchains нужно было создавать правило в каждой цепочке, прослеживая весь маршрут пакета, теперь достаточно одного. Появление модулей позволяло очень просто расширять возможности. В процессе развития проекта iptables был портирован для IPv6 (в 2011 году, ip6tables), добавлялись дополнительные модули (ULOG, nf_conntrack), он научился производить разные манипуляции с пакетами, классифицировать трафик (до седьмого уровня OSI), балансировать нагрузку и многое другое. С ростом количества функций усложнились и настройки. При этом, даже несмотря на некоторую унификацию, каждое расширение имеет свой синтаксис, одни поддерживают диапазоны, отрицание, префиксы, другие — нет. Поначалу каждое изменение правил требовало полного перезапуска брандмауэра, включая выгрузку модулей, что приводило к разрыву установленных соединений. Сейчас такой проблемы нет.
Для простых случаев настройка при помощи iptables — дело нехитрое, но в сложных сетях управлять большим количеством правил становится тяжело; чтобы изучить все настройки и понять, как оно работает, нужно потратить время. Трудно с ходу разобраться, что делают все цепочки, правила начинают повторяться, их становится сложно обслуживать, обновлять и переносить на другие системы.
Неудивительно, что для решения этих проблем были придуманы разные надстройки. Так, в Ubuntu для простой настройки правил используется ufw (Uncomplicated Firewall — несложный файрвол). Например, чтобы открыть доступ к SSH-порту, достаточно ввести
$ sudo ufw allow 22
Разработчики приложений могут создавать готовые профили, которые активируются при установке пакета, избавляя пользователя от выдумывания и ввода правил.
Еще один известный проект, позволяющий легко поддерживать сложные правила, — FERM (for Easy Rule Making). В FERM все правила хранятся в одном файле, который легко читается, редактируется и загружается одной командой. Такой файл просто переносить между компьютерами. Сами правила группируются в блоки, содержат переменные, списки, что позволяет задать те же настройки в более коротком и понятном виде. Итоговый размер правил FERM раза в три меньше аналогичных для iptables. Например, запрещаем все соединения, кроме HTTP, SSH и FTP.
chain INPUT {
policy DROP;
mod state state (RELATED ESTABLISHED) ACCEPT;
proto tcp dport (http ssh ftp) ACCEPT;
}
Под капотом FERM находится обычный Perl-скрипт, который конвертирует конфигурационные файлы в правила iptables.
В Fedora 18 был анонсирован демон firewalld, ставший официальным приложением для управления настройками netfilter в RHEL 7 / CentOS 7. Последние становятся все популярнее на VDS, а значит, придется столкнуться с их особенностями.
Возможности 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, имеющая простой синтаксис и позволяющая получать информацию о состоянии службы, конфигурации брандмауэра и изменять правила.
Смотрим статус:
# systemctl status firewalld
# firewall-cmd --state
running
Разрешить соединение на определенный порт очень просто:
# firewall-cmd --permanent --add-port=22/tcp
Чтобы любые изменения вступили в силу, всегда после правок должна быть запущена команда
# firewall-cmd --reload
Для удаления порта из правил используется параметр --remove-port
:
# firewall-cmd --remove-port=22/tcp
Вообще, многие команды --add-*
имеют значения для проверки статуса --query-*
, --list-*
— список, изменения --change-*
или удаления --remove
соответствующего значения. Для краткости на этом не будем дальше заострять внимание. После релоада правил проверяем:
# firewall-cmd --list-ports
В firewalld предусмотрен режим, позволяющий одной командой заблокировать все соединения:
# firewall-cmd --panic-on
Для проверки, в каком режиме находится файрвол, есть специальный ключ:
# firewall-cmd --query-panic
Отключается panic mode:
# firewall-cmd --panic-off
В firewalld необязательно знать, какой порт привязан к сервису, достаточно указать название сервиса. Все остальное утилита возьмет на себя.
После установки firewalld знает настройки более 50 сервисов, получаем их список.
# firewall-cmd --get-services
Разрешим подключение к HTTP:
# firewall-cmd --add-service=http
Используя фигурные скобки, можно задавать сразу несколько сервисов. Информация по настройкам сервисов доступна при помощи
# firewall-cmd --info-service=http
Firewalld хранит все настройки в XML-файлах в каталогах в /usr/lib/firewalld. В частности, сервисы лежат в services. Внутри файла описание: название, протокол и порт.
<?xml version="1.0" encoding="utf-8"?>
<service>
<short>MySQL</short>
<description>MySQL Database Server</description>
<port protocol="tcp" port="3600"/>
</service>
Это каталог системный, и менять там ничего нельзя. Если нужно переопределить настройки или создать свой сервис, то копируем любой файл в качестве шаблона в /etc/firewalld/services
, правим под свои условия и применяем настройки.
Для настройки ICMP используется отдельный набор правил. Получаем список поддерживаемых типов ICMP:
# firewall-cmd --get-icmptypes
Проверяем статус:
# firewall-cmd --zone=public --query-icmp-block=echo-reply
# firewall-cmd --zone=public --add-icmp-block=echo-reply
Управление зонами
Для определения уровня доверия сетевому соединению в 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 --permanent --new-zone=zone_name
Все пакеты, не попадающие под определенные зоны, обрабатываются в зоне по умолчанию.
# firewall-cmd --get-default-zone
Теперь — какие зоны сейчас активны и какие интерфейсы к ним привязаны.
# firewall-cmd --get-active-zones
Также можем получить обратную информацию — к какой зоне привязан интерфейс.
# firewall-cmd --get-zone-of-interface=eno1
Смотрим настройки зоны (сервисы, порты, протоколы...).
# firewall-cmd --zone=public --list-all
# firewall-cmd --zone=public --list-services
Если параметр пуст, то это значит, что настройки не установлены. При необходимости переназначаем интерфейс зоне:
# firewall-cmd --zone=home --add-interface=eno1 --permanent
Если сейчас проверить вывод firewall-cmd --zone=public --list-all
, то увидим, что из списка установок пропал сетевой интерфейс. Разрешим подключение сервиса:
# firewall-cmd --zone=home --add-service=openvpn --permanent
Удаляется он так же:
# firewall-cmd --zone=home --remove-service=openvpn --permanent
К зонам можно привязывать и другие источники, определяемые по MAC, отдельному IP или адресу сети. Пакет, пришедший из такого источника, будет обрабатываться по правилам зоны.
# firewall-cmd --permanent --zone=trusted --add-source=192.168.1.0/24
Список всех source смотрим при помощи --zone=trusted --list-sources
. NAT, позволяющий нескольким компьютерам подключаться к сети, в firewalld включается одной командой. Смотрим текущие настройки маскарадинга:
# firewall-cmd --zone=external --query-masquerade
Если в ответ получим no
, то включаем:
# firewall-cmd --zone=external --add-masquerade
Это все. Для доступа извне настроим форвардинг порта в один из компьютеров. Например, нам нужен доступ по SSH к внутреннему серверу:
# firewall-cmd --zone=external --add-forward-port=port=22:proto=tcp:toport=22:toaddr=192.168.1.100
Проверяем:
# firewall-cmd --zone=external --list-all
Удаляется правило форвардинга при помощи --remove-forward-port
.
Сложные правила
Для отдельного ПК или небольших сетей базовых возможностей вполне хватает, для настройки сложных правил в firewalld изначально предлагался так называемый direct-синтаксис, чуть позже появился собственный язык Rich Language. В первом варианте достаточно знать синтаксис iptables, рекомендуется использовать в крайнем случае, так как правила не сохраняются после перезагрузки.
Синтаксис direct правила такой:
# firewall-cmd [--permanent] --direct --add-rule { ipv4 | ipv6 | eb } <table> <chain> <priority> <args>
Позиция
# firewall-cmd --direct --get-chains ipv4 filter
# firewall-cmd --direct --get-rules ipv4 filter input
Добавляем правило, разрешающее соединение по 25-му порту:
# firewall-cmd --direct --add-rule ipv4 filter INPUT 0 -m tcp -p tcp --dport 25 -j ACCEPT
Пробросим соединение по 22-му на другой сервер:
# firewall-cmd --permanent --direct --add-rule ipv4 filter FORWARD 0 -i eno1 -o eno2 -p tcp --dport 22 -m state --state NEW,RELATED,ESTABLISHED -j ACCEPT
Проверяем:
# firewall-cmd --direct --get-all-rules
Rich Language позволяет записывать сложные правила в более удобном для понимания виде. В правиле можно указывать любые параметры, характеризующие пакет: источник, назначение, сервис, порт, протокол, маскарадинг, журналирование, аудит и действие. Например, разрешим подсети соединяться по HTTP и добавляем аудит:
# firewall-cmd --permanent --zone=public --add-rich-rule="rule family="ipv4" source address="192.168.0.0/24" service name="http" audit limit value="1/m" accept
Большой плюс Rich Language в том, что все параметры можно описать в XML в файле зоны. Формат файла очень простой и повторяет названия параметров:
<rule>
<service name="ssh"/>
<accept/>
</rule>
Настройка файрвола — дело привычки. Часто удобнее вбить команду, которой пользуешься уже не один год, чем осваивать новую утилиту. Поэтому иногда все-таки хочется вернуть классический инструмент. Это не проблема. Iptables в CentOS 7 не ставится, поэтому его нужно вернуть:
# yum install -y iptables-services
Чтобы не настраивать все повторно, лучше сохранить текущие правила, сгенерированные firewalld.
# iptables-save > /etc/sysconfig/iptables
# ip6tables-save > /etc/sysconfig/ip6tables
Останавливаем firewalld и запускаем iptables:
# systemctl stop firewalld && systemctl disable firewalld
# systemctl start iptables && systemctl enable iptables
# systemctl start ip6tables && systemctl enable ip6tables
Проверяем текущие правила:
# iptables -L
# iptables -S
Запрещаем автозапуск firewalld при загрузке ОС:
# systemctl disable firewalld
Выводы
Как видишь, ничего сложного! Firewalld очень упрощает установки, особенно если учесть, что настройки легко перенести.