Файрвол Linux с nftables и iptables¶
iptables считается устаревшим в пользу nftables на современных ядрах, хотя всё ещё широко используется (и ufw/firewalld оба оборачивают один или другой под капотом). Эта статья охватывает и базовый механизм, и инструменты уровня дистрибутива поверх него.
Как это устроено¶
Модель фильтрации: таблицы, цепочки, правила¶
И iptables, и nftables разделяют одну концептуальную модель: пакеты проходят через цепочки (INPUT, OUTPUT, FORWARD — стандартные), сгруппированные в таблицы, каждая цепочка содержит упорядоченный список правил. Первое совпавшее правило решает судьбу пакета (ACCEPT, DROP, REJECT), правила проверяются сверху вниз.
nftables (современная замена)¶
Минимальный набор правил, записанный в файл и загруженный:
# /etc/nftables.conf
flush ruleset
table inet filter {
chain input {
type filter hook input priority 0; policy drop;
ct state established,related accept
iif lo accept
tcp dport 22 accept
ip protocol icmp accept
ip6 nexthdr icmpv6 accept
}
}
Читаем: policy drop означает всё, что явно не разрешено, отбрасывается — позиция default-deny, единственная безопасная настройка по умолчанию для хоста, смотрящего в интернет. ct state established,related accept критично важен и легко забывается: без него обратный трафик для соединений, которые вы сами инициировали наружу (DNS-запросы, обновления пакетов, исходящие вызовы API), тоже отбрасывался бы, поскольку у цепочки нет памяти о том, что «этот ответ относится к соединению, которое я разрешил наружу». iif lo accept разрешает трафик loopback (многие локальные сервисы общаются друг с другом через 127.0.0.1, например, приложение-сервер с локальным прокси БД) — без этого базовое локальное межпроцессное взаимодействие ломается.
flush ruleset в начале делает загрузку идемпотентной: без него nft -f добавляет правила к уже загруженным, и повторная загрузка файла их дублирует. Проверить синтаксис без применения: sudo nft -c -f /etc/nftables.conf.
iptables (всё ещё распространён, особенно где инструментарий nftables ещё не стал¶
стандартом)
Эквивалентная политика в синтаксисе iptables:
sudo iptables -A INPUT -i lo -j ACCEPT
sudo iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
sudo iptables -A INPUT -p tcp --dport 22 -j ACCEPT
sudo iptables -P INPUT DROP # в последнюю очередь: default-deny включаем, когда правила accept уже на месте
Порядок важен, если вы вводите это по SSH: если сначала выполнить -P INPUT DROP, ваша сессия борвётся до появления правила ESTABLISHED. Правила iptables хранятся только в памяти — сохраняйте их через iptables-save и пакет iptables-persistent (Debian/Ubuntu) или iptables-services (RHEL-подобные).
Счётчики пакетов/байт -v реально полезны для диагностики: нулевой счётчик у правила, которое вы ожидали увидеть совпавшим, говорит, что трафик вообще до него не доходит (неверный порядок, не тот интерфейс, более раннее правило уже его перехватило).
ufw (фронтенд Ubuntu, оборачивает iptables/nftables)¶
sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow 22/tcp
sudo ufw allow from 203.0.113.0/24 to any port 5432
sudo ufw enable
sudo ufw status verbose
ufw allow from <subnet> to any port <port> — паттерн для ограничения сервиса (базы данных, админ-панели) конкретным диапазоном источников вместо всего интернета — на практике гораздо полезнее, чем голый allow <port>.
firewalld (фронтенд RHEL-семейства)¶
sudo firewall-cmd --permanent --add-service=ssh
sudo firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="203.0.113.0/24" port port="5432" protocol="tcp" accept'
sudo firewall-cmd --reload
sudo firewall-cmd --list-all
--permanent записывает правило на диск, но не применяет его немедленно — нужен --reload (или --permanent + последующая перезагрузка), чтобы оно вступило в силу, в то время как команда без --permanent применяется немедленно, но теряется при следующей перезагрузке конфига/ребуте. Очень частая ошибка — забыть одну из половинок этой пары.
Различия Ubuntu/Debian и RHEL-подобных систем¶
| Ubuntu/Debian | RHEL-подобные | |
|---|---|---|
| Фронтенд | ufw | firewalld |
| Движок под капотом (современные релизы) | nftables | nftables (слой совместимости iptables-nft на старых) |
| Концепция зон | Нет встроенной концепции зон | firewalld организует правила в именованные «зоны» (public, internal и т.д.) с разной политикой по умолчанию |
Практическое задание¶
- На тестовой VM (не на хосте, к которому вы активно подключены по SSH без доступа к консоли) проверьте текущий набор правил через
sudo nft list rulesetилиsudo iptables -L -n -v. - Добавьте правило, разрешающее ещё не используемый вами порт (например, 8080/tcp), через фронтенд-инструмент вашего дистрибутива.
- Убедитесь через
ufw status verbose/firewall-cmd --list-all/nft list ruleset, что правило присутствует, затем удалите его.
Как проверить, что всё сделано правильно¶
- До добавления правила:
sudo ss -tulnp | grep 8080должен ничего не показывать, а попытка подключения к этому порту с другого хоста должна зависать/отклоняться. - После добавления правила (с чем-то реально слушающим, например,
python3 -m http.server 8080для быстрого теста): соединение должно пройти с разрешённого источника и провалиться с запрещённого.
Типичные ошибки¶
- Забыть правило
established,related/ «allow outgoing» при переходе на политику default-deny, ломая весь исходящий-инициированный обратный трафик (DNS, обновления, вызовы API) — не только входящие соединения. - Тестирование изменений файрвола через то же самое соединение, которое может быть обрезано этими изменениями, без консоли/доступа вне полосы в качестве запасного варианта на удалённом хосте.
- Разделение runtime/
--permanentу firewalld: применение правила с--permanentи забытый--reload, затем недоумение, почему «не сработало» (сработает, после следующей перезагрузки конфига или ребута — просто ещё нет).
⚠ Опасные команды¶
iptables -F(flush) при уже действующейpolicy DROPмгновенно блокирует весь трафик, ещё не добавленный обратно, включая вашу собственную SSH-сессию — на удалённом хосте без доступа к консоли это мгновенная, жёсткая блокировка. Всегда имейте план отката (запланированная задачаat/cron, откатывающая набор правил через 1-2 минуты — распространённая страховка именно для этого сценария), прежде чем тестировать новую политику default-deny удалённо.- Включение
ufwсdefault deny incomingбез предварительного разрешения собственного SSH-порта. Уже установленная сессия обычно остаётся жива, поэтому всё выглядит нормально — но открыть новое соединение вы уже не сможете, а обрыв сессии или перезагрузка закроют доступ. Выполнитеsudo ufw allow 22/tcp(или ваш реальный порт SSH) доsudo ufw enable.
Связанные статьи¶
Контрольные вопросы¶
- Почему
ct state established,related accept(или его эквивалент в iptables) необходим в наборе правил default-deny? - В чём практический риск запуска
iptables -Fна удалённом хосте с уже установленной политикойDROP? - В чём разница между правилом
firewalld, применённым с и без--permanent? - Как проверить, что конкретное правило файрвола реально совпадает с реальным трафиком, используя только вывод самого
iptables?