Содержание статьи
Всем хорош iptables, да только синтаксис правил у него достаточно неочевидный (куча всяческих опций и прочее). Сейчас, конечно, появился его потомок, nftables, но пока что он не очень распространен и поддерживает не все возможности предшественника. Для iptables же за время его существования было создано немало фронтендов и конфигураторов, один из которых, Shorewall, мы и рассмотрим.
Введение
Разработка Shorewall началась, когда автор осознал негибкость предыдущего варианта фронтенда, Seawall, который сам же разработал в 1999-м. Возможности Shorewall весьма широки:
- поддержка и автоматическое определение доступных особенностей Netfilter/iptables. Это крайне полезно, поскольку его версии могут разниться от дистрибутива к дистрибутиву;
- деление сетей на зоны. При этом как несколько сетевых интерфейсов могут соответствовать одной зоне, так и один интерфейс может соответствовать нескольким зонам. Есть также поддержка вложенных и пересекающихся зон;
- поддержка всевозможных видов NAT;
- возможность простого использования на одном брандмауэре/роутере нескольких провайдеров;
- централизованное управление несколькими брандмауэрами с установленным Shorewall Lite;
- возможность написания собственных расширений, если основной функциональности почему-либо окажется недостаточно,
и многие другие.
На данный момент в репозиториях Ubuntu 15.04 имеется версия 4.6.4, которую мы и рассмотрим.
Установка и архитектура
Перед установкой стоит удалить ufw — стандартный фронтенд iptables в Ubuntu, а уже потом устанавливать Shorewall. Для этого набираем следующие команды:
$ sudo apt-get remove ufw
$ sudo apt-get install shorewall
Перед настройкой стоит описать его архитектуру. У Shorewall есть шесть пакетов: Shorewall Core, Shorewall/Shorewall6, Shorewall-lite/Shorewall6-lite и Shorewall-init. Первый пакет используется всеми остальными, вторые два предоставляют Shorewall для IPv4/IPv6 соответственно, следующие два предлагают версию, которую нужно устанавливать на брандмауэрах при непосредственном управлении ими, и, наконец, последний предоставляет некоторые возможности для upstart. Мы будем говорить только о собственно Shorewall.
Shorewall, в свою очередь, состоит из нескольких компонентов. Рассмотрим их подробнее.
/sbin/shorewall
— утилита для администрирования, через которую и выполняется всяческое обслуживание, включая загрузку правил при запуске системы. На самом деле это shell-скрипт.
В каталоге /usr/share/shorewall/
лежат уже основные компоненты Shorewall:
compiler.pl
— «сердце» Shorewall, скрипт на Perl, который и компилирует правила Shorewall в правила iptables; когда-то была альтернативная версия Shorewall, целиком написанная на Shell, но от нее отказались из-за проблем с быстродействием;action.template
— шаблон для создания действий. «Действия» — некий набор правил для iptables, который, в свою очередь, тоже можно представить как шаблон. Для знакомых с iptables это можно выразить проще — цепочка (chain) в таблице filter;action.*
— файлы, содержащие стандартные действия;actions.std
— файл, содержащий список стандартных действий;configfiles/
— каталог, содержащий файл для создания каталога экспорта в Shorewall-lite;configpath
— файл, содержащий дистрибутивоспецифичные пути;firewall
— shell-скрипт, обрабатывающий команды add и delete, предназначенные для добавления хостов и подсетей в динамические зоны, которые, как правило, применяются при создании VPN, и удаления их. Также этот скрипт обрабатывает команды stop и clear, когда в системе нет текущего скомпилированного набора правил;functions
— символическая ссылка на lib.base, предназначенная для сохранения совместимости со старыми версиями Shorewall;init
— символическая ссылка на init-скрипт;lib.*
— библиотеки функций, используемые в shell-скриптах;macro.*
— стандартные макросы для Shorewall. Макросы позволяют задавать имена для наборов из одного или нескольких правил iptables;modules
иmodules.*
— файлы, управляющие загрузкой модулей. Причем если первый оперирует сразу группами модулей и его можно переопределить, скопировав в каталог конфигов, то остальные эти группы определяют, и их трогать не нужно;prog.*
— фрагменты shell-скриптов, использующиеся в качестве входных данных для компилятора правил;Shorewall/
— каталог, содержащий модули Perl, используемые этим компилятором;version
— файл, содержащий сведения о текущей версии Shorewall;wait4ifup
— Shell-скрипт, который может использоваться скриптами расширения для ожидания доступности какого-либо интерфейса.


Хакер #202. Скажи нет большому брату!

В каталоге /etc/shorewall
лежат файлы конфигурации для IPv4-версии фронтенда.
/var/lib/shorewall
используется для хранения информации о состоянии. Там могут находиться, например, файлы:
.iptables-restore-input
— файл, передаваемый в iptables-restore и предназначенный для ускорения восстановления правил при запуске/перезапуске и для отладки;.modules
— список модулей, использовавшихся при последнем запуске/перезапуске;restore
— скрипт, используемый при выполнении команды shorewall restore;.restore
— опять же скрипт, использовавшийся во время последнего удачного выполнения командshorewall start
,shorewall restart
илиshorewall refresh
;save
— создается по команде shorewall save и служит для восстановления динамического черного списка после запуска/перезапуска;state
— записывается состояние брандмауэра.
Посмотрим вкратце, как все это работает, на примере. При компиляции (shorewall compile
) вызывается скрипт /sbin/shorewall
, подключающий библиотеку функций lib.cli
и вызывающий функцию shorewall_cli
, которая парсит аргументы. Затем в данной функции из lib.cli-std
вызывается функция compile_command
, также парсящая аргументы (уже свои), и в итоге она выполняет очередную функцию — compiler
. В конечном счете вызывается скрипт на Perl, в свою очередь компилирующий shell-скрипт, выполняемый уже другой командой (к примеру, shorewall start
).
При запуске указанной выше команды первый этап парсинга выполняется аналогично. Затем вызывается функция get_config
из файла lib.cli-std
, устанавливающая переменные, получаемые из файла конфигурации. Следом выполняется функция start_command
, которая, в свою очередь, вызывает функцию run_it
, уже и выполняющую скомпилированный из набора правил скрипт.
Стоит заметить, что Shorewall жестко привязан к суперпользователю (в скриптах зашиты проверки на UID = 0
), так что при использовании Capabilities администраторы оказываются в пролете.
Посмотрим, как данный фронтенд настраивать, в том числе синтаксис правил.
Конфигурирование Shorewall
Поскольку Shorewall позволяет сделать много чего, то и конфигурационных файлов у него достаточно. В простейшем случае, однако, можно обойтись пятью-шестью. Взглянем на них.
/etc/shorewall/shorewall.conf
— файл, управляющий глобальными настройками Shorewall. Посмотрим некоторые его интересные места:
# Допускается ли запуск Shorewall?
STARTUP_ENABLED=Yes
# Вывод сообщений при запуске. 0 — вообще не выводить, 1 — выводить только важные сообщения, 2 — максимальный уровень
VERBOSITY=1
# <...>
# Логирование «марсианских пакетов» (адреса источника/назначения которых зарезервированы) на всех интерфейсах. Даже если его здесь отключить, всегда можно включить для конкретного интерфейса. Может принимать значения Yes, No и Keep — оставить как есть
LOG_MARTIANS=Yes
# Уровень логирования поведения при запуске в файл, указанный в параметре STARTUP_LOG? -1 — отключено, 0 — только ошибки, 1 — логировать основные сообщения, 2 — логировать все
LOG_VERBOSITY=2
# Местонахождение лог-файла, который команды для просмотра информации (такие как shorewall dump или shorewall show log) будут обрабатывать
# <...>
# Файл лога запуска
STARTUP_LOG=/var/log/shorewall-init.log
# <...>
# Следующие строки описывают действия по умолчанию для политик. Эти действия применяются до применения к соединению основных политик. Список встроенных действий можно получить в файле /usr/share/shorewall/actions.std
ACCEPT_DEFAULT=none
DROP_DEFAULT=Drop
NFQUEUE_DEFAULT=none
QUEUE_DEFAULT=none
REJECT_DEFAULT=Reject
# <...>
# Поддержка учета трафика
ACCOUNTING=Yes
# Таблица для учета. Возможно использовать либо filter, либо mangle
ACCOUNTING_TABLE=filter
# Автоматически связывать хелперы с приложениями. Начиная с ядра 3.5 их, однако, рекомендуется включать вручную
AUTOHELPERS=Yes
# Файлы с именами, как у цепочек, интерпретируются как скрипты. Это было необходимо до появления возможности inline-вставок BEGIN PERL...END PERL в файлах конфигурации, сейчас же опционально
CHAIN_SCRIPtS=Yes
# <...>
# Использование таблицы MANGLE при генерации правил
MANGLE_ENABLED=Yes
# <...>
# Оптимизация генерируемых правил. Тут допустимы категории 0, 1, 2, 4, 8 и 16, их комбинации, достигаемые обычным сложением, а также значения All и None (последнее аналогично нулевой категории). В частности, категория 2 означает, что все правила ACCEPT будут объединяться в одну цепочку. Остальные оптимизации более сложны
OPTIMIZE=0
# <...>
/etc/shorewall/zones
описывает сетевые зоны, представляет собой таблицу. Кратко расскажем про ее столбцы и приведем пример.
Столбец ZONE определяет имя зоны. Имя должно начинаться с буквы, может содержать буквы, цифры и подчеркивания и, при формате логирования по умолчанию, быть не более шести символов. Имена all, any, none, DEST и SOURCE зарезервированы. Порядок, в котором Shorewall определяет соответствие пакетов зонам, соответствует порядку определения зон. Допустимо также определение вложенных зон, но это выходит за рамки данной статьи.
Столбец TYPE определяет тип зоны и может быть одним из следующих:
ipv4
— стандартный тип, если в данном столбце ничего не задано или стоит прочерк, то применяется по умолчанию. Соединение с некоторыми хостами зоны может быть зашифрованным.ipsec
илиipsec4
— соединение со всеми компьютерами зоны шифровано.firewall
— описывает собственно зону брандмауэра.
Есть еще и другие типы, но смысла рассматривать их нет.
OPTIONS, IN OPTIONS и OUT OPTIONS — определяют опции (в основном относящиеся к IPSec, например proto указывает протокол инкапсуляции) для двунаправленного, входящего и исходящего трафика соответственно.
Пример файла:
#ZONE TYPE OPTIONS IN OPTIONS OUT OPTIONS
fw firewall
net ipv4
Файл /etc/shorewall/interfaces
содержит описание сетевых интерфейсов, которые могут использоваться в Shorewall, и сопоставляет их с зонами. Существует два формата данного файла — со столбцом BROADCAST
, используемым для предоставления интерфейсу широковещательного адреса, и без него. Формат без данного столбца задается строкой ?FORMAT 2
. Перечислим вкратце доступные столбцы:
ZONE
— указывается зона, присутствующая в файле zones;INTERFACE
— логическое имя интерфейса; каждый интерфейс может быть указан в данном файле только один раз. Виртуальные интерфейсы указывать нельзя. Допустимо использовать и символы подстановки — например, ppp+ соответствует и ppp0, и ppp5, но не ppp;OPTIONS
— список различных опций, разделенных запятыми. К примеру, опция dhcp используется чаще всего для указания того, что интерфейс получает адрес по DHCP, а опция net предоставляет возможность ограничить список подсетей для конкретной зоны.
Пример файла interfaces
:
?FORMAT 2
#ZONE INTERFACE OPTIONS
- lo ignore
net all dhcp,physical=+,routeback
Файл /etc/shorewall/policy
определяет общие политики для соединений между зонами, если пакет или соединение не соответствует ни одному правилу. Порядок строк в этом файле имеет значение. Посмотрим, какие в этом файле столбцы:
- SOURCE — источник. Может быть именем зоны, $FW (самим брандмауэром), all и all+ — последнее значение переопределяет внутризоновую политику;
- DEST — назначение. Значения аналогичны SOURCE;
- POLICY — политика. Тут используются те самые значения, которые были указаны в файле shorewall.conf. Через двоеточие можно задать конкретное действие из списка действий
/usr/share/shorewall/actions.std
или макрос. Если стоит NONE, над пакетом не будет произведено никакое действие. Нужно отметить, что NONE не может использоваться, если в качестве источника/назначения указан $FW или all; - LOG LEVEL — позволяет определить уровень логирования для соединений, соответствующих данной политике. Может быть от debug до emerg, плюс возможно указывать ULOG иди NFLOG для направления логов в соответствующий демон;
- BURST:LIMIT — позволяет задать ограничения на количество соединений за единицу времени как для адреса источника, так и для адреса назначения.
Пример:
#SOURCE DEST POLICY LOG LEVEL BURST:LIMIT
$FW net ACCEPT
net all DROP
Тут разрешаются все исходящие соединения от компьютера брандмауэра в зону net и запрещаются все соединения, приходящие из данной зоны.
Наконец, файл /etc/shorewall/rules
содержит собственно правила. Этот файл делится еще и на секции. Рассмотрим их. В cекции ALL задаются правила, которые будут применяться независимо от состояния соединения для пакета. Для создания правил на пакеты с учетом состояний ESTABLISHED и RELATED предназначены секции ESTABLISHED и RELATED соответственно. В качестве действий для них допустимы лишь ACCEPT, DROP, REJECT, LOG и QUEUE. Правила для пакетов в состоянии INVALID задаются в секции с соответствующим именем. Доступные действия аналогичны тем же, что описывались чуть выше. UNTRACKED применяется для тех пакетов, чье состояние нельзя отследить. Доступные действия опять же идентичны предыдущим.
В секции NEW указываются правила не только для пакетов с соответствующим состоянием. Правила, указанные в ней, применяются и для пакетов с состояниями INVALID и UNTRACKED, если они отсутствуют в нужных секциях. Также, если в файле не указана ни одна секция, подразумевается, что есть только описываемая. Имена столбцов в данном случае говорят сами за себя или аналогичны тем, что были описаны ранее, поэтому их рассматривать не будем, а приведем сразу пример:
#ACTION SOURCE DEST PROTO DEST PORT SOURCE PORT(S)
?SECTION ALL
?SECTION ESTABLISHED
?SECTION RELATED
?SECTION INVALID
?SECTION UNTRACKED
?SECTION NEW
Invalid(DROP) net $FW tcp
SSH(ACCEPT) net $FW
Ping(ACCEPT) net $FW
Возможно, этот пример покажется удивительным, но на самом деле действия, указанные в нем, либо соответствуют одному из действий в файле action.std
(как в случае с действием Invalid(DROP), запрещающим пакеты в состоянии Invalid), либо являются макросами, как в случае с SSH(ACCEPT) и Ping(ACCEPT), разрешающими, соответственно, SSH и Ping. Во всех правилах в данном примере в качестве источника указывается зона net, а в качестве назначения сам компьютер с брандмауэром.
Nftables
Nftables представляет собой нечто аналогичное bpf: утилита nft компилирует правила в байт-код и передает его в ядро. Это позволяет не только значительно улучшить гибкость, но и уменьшить количество кода ядра. Так, отпадает надобность в реализации расширений режима ядра для поддержки всякого вновь появляющегося протокола. В качестве же базовых «кирпичиков» выступают элементы старого доброго Netfilter, такие как хуки.
Синтаксис утилиты nft, однако, отличается от синтаксиса старых утилит и представляет собой иерархический язык, более подходящий для описания правил, нежели линейный стиль iptables. Парсер для этого языка сгенерирован с помощью BISON.
Shorewall на ноутбуке
Модифицируем базовый пример для ноутбука. Для простоты предположим, что дома ноутбук подключен кабелем к локальной сети и владелец его считает эту сеть доверенной, а «на выезде» он пользуется беспроводной сетью, которая, понятно, недоверенная.
Определим зоны home и wifi, для чего в файл zones добавляем строчки:
home ipv4
wifi ipv4
Затем добавляем зоны в файл interfaces:
home eth0 dhcp
wifi wlan0 dhcp
И настраиваем политики (предварительно закомментировав уже существующие):
$FW home ACCEPT
home $FW ACCEPT
$FW wifi ACCEPT
wifi $FW DROP
В файле правил, опять же после комментирования существующих, записываем следующие строчки:
Invalid(DROP) home $FW tcp
Ping(ACCEPT) wifi $FW
Проверяем, компилируем и запускаем:
# shorewall check
# shorewall compile && shorewall start


Все, ноутбук защищен.
Заключение
Shorewall остается очень мощным инструментом даже сейчас, с появлением nftables. Оно, впрочем, неудивительно, поскольку это более высокоуровневый инструмент. Конфигурировать его тоже легче, что мы и увидели из примеров. Но как Shorewall можно сравнить с языком высокого уровня, так и iptables можно сравнить с ассемблером — а, как известно, в некоторых случаях (хотя и далеко не во всех) код на ассемблере, написанный человеком, более быстрый, нежели сгенерированный машиной.


Shorewall будет полезен как тем, кому нужно быстро составить простенький сетевой экран, так и, напротив, тем, кому требуется супернавороченный брандмауэр с роутингом и шейпингом трафика. Также он довольно быстро развивается — совсем недавно у него вышла версия 5.0.
Таким образом, Shorewall подходит очень большому кругу пользователей. Скорее всего, подойдет он и тебе.