Здравствуйте читатели и гости моего блога. Сегодня я хочу рассказать о защите системы при помощи встроенного в ядро Lin­ux межсетевого экрана Net­fil­ter. Когда я делал попытки изучать данный способ защиты, то столкнулся с отсутствием вменяемых статей посвященных этому вопросу. Все что я находил представляло из себя разрозненные отрывки не связанной между собой информации, никак не объясняющей те или иные интересующие меня моменты.

Статьи найденные мной выглядели примерно следующим образом: у автора статьи уже есть или внезапно появляется VPS/VDS сервер с которым все было хорошо до определенного момента, а потом на него начинаются различного рода атаки. Но автор умный, он применяет определенное правило для межсетевого экрана и все сразу становится хорошо. Но ни один из них не пишет почему нужно применять именно это правило и чем он руководствовался при его выборе. Все просто. Есть проблема, есть правило, есть результат - статья завершена, все встают и хлопают.

За все то время я нигде не нашел единой информации которая могла бы провести за руку от начала и до конца. Чтобы начать самому разбираться в правилах, пришлось самостоятельно изучать официальные руководства и мануалы, попутно сверяясь с более-менее понятными статьями и примерами.

Поначалу я хотел написать одну статью, но в процессе написания понял что так дело не пойдет, слишком большой объем информации. Поэтому я решил разбить статью на несколько частей, в которых буду последовательно и подробно описывать механизм и способы защиты с помощью межсетевого экрана Net­fil­ter и правил ipt­a­bles.

Механизм работы & термины

Защита основывается на встроенном в ядро Lin­ux межсетевом экране Net­fil­ter. Межсетевой экран или как его еще называют, фаервол, представляет из себя набор средств для контроля и фильтрации проходящих сетевых пакетов (трафика), в соответствии с заданными правилами.

Для управления фаерволом используется утилита ipt­a­bles. С помощью нее создаются правила, определяющие регулировку и фильтрацию трафика. Обычно, когда говорят - Net­fil­ter, то имеют ввиду только элементы межсетевого экрана являющиеся частью ядра. Все что не относится к ядру, как-то: таблицы, цепочки, правила - называют ipt­a­bles. Во избежание путаницы, правильно будет называть всю систему - netfilter/iptables.

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

  • Критерий - логическое выражение определяющее попадает ли данный пакет под действие правила.
  • Действие - действие которое надо проделать с пакетом если он соответствует заданному критерию.
  • Счетчик - компонент учитывающий количество пакетов, попавших под критерий данного правила.

Правила объединяются в цепочки, даже одно правило будет считаться цепочкой. Цепочки могут быть базовыми или пользовательскими.

  • Базовая цепочка - цепочка правил по умолчанию. Каждый входящий, исходящий или транзитный пакет обязан пройти базовые цепочки различных таблиц. Базовая цепочка отличается от пользовательской наличием так называемых, политик по умолчанию (Default Pol­i­cy). Политика по умолчанию - это действие применяемое к пакетам не попавшим под заданные правила. Имена базовых цепочек всегда должны записываться в верхнем регистре: PREROUTING, INPUT, FORWARD, OUTPUT, POSTROUTING.
  • PREROUTING - цепочка первоначальной обработки пакетов.
  • INPUT - цепочка для входящих пакетов предназначенных для локальных служб и приложений.
  • FORWARD - цепочка транзитных пакетов, вход ------>>> выход
  • OUTPUT - цепочка исходящих пакетов сформированных локальными службами и приложениями.
  • POSTROUTING - цепочка окончательной обработки пакетов покидающих систему. Сюда могут попадать пакеты из цепочек OUTPUT & FORWARD.
  • Пользовательская цепочка - цепочка созданная пользователем.

Цепочки, в свою очередь, объединяются в таблицы.

Таблицы представляют из себя совокупность базовых и пользовательских цепочек, имеющих общее назначение. Имена таблиц записываются в нижнем регистре. Если таблица в правиле не указывается, то по умолчанию правило принадлежит таблице fil­ter.

  • raw - редко используемая таблица, которая просматривается до передачи пакета системе определения состояний con­ntrack. Может использоваться для маркировки пакетов, которые не должны обрабатываться системой изменения состояний, для этого в правиле необходимо указать действие NOTRACK. Может присутствовать в цепочках - PREROUTING и OUTPUT.
  • man­gle - таблица содержащая правила для модификации пакетов, может встречаться во всех цепочках.
  • nat - таблица для пакетов создающих новые соединения. может использоваться для подмены адреса отправителя или получателя. Изменения применяется к первому пакету из потока, ко всем остальным применяется автоматически. Встречается в цепочках - PREROUTING, OUTPUT, POSTROUTING.
  • fil­ter - основная таблица по умолчанию, если название таблицы не указывается. Используется для фильтрации пакетов, присутствует только в - INPUT, FORWARD, OUTPUT цепочках.

Пути прохождения трафика

Пакет поступивший на сетевой интерфейс перехватывается драйвером устройства и передается в ядро системы, где начинает проходить определенную последовательность цепочек, начиная с цепочки PREROUTING при ее наличии. После прохода цепочки PREROUTING, происходит сверка с таблицей маршрутизации (Rout­ing) где устанавливается принадлежность пакета, в зависимости от принадлежности определяется его дальнейший путь.

Если пакет адресован локальной системе, то он передается в цепочку INPUT и после обработки содержащимися в ней правилами отправляется локальным процессам или приложениям. Если пакет не адресован локальной системе, то он отправляется в цепочку FORWARD.

После обработки пакета локальным процессом или приложением, происходит формирование ответного пакета, если это необходимо. Пакет покидающий локальную систему, в соответствии с правилами маршрутизации (Rout­ing), направляется в цепочку OUTPUT.

Пакеты из цепочек OUTPUT/FORWARD, снова маршрутизируются (Rout­ing) и отправляются в цепочку POSTROUTING, после чего окончательно покидают ядро и попадают во внешнюю сеть.

Для представления путей прохождения пакетов можно ознакомиться со схемой. Очень важно иметь представление о движении трафика, это здорово помогает при написании правил.

iptables netfilter

В природе существует три вида трафика и соответственно три маршрута прохождения пакетов.

Входящие пакеты  для локальных приложений

Прохождение цепочки PREROUTING:

  • Проверяется таблица raw (может не быть), после происходит отслеживание состояний con­ntrack
  • Проверяется таблица man­gle (может не быть)
  • Проверяется таблица nat (Может использоваться для DNAT - модификации адреса получателя ), которой тоже может не быть.

Таблицы с пометкой "может не быть", означают что они не указаны в правилах или не указаны правила для них, замечание верно в любом случае. Несмотря на это PREROUTING существует, в случае отсутствия правил пакет проходит определение состояний и передается в rout­ing, а после в цепочку INPUT.

Прохождение цепочки INPUT:

  • Проверяется таблица man­gle (может не быть)
  • Проверяется таблица fil­ter (обязательна)

После обработки правилами таблицы fil­ter пакет передается соответствующему локальному приложению или процессу.

Исходящие пакеты от локальных приложений

При маршрутизации определяется исходящий адрес, выходной интерфейс, пакет передается в цепочку OUTPUT.

Прохождение цепочки OUTPUT:

  • Проверяется таблица raw (может не быть), после происходит отслеживание состояний con­ntrack
  • Проверяется таблица man­gle (может не быть)
  • Проверяется таблица nat (NAT - для локально сгенерированных пакетов) (может не быть)
  • Проверяется таблица fil­ter (обязательна)

Повторная маршрутизация, передача пакета в цепочку POSTROUTING

Прохождение цепочки POSTROUTING:

  • Проверяется таблица man­gle (может не быть)
  • Проверяется таблица nat (Может использоваться для SNATмодификации адреса источника) (может не быть)

В любом случае выход пакета во внешнюю сеть.

Транзитные/проходящие мимо пакеты

Прохождение цепочки PREROUTING:

  • Проверяется таблица raw (может не быть), после происходит отслеживание состояний con­ntrack
  • Проверяется таблица man­gle (может не быть)
  • Проверяется таблица nat (Может использоваться для DNAT - модификации адреса получателя ), которой тоже может не быть.

Маршрутизация: если пакет не предназначен для локальных приложений, то он передается в цепочку FORWARD

Прохождение цепочки FORWARD:

  • Проверяется таблица man­gle (может не быть)
  • Проверяется таблица fil­ter (обязательна)

Повторная маршрутизация, передача пакета в цепочку POSTROUTING

Прохождение цепочки POSTROUTING:

  • Проверяется таблица man­gle (может не быть)
  • Проверяется таблица nat (Может использоваться для SNAT и MASQUERADING) (может не быть)

Таблицы nat и man­gle могут изменять получателя или отправителя пакета, поэтому пакеты несколько раз сверяются с таблицей маршрутизации.

Conntrack - механизм определения состояний

Механизм определения состояний (state machine, con­nec­tion track­ing, con­ntrack) отдельная часть netfilter/iptables. Con­ntrack представляет из себя трассировщик соединений, путем отслеживания которых, con­ntrack определяет принадлежность сетевых пакетов к тому или иному соединению. После чего информация о принадлежности пакета предоставляется фаерволу.

Пакеты могут не отслеживаться, для этого пакет должен быть помечен действием NOTRACK в таблице raw, в которую входят цепочки правил PREROUTIG & OUTPUT.

Установив принадлежность пакета, происходит определение его дальнейшего пути. Существует четыре вида состояния соединений.

  • NEW - Пакет принадлежит новому соединению и является первым для данного соединения.
  • ESTABLISHEDУже установленное соединение, пакет принадлежащий ему не является первым пакетом в соединении. Чтобы соединение стало установленным, требуется чтобы хост передал пакет и получил на него ответ от другого хоста, после получения ответа соединение считается установленным и становится ESTABLISHED. Соединения NEW и RELATED после получения ответа переходят в состояние ESTABLISHED.
  • RELATED - Данное соединение и принадлежащие ему пакеты, связаны с соединением ESTABLISHED или являются его производным.
  • INVALIDНеопределенное соединение, пакет не идентифицируется и не получает определенного статуса.

Механизм con­ntrack позволяет не фильтровать лишний раз входящий трафик относящийся к уже установленным соединениям. Предоставляет возможность получения ответного трафика при полностью закрытом входе.

Правила iptables и их составляющие

Все пакеты проходят через цепочки, а цепочка это ни что иное как набор правил регулирующий прохождение пакетов. Пока пакет проходит через цепочку, к нему применяются все правила в порядке следования. Если пакет соответствует установленному в правиле критерию, то к нему применяется установленное в правиле действие.

Выглядят правила примерно следующим образом, так как жестких требований к написанию правил нет, за исключением отдельных частей.

ipt­a­bles [-t таблица][команда][критерий][действие]

Сначала принято указывать таблицу к которой будет относится правило, указывать таблицу можно в любом месте, но негласно принято указывать таблицу вначале. Для указания таблицы используется ключ -t.

Например: ipt­a­bles -t nat - указывает что правило будет относится к таблице nat

Команды

После таблицы указывается команда. Если таблица не указана, то команда всегда должна быть первой.

Например:

ipt­a­bles -t nat -F или ipt­a­bles -F -t nat

Данное правило очищает таблицу nat, поскольку таблица может указываться в любом месте, то обе формы записи будут правильны.

Список доступных команд, запись в верхнем регистре.

Команда -A, --append
Пример ipt­a­bles -A INPUT
Описание Добавляет новое правило в конец заданной цепочки.
Команда -D, --delete
Пример ipt­a­bles -D INPUT --dport 80 -j DROP или ipt­a­bles -D INPUT 1
Описание Удаление правила из цепочки. Команда имеет два формата записи, первый -- когда задается критерий сравнения с опцией -D (см. первый пример), второй -- порядковый номер правила. Если задается критерий сравнения, то удаляется правило, которое имеет в себе этот критерий, если задается номер правила, то будет удалено правило с заданным номером. Счет правил в цепочках начинается с 1.
Команда -R, --replace
Пример ipt­a­bles -R INPUT 1 -s 192.168.0.1 -j DROP
Описание Эта команда заменяет одно правило другим. В основном она используется во время отладки новых правил.
Команда -I, --insert
Пример ipt­a­bles -I INPUT 1 --dport 80 -j ACCEPT
Описание Вставляет новое правило в цепочку. Число, следующее за именем цепочки указывает номер правила, перед которым нужно вставить новое правило, другими словами число задает номер для вставляемого правила. В примере выше, указывается, что данное правило должно быть 1-м в цепочке INPUT.
Команда -L, --list
Пример ipt­a­bles -L INPUT
Описание Вывод списка правил в заданной цепочке, в данном примере предполагается вывод правил из цепочки INPUT. Если имя цепочки не указывается, то выводится список правил для всех цепочек. Формат вывода зависит от наличия дополнительных ключей в команде, например -n, -v, и пр.
Команда -F, --flush
Пример ipt­a­bles -F INPUT
Описание Сброс (удаление) всех правил из заданной цепочки (таблицы). Если имя цепочки и таблицы не указывается, то удаляются все правила, во всех цепочках.
Команда -Z, --zero
Пример ipt­a­bles -Z INPUT
Описание Обнуление всех счетчиков в заданной цепочке. Если имя цепочки не указывается, то подразумеваются все цепочки. При использовании ключа -v совместно с командой -L, на вывод будут поданы и состояния счетчиков пакетов, попавших под действие каждого правила. Допускается совместное использование команд -L и -Z. В этом случае будет выдан сначала список правил со счетчиками, а затем произойдет обнуление счетчиков.
Команда -N, --new-chain
Пример ipt­a­bles -N new_name_chain
Описание Создается новая цепочка с заданным именем в заданной таблице В выше приведенном примере создается новая цепочка с именем new_name_chain. Имя цепочки должно быть уникальным и не должно совпадать с зарезервированными именами цепочек.
Команда -X, --delete-chain
Пример ipt­a­bles -X new_name_chain
Описание Удаление заданной цепочки из заданной таблицы. Удаляемая цепочка не должна иметь правил и не должно быть ссылок из других цепочек на удаляемую цепочку. Если имя цепочки не указано, то будут удалены все цепочки заданной таблице кроме встроенных.
Команда -P, --pol­i­cy
Пример ipt­a­bles -P INPUT DROP
Описание Задает политику по-умолчанию для заданной цепочки. Политика по-умолчанию определяет действие, применяемое к пакетам не попавшим под действие ни одного из правил в цепочке. В качестве политики по умолчанию допускается использовать DROP и ACCEPT.
Команда -E, --rename-chain
Пример ipt­a­bles -E new_name_chain chain_new_name
Описание Команда -E выполняет переименование пользовательской цепочки. В примере цепочка new_name_chain будет переименована в цепочку chain_new_name.

 

Дополнительные ключи

Команды могут использоваться с дополнительными ключами, запись в нижнем регистре.

Ключ -v, --ver­bose
Команды, с которыми используется --list, --append, --insert, --delete, --replace
Описание Используется для повышения информативности вывода и, как правило, используется совместно с командой --list. В случае использования с командой --list, в вывод этой команды включаются так же имя интерфейса, счетчики пакетов и байт для каждого правила. Формат вывода счетчиков предполагает вывод кроме цифр числа еще и символьные множители K (x1000), M (x1,000,000) и G (x1,000,000,000). Для того, чтобы заставить команду --list выводить полное число (без употребления множителей) требуется применять ключ -x, который описан ниже. Если ключ -v, --ver­bose используется с командами --append, --insert, --delete или --replace, то будет выведен подробный отчет о произведенной операции.
Ключ -x, --exact
Команды, с которыми используется --list
Описание Для всех чисел в выходных данных выводятся их точные значения без округления и без использования множителей K, M, G. Этот ключ используется только с командой --list и не применим с другими командами.
Ключ -n, --numer­ic
Команды, с которыми используется --list
Описание Заставляет ipt­a­bles выводить IP-адреса и номера портов в числовом виде предотвращая попытки преобразовать их в символические имена. Данный ключ используется только с командой --list.
Ключ --line-num­bers
Команды, с которыми используется --list
Описание Ключ --line-num­bers включает режим вывода номеров строк при отображении списка правил командой --list. Номер строки соответствует позиции правила в цепочке. Этот ключ используется только с командой --list.
Ключ -c, --set-coun­ters
Команды, с которыми используется --insert, --append, --replace
Описание Этот ключ используется для установки начального значения счетчиков пакетов и байт в заданное значение при создании нового правила. Например, ключ --set-coun­ters 20 4000 установит счетчик пакетов = 20, а счетчик байт = 4000.
Ключ --mod­probe
Команды, с которыми используется Все
Описание Ключ --mod­probe определяет команду загрузки модуля ядра. Данный ключ может использоваться в случае, когда модули ядра находится вне пути поиска (search path). Этот ключ может использоваться с любой командой.

 

Например:

ipt­a­bles -L -v -n - посмотреть список правил.

  • -L - команда вывода списка правил
  • -v - ключ повышающий информативность вывода
  • -n - вывод портов и ip-адресов в числовом виде

Критерии

После команды указывается критерий, условие которому должен соответствовать проходящий пакет. (например: ip-адрес источника или назначения, порт, интерфейс, протокол)

Критерии подразделяются на пять групп.

Общие критерии

Общие критерии могут употребляться в любых правилах.

Критерий -p, --pro­to­col
Пример ipt­a­bles -A INPUT -p tcp
Описание Этот критерий используется для указания типа протокола. Примерами протоколов могут быть TCP, UDP и ICMP. Прежде всего, в качестве имени протокола в данный критерий можно передавать один из трех вышеупомянутых протоколов, а также ключевое слово all. Критерию может передаваться и список протоколов, разделенных запятыми, например так: udp, tcp. Если данному критерию передается числовое значение 0, то это эквивалентно использованию спецификатора all, который подразумевается по умолчанию, когда критерий --pro­to­col не используется. Для логической инверсии критерия, перед именем протокола (списком протоколов) используется символ !, например --pro­to­col ! tcp подразумевает пакеты протоколов, UDP и ICMP.
Критерий -s, --src, --source
Пример ipt­a­bles -A INPUT -s 192.168.1.1
Описание IP-адрес(а) источника пакета. Адрес источника может указываться так, как показано в примере, тогда подразумевается единственный IP-адрес. А можно указать адрес в виде address/mask, например как 192.168.0.0/255.255.255.0, или более современным способом 192.168.0.0/24, т.е. фактически определяя диапазон адресов Как и ранее, символ !, установленный перед адресом, означает логическое отрицание, т.е. --source ! 192.168.0.0/24 означает любой адрес кроме адресов 192.168.0.x.
Критерий -d, --dst, --des­ti­na­tion
Пример ipt­a­bles -A INPUT -d 192.168.1.1
Описание IP-адрес(а) получателя. Имеет синтаксис схожий с критерием --source, за исключением того, что подразумевает адрес места назначения. Точно так же может определять как единственный IP-адрес, так и диапазон адресов. Символ ! используется для логической инверсии критерия.
Критерий -i, --in-inter­face
Пример ipt­a­bles -A INPUT -i eth0
Описание Интерфейс, с которого был получен пакет. Использование этого критерия допускается только в цепочках INPUT, FORWARD и PREROUTING. При отсутствии этого критерия предполагается любой интерфейс, что равносильно использованию критерия -i +. Как и прежде, символ ! инвертирует результат совпадения. Если имя интерфейса завершается символом +, то критерий задает все интерфейсы, начинающиеся с заданной строки, например -i PPP+ обозначает любой PPP интерфейс, а запись -i ! eth+ -- любой интерфейс, кроме любого eth.
Критерий -o, --out-inter­face
Пример ipt­a­bles -A FORWARD -o eth0
Описание Задает имя выходного интерфейса. Этот критерий допускается использовать только в цепочках OUTPUT, FORWARD и POSTROUTING, в противном случае будет генерироваться сообщение об ошибке. При отсутствии этого критерия предполагается любой интерфейс, что равносильно использованию критерия -o +. Как и прежде, символ ! инвертирует результат совпадения. Если имя интерфейса завершается символом +, то критерий задает все интерфейсы, начинающиеся с заданной строки, например -o eth+ обозначает любой eth интерфейс, а запись -o ! eth+ - любой интерфейс, кроме любого eth.
Критерий -f, --frag­ment
Пример ipt­a­bles -A INPUT -f
Описание Правило распространяется на все фрагменты фрагментированного пакета, кроме первого, сделано это потому, что нет возможности определить исходящий/входящий порт для фрагмента пакета, а для ICMP-пакетов определить их тип. Как и раньше, допускается использования символа ! для инверсии результата сравнения. только в данном случае символ ! должен предшествовать критерию -f, например ! -f. Инверсия критерия трактуется как "все первые фрагменты фрагментированных пакетов и/или нефрагментированные пакеты, но не вторые и последующие фрагменты фрагментированных пакетов".

 

  • Неявные критерии - критерии указанные неявно, становятся доступны при указании критерия -p. Например -p tcp.
  • Явные критерии - загружаются при помощи ключа -m. Например -m tcp. Если в правиле что-то не работает, при указании критериев TCP, UDP, ICMP, то можно указать их например так…

ipt­a­bles -A INPUT -p tcp -m tcp --dport 80 -j ACCEPT - разрешить входящие TCP соединения на 80 порт, для обращения к web-серверу. Указание на использование протокола tcp происходит двумя способами, при помощи критериев -m и -p.

TCP критерии

TCP критерии работают только с TCP пакетами, нужно обозначить использование протокола TCP "-p tcp". Протокол должен указываться перед специфичными критериями приведенными ниже.

Критерий --sport, --source-port
Пример ipt­a­bles -A INPUT -p tcp --sport 22
Описание Исходный порт, с которого был отправлен пакет. Номера портов могут задаваться в виде интервала из минимального и максимального номеров, например --source-port 22:80. Если опускается минимальный порт, т.е. когда критерий записывается как --source-port :80, то в качестве начала диапазона принимается число 0. Если опускается максимальный порт, т.е. когда критерий записывается как --source-port 22:, то в качестве конца диапазона принимается число 65535. Допускается такая запись --source-port 80:22, в этом случае ipt­a­bles поменяет числа 22 и 80 местами, т.е. подобного рода запись будет преобразована в --source-port 22:80. Как и раньше, символ используется для инверсии. Так критерий --source-port ! 22 подразумевает любой порт, кроме 22. Инверсия может применяться и к диапазону портов, например --source-port ! 22:80. За дополнительной информацией обращайтесь к описанию критерия mul­ti­port.
Критерий --dport, --des­ti­na­tion-port
Пример ipt­a­bles -A INPUT -p tcp --dport 22
Описание Порт или диапазон портов, на который адресован пакет. Аргументы задаются в том же формате, что и для --source-port.
Критерий --tcp-flags
Пример ipt­a­bles -p tcp --tcp-flags SYN,FIN,ACK,SYN
Описание Определяет маску и флаги tcp-пакета. Пакет считается удовлетворяющим критерию, если из перечисленных флагов в первом списке в единичное состояние установлены флаги из второго списка. Так для вышеуказанного примера под критерий подпадают пакеты у которых флаг SYN установлен, а флаги FIN и ACK сброшены. В качестве аргументов критерия могут выступать флаги SYN, ACK, FIN, RST, URG, PSH, а так же зарезервированные идентификаторы all и none. all - значит ВСЕ флаги и none - НИ ОДИН флаг. Так, критерий --tcp-flags ALL NONE означает - "все флаги в пакете должны быть сброшены". Как и ранее, символ ! означает инверсию критерия Важно: имена флагов в каждом списке должны разделяться запятыми, пробелы служат для разделения списков.
Критерий --syn
Пример ipt­a­bles -p tcp --syn
Описание Критерию соответствуют пакеты с установленным флагом SYN и сброшенными флагами ACK и FIN. Этот критерий аналогичен критерию --tcp-flags SYN,ACK,FIN,SYN. Такие пакеты используются для открытия соединения TCP. Заблокировав такие пакеты, вы надежно заблокируете все входящие запросы на соединение, однако этот критерий не способен заблокировать исходящие запросы на соединение. Как и ранее, допускается инвертирование критерия символом !. Так критерий ! --syn означает -- "все пакеты, не являющиеся запросом на соединение", т.е. все пакеты с установленными флагами FIN или ACK.
Критерий --tcp-option
Пример ipt­a­bles -p tcp --tcp-option 16
Описание Удовлетворяющим условию данного критерия будет будет считаться пакет, TCP параметр которого равен заданному числу. TCP Option - это часть заголовка пакета. Она состоит из 3 различных полей. Первое 8-ми битовое поле содержит информацию об опциях, используемых в данном соединении. Второе 8-ми битовое поле содержит длину поля опций. Если следовать стандартам до конца, то следовало бы реализовать обработку всех возможных вариантов, однако, вместо этого мы можем проверить первое поле и в случае, если там указана неподдерживаемая нашим брандмауэром опция, то просто перешагнуть через третье поле (длина которого содержится во втором поле). Пакет, который не будет иметь полного TCP заголовка, будет сброшен автоматически при попытке изучения его TCP параметра. Как и ранее, допускается использование флага инверсии условия !.

 

UDP критерии

UDP критерии работают только с UDP пакетами, нужно обозначить использование протокола UDP "-p udp". Протокол должен указываться перед специфичными критериями приведенными ниже.

Критерий --sport, --source-port
Пример ipt­a­bles -A INPUT -p udp --sport 53
Описание Исходный порт, с которого был отправлен пакет. Номера портов могут задаваться в виде интервала из минимального и максимального номеров, например -source-port 22:80. Если опускается минимальный порт, т.е. когда критерий записывается как --source-port :80, то в качестве начала диапазона принимается число 0. Если опускается максимальный порт, т.е. когда критерий записывается как --source-port 22: , то в качестве конца диапазона принимается число 65535. Допускается такая запись --source-port 80:22 , в этом случае ipt­a­bles поменяет числа 22 и 80 местами, т.е. подобного рода запись будет преобразована в --source-port 22:80 . Как и раньше, символ используется для инверсии. Так критерий --source-port ! 22 подразумевает любой порт, кроме 22. Инверсия может применяться и к диапазону портов, например --source-port ! 22:80.
Критерий --dport, --des­ti­na­tion-port
Пример ipt­a­bles -A INPUT -p udp --dport 53
Описание Порт, на который адресован пакет. Формат аргументов полностью аналогичен принятому в критерии --source-port.

 

ICMP критерии

ICMP используется для сообщения об ошибках и управления соединениями. Использование протокола должно быть указано как "-p icmp". Помимо специфичных критериев, для работы с ICMP могут использоваться и общие критерии.

Критерий --icmp-type
Пример ipt­a­bles -A INPUT -p icmp --icmp-type 8
Описание Тип сообщения ICMP определяется номером или именем. Чтобы получить список имен ICMP значений выполните команду ipt­a­bles --pro­to­col icmp --help Как и ранее, символ ! инвертирует критерий, например --icmp-type ! 8.

 

Специальные критерии
Критерий Limit
Ключ --lim­it
Пример ipt­a­bles -A INPUT -m lim­it --lim­it 3/hour
Описание Устанавливается средняя скорость "освобождения емкости" за единицу времени. В качестве аргумента указывается число пакетов и время. Допустимыми считаются следующие единицы измерения времени: /second /minute /hour /day. По умолчанию принято значение 3 пакета в час, или 3/hour. Использование флага инверсии условия ! в данном критерии недопустим.
Ключ --lim­it-burst
Пример ipt­a­bles -A INPUT -m lim­it --lim­it-burst 5
Описание Устанавливает максимальное значение числа burst lim­it для критерия lim­it. Это число увеличивается на единицу если получен пакет, подпадающий под действие данного правила, и при этом средняя скорость (задаваемая ключом --lim­it) поступления пакетов уже достигнута. Так происходит до тех пор, пока число burst lim­it не достигнет максимального значения, устанавливаемого ключом --lim­it-burst. После этого правило начинает пропускать пакеты со скоростью, задаваемой ключом --lim­it. Значение по-умолчанию принимается равным 5.

 

Критерий MAC
Ключ --mac-source
Пример ipt­a­bles -A INPUT -m mac --mac-source 00:00:00:00:00:01
Описание MAC адрес сетевого узла, передавшего пакет. MAC адрес должен указываться в форме XX:XX:XX:XX:XX:XX. Как и ранее, символ ! используется для инверсии критерия, например --mac-source ! 00:00:00:00:00:01, что означает - "пакет с любого узла, кроме узла, который имеет MAC адрес 00:00:00:00:00:01" . Этот критерий имеет смысл только в цепочках PREROUTING, FORWARD и INPUT и нигде более.

 

Критерий MARK
Ключ --mark
Пример ipt­a­bles -t man­gle -A INPUT -m mark --mark 1
Описание Критерий производит проверку пакетов, которые были предварительно "помечены". Метки устанавливаются действием mark, которое мы будем рассматривать ниже. Все пакеты, проходящие через net­fil­ter имеют специальное поле mark. Запомните, что нет никакой возможности передать состояние этого поля вместе с пакетом в сеть. Поле mark является целым беззнаковым, таким образом можно создать не более 4294967296 различных меток. Допускается использовать маску с меткам. В данном случае критерий будет выглядеть подобным образом: --mark 1/1. Если указывается маска, то выполняется логическое and метки и маски.

 

Критерий Multiport
Ключ --source-port
Пример ipt­a­bles -A INPUT -p tcp -m mul­ti­port --source-port 22,53,80,110
Описание Служит для указания списка исходящих портов. С помощью данного критерия можно указать до 15 различных портов. Названия портов в списке должны отделяться друг от друга запятыми, пробелы в списке не допустимы. Данное расширение может использоваться только совместно с критериями -p tcp или -p udp. Главным образом используется как расширенная версия обычного критерия --source-port.
Ключ --des­ti­na­tion-port
Пример ipt­a­bles -A INPUT -p tcp -m mul­ti­port --des­ti­na­tion-port 22,53,80,110
Описание Служит для указания списка входных портов. Формат задания аргументов полностью аналогичен -m mul­ti­port --source-port.
Ключ --port
Пример ipt­a­bles -A INPUT -p tcp -m mul­ti­port --port 22,53,80,110
Описание Данный критерий проверяет как исходящий так и входящий порт пакета. Формат аргументов аналогичен критерию --source-port и --des­ti­na­tion-port. Обратите внимание на то что данный критерий проверяет порты обеих направлений, т.е. если вы пишете -m mul­ti­port --port 80, то под данный критерий подпадают пакеты, идущие с порта 80 на порт 80.

 

Критерий Owner
Ключ --uid-own­er
Пример ipt­a­bles -A OUTPUT -m own­er --uid-own­er 500
Описание Производится проверка "владельца" по User ID (UID). Подобного рода проверка может использоваться, к примеру, для блокировки выхода в Интернет отдельных пользователей.
Ключ --gid-own­er
Пример ipt­a­bles -A OUTPUT -m own­er --gid-own­er 0
Описание Производится проверка "владельца" пакета по Group ID (GID).
Ключ --pid-own­er
Пример ipt­a­bles -A OUTPUT -m own­er --pid-own­er 78
Описание Производится проверка "владельца" пакета по Process ID (PID). Этот критерий достаточно сложен в использовании, например, если мы хотим позволить передачу пакетов на HTTP порт только от заданного демона, то нам потребуется написать небольшой сценарий, который получает PID процесса (хотя бы через ps) и затем подставляет найденный PID в правила.
Ключ --sid-own­er
Пример ipt­a­bles -A OUTPUT -m own­er --sid-own­er 100
Описание Производится проверка Ses­sion ID пакета. Значение SID наследуются дочерними процессами от "родителя", так, например, все процессы HTTPD имеют один и тот же SID. Этот сценарий можно запускать по времени для проверки наличия процесса HTTPD, и в случае отсутствия - перезапустить "упавший" процесс, после чего сбросить содержимое цепочки OUTPUT и ввести ее снова.

 

Критерий State
Ключ --state
Пример ipt­a­bles -A INPUT -m state --state RELATED,ESTABLISHED
Описание Проверяется признак состояния соединения (state) На сегодняшний день можно указывать 4 состояния: INVALID, ESTABLISHED, NEW и RELATED. INVALID подразумевает, что пакет связан с неизвестным потоком или соединением и, возможно содержит ошибку в данных или в заголовке. Состояние ESTABLISHED указывает на то, что пакет принадлежит уже установленному соединению через которое пакеты идут в обеих направлениях. Признак NEW подразумевает, что пакет открывает новое соединение или пакет принадлежит однонаправленному потоку. И наконец, признак RELATED указывает на то что пакет принадлежит уже существующему соединению, но при этом он открывает новое соединение.

 

Критерий TOS
Ключ --tos
Пример ipt­a­bles -A INPUT -p tcp -m tos --tos 0x16
Описание Данный критерий предназначен для проверки установленных битов TOS, которые описывались выше. Как правило поле используется для нужд маршрутизации, но вполне может быть использовано с целью "маркировки" пакетов для использования с iproute2 и дополнительной маршрутизации в lin­ux. В качестве аргумента критерию может быть передано десятичное или шестнадцатиричное число, или мнемоническое описание бита, мнемоники и их числовое значение вы можете получить выполнив команду ipt­a­bles -m tos -h.

 

Критерий TTL
Ключ --ttl
Пример ipt­a­bles -A OUTPUT -m ttl --ttl 60
Описание Производит проверку поля TTL на равенство заданному значению.

Действия и переходы

Действие - это действие, которое необходимо применить к пакету при соответствии критерию. Действия бывают двух видов.

Терминальные действия

Если в результате действия пакет прекращает свое прохождение по цепочке, то такое действие называется терминальным.

  • ACCEPTпакет прекращает движение по цепочке и считается принятым. Однако может продолжить движение в других таблицах.
  • DROPдействие полностью сбрасывающее пакет. Сброшенный пакет прекращает дальнейшее движение и не передается в другие таблицы.
  • REJECTто же самое что и DROP, только в отличие от DROP отправляется сообщение об ошибке.
  • NFQUEUEпередает специальному демону весь пакет целиком. Пакет прекращает движение по цепочке.
Нетерминальные действия

Если в результате действия пакет продолжает свое прохождение по цепочке, то такое действие называется нетерминальным.

  • DNAT - используется для преобразования адреса места назначения в IP заголовке пакета. Пакет продолжает движение по цепочке.
  • LOGслужит для журналирования отдельных пакетов и событий, производит запись в log-файл. Пакет продолжает движение по цепочке.
  • MARKиспользуется для установки меток на пакеты. Пакет продолжает движение по цепочке.
  • SNATиспользуется для преобразования сетевых адресов, изменяет исходящий ip-адрес в заголовке пакета. Принято использовать при статическом ip-адресе. Пакет продолжает движение по цепочке.
  • MASQUERADEто же самое что и SNAT, используется когда ip-адрес динамический.
  • MIRRORв результате действия в пакете меняются местами поля source и des­ti­na­tion, после чего пакет выкидывается в сеть. Атакующий над пакетом которого было произведено подобное действие, может пытаться взломать сам себя. Применять стоит с осторожностью, так как может привести к зацикливанию пакетов и вызвать отказ в обслуживании.
  • REDIRECTвыполняет перенаправление пакетов на другой порт. Пакет продолжает движение по цепочке.
  • TOSпроизводит установку битов в поле type of ser­vice IP заголовка. Данное поле обрабатывается маршрутизаторами для выбора маршрута движения пакета. Пакет продолжает движение по цепочке.
  • TTLиспользуется для изменения содержимого поля time to live в IP заголовке.
  • ULOG - возможность журналирования пакетов в пользовательском пространстве. Заменяет традиционное действие LOG, базирующееся на системном журнале.

Для примера возьмем два правила, одно с нетерминальным действием, другое с терминальным действием. Если вначале поставить правило с терминальным действием, то второе выполнятся не будет.

Первое правило позволяет принимать запросы на 80-м порту. Второе правило должно отмечать эти пакеты в log-файле. При такой форме второе правило работать не будет, так как пакет будет принят и отправлен на 80 порт web-сервера и до второго правила в цепочке просто не дойдет.

Для того чтобы это работало, правила надо поменять местами, то есть терминальное действие всегда должно находиться в конце цепочки.

Пакет соответствующий -p tcp критерию сначала отметится в логе, а потом будет передан на 80 порт web-сервера, окончательно покинув цепочку.

Если в процессе прохождения к пакету не было применено ни одного терминального действия, то к нему будет применена политика по умолчанию, установленная для цепочки. Причем это действие будет обязательно терминальным.

Действие RETURN

Пакет полностью прекращает движение по текущей цепочке и возвращается в предыдущую. Занимает промежуточное положение между терминальными и нетерминальными действиями, так как может прервать обработку пакета, но необязательно в рамках текущей цепочки.

Переходы

Переход, как и действие, указывает правилу что надо делать с пакетом, если он соответствует критерию. Для указания перехода ставится ключ "-j" и указывается цепочка правил на которую выполняется переход. Новая цепочка обязательно должна находиться в той же таблице, что и цепочка из которой выполняется переход. Новая цепочка должна быть создана до того как на нее будет выполняться переход.

Ключ "-j" универсален и используется для указания не только переходов, но и действий.

ipt­a­bles -N new_chain_name - создаем новую цепочку.

ipt­a­bles -A INPUT -s 192.168.1.10 -j new_name_chain - все пакеты с адреса 192.168.1.10 переходят на цепочку new_name_chain

Пакет переданный с определенного адреса, переходит на заранее созданную цепочку, где может продолжать обрабатываться правилами новой цепочки. Пакеты не соответствующие критерию (ip-адресу) продолжают движение по цепочке INPUT.

Небольшая практика

Рассмотрим следующую ситуацию. Есть некий компьютер, доступ на который нужно разрешить только с двух адресов - 192.168.1.2 и 192.168.1.200, все пакеты с этих машин должны попадать в логи. Для остальных доступ должен быть закрыт. Нужно ограничить исходящие соединения, но поскольку система должна обновляться, то оставить лазейку для проведения обновлений.

Подобное задание я решил следующим набором правил, здесь есть все что нужно.

Сейчас они ничего не говорят тому, кто только начал знакомство с ipt­a­bles, поэтому разберем по порядку все что написано.

Очистим цепочки правил в таблице fil­ter, если у вас девственно чистая система, на которой еще не пользовались фаерволом, то оно не является обязательным к использованию. Это правило я привожу исключительно для примера.

Если его применить на системе с настроенным фаерволом, то можно остаться с разорванным SSH-соединением и невозможностью удаленного доступа. Правила разрешающие вход будут удалены, а политики по умолчанию останутся без изменений, то есть закрытыми, об этом позже.

Именно поэтому, чтобы не остаться без доступа к серверу я записал правила в таком порядке, в таком же порядке я добавляю их в фаервол.

Чтобы проверить текущее состояние фаервола и удостовериться в том что все чисто и открыто, можно выполнить следующую команду.

Обращаем внимание на те самые политики по умолчанию "pol­i­cy", везде отображается значение ACCEPT, это значит что все цепочки открыты для приема соединений.

Открываем соединения только для определенных ip-адресов - 192.168.1.2 и 192.168.1.200, все соединения с этих адресов заносятся в логи.

Пакет с разрешенного адреса попадает в таблицу и обрабатывается первым правилом в цепочке и заносится в лог. Пакет движется дальше и к нему применяется действие из второго правила, пакет принимается и покидает цепочку.

Насчет использования префикса "input_connect: ", он может быть любым и должен записываться в кавычках. Использование префикса необходимо в том случае когда запись логов происходит в системные лог-файлы mes­sages или sys­log, во избежание путаницы.

Вот так выглядит отрывок лог-файла /var/log/messages c отмеченными входящими пакетами с адреса 192.168.1.2

Напоминаю, все приводится исключительно в виде примеров, по хорошему запись логов должна проводиться в отдельный файл. Как это сделать я расскажу в отдельной статье.

Разрешаем трафик локального интерфейса, для функционирования служб и приложений.

Разрешаем выходной трафик на сетевом интерфейсе enp0s3, для проведения обновлений и т.д.

Закрываем все соединения при помощи Default Pol­i­cy (политик по умолчанию) в след. цепочках: INPUT, OUTPUT, FORWARD. Этим достигается полный запрет входящего трафика со всех адресов кроме разрешенных, ограничение исходящего трафика и запрет транзитных пакетов.

Обратите внимание, что политики задают только после того, как заданы правила разрешающие соединение для вас самих.

Последнее что от нас требовалось, это разрешить свободное прохождение пакетов относящихся к уже установленным соединениям, это самый интересный момент. Заодно станет понятно как работает определение состояний con­ntrack. Пробуем выполнить команду обновления системы.

В ответ получаем массу ошибок "Could not resolve host" - это означает что системе не удается получить ответ от зеркала с которого происходит обновление.

Система не обновляется, ответные пакеты не приходят. Это неудивительно, мы можем получать пакеты только с двух адресов в число которых зеркала обновлений не входят. Для решения проблемы придется прибегнуть к помощи определения состояний con­ntrack.

Добавляем правила разрешающие беспрепятственный проход пакетов принадлежащих к уже установленным соединениям.

Ответные пакеты принадлежащие соединениям ESTABLISHED и RELATED, будут пропущены, и неважно что адрес с которого поступил пакет не входит в список разрешенных.

Сравним вывод действующих правил с предыдущим выводом, когда все было открыто.

На данном примере мы получили вполне огороженную от посторонних запросов машину, со свободным доступом для избранных. Это может быть какой нибудь сервер для определенного круга лиц. А список адресов со временем можно расширить, просто дописав нужный адрес в правило. Это всего лишь пример, первое что пришло мне в голову, когда я придумывал задачу для практической части.

Конечно данной статьи недостаточно, я всего лишь рассказал про основы. Если хотите знать, а не бездумно копировать готовые правила, то вам как минимум надо изучить документацию к ipt­a­bles. Рекомендую следующую литературу, в свое время я учился по ней:

https://ru.wikibooks.org/wiki/Iptables

https://www.opennet.ru/docs/RUS/iptables/

Для знающих английский, официальная документация:

http://www.netfilter.org/documentation/index.html

https://www.frozentux.net/iptables-tutorial/iptables-tutorial.html