Управление фильтрацией пакетов с помощью iptables

LinuxBeginner
Практиковаться сейчас

Введение

iptables — это интерфейс командной строки для управления правилами фильтрации пакетов в Linux. Хотя во многих современных дистрибутивах эти правила реализуются через внутреннюю систему nftables, администраторам по-прежнему приходится работать с задачами и существующими системами, использующими синтаксис команды iptables.

Для начала удобно представить брандмауэр как упорядоченный список проверок. Пакет попадает в цепочку, каждое правило проверяет, соответствует ли он таким условиям, как интерфейс, протокол или порт, а цель, например ACCEPT или REJECT, определяет дальнейшее действие. Цепочка INPUT обрабатывает пакеты, адресованные локальному хосту. Поскольку правила проверяются сверху вниз, важны как их содержимое, так и положение в цепочке.

В этой лабораторной работе вы будете работать с одним локальным веб-сервисом и внесёте минимальные изменения только для его TCP-порта. Вы проверите текущее состояние брандмауэра, добавите правило для отклонения запросов, подтвердите его действие реальным трафиком, замените это правило явным разрешением, а затем удалите созданное в рамках лабораторной работы правило, не очищая и не переписывая остальные настройки брандмауэра.

Проверка брандмауэра и тестового сервиса

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

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

cd /home/labex/project

Используйте command -v, чтобы определить исполняемый файл, который будет запускаться вашей оболочкой.

command -v iptables

Такая проверка надёжнее, чем предположение, что команда установлена: она показывает фактический путь к исполняемому файлу, обычно /usr/sbin/iptables, и возвращает ненулевой код завершения, если оболочка не может его найти.

Выведите сведения о версии и внутренней системе. На этом хосте Ubuntu в выводе обычно присутствует nf_tables; это означает, что привычный синтаксис iptables преобразуется в современную внутреннюю систему правил ядра.

sudo iptables --version

Вы должны увидеть вывод, похожий на следующий:

iptables v1.8... (nf_tables)

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

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

curl --noproxy '*' --fail --silent http://127.0.0.1:18086/health

Здесь 127.0.0.1 — IPv4-адрес обратной связи. Поэтому трафик выходит через локальный интерфейс lo и возвращается через него же, не попадая во внешнюю сеть. Параметр --noproxy '*' не позволяет настройкам прокси перенаправить запрос, --fail заставляет curl возвращать ошибку при HTTP-сбое, а --silent скрывает индикатор выполнения, чтобы ответ сервиса было проще прочитать.

Сервис возвращает:

iptables filter service ready

Проверка цепочки INPUT и добавление правила отклонения

На этом этапе вы изучите текущую цепочку INPUT и добавите одно точечное правило, отклоняющее TCP-трафик через обратный интерфейс к тестовому порту.

Параметр -S выводит правила в форме, похожей на команды. Указание INPUT ограничивает вывод пакетами, предназначенными для этого хоста.

sudo iptables -S INPUT

В первой строке обычно отображается политика цепочки, например -P INPUT ACCEPT. Политика используется как резервное действие только в том случае, если ни одно предыдущее правило не приняло окончательного решения. Следующие строки, начинающиеся с -A INPUT, содержат правила, добавленные в эту цепочку.

Для просмотра в эксплуатационном формате параметр -L выводит список правил цепочки, -n отключает медленное разрешение имён, а --line-numbers показывает позицию каждого правила. Порядок правил имеет значение: результат пакета определяется первой совпавшей завершающей целью.

Добавьте правило на позицию 1 с помощью -I INPUT 1. Оно соответствует интерфейсу обратной связи lo, протоколу TCP и порту назначения 18086. Цель REJECT с параметром tcp-reset немедленно отклоняет соединение, не заставляя клиент ждать истечения времени ожидания для отброшенного пакета.

sudo iptables -I INPUT 1 -i lo -p tcp --dport 18086 -j REJECT --reject-with tcp-reset

Читайте команду слева направо: -i lo ограничивает входящий интерфейс, -p tcp выбирает протокол, --dport 18086 задаёт сервис, а -j REJECT передаёт обработку цели отклонения. Параметр -I вставляет правило в указанную позицию; напротив, -A добавил бы его в конец цепочки, где более раннее совпадающее правило могло бы не позволить до него дойти. Такое точное сочетание условий не блокирует другие порты и внешние интерфейсы.

REJECT и DROP работают по-разному. REJECT отправляет ответ об ошибке, а DROP молча отбрасывает пакет. Сброс TCP позволяет этому локальному тесту завершиться быстро и предсказуемо, что удобнее для диагностики, чем ожидание тайм-аута.

Используйте -C, чтобы проверить наличие именно этого правила. При успешной проверке команда завершается с кодом 0. В данной системе реализация на базе nftables также выводит нормализованное правило; другие реализации могут завершать проверку без вывода.

sudo iptables -C INPUT -i lo -p tcp --dport 18086 -j REJECT --reject-with tcp-reset

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

Снова выведите цепочку. Новое правило должно находиться на позиции 1 и содержать обозначение tcp dpt:18086.

sudo iptables -L INPUT -n --line-numbers

Проверка заблокированного трафика

На этом этапе вы повторите исходный запрос и проверите счётчики правила, чтобы доказать: трафик отклонил брандмауэр, а не приложение.

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

if curl --noproxy '*' --fail --silent http://127.0.0.1:18086/health; then
  echo "Unexpected: request succeeded"
else
  echo "Expected: iptables rejected the request"
fi

Условия оболочки принимают решение по коду завершения команды: нулевой код выбирает ветку then, а ненулевой — else. Отправленный брандмауэром сброс заставляет curl завершиться с ненулевым кодом, поэтому переход в ветку else является ожидаемым результатом.

Ожидаемое сообщение:

Expected: iptables rejected the request

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

sudo iptables -L INPUT -n -v --line-numbers

В выводе столбец pkts содержит количество совпавших пакетов, а bytes — их общий размер. Счётчики служат важным подтверждением: проверка с помощью -C доказывает наличие правила, а увеличение счётчика показывает, что реальный трафик достиг правила и совпал с ним. Если счётчик остался равен нулю, проверьте интерфейс, протокол, порт и положение правила, прежде чем искать причину в приложении.

Замена правила отклонения правилом разрешения

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

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

sudo iptables -D INPUT -i lo -p tcp --dport 18086 -j REJECT --reject-with tcp-reset

Правила также можно удалять по номеру строки, однако номера меняются при добавлении и удалении правил. Удаление по точному описанию понятнее в повторяемой процедуре и снижает вероятность удаления соседнего правила. Не используйте здесь iptables -F: очистка удалит все правила выбранной цепочки, включая правила, не относящиеся к этой лабораторной работе.

Добавьте правило ACCEPT для того же интерфейса, протокола и порта.

sudo iptables -I INPUT 1 -i lo -p tcp --dport 18086 -j ACCEPT

ACCEPT разрешает совпавшему пакету продолжить обработку в сетевом стеке. Правило добавляется на позицию 1, чтобы его результат не перекрывался более ранним завершающим правилом. Обратите внимание: условия совпадения остались такими же точными, как и раньше; изменилась только цель.

Проверьте точное правило разрешения.

sudo iptables -C INPUT -i lo -p tcp --dport 18086 -j ACCEPT

Повторите исходный запрос к конечной точке состояния.

curl --noproxy '*' --fail --silent http://127.0.0.1:18086/health

Ответ снова доступен:

iptables filter service ready

Удаление правила, созданного в рамках лабораторной работы

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

Удалите точное правило ACCEPT. Как и прежде, эта команда не очищает цепочку и не затрагивает правила, принадлежащие платформе или другому администратору.

sudo iptables -D INPUT -i lo -p tcp --dport 18086 -j ACCEPT

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

Снова проверьте наличие правила. На этот раз ошибка ожидаема, поэтому || выполнит сообщение справа только в том случае, если iptables -C вернёт ненулевой код завершения.

sudo iptables -C INPUT -i lo -p tcp --dport 18086 -j ACCEPT 2>/dev/null || echo "Lab allow rule removed"

Вы должны увидеть:

Lab allow rule removed

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

curl --noproxy '*' --fail --silent http://127.0.0.1:18086/health

Итоги

Вы определили реализацию iptables и изучили цепочку INPUT, добавили и проверили точное правило отклонения, подтвердили его действие реальным трафиком и счётчиками, заменили его правилом разрешения и удалили только изменение, внесённое в рамках лабораторной работы. Эти операции дают необходимую практику управления фильтрацией пакетов на уровне команд и помогают безопасно работать с брандмауэром, не очищая несвязанные настройки.