Сегодня я хочу рассказать о защите системы при помощи встроенного в ядро Linux межсетевого экрана Netfilter.
Поначалу я хотел написать одну статью, но в процессе написания понял что так дело не пойдет, слишком большой объем информации. Поэтому я решил разбить статью на несколько частей, в которых буду последовательно и подробно описывать механизм и способы защиты с помощью межсетевого экрана Netfilter и правил iptables.
Механизм работы & термины
Защита основывается на встроенном в ядро Linux межсетевом экране Netfilter. Межсетевой экран или как его еще называют, фаервол, представляет из себя набор средств для контроля и фильтрации проходящих сетевых пакетов (трафика), в соответствии с заданными правилами.
Для управления фаерволом используется утилита iptables. С помощью нее создаются правила, определяющие регулировку и фильтрацию трафика. Обычно, когда говорят - Netfilter, то имеют ввиду только элементы межсетевого экрана являющиеся частью ядра.
Все что не относится к ядру, как-то: таблицы, цепочки, правила - называют iptables. Во избежание путаницы, правильно будет называть всю систему - netfilter/iptables.
Вся фильтрация и регулировка трафика определяется правилами. Правила состоят из критерия, действия и счетчика. Если пакет соответствует критерию, то к нему применяется действие и он учитывается счетчиком.
Если в правиле отсутствует заданный критерий определяющий нужный пакет, то по умолчанию будет использоваться критерий - "все пакеты" и правило применяется ко всем пакетам, а не к конкретному их виду. Действие тоже может отсутствовать в правиле, тогда правило будет работать как счетчик.
- Критерий - логическое выражение определяющее попадает ли данный пакет под действие правила.
- Действие - действие которое надо проделать с пакетом если он соответствует заданному критерию.
- Счетчик - компонент учитывающий количество пакетов, попавших под критерий данного правила.
Правила объединяются в цепочки, даже одно правило будет считаться цепочкой. Цепочки могут быть базовыми или пользовательскими.
- Базовая цепочка - цепочка правил по умолчанию. Каждый входящий, исходящий или транзитный пакет обязан пройти базовые цепочки различных таблиц. Базовая цепочка отличается от пользовательской наличием так называемых, политик по умолчанию (Default Policy). Политика по умолчанию - это действие применяемое к пакетам не попавшим под заданные правила. Имена базовых цепочек всегда должны записываться в верхнем регистре: PREROUTING, INPUT, FORWARD, OUTPUT, POSTROUTING.
- PREROUTING - цепочка первоначальной обработки пакетов.
- INPUT - цепочка для входящих пакетов предназначенных для локальных служб и приложений.
- FORWARD - цепочка транзитных пакетов, вход ------>>> выход
- OUTPUT - цепочка исходящих пакетов сформированных локальными службами и приложениями.
- POSTROUTING - цепочка окончательной обработки пакетов покидающих систему. Сюда могут попадать пакеты из цепочек OUTPUT & FORWARD.
- Пользовательская цепочка - цепочка созданная пользователем.
Цепочки, в свою очередь, объединяются в таблицы.
Таблицы представляют из себя совокупность базовых и пользовательских цепочек, имеющих общее назначение. Имена таблиц записываются в нижнем регистре. Если таблица в правиле не указывается, то по умолчанию правило принадлежит таблице filter.
- raw - редко используемая таблица, которая просматривается до передачи пакета системе определения состояний conntrack. Может использоваться для маркировки пакетов, которые не должны обрабатываться системой изменения состояний, для этого в правиле необходимо указать действие NOTRACK. Может присутствовать в цепочках - PREROUTING и OUTPUT.
- mangle - таблица содержащая правила для модификации пакетов, может встречаться во всех цепочках.
- nat - таблица для пакетов создающих новые соединения. может использоваться для подмены адреса отправителя или получателя. Изменения применяется к первому пакету из потока, ко всем остальным применяется автоматически. Встречается в цепочках - PREROUTING, OUTPUT, POSTROUTING.
- filter - основная таблица по умолчанию, если название таблицы не указывается. Используется для фильтрации пакетов, присутствует только в - INPUT, FORWARD, OUTPUT цепочках.
Пути прохождения трафика
Пакет поступивший на сетевой интерфейс перехватывается драйвером устройства и передается в ядро системы, где начинает проходить определенную последовательность цепочек, начиная с цепочки PREROUTING при ее наличии. После прохода цепочки PREROUTING, происходит сверка с таблицей маршрутизации (Routing) где устанавливается принадлежность пакета, в зависимости от принадлежности определяется его дальнейший путь.
Если пакет адресован локальной системе, то он передается в цепочку INPUT и после обработки содержащимися в ней правилами отправляется локальным процессам или приложениям. Если пакет не адресован локальной системе, то он отправляется в цепочку FORWARD.
После обработки пакета локальным процессом или приложением, происходит формирование ответного пакета, если это необходимо. Пакет покидающий локальную систему, в соответствии с правилами маршрутизации (Routing), направляется в цепочку OUTPUT.
Пакеты из цепочек OUTPUT/FORWARD, снова маршрутизируются (Routing) и отправляются в цепочку POSTROUTING, после чего окончательно покидают ядро и попадают во внешнюю сеть.
Для представления путей прохождения пакетов можно ознакомиться со схемой. Очень важно иметь представление о движении трафика, это здорово помогает при написании правил.
Существует три вида трафика и соответственно три маршрута прохождения пакетов.
Входящие пакеты для локальных приложений
Прохождение цепочки PREROUTING:
- Проверяется таблица raw (может не быть), после происходит отслеживание состояний conntrack
- Проверяется таблица mangle (может не быть)
- Проверяется таблица nat (Может использоваться для DNAT - модификации адреса получателя ), которой тоже может не быть.
Таблицы с пометкой "может не быть", означают что они не указаны в правилах или не указаны правила для них, замечание верно в любом случае. Несмотря на это PREROUTING существует, в случае отсутствия правил пакет проходит определение состояний и передается в routing, а после в цепочку INPUT.
Прохождение цепочки INPUT:
- Проверяется таблица mangle (может не быть)
- Проверяется таблица filter (обязательна)
После обработки правилами таблицы filter пакет передается соответствующему локальному приложению или процессу.
Исходящие пакеты от локальных приложений
При маршрутизации определяется исходящий адрес, выходной интерфейс, пакет передается в цепочку OUTPUT.
Прохождение цепочки OUTPUT:
- Проверяется таблица raw (может не быть), после происходит отслеживание состояний conntrack
- Проверяется таблица mangle (может не быть)
- Проверяется таблица nat (NAT - для локально сгенерированных пакетов) (может не быть)
- Проверяется таблица filter (обязательна)
Повторная маршрутизация, передача пакета в цепочку POSTROUTING
Прохождение цепочки POSTROUTING:
- Проверяется таблица mangle (может не быть)
- Проверяется таблица nat (Может использоваться для SNAT - модификации адреса источника) (может не быть)
В любом случае выход пакета во внешнюю сеть.
Транзитные/проходящие мимо пакеты
Прохождение цепочки PREROUTING:
- Проверяется таблица raw (может не быть), после происходит отслеживание состояний conntrack
- Проверяется таблица mangle (может не быть)
- Проверяется таблица nat (Может использоваться для DNAT - модификации адреса получателя ), которой тоже может не быть.
Маршрутизация: если пакет не предназначен для локальных приложений, то он передается в цепочку FORWARD
Прохождение цепочки FORWARD:
- Проверяется таблица mangle (может не быть)
- Проверяется таблица filter (обязательна)
Повторная маршрутизация, передача пакета в цепочку POSTROUTING
Прохождение цепочки POSTROUTING:
- Проверяется таблица mangle (может не быть)
- Проверяется таблица nat (Может использоваться для SNAT и MASQUERADING) (может не быть)
Таблицы nat и mangle могут изменять получателя или отправителя пакета, поэтому пакеты несколько раз сверяются с таблицей маршрутизации.
Conntrack - механизм определения состояний
Механизм определения состояний (state machine, connection tracking, conntrack) отдельная часть netfilter/iptables. Conntrack представляет из себя трассировщик соединений, путем отслеживания которых, conntrack определяет принадлежность сетевых пакетов к тому или иному соединению. После чего информация о принадлежности пакета предоставляется фаерволу.
Пакеты могут не отслеживаться, для этого пакет должен быть помечен действием NOTRACK в таблице raw, в которую входят цепочки правил PREROUTIG & OUTPUT.
Установив принадлежность пакета, происходит определение его дальнейшего пути. Существует четыре вида состояния соединений.
- NEW - Пакет принадлежит новому соединению и является первым для данного соединения.
- ESTABLISHED - Уже установленное соединение, пакет принадлежащий ему не является первым пакетом в соединении. Чтобы соединение стало установленным, требуется чтобы хост передал пакет и получил на него ответ от другого хоста, после получения ответа соединение считается установленным и становится ESTABLISHED. Соединения NEW и RELATED после получения ответа переходят в состояние ESTABLISHED.
- RELATED - Данное соединение и принадлежащие ему пакеты, связаны с соединением ESTABLISHED или являются его производным.
- INVALID - Неопределенное соединение, пакет не идентифицируется и не получает определенного статуса.
Механизм conntrack позволяет не фильтровать лишний раз входящий трафик относящийся к уже установленным соединениям. Предоставляет возможность получения ответного трафика при полностью закрытом входе.
Правила iptables и их составляющие
Все пакеты проходят через цепочки (наборы правил), регулирующих прохождение пакетов. Пока пакет проходит через цепочку, к нему применяются все правила в порядке следования. Если пакет соответствует установленному в правиле критерию, то к нему применяется установленное в правиле действие.
Выглядят правила примерно следующим образом, так как жестких требований к написанию правил нет, за исключением отдельных частей.
iptables [-t таблица][команда][критерий][действие]
Сначала принято указывать таблицу к которой будет относится правило, указывать таблицу можно в любом месте, но негласно принято указывать таблицу вначале. Для указания таблицы используется ключ -t.
Например: iptables -t nat - указывает что правило будет относится к таблице nat
Команды
После таблицы указывается команда. Если таблица не указана, то команда всегда должна быть первой.
Например:
iptables -t nat -F или iptables -F -t nat
Данное правило очищает таблицу nat, поскольку таблица может указываться в любом месте, то обе формы записи будут правильны.
Список доступных команд, запись в верхнем регистре.
Команда | -A, --append |
Пример | iptables -A INPUT |
Описание | Добавляет новое правило в конец заданной цепочки. |
Команда | -D, --delete |
Пример | iptables -D INPUT --dport 80 -j DROP или iptables -D INPUT 1 |
Описание | Удаление правила из цепочки. Команда имеет два формата записи, первый -- когда задается критерий сравнения с опцией -D (см. первый пример), второй -- порядковый номер правила. Если задается критерий сравнения, то удаляется правило, которое имеет в себе этот критерий, если задается номер правила, то будет удалено правило с заданным номером. Счет правил в цепочках начинается с 1. |
Команда | -R, --replace |
Пример | iptables -R INPUT 1 -s 192.168.0.1 -j DROP |
Описание | Эта команда заменяет одно правило другим. В основном она используется во время отладки новых правил. |
Команда | -I, --insert |
Пример | iptables -I INPUT 1 --dport 80 -j ACCEPT |
Описание | Вставляет новое правило в цепочку. Число, следующее за именем цепочки указывает номер правила, перед которым нужно вставить новое правило, другими словами число задает номер для вставляемого правила. В примере выше, указывается, что данное правило должно быть 1-м в цепочке INPUT. |
Команда | -L, --list |
Пример | iptables -L INPUT |
Описание | Вывод списка правил в заданной цепочке, в данном примере предполагается вывод правил из цепочки INPUT. Если имя цепочки не указывается, то выводится список правил для всех цепочек. Формат вывода зависит от наличия дополнительных ключей в команде, например -n, -v, и пр. |
Команда | -F, --flush |
Пример | iptables -F INPUT |
Описание | Сброс (удаление) всех правил из заданной цепочки (таблицы). Если имя цепочки и таблицы не указывается, то удаляются все правила, во всех цепочках. |
Команда | -Z, --zero |
Пример | iptables -Z INPUT |
Описание | Обнуление всех счетчиков в заданной цепочке. Если имя цепочки не указывается, то подразумеваются все цепочки. При использовании ключа -v совместно с командой -L, на вывод будут поданы и состояния счетчиков пакетов, попавших под действие каждого правила. Допускается совместное использование команд -L и -Z. В этом случае будет выдан сначала список правил со счетчиками, а затем произойдет обнуление счетчиков. |
Команда | -N, --new-chain |
Пример | iptables -N new_name_chain |
Описание | Создается новая цепочка с заданным именем в заданной таблице В выше приведенном примере создается новая цепочка с именем new_name_chain. Имя цепочки должно быть уникальным и не должно совпадать с зарезервированными именами цепочек. |
Команда | -X, --delete-chain |
Пример | iptables -X new_name_chain |
Описание | Удаление заданной цепочки из заданной таблицы. Удаляемая цепочка не должна иметь правил и не должно быть ссылок из других цепочек на удаляемую цепочку. Если имя цепочки не указано, то будут удалены все цепочки заданной таблице кроме встроенных. |
Команда | -P, --policy |
Пример | iptables -P INPUT DROP |
Описание | Задает политику по-умолчанию для заданной цепочки. Политика по-умолчанию определяет действие, применяемое к пакетам не попавшим под действие ни одного из правил в цепочке. В качестве политики по умолчанию допускается использовать DROP и ACCEPT. |
Команда | -E, --rename-chain |
Пример | iptables -E new_name_chain chain_new_name |
Описание | Команда -E выполняет переименование пользовательской цепочки. В примере цепочка new_name_chain будет переименована в цепочку chain_new_name. |
Дополнительные ключи
Команды могут использоваться с дополнительными ключами, запись в нижнем регистре.
Ключ | -v, --verbose |
Команды, с которыми используется | --list, --append, --insert, --delete, --replace |
Описание | Используется для повышения информативности вывода и, как правило, используется совместно с командой --list. В случае использования с командой --list, в вывод этой команды включаются так же имя интерфейса, счетчики пакетов и байт для каждого правила. Формат вывода счетчиков предполагает вывод кроме цифр числа еще и символьные множители K (x1000), M (x1,000,000) и G (x1,000,000,000). Для того, чтобы заставить команду --list выводить полное число (без употребления множителей) требуется применять ключ -x, который описан ниже. Если ключ -v, --verbose используется с командами --append, --insert, --delete или --replace, то будет выведен подробный отчет о произведенной операции. |
Ключ | -x, --exact |
Команды, с которыми используется | --list |
Описание | Для всех чисел в выходных данных выводятся их точные значения без округления и без использования множителей K, M, G. Этот ключ используется только с командой --list и не применим с другими командами. |
Ключ | -n, --numeric |
Команды, с которыми используется | --list |
Описание | Заставляет iptables выводить IP-адреса и номера портов в числовом виде предотвращая попытки преобразовать их в символические имена. Данный ключ используется только с командой --list. |
Ключ | --line-numbers |
Команды, с которыми используется | --list |
Описание | Ключ --line-numbers включает режим вывода номеров строк при отображении списка правил командой --list. Номер строки соответствует позиции правила в цепочке. Этот ключ используется только с командой --list. |
Ключ | -c, --set-counters |
Команды, с которыми используется | --insert, --append, --replace |
Описание | Этот ключ используется для установки начального значения счетчиков пакетов и байт в заданное значение при создании нового правила. Например, ключ --set-counters 20 4000 установит счетчик пакетов = 20, а счетчик байт = 4000. |
Ключ | --modprobe |
Команды, с которыми используется | Все |
Описание | Ключ --modprobe определяет команду загрузки модуля ядра. Данный ключ может использоваться в случае, когда модули ядра находится вне пути поиска (search path). Этот ключ может использоваться с любой командой. |
Например:
iptables -L -v -n - посмотреть список правил.
- -L - команда вывода списка правил
- -v - ключ повышающий информативность вывода
- -n - вывод портов и ip-адресов в числовом виде
Критерии
После команды указывается критерий, условие которому должен соответствовать проходящий пакет. (например: ip-адрес источника или назначения, порт, интерфейс, протокол)
Критерии подразделяются на пять групп.
Общие критерии
Общие критерии могут употребляться в любых правилах.
Критерий | -p, --protocol |
Пример | iptables -A INPUT -p tcp |
Описание | Этот критерий используется для указания типа протокола. Примерами протоколов могут быть TCP, UDP и ICMP. Прежде всего, в качестве имени протокола в данный критерий можно передавать один из трех вышеупомянутых протоколов, а также ключевое слово all. Критерию может передаваться и список протоколов, разделенных запятыми, например так: udp, tcp. Если данному критерию передается числовое значение 0, то это эквивалентно использованию спецификатора all, который подразумевается по умолчанию, когда критерий --protocol не используется. Для логической инверсии критерия, перед именем протокола (списком протоколов) используется символ !, например --protocol ! tcp подразумевает пакеты протоколов, UDP и ICMP. |
Критерий | -s, --src, --source |
Пример | iptables -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, --destination |
Пример | iptables -A INPUT -d 192.168.1.1 |
Описание | IP-адрес(а) получателя. Имеет синтаксис схожий с критерием --source, за исключением того, что подразумевает адрес места назначения. Точно так же может определять как единственный IP-адрес, так и диапазон адресов. Символ ! используется для логической инверсии критерия. |
Критерий | -i, --in-interface |
Пример | iptables -A INPUT -i eth0 |
Описание | Интерфейс, с которого был получен пакет. Использование этого критерия допускается только в цепочках INPUT, FORWARD и PREROUTING. При отсутствии этого критерия предполагается любой интерфейс, что равносильно использованию критерия -i +. Как и прежде, символ ! инвертирует результат совпадения. Если имя интерфейса завершается символом +, то критерий задает все интерфейсы, начинающиеся с заданной строки, например -i PPP+ обозначает любой PPP интерфейс, а запись -i ! eth+ -- любой интерфейс, кроме любого eth. |
Критерий | -o, --out-interface |
Пример | iptables -A FORWARD -o eth0 |
Описание | Задает имя выходного интерфейса. Этот критерий допускается использовать только в цепочках OUTPUT, FORWARD и POSTROUTING, в противном случае будет генерироваться сообщение об ошибке. При отсутствии этого критерия предполагается любой интерфейс, что равносильно использованию критерия -o +. Как и прежде, символ ! инвертирует результат совпадения. Если имя интерфейса завершается символом +, то критерий задает все интерфейсы, начинающиеся с заданной строки, например -o eth+ обозначает любой eth интерфейс, а запись -o ! eth+ - любой интерфейс, кроме любого eth. |
Критерий | -f, --fragment |
Пример | iptables -A INPUT -f |
Описание | Правило распространяется на все фрагменты фрагментированного пакета, кроме первого, сделано это потому, что нет возможности определить исходящий/входящий порт для фрагмента пакета, а для ICMP-пакетов определить их тип. Как и раньше, допускается использования символа ! для инверсии результата сравнения. только в данном случае символ ! должен предшествовать критерию -f, например ! -f. Инверсия критерия трактуется как "все первые фрагменты фрагментированных пакетов и/или нефрагментированные пакеты, но не вторые и последующие фрагменты фрагментированных пакетов". |
- Неявные критерии - критерии указанные неявно, становятся доступны при указании критерия -p. Например -p tcp.
- Явные критерии - загружаются при помощи ключа -m. Например -m tcp. Если в правиле что-то не работает, при указании критериев TCP, UDP, ICMP, то можно указать их например так…
iptables -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 |
Пример | iptables -A INPUT -p tcp --sport 22 |
Описание | Исходный порт, с которого был отправлен пакет. Номера портов могут задаваться в виде интервала из минимального и максимального номеров, например --source-port 22:80. Если опускается минимальный порт, т.е. когда критерий записывается как --source-port :80, то в качестве начала диапазона принимается число 0. Если опускается максимальный порт, т.е. когда критерий записывается как --source-port 22:, то в качестве конца диапазона принимается число 65535. Допускается такая запись --source-port 80:22, в этом случае iptables поменяет числа 22 и 80 местами, т.е. подобного рода запись будет преобразована в --source-port 22:80. Как и раньше, символ ! используется для инверсии. Так критерий --source-port ! 22 подразумевает любой порт, кроме 22. Инверсия может применяться и к диапазону портов, например --source-port ! 22:80. За дополнительной информацией обращайтесь к описанию критерия multiport. |
Критерий | --dport, --destination-port |
Пример | iptables -A INPUT -p tcp --dport 22 |
Описание | Порт или диапазон портов, на который адресован пакет. Аргументы задаются в том же формате, что и для --source-port. |
Критерий | --tcp-flags |
Пример | iptables -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 |
Пример | iptables -p tcp --syn |
Описание | Критерию соответствуют пакеты с установленным флагом SYN и сброшенными флагами ACK и FIN. Этот критерий аналогичен критерию --tcp-flags SYN,ACK,FIN,SYN. Такие пакеты используются для открытия соединения TCP. Заблокировав такие пакеты, вы надежно заблокируете все входящие запросы на соединение, однако этот критерий не способен заблокировать исходящие запросы на соединение. Как и ранее, допускается инвертирование критерия символом !. Так критерий ! --syn означает -- "все пакеты, не являющиеся запросом на соединение", т.е. все пакеты с установленными флагами FIN или ACK. |
Критерий | --tcp-option |
Пример | iptables -p tcp --tcp-option 16 |
Описание | Удовлетворяющим условию данного критерия будет будет считаться пакет, TCP параметр которого равен заданному числу. TCP Option - это часть заголовка пакета. Она состоит из 3 различных полей. Первое 8-ми битовое поле содержит информацию об опциях, используемых в данном соединении. Второе 8-ми битовое поле содержит длину поля опций. Если следовать стандартам до конца, то следовало бы реализовать обработку всех возможных вариантов, однако, вместо этого мы можем проверить первое поле и в случае, если там указана неподдерживаемая нашим брандмауэром опция, то просто перешагнуть через третье поле (длина которого содержится во втором поле). Пакет, который не будет иметь полного TCP заголовка, будет сброшен автоматически при попытке изучения его TCP параметра. Как и ранее, допускается использование флага инверсии условия !. |
UDP критерии
UDP критерии работают только с UDP пакетами, нужно обозначить использование протокола UDP "-p udp". Протокол должен указываться перед специфичными критериями приведенными ниже.
Критерий | --sport, --source-port |
Пример | iptables -A INPUT -p udp --sport 53 |
Описание | Исходный порт, с которого был отправлен пакет. Номера портов могут задаваться в виде интервала из минимального и максимального номеров, например -source-port 22:80. Если опускается минимальный порт, т.е. когда критерий записывается как --source-port :80, то в качестве начала диапазона принимается число 0. Если опускается максимальный порт, т.е. когда критерий записывается как --source-port 22: , то в качестве конца диапазона принимается число 65535. Допускается такая запись --source-port 80:22 , в этом случае iptables поменяет числа 22 и 80 местами, т.е. подобного рода запись будет преобразована в --source-port 22:80 . Как и раньше, символ ! используется для инверсии. Так критерий --source-port ! 22 подразумевает любой порт, кроме 22. Инверсия может применяться и к диапазону портов, например --source-port ! 22:80. |
Критерий | --dport, --destination-port |
Пример | iptables -A INPUT -p udp --dport 53 |
Описание | Порт, на который адресован пакет. Формат аргументов полностью аналогичен принятому в критерии --source-port. |
ICMP критерии
ICMP используется для сообщения об ошибках и управления соединениями. Использование протокола должно быть указано как "-p icmp". Помимо специфичных критериев, для работы с ICMP могут использоваться и общие критерии.
Критерий | --icmp-type |
Пример | iptables -A INPUT -p icmp --icmp-type 8 |
Описание | Тип сообщения ICMP определяется номером или именем. Чтобы получить список имен ICMP значений выполните команду iptables --protocol icmp --help Как и ранее, символ ! инвертирует критерий, например --icmp-type ! 8. |
Специальные критерии
Критерий Limit
Ключ | --limit |
Пример | iptables -A INPUT -m limit --limit 3/hour |
Описание | Устанавливается средняя скорость "освобождения емкости" за единицу времени. В качестве аргумента указывается число пакетов и время. Допустимыми считаются следующие единицы измерения времени: /second /minute /hour /day. По умолчанию принято значение 3 пакета в час, или 3/hour. Использование флага инверсии условия ! в данном критерии недопустим. |
Ключ | --limit-burst |
Пример | iptables -A INPUT -m limit --limit-burst 5 |
Описание | Устанавливает максимальное значение числа burst limit для критерия limit. Это число увеличивается на единицу если получен пакет, подпадающий под действие данного правила, и при этом средняя скорость (задаваемая ключом --limit) поступления пакетов уже достигнута. Так происходит до тех пор, пока число burst limit не достигнет максимального значения, устанавливаемого ключом --limit-burst. После этого правило начинает пропускать пакеты со скоростью, задаваемой ключом --limit. Значение по-умолчанию принимается равным 5. |
Критерий MAC
Ключ | --mac-source |
Пример | iptables -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 |
Пример | iptables -t mangle -A INPUT -m mark --mark 1 |
Описание | Критерий производит проверку пакетов, которые были предварительно "помечены". Метки устанавливаются действием mark, которое мы будем рассматривать ниже. Все пакеты, проходящие через netfilter имеют специальное поле mark. Запомните, что нет никакой возможности передать состояние этого поля вместе с пакетом в сеть. Поле mark является целым беззнаковым, таким образом можно создать не более 4294967296 различных меток. Допускается использовать маску с меткам. В данном случае критерий будет выглядеть подобным образом: --mark 1/1. Если указывается маска, то выполняется логическое and метки и маски. |
Критерий Multiport
Ключ | --source-port |
Пример | iptables -A INPUT -p tcp -m multiport --source-port 22,53,80,110 |
Описание | Служит для указания списка исходящих портов. С помощью данного критерия можно указать до 15 различных портов. Названия портов в списке должны отделяться друг от друга запятыми, пробелы в списке не допустимы. Данное расширение может использоваться только совместно с критериями -p tcp или -p udp. Главным образом используется как расширенная версия обычного критерия --source-port. |
Ключ | --destination-port |
Пример | iptables -A INPUT -p tcp -m multiport --destination-port 22,53,80,110 |
Описание | Служит для указания списка входных портов. Формат задания аргументов полностью аналогичен -m multiport --source-port. |
Ключ | --port |
Пример | iptables -A INPUT -p tcp -m multiport --port 22,53,80,110 |
Описание | Данный критерий проверяет как исходящий так и входящий порт пакета. Формат аргументов аналогичен критерию --source-port и --destination-port. Обратите внимание на то что данный критерий проверяет порты обеих направлений, т.е. если вы пишете -m multiport --port 80, то под данный критерий подпадают пакеты, идущие с порта 80 на порт 80. |
Критерий Owner
Ключ | --uid-owner |
Пример | iptables -A OUTPUT -m owner --uid-owner 500 |
Описание | Производится проверка "владельца" по User ID (UID). Подобного рода проверка может использоваться, к примеру, для блокировки выхода в Интернет отдельных пользователей. |
Ключ | --gid-owner |
Пример | iptables -A OUTPUT -m owner --gid-owner 0 |
Описание | Производится проверка "владельца" пакета по Group ID (GID). |
Ключ | --pid-owner |
Пример | iptables -A OUTPUT -m owner --pid-owner 78 |
Описание | Производится проверка "владельца" пакета по Process ID (PID). Этот критерий достаточно сложен в использовании, например, если мы хотим позволить передачу пакетов на HTTP порт только от заданного демона, то нам потребуется написать небольшой сценарий, который получает PID процесса (хотя бы через ps) и затем подставляет найденный PID в правила. |
Ключ | --sid-owner |
Пример | iptables -A OUTPUT -m owner --sid-owner 100 |
Описание | Производится проверка Session ID пакета. Значение SID наследуются дочерними процессами от "родителя", так, например, все процессы HTTPD имеют один и тот же SID. Этот сценарий можно запускать по времени для проверки наличия процесса HTTPD, и в случае отсутствия - перезапустить "упавший" процесс, после чего сбросить содержимое цепочки OUTPUT и ввести ее снова. |
Критерий State
Ключ | --state |
Пример | iptables -A INPUT -m state --state RELATED,ESTABLISHED |
Описание | Проверяется признак состояния соединения (state) На сегодняшний день можно указывать 4 состояния: INVALID, ESTABLISHED, NEW и RELATED. INVALID подразумевает, что пакет связан с неизвестным потоком или соединением и, возможно содержит ошибку в данных или в заголовке. Состояние ESTABLISHED указывает на то, что пакет принадлежит уже установленному соединению через которое пакеты идут в обеих направлениях. Признак NEW подразумевает, что пакет открывает новое соединение или пакет принадлежит однонаправленному потоку. И наконец, признак RELATED указывает на то что пакет принадлежит уже существующему соединению, но при этом он открывает новое соединение. |
Критерий TOS
Ключ | --tos |
Пример | iptables -A INPUT -p tcp -m tos --tos 0x16 |
Описание | Данный критерий предназначен для проверки установленных битов TOS, которые описывались выше. Как правило поле используется для нужд маршрутизации, но вполне может быть использовано с целью "маркировки" пакетов для использования с iproute2 и дополнительной маршрутизации в linux. В качестве аргумента критерию может быть передано десятичное или шестнадцатиричное число, или мнемоническое описание бита, мнемоники и их числовое значение вы можете получить выполнив команду iptables -m tos -h. |
Критерий TTL
Ключ | --ttl |
Пример | iptables -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 и destination, после чего пакет выкидывается в сеть. Атакующий над пакетом которого было произведено подобное действие, может пытаться взломать сам себя. Применять стоит с осторожностью, так как может привести к зацикливанию пакетов и вызвать отказ в обслуживании.
- REDIRECT - выполняет перенаправление пакетов на другой порт. Пакет продолжает движение по цепочке.
- TOS - производит установку битов в поле type of service IP заголовка. Данное поле обрабатывается маршрутизаторами для выбора маршрута движения пакета. Пакет продолжает движение по цепочке.
- TTL - используется для изменения содержимого поля time to live в IP заголовке.
- ULOG - возможность журналирования пакетов в пользовательском пространстве. Заменяет традиционное действие LOG, базирующееся на системном журнале.
Для примера возьмем два правила, одно с нетерминальным действием, другое с терминальным действием. Если вначале поставить правило с терминальным действием, то второе выполнятся не будет.
iptables -A INPUT -p tcp --dport 80 -j ACCEPT iptables -A INPUT -p tcp --dport 80 -j LOG --log-prefix "HTTP: "
Первое правило позволяет принимать запросы на 80-м порту. Второе правило должно отмечать эти пакеты в log-файле. При такой форме второе правило работать не будет, так как пакет будет принят и отправлен на 80 порт web-сервера и до второго правила в цепочке просто не дойдет.
Для того чтобы это работало, правила надо поменять местами, то есть терминальное действие всегда должно находиться в конце цепочки.
iptables -A INPUT -p tcp --dport 80 -j LOG --log-prefix "HTTP: " iptables -A INPUT -p tcp --dport 80 -j ACCEPT
Пакет соответствующий -p tcp критерию сначала отметится в логе, а потом будет передан на 80 порт web-сервера, окончательно покинув цепочку.
Если в процессе прохождения к пакету не было применено ни одного терминального действия, то к нему будет применена политика по умолчанию, установленная для цепочки. Причем это действие будет обязательно терминальным.
Действие RETURN
Пакет полностью прекращает движение по текущей цепочке и возвращается в предыдущую. Занимает промежуточное положение между терминальными и нетерминальными действиями, так как может прервать обработку пакета, но необязательно в рамках текущей цепочки.
Переходы
Переход, как и действие, указывает правилу что надо делать с пакетом, если он соответствует критерию. Для указания перехода ставится ключ "-j" и указывается цепочка правил на которую выполняется переход. Новая цепочка обязательно должна находиться в той же таблице, что и цепочка из которой выполняется переход. Новая цепочка должна быть создана до того как на нее будет выполняться переход.
Ключ "-j" универсален и используется для указания не только переходов, но и действий.
iptables -N new_chain_name - создаем новую цепочку.
iptables -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, все пакеты с этих машин должны попадать в логи. Для остальных доступ должен быть закрыт. Нужно ограничить исходящие соединения, но поскольку система должна обновляться, то оставить лазейку для проведения обновлений.
Подобное задание я решил следующим набором правил, здесь есть все что нужно.
iptables -F iptables -A INPUT -s 192.168.1.2,192.168.1.200 -j LOG --log-prefix "input_connect: " iptables -A INPUT -s 192.168.1.2,192.168.1.200 -j ACCEPT iptables -A INPUT -p all -i lo -j ACCEPT iptables -A OUTPUT -p all -o lo -j ACCEPT iptables -A OUTPUT -p all -o enp0s3 -j ACCEPT iptables -P INPUT DROP iptables -P OUTPUT DROP iptables -P FORWARD DROP iptables -A INPUT -p all -m state --state ESTABLISHED,RELATED -j ACCEPT iptables -A OUTPUT -p all -m state --state ESTABLISHED,RELATED -j ACCEPT
Сейчас они ничего не говорят тому, кто только начал знакомство с iptables, поэтому разберем по порядку все что написано.
Очистим цепочки правил в таблице filter, если у вас девственно чистая система, на которой еще не пользовались фаерволом, то оно не является обязательным к использованию. Это правило я привожу исключительно для примера.
iptables -F
Если его применить на системе с настроенным фаерволом, то можно остаться с разорванным SSH-соединением и невозможностью удаленного доступа. Правила разрешающие вход будут удалены, а политики по умолчанию останутся без изменений, то есть закрытыми, об этом позже.
Именно поэтому, чтобы не остаться без доступа к серверу я записал правила в таком порядке, в таком же порядке я добавляю их в фаервол.
Чтобы проверить текущее состояние фаервола и удостовериться в том что все чисто и открыто, можно выполнить следующую команду.
iptables -L -n -v -L - вывод списка правил -n - вывод ip-адресов и портов в числовом виде -v - повышение информативности вывода / подробнее все будет Выхлоп следующего вида означает что все открыто и никаких правил не задано: Chain INPUT (policy ACCEPT 0 packets, 0 bytes) pkts bytes target prot opt in out source destination Chain FORWARD (policy ACCEPT 0 packets, 0 bytes) pkts bytes target prot opt in out source destination Chain OUTPUT (policy ACCEPT 0 packets, 0 bytes) pkts bytes target prot opt in out source destination
Обращаем внимание на те самые политики по умолчанию "policy", везде отображается значение ACCEPT, это значит что все цепочки открыты для приема соединений.
Открываем соединения только для определенных ip-адресов - 192.168.1.2 и 192.168.1.200, все соединения с этих адресов заносятся в логи.
# Заносим в лог все пакеты с разрешенных ip-адресов, адреса пишутся через запятую: iptables -A INPUT -s 192.168.1.2,192.168.1.200 -j LOG --log-prefix "input_connect: " # Разрешаем доступ только с двух разрешенных ip-адресов: iptables -A INPUT -s 192.168.1.2,192.168.1.200 -j ACCEPT -A - Добавляет новое правило в конец цепочки INPUT -s - указываем ip-адрес, в нашем случае 2 шт, адреса можно указывать через запятую -j - указываем на использование действия LOG, все пакеты будут отмечаться в логах --log-prefix - задаем префикс которым будут помечаться наши логи "input_connect: " -j ACCEPT - указание терминального действия во втором правиле, пакет принимается и покидает цепочку.
Пакет с разрешенного адреса попадает в таблицу и обрабатывается первым правилом в цепочке и заносится в лог. Пакет движется дальше и к нему применяется действие из второго правила, пакет принимается и покидает цепочку.
Насчет использования префикса "input_connect: ", он может быть любым и должен записываться в кавычках. Использование префикса необходимо в том случае когда запись логов происходит в системные лог-файлы messages или syslog, во избежание путаницы.
Вот так выглядит отрывок лог-файла /var/log/messages c отмеченными входящими пакетами с адреса 192.168.1.2
Mar 9 03:23:40 test2 systemd: Starting Session 3 of user root. Mar 9 03:23:40 test2 kernel: input_connect: IN=enp0s3 OUT= MAC=08:00:27:b4:f8:0b:00:1e:8c:67:b3:7e:08:00 SRC=192.168.1.2 DST=192.168.1.210 LEN=140 TOS=0x00 PREC=0x00 TTL=128 ID=22625 DF PROTO=TCP SPT=5990 DPT=22 WINDOW=16157 RES=0x00 ACK PSH URGP=0 Mar 9 03:23:40 test2 kernel: input_connect: IN=enp0s3 OUT= MAC=08:00:27:b4:f8:0b:00:1e:8c:67:b3:7e:08:00 SRC=192.168.1.2 DST=192.168.1.210 LEN=92 TOS=0x00 PREC=0x00 TTL=128 ID=22626 DF PROTO=TCP SPT=5990 DPT=22 WINDOW=16157 RES=0x00 ACK PSH URGP=0 Mar 9 03:23:40 test2 kernel: input_connect: IN=enp0s3 OUT= MAC=08:00:27:b4:f8:0b:00:1e:8c:67:b3:7e:08:00 SRC=192.168.1.2 DST=192.168.1.210 LEN=40 TOS=0x00 PREC=0x00 TTL=128 ID=22629 DF PROTO=TCP SPT=5990 DPT=22 WINDOW=16119 RES=0x00 ACK URGP=0 Mar 9 03:23:40 test2 kernel: input_connect: IN=enp0s3 OUT= MAC=08:00:27:b4:f8:0b:00:1e:8c:67:b3:7e:08:00 SRC=192.168.1.2 DST=192.168.1.210 LEN=52 TOS=0x00 PREC=0x00 TTL=128 ID=22636 DF PROTO=TCP SPT=5990 DPT=22 WINDOW=16098 RES=0x00 ACK URGP=0 Mar 9 03:23:42 test2 kernel: input_connect: IN=enp0s3 OUT= MAC=08:00:27:b4:f8:0b:00:1e:8c:67:b3:7e:08:00 SRC=192.168.1.2 DST=192.168.1.210 LEN=92 TOS=0x00 PREC=0x00 TTL=128 ID=22930 DF PROTO=TCP SPT=4150 DPT=22 WINDOW=16425 RES=0x00 ACK PSH URGP=0 Mar 9 03:23:42 test2 kernel: input_connect: IN=enp0s3 OUT= MAC=08:00:27:b4:f8:0b:00:1e:8c:67:b3:7e:08:00 SRC=192.168.1.2 DST=192.168.1.210 LEN=40 TOS=0x00 PREC=0x00 TTL=128 ID=22955 DF PROTO=TCP SPT=4150 DPT=22 WINDOW=16408 RES=0x00 ACK URGP=0 Mar 9 03:23:42 test2 kernel: input_connect: IN=enp0s3 OUT= MAC=08:00:27:b4:f8:0b:00:1e:8c:67:b3:7e:08:00 SRC=192.168.1.2 DST=192.168.1.210 LEN=92 TOS=0x00 PREC=0x00 TTL=128 ID=22956 DF PROTO=TCP SPT=4150 DPT=22 WINDOW=16408 RES=0x00 ACK PSH URGP=0 Mar 9 03:23:43 test2 kernel: input_connect: IN=enp0s3 OUT= MAC=08:00:27:b4:f8:0b:00:1e:8c:67:b3:7e:08:00 SRC=192.168.1.2 DST=192.168.1.210 LEN=40 TOS=0x00 PREC=0x00 TTL=128 ID=22976 DF PROTO=TCP SPT=4150 DPT=22 WINDOW=16387 RES=0x00 ACK URGP=0 Mar 9 03:23:43 test2 kernel: input_connect: IN=enp0s3 OUT= MAC=08:00:27:b4:f8:0b:00:1e:8c:67:b3:7e:08:00 SRC=192.168.1.2 DST=192.168.1.210 LEN=92 TOS=0x00 PREC=0x00 TTL=128 ID=22991 DF PROTO=TCP SPT=4150 DPT=22 WINDOW=16387 RES=0x00 ACK PSH URGP=0 Mar 9 03:23:43 test2 kernel: input_connect: IN=enp0s3 OUT= MAC=08:00:27:b4:f8:0b:00:1e:8c:67:b3:7e:08:00 SRC=192.168.1.2 DST=192.168.1.210 LEN=40 TOS=0x00 PREC=0x00 TTL=128 ID=23015 DF PROTO=TCP SPT=4150 DPT=22 WINDOW=16354 RES=0x00 ACK URGP=0
Напоминаю, все приводится исключительно в виде примеров, по хорошему запись логов должна проводиться в отдельный файл. Как это сделать я расскажу в отдельной статье.
Разрешаем трафик локального интерфейса, для функционирования служб и приложений.
# разрешаем весь входящий трафик на локальном интерфейсе iptables -A INPUT -p all -i lo -j ACCEPT # разрешаем весь исходящий трафик на локальном интерфейсе iptables -A OUTPUT -p all -o lo -j ACCEPT -A - добавляем правила для цепочек INPUT & OUTPUT -p - указываем правилу что оно будет работать со всеми протоколами (all) -i - указываем входной сетевой интерфейс - lo (локальный) -o - указываем выходной сетевой интерфейс - lo (локальный) -j - указываем действие ACCEPT (принимать все)
Разрешаем выходной трафик на сетевом интерфейсе enp0s3, для проведения обновлений и т.д.
# разрешаем исходящие соединения на интерфейсе enp0s3 iptables -A OUTPUT -p all -o enp0s3 -j ACCEPT -A - добавляем правила для цепочки OUTPUT -p - указываем правилу что оно будет работать со всеми протоколами (all) -o - указываем выходной сетевой интерфейс - enp0s3 -j - указываем действие ACCEPT (принимать все)
Закрываем все соединения при помощи Default Policy (политик по умолчанию) в след. цепочках: INPUT, OUTPUT, FORWARD. Этим достигается полный запрет входящего трафика со всех адресов кроме разрешенных, ограничение исходящего трафика и запрет транзитных пакетов.
# закрываем цепочку INPUT iptables -P INPUT DROP # закрываем цепочку OUTPUT iptables -P OUTPUT DROP # закрываем цепочку FORWARD iptables -P FORWARD DROP -P - действие задающее политику по умолчанию DROP (скидывать все)
Обратите внимание, что политики задают только после того, как заданы правила разрешающие соединение для вас самих.
Последнее что от нас требовалось, это разрешить свободное прохождение пакетов относящихся к уже установленным соединениям, это самый интересный момент. Заодно станет понятно как работает определение состояний conntrack. Пробуем выполнить команду обновления системы.
yum update -y
В ответ получаем массу ошибок "Could not resolve host" - это означает что системе не удается получить ответ от зеркала с которого происходит обновление.
Загружены модули: fastestmirror Could not retrieve mirrorlist http://mirrorlist.centos.org/?release=7&arch=x86_64&repo=os&infra=stock error was 14: curl#6 - "Could not resolve host: mirrorlist.centos.org; Неизвестная ошибка"
Система не обновляется, ответные пакеты не приходят. Это неудивительно, мы можем получать пакеты только с двух адресов в число которых зеркала обновлений не входят. Для решения проблемы придется прибегнуть к помощи определения состояний conntrack.
Добавляем правила разрешающие беспрепятственный проход пакетов принадлежащих к уже установленным соединениям.
# Разрешаем входящий трафик для установленных соединений и их производных: iptables -A INPUT -p all -m state --state ESTABLISHED,RELATED -j ACCEPT iptables -A OUTPUT -p all -m state --state ESTABLISHED,RELATED -j ACCEPT -A - добавляем правила для цепочек INPUT & OUTPUT -p - указываем правилу что оно будет работать со всеми протоколами (all) -m - явно указываем на определение состояния state --state - указываем критерий для состояний ESTABLISHED и RELATED -j - указываем действие ACCEPT (принимать все)
Ответные пакеты принадлежащие соединениям ESTABLISHED и RELATED, будут пропущены, и неважно что адрес с которого поступил пакет не входит в список разрешенных.
Сравним вывод действующих правил с предыдущим выводом, когда все было открыто.
[root@test2 ~]# iptables -L -n -v Chain INPUT (policy DROP 13 packets, 704 bytes) pkts bytes target prot opt in out source destination 1937 95746 LOG all -- * * 192.168.1.2 0.0.0.0/0 LOG flags 0 level 4 prefix "input_connect: " 103 10750 LOG all -- * * 192.168.1.200 0.0.0.0/0 LOG flags 0 level 4 prefix "input_connect: " 1933 95434 ACCEPT all -- * * 192.168.1.2 0.0.0.0/0 103 10750 ACCEPT all -- * * 192.168.1.200 0.0.0.0/0 0 0 ACCEPT all -- lo * 0.0.0.0/0 0.0.0.0/0 63060 104M ACCEPT all -- * * 0.0.0.0/0 0.0.0.0/0 state RELATED,ESTABLISHED Chain FORWARD (policy DROP 0 packets, 0 bytes) pkts bytes target prot opt in out source destination Chain OUTPUT (policy DROP 0 packets, 0 bytes) pkts bytes target prot opt in out source destination 0 0 ACCEPT all -- * lo 0.0.0.0/0 0.0.0.0/0 37539 4264K ACCEPT all -- * enp0s3 0.0.0.0/0 0.0.0.0/0 0 0 ACCEPT all -- * * 0.0.0.0/0 0.0.0.0/0 state RELATED,ESTABLISHED
На данном примере мы получили вполне огороженную от посторонних запросов машину, со свободным доступом для избранных. Это может быть какой нибудь сервер для определенного круга лиц. А список адресов со временем можно расширить, просто дописав нужный адрес в правило. Это всего лишь пример, первое что пришло мне в голову, когда я придумывал задачу для практической части.
Конечно данной статьи недостаточно, я всего лишь рассказал про основы. Если хотите знать, а не бездумно копировать готовые правила, то вам как минимум надо изучить документацию к iptables. Рекомендую следующую литературу, в свое время я учился по ней:
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