MHOSTMHOST

Основы iptables

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

Что понадобится

  • VPS mHost на Ubuntu 22.04/24.04, Debian 11/12 или AlmaLinux/Rocky Linux 8/9.
  • Доступ по SSH под root или пользователем с sudo.

Шаг 1. Проверьте, что iptables установлен

На Ubuntu и Debian команда iptables обычно уже есть в системе «из коробки» (как обёртка над nftables — iptables-nft, но с привычным синтаксисом). Проверьте версию:

bash
iptables -V

Если команда не найдена, установите пакет:

Ubuntu / Debian

bash
sudo apt update
sudo apt install iptables

AlmaLinux / Rocky Linux

bash
sudo dnf install iptables
Важно: AlmaLinux и Rocky Linux по умолчанию используют не iptables, а firewalld (поверх nftables) — проверить, активен ли он, можно командой systemctl status firewalld. Одновременно firewalld и iptables не работают — это два конфликтующих менеджера одного и того же netfilter. Начиная с версии 9 сами утилиты iptables на AlmaLinux/Rocky официально считаются устаревшими (deprecated). Понятия и синтаксис команд из этой статьи (шаги 2–5) верны для iptables на любом дистрибутиве, но как способ настроить файрвол на боевом сервере статья рассчитана на Ubuntu/Debian; на AlmaLinux/Rocky для этого используйте firewalld.

Шаг 2. Разберитесь с цепочками и политиками

iptables фильтрует трафик через таблицы, а внутри таблицы — через цепочки правил. Для файрвола нужна таблица filter (она используется по умолчанию, отдельно указывать её не нужно) с тремя встроенными цепочками:

  • INPUT — пакеты, адресованные самому серверу: входящие подключения по SSH, HTTP и т. д.;
  • OUTPUT — пакеты, которые генерирует сам сервер: исходящие запросы;
  • FORWARD — пакеты, которые сервер пересылает транзитом. На обычном VPS (не роутере) через эту цепочку ничего не идёт.

У каждой встроенной цепочки есть политика по умолчанию — что делать с пакетом, если ни одно правило в цепочке не подошло. Политикой может быть только ACCEPT (пропустить) или DROP (молча отбросить) — REJECT как политику цепочки iptables не принимает, только как цель (target) отдельного правила.

Пока вы не настроили ни одного правила, политика всех трёх цепочек — ACCEPT, то есть разрешено абсолютно всё. Посмотреть текущие политики:

bash
sudo iptables -L -n

Первая строка каждой цепочки в выводе выглядит как Chain INPUT (policy ACCEPT) — это и есть текущая политика.

Шаг 3. Посмотрите текущие правила

Более подробный вывод — со счётчиками пакетов/байт и именами интерфейсов:

bash
sudo iptables -L -v -n

-L выводит правила (без аргумента — все цепочки таблицы filter), -v добавляет счётчики и интерфейсы, -n — не резолвит адреса и порты в имена (без этого флага вывод может быть заметно медленнее).

Чтобы увидеть номера строк — пригодится перед удалением конкретного правила:

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

Правило удаляется по номеру строки из этого вывода и имени цепочки: sudo iptables -D <цепочка> <номер> — например, sudo iptables -D INPUT 3 удалит третье правило цепочки INPUT.

А чтобы получить правила в виде готовых команд iptables (удобно скопировать или сравнить с тем, что вы собираетесь применить):

bash
sudo iptables -S

Шаг 4. Разрешите SSH и HTTP

Прежде чем включать политику DROP (шаг 5), добавьте правила, которые разрешают нужный трафик, — иначе после DROP сервер станет недоступен вообще ни по чему, включая SSH.

Разрешите трафик на loopback-интерфейсе (lo) — им пользуются многие локальные службы:

bash
sudo iptables -A INPUT -i lo -j ACCEPT

Разрешите уже установленные и связанные с ними соединения — иначе будут обрываться ответы на исходящие запросы самого сервера (например, к DNS или репозиторию пакетов):

bash
sudo iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT

Теперь разрешите сам SSH и HTTP:

bash
sudo iptables -A INPUT -p tcp --dport 22 -j ACCEPT
sudo iptables -A INPUT -p tcp --dport 80 -j ACCEPT
Совет: если вы уже меняли порт SSH по умолчанию (см. статью «Усиление SSH»), подставьте вместо 22 свой порт. Если сервер также отдаёт HTTPS, добавьте порт 443 точно так же: sudo iptables -A INPUT -p tcp --dport 443 -j ACCEPT.
Совет: то же самое в ufw делается короче — ufw allow ssh и ufw allow 80/tcp. Если синтаксис iptables кажется избыточным, посмотрите статью «Настройка файрвола UFW»: это дружелюбная надстройка над тем же iptables/nftables, с более простыми командами и готовыми профилями приложений.

Проверьте, что правила добавились:

bash
sudo iptables -L -v -n

Шаг 5. Включите политику DROP по умолчанию

Важно: это самый рискованный шаг статьи — ошибка здесь может отрезать вас от сервера по SSH. Не закрывайте текущую SSH-сессию — откройте отдельное, второе подключение для проверки, и держите под рукой консоль VNC в VMmanager 6: через неё можно зайти на сервер и исправить правила, даже если SSH недоступен.
Совет: дополнительная подстраховка — пока вы не сохранили правила (шаг 6), перезагрузка сервера обычно возвращает политики обратно в ACCEPT. То есть даже полностью ошибочную настройку на этом шаге можно исправить перезагрузкой из VMmanager 6, без переустановки ОС.

Когда правила из шага 4 уже на месте, включите DROP по умолчанию для входящего трафика и транзита:

bash
sudo iptables -P INPUT DROP
sudo iptables -P FORWARD DROP

Политику OUTPUT мы намеренно оставляем ACCEPT — фильтрация исходящего трафика (egress-фильтрация) полезна, но её легко настроить неправильно и сломать себе DNS, обновления пакетов и подобное; это отдельная, более продвинутая тема, которая в эту статью не входит.

Поскольку правило для ESTABLISHED,RELATED уже добавлено, ваша текущая SSH-сессия не оборвётся — политика DROP применяется только к новым соединениям, которые не подошли ни под одно правило. Тем не менее из второй, новой сессии проверьте, что подключение по SSH по-прежнему работает:

bash
ssh root@185.246.66.12

И посмотрите итоговое состояние:

bash
sudo iptables -L -v -n

В выводе должно быть Chain INPUT (policy DROP) и Chain FORWARD (policy DROP), а выше — ACCEPT-правила для loopback, ESTABLISHED/RELATED, SSH и HTTP.

Готово: новое SSH-подключение открывается, сайт на порту 80 отвечает, а всё остальное входящее — отбрасывается по умолчанию.

Шаг 6. Сохраните правила: iptables-persistent / netfilter-persistent

Правила и политики, которые вы настроили, живут только в памяти ядра — после перезагрузки сервера они слетят, и снова будут действовать политики ACCEPT по умолчанию. Чтобы правила переживали перезагрузку, на Ubuntu/Debian используется пакет iptables-persistent, который ставит системную службу netfilter-persistent:

bash
sudo apt update
sudo apt install iptables-persistent

Во время установки пакет дважды спросит, сохранить ли текущие правила — отдельно для IPv4 и отдельно для IPv6. Согласитесь в обоих случаях: IPv4-правила — это как раз то, что вы настроили в шагах 4–5, а пустой набор для IPv6 ничему не помешает, даже если вы им не пользуетесь.

Правила сохраняются в /etc/iptables/rules.v4/etc/iptables/rules.v6 — для IPv6). Убедитесь, что служба, которая подхватывает их при загрузке, включена в автозапуск:

bash
sudo systemctl enable --now netfilter-persistent

Если после этого вы ещё раз поменяете правила (например, откроете дополнительный порт), не забудьте сохранить их заново — иначе после перезагрузки вернётся старый набор:

bash
sudo netfilter-persistent save

Проверить, что сохранённые правила корректно загружаются, можно без перезагрузки сервера:

bash
sudo netfilter-persistent reload
Совет: команда sudo dpkg-reconfigure iptables-persistent в любой момент заново задаёт те же вопросы про сохранение текущих правил, что и при первой установке.

(Этот способ — про Ubuntu/Debian. На AlmaLinux/Rocky, как отмечено в шаге 1, файрволом по умолчанию управляет firewalld, а не iptables-persistent.)

Что дальше

Вы настроили базовый файрвол вручную: цепочки, политика DROP по умолчанию и нужные разрешения (SSH, HTTP) переживают перезагрузку. Тот же результат короче достигается через ufw — дружелюбную надстройку над тем же iptables/nftables. Дальше имеет смысл закрыть подбор пароля по SSH статьёй «Fail2ban», усилить сам SSH — «Усиление SSH», — и свериться с общим «Чек-листом безопасности сервера».