Вступление
Надежный фаервол – один из важнейших аспектов защиты любой современной ОС. Большинство дистрибутивов Linux содержат несколько различных инструментов фаервола. Данное руководство посвящено одному из наиболее популярных – iptables.
Итак, iptables – это стандартный фаервол, включенный в большинство дистрибутивов Linux по умолчанию (для его замены разрабатывается nftables). На самом деле, iptables – это пользовательский интерфейс для управления системой netfilter, которая, в свою очередь, управляет сетевым стеком Linux. iptables сравнивает каждый поступающий пакет с набором установленных правил, а затем решает, что с ним делать дальше.
В предыдущей статье речь шла о том, как именно работает iptables. Данная статья сконцентрирована на практических примерах, демонстрирующих создание базового набора правил для сервера Ubuntu 14.04.
Базовые команды iptables
Данный раздел содержит основные команды, с помощью которых можно создать сложный набор правил и управлять интерфейсом iptables в целом.
Запомните: команды iptables нужно запускать с root-привилегиями. Это значит, что нужно выполнить одно из следующих действий:
- войти в систему как пользователь root;
- использовать su или sudo -i, чтобы развернуть оболочку root;
- начинать все команды с sudo (рекомендуемый способ в Ubuntu).
В данном руководстве применяется последний вариант.
Итак, для начала нужно просмотреть список текущих правил iptables. Для этого используется флаг -L:
sudo iptables -L
Chain INPUT (policy ACCEPT)
target prot opt source destination
Chain FORWARD (policy ACCEPT)
target prot opt source destination
Chain OUTPUT (policy ACCEPT)
target prot opt source destination
Как можно видеть, список содержит три цепочки по умолчанию (INPUT, OUTPUT и FORWARD), в каждой из которых установлена политика по умолчанию (на данный момент это ACCEPT). Также можно видеть названия столбцов. Но в данном списке нет самих правил, поскольку Ubuntu поставляется без набора правил по умолчанию.
С помощью флага -S данный список можно просмотреть в другом формате, который отражает команды, необходимые для активации правил и политик:
sudo iptables -S
-P INPUT ACCEPT
-P FORWARD ACCEPT
-P OUTPUT ACCEPT
Чтобы реплицировать конфигурации, нужно только ввести sudo iptables в начале каждой строки результата. (В зависимости от конфигураций, эта процедура может оказаться немного более сложной при удаленном подключении; если правила, разрешающие текущее соединение, еще не установлены, не стоит устанавливать политику DROP).
Чтобы сбросить текущие правила (если таковые есть), наберите:
sudo iptables -F
Опять же, на данном этапе политика по умолчанию очень важна, потому что она не изменится при помощи предыдущей команды несмотря на то, что все правила будут удалены из цепочек.
Прежде чем сбросить правила при удаленном подключении необходимо убедиться, что в цепочках INPUT и OUTPUT установлена политика ACCEPT. Это делается так:
sudo iptables -P INPUT ACCEPT
sudo iptables -P OUTPUT ACCEPT
sudo iptables -F
Создав правила, разрешающие удаленное подключение, можно установить политику DROP. Итак, перейдем непосредственно к созданию правил.
Создание правил iptables
Как уже было сказано выше, данное руководство сконцентрировано на работе с цепочкой INPUT, поскольку она отвечает за входящий трафик. Для начала нужно рассмотреть уже упомянутое правило – правило, которое разрешает текущее SSH-подключение.
Оно выглядит так:
sudo iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
Конечно, сначала оно может показаться невероятно сложным; чтобы понять данное правило, ознакомьтесь с его компонентами:
- -A INPUT: флаг -А добавляет (append) правило в конец цепочки. Эта часть команды сообщает iptables о необходимости внести правило в конец цепочки INPUT.
- -m conntrack: кроме набора основных функций iptables также имеет набор расширений, или модулей, которые отвечают за дополнительные возможности фаервола. Данная часть команды говорит о том, что пользователю необходим доступ к функциям модуля conntrack. Этот модуль позволяет использовать команды, решающие, что делать с пакетом, на основе его отношения к предыдущим соединениям.
- –ctstate: одна из команд, доступных при вызове модуля conntrack. Данная команда позволяет отслеживать отношение пакетов к другим пакетам, просмотренным ранее. Ей заданы значения ESTABLISHED (что позволяет принимать пакеты, которые являются частью существующего соединения) и RELATED (принимает пакеты, которые связаны с уже установленным соединением). Именно эта часть правила отвечает за текущую сессию SSH.
- –j ACCEPT: указывает действие (target), которое нужно выполнить над пакетом, который отвечает правилу. В этом случае iptables будет принимать (accept) пакеты, которые отвечают предыдущим критериям.
Данное правило нужно поместить в начало, чтобы убедиться, что уже существующие соединения совпадают с правилами, приняты и выходят из цепи, не достигнув правил DROP.
Запросив список правил, можно увидеть изменения:
sudo iptables -L
Chain INPUT (policy ACCEPT)
target prot opt source destination
ACCEPT all -- anywhere anywhere ctstate RELATED,ESTABLISHED
Chain FORWARD (policy ACCEPT)
target prot opt source destination
Chain OUTPUT (policy ACCEPT)
target prot opt source destination
Ознакомившись с базовым синтаксисом, создайте еще несколько правил, принимающих соединение.
Принятие других важных подключений
Ранее iptables получил команду не сбрасывать все текущие соединения, а также принять все соединения, имеющие к ним отношение. Теперь нужно создать правила, принимающие соединения, которые не отвечают вышеперечисленным критериям.
Оставьте открытыми два порта: порт SSH (в данном руководстве используется порт по умолчанию – 22; если данное значение было изменено, не забудьте ввести новое значение); кроме того, предположим, что на данном компьютере веб-сервер запущен на порту 80 по умолчанию (не добавляйте это правило, если это не так).
Итак, строки, которые нужно использовать для создания таких правил, выглядят так:
sudo iptables -A INPUT -p tcp --dport 22 -j ACCEPT
sudo iptables -A INPUT -p tcp --dport 80 -j ACCEPT
Как видите, они очень похожи на первое правило; возможно, они имеют даже более простую структуру. Новые опции:
- –p tcp: данная опция пропускает пакеты, использующие TCP (потоко-ориентированный протокол, который используется большинством приложений, поскольку обеспечивает надежную связь).
- —dport: данная опция доступна при использовании флага -p tcp. Она указывает входящий порт, с которым должен совпасть порт пакета. Первое правило пропускает пакеты TCP, направленные на порт 22, а второе правило принимает TCP-трафик, идущий на порт 80.
Теперь нужно создать еще одно правило ACCEPT, чтобы убедиться, что сервер работает должным образом. Как правило, сервисы взаимодействуют путем обмена пакетами; для этого они используют сетевой псевдоинтерфейс кольцевой связи – так называемый loopback device, который направляет трафик обратно на его источник, а не на другие компьютеры.
То есть, если сервису 1 необходимо установить связь с сервисом 2, прослушивающим соединения на порту 4555, то сервис 1 отправляет пакет на порт 4555 с помощью loopback device. Такое поведение нужно разрешить, поскольку оно является важным условием правильной работы многих программ.
Для этого добавьте следующее правило:
sudo iptables -I INPUT 1 -i lo -j ACCEPT
Оно немного отличается от предыдущих правил; рассмотрите его подробнее:
- –I INPUT 1: флаг -I говорит iptables вставить (insert) правило. Данный флаг отличается от флага -А (который просто вносит правило в конец цепочки); он указывает цепочку, в которую нужно внести правило, и расположение правила в ней. В данном случае, правило нужно вставить в самое начало цепи INPUT, вследствие чего все правила передвинутся на одну позицию. Это правило нужно разместить в начале цепочки, поскольку оно является одним из основных правил и не должно зависеть от остальных.
- –i lo: данный компонент правила пропускает пакеты, которые используют интерфейс lo (“lo” – это другое название для loopback device). Это значит, что любой пакет, использующий данный интерфейс, должен быть принят.
Чтобы просмотреть текущие правила, используйте флаг -S, поскольку флаг -L не выводит некоторую информацию (например, интерфейс, к которому привязано правило, что очень важно в случае с последним правилом):
sudo iptables -S
-P INPUT ACCEPT
-P FORWARD ACCEPT
-P OUTPUT ACCEPT
-A INPUT -i lo -j ACCEPT
-A INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A INPUT -p tcp -m tcp --dport 22 -j ACCEPT
-A INPUT -p tcp -m tcp --dport 80 -j ACCEPT
Создание правил DROP
Итак, на данный момент было создано 4 правила, которые принимают пакеты, основываясь на определенные критерии. Тем не менее, сейчас сервер все равно не блокирует никаких других пакетов.
Если пакет проходит по цепочке INPUT и не отвечает ни одному из четырех правил, будет выполнена политика по умолчанию (ACCEPT), которая так или иначе примет данный пакет. Теперь ее нужно изменить.
Это можно сделать двумя способами, которые имеют достаточно существенные различия.
Первый способ – отредактировать политику по умолчанию цепочки INPUT; для этого наберите:
sudo iptables -P INPUT DROP
Данная политика будет отслеживать и сбрасывать все пакеты, не отвечающие ни одному из правил цепочки INPUT. Одним из последствий этого типа конструкции является то, что она будет сбрасывать пакеты даже после сброса самих правил.
Конечно, это повышает уровень безопасности сервера; тем не менее, это может повлечь за собой серьезные последствия, если у пользователя нет другого способа подключиться к серверу. Чаще всего хостинг-провайдеры предоставляют веб-консоль для подключения к серверу в случае возникновения подобных проблем. Такая консоль работает как виртуальное локальное соединение, потому iptables не отреагирует на нее.
Можно сделать так, чтобы сервер автоматически сбрасывал соединение, если правила удалены. Это сделает сервер более защищенным и труднодоступным. Также это означает, что можно вносить правила в конец цепочки, и при этом все нежелательные пакеты будут сброшены.
Альтернативный подход заключается в следующем: в конец цепочки нужно внести правило, сбрасывающее все несоответствующие пакеты, при этом сохраняя политику ACCEPT.
Чтобы вернуть цепочке INPUT политику ACCEPT, наберите:
sudo iptables -P INPUT ACCEPT
Теперь можно внести в конец данной цепочки правило, которое будет сбрасывать все несоответствующие пакеты:
sudo iptables -A INPUT -j DROP
В нормальных рабочих условиях результат будет точно такой же, как при использовании политики DROP. Это правило сбрасывает каждый пакет, который достигает его, что предотвращает попадание на сервер пакетов, не соответствующих установленным правилам.
В основном, второй подход применяется в случае необходимости сохранить политику ACCEPT, которая принимает трафик. То есть, даже если все правила сброшены, пользователь может получить доступ к машине в сети. Этот подход позволяет выполнить действия по умолчанию без необходимости менять политику, которая будет применяться к пустой цепочке.
Конечно, это также означает, что любое правило, которое необходимо внести в конец цепочки, должно находиться перед правилом сброса. Это можно сделать, либо временно удалив правило сброса:
sudo iptables -D INPUT -j DROP
sudo iptables -A INPUT новое_правило
sudo iptables -A INPUT -j DROP
либо вставив новое правило в конец цепи (но перед правилом сброса), указав номер строки. Чтобы внести правило в строку 4, наберите:
sudo iptables -I INPUT 4 новое_правило
Если правил много, вычислить номер строки вручную достаточно проблематично; в таком случае iptables может пронумеровать строки:
sudo iptables -L --line-numbers
Chain INPUT (policy DROP)
num target prot opt source destination
1 ACCEPT all -- anywhere anywhere
2 ACCEPT all -- anywhere anywhere ctstate RELATED,ESTABLISHED
3 ACCEPT tcp -- anywhere anywhere tcp dpt:ssh
4 ACCEPT tcp -- anywhere anywhere tcp dpt:http
Chain FORWARD (policy ACCEPT)
num target prot opt source destination
Chain OUTPUT (policy ACCEPT)
num target prot opt source destination
Это позволяет убедиться, что правило было внесено в нужную строку.
Сохранение настроек iptables
По умолчанию все несохраненные правила действуют до следующей перезагрузки сервера; сразу же после перезагрузки несохраненные правила будут потеряны.
В некоторых случаях это полезно, поскольку дает возможность пользователям, случайно заблокировавшим себя, получить доступ к серверу. Тем не менее, в большинстве случаев все же удобнее сохранить правила и загружать их при запуске сервера.
Это можно сделать несколькими способами; самый простой из них – использовать пакет iptables-persistent, который можно загрузить из репозитория Ubuntu по умолчанию:
sudo apt-get update
sudo apt-get install iptables-persistent
Во время инсталляции пакет уточнит, нужно ли сохранить текущие правила для дальнейшей автоматической загрузки; если текущие правила были протестированы (позволяют создавать SSH-подключения) и соответствуют всем требованиям, их можно сохранить.
Так же пакет спросит, нужно ли сохранить существующие правила IPv6 (они устанавливаются при помощи утилиты ip6tables, которая контролирует поступающие пакеты IPv6 почти таким же образом).
По завершении установки появится новый сервис под названием iptables-persistent, который будет запускаться при перезагрузке сервера и возобновлять установленные правила.
Итоги
Данное руководство помогает настроить фаервол согласно требованиям пользователя. Конечно, существует еще огромное множество подобных утилит, и некоторые из них могут оказаться проще в использовании; все же, iptables – один из лучших инструментов, хотя бы потому что он демонстрирует некоторые основные структуры netfilter и включен во многие системы.