Iptables правила - общая информация и как это работает.

Основные правила

1) Фаервол iptables работает путем сравнения сетевого трафика с набором правил.
Правило — это свойства, которыми должен обладать пакет, чтобы получить доступ к серверу, а также действие, которое нужно выполнить над пакетами, соответствующими правилам.
Существует множество опций-действий, которые можно выполнить, если пакет соответствует определенному правилу.
Можно установить тип протокола пакета, адрес и порт источника или назначения, используемый интерфейс, отношение пакета к предыдущим пакетам, и т.д.

2) Target указывает, какое действие должно быть выполнено, если пакет соответствует правилу.
Target может содержать окончательное решение относительно данного пакета (принять его или сбросить соединение), а также может передать пакет для обработки другой цепочке или же просто внести пакет в журнал. Примеры: ACCEPT, DROP, REJECT

3) Порядок правил в цепи имеет огромнейшее значение.
Правила должны быть расположены таким образом, чтобы пакет сначала проходил через более конкретные правила, а потом — через более общие.
Другими словами, правила в начале цепочки должны быть более специфическими и подробными, чем правила в конце.
Тогда пакет будет проходить сначала специфические правила, а затем — более общие, что создает расширяющийся шаблон.
Если пакет не соответствует никаким правилам цепочки, то он отвечает самому общему правилу — политике по умолчанию.

4) Для начала нужно убедиться, что iptables уже содержит правила, которые сохраняют текущие соединения даже при выполнении политики сброса по умолчанию.
Это особенно важно при подключении к серверу по SSH. При неверной настройке - потеряем доступ к консоли.

5) Правила фаервола объединяются в группы, которые называются цепочками (chains).
Цепочка представляет собой последовательность правил, относительно которой проверяется пакет.
Если пакет совпадает с одним из правил, фаервол выполняет указанное действие - при этом пакет не проверяется остальными правилами в цепочке.
Из этого следует вывод, что верхние правила важнее!
Такие цепочки создаются пользователем по мере необходимости. По умолчанию существует три цепочки:
- INPUT: обрабатывает все входящие на сервер пакеты;
- OUTPUT: содержит правила для исходящего трафика;
- FORWARD: используется для обработки предназначенного для других серверов трафика, который не был создан на данном сервере.
Эта цепочка в основном необходима для маршрутизации запросов на другие серверы.

Каждая цепочка может содержать ноль или больше правил, а также имеет политику по умолчанию (policy).
Политика определяет действие, которое необходимо выполнить в случае если пакет не соответствует ни одному правилу (такой пакет можно сбросить — drop, или принять — accept).

Теперь о самой настройке:
Итак, для начала нужно просмотреть список текущих правил 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 -F
Прежде чем сбросить правила при удаленном подключении необходимо убедиться, что в цепочках INPUT и OUTPUT установлена политика ACCEPT. Это делается так:
sudo iptables -P INPUT ACCEPT
sudo iptables -P OUTPUT ACCEPT
sudo iptables -F
1) Правило, которое разрешает текущее 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.

2) Добавить разрешение на новые подключения по портам 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.

Разрешить loopback интерфейс

Теперь нужно создать еще одно правило 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, который будет запускаться при перезагрузке сервера и возобновлять установленные правила.