nftables — современная замена iptables в ядрах Linux 3.13 и новее. Она использует единый интерпретатор конфигурации, удобный синтаксис выражений и атомарное применение правил: при ошибке старая конфигурация остаётся рабочей. Разберём переход с iptables, базовые правила и диагностику.
Почему nftables, а не iptables
В iptables каждая таблица — отдельный механизм, а применение правил происходит по одному. В nftables правила описываются в одном файле и применяются целиком. Это упрощает конфигурацию и убирает состояние «часть правил применилась».
# проверить, установлен ли nft
nft --version
# текущие правила (все семейства)
sudo nft list ruleset
# аналог в iptables
sudo iptables -L -n --line-numbers | head -30
Утилита nft показывает и изменяет правила. Таблицы описаны в /etc/nftables.conf или в файлах каталога /etc/nftables.d/.
Базовый конфиг
Минимальный файрвол: разрешить SSH, исходящие соединения и ответы, всё остальное по умолчанию отклонять. Порядок правил важен: первое совпавшее выигрывает.
# /etc/nftables.conf
#!/usr/sbin/nft -f
flush ruleset
table inet filter {
chain input {
type filter hook input priority 0; policy drop;
ct state established,related accept
iif lo accept
ct state invalid drop
tcp dport 22 accept
icmp type echo-request accept
icmpv6 type { echo-request, nd-router-solicit, nd-router-advert } accept
}
chain forward {
type filter hook forward priority 0; policy drop;
}
chain output {
type filter hook output priority 0; policy accept;
}
}
Файл начинается с flush ruleset: при ошибке загрузки правила очищаются — поэтому сначала проверяйте синтаксис.
# проверить синтаксис БЕЗ применения
sudo nft -c -f /etc/nftables.conf
# применить
sudo nft -f /etc/nftables.conf
# убедиться
sudo nft list ruleset | head -40
# включить автозагрузку
sudo systemctl enable nftables
Практика безопасности: ограничение SSH
Даже открытый порт 22 стоит ограничить: лимит новых соединений снижает эффективность перебора, а исключения для своей подсети убирают лишний шум.
# ограничение по состоянию соединений
tcp dport 22 ct state new meter ssh-meter { ip saddr limit rate 5/minute burst 10 packets } accept
# доступ к SSH только из доврененной сети
ip saddr 10.0.0.0/24 tcp dport 22 accept
# закрыть всё остальное на входе
# policy drop в цепочке input
Такая конструкция оставит вашу сессию рабочей при ошибке: существующие соединения проходят по правилу ct state established.
Логирование и диагностика
Полезно логировать отклонённые пакеты — иначе непонятно, почему сервис недоступен.
# лог отброшенных входящих
log prefix "nft-drop: " flags all counter drop
# смотреть события
sudo journalctl -k -f | grep -i nft-drop
# счётчики по цепочкам
sudo nft list ruleset | grep -E "counter|drop|accept" | head -30
Включайте лог выборочно: без фильтра он засорит журнал. Ограничьте по подсети или порту.
Миграция с iptables
Часто используется совместимый слой iptables-nft: команды iptables работают поверх nftables. Это удобно для старых скриптов, но мешает увидеть реальные правила.
# какой backend используется
iptables -V
# если видно "-nft", правила на самом деле в nftables
sudo nft list ruleset | head -40
# конвертация (грубая)
iptables-save > /tmp/iptables.rules
apt install iptables-nft
sudo iptables-restore /tmp/iptables.rules
sudo nft list ruleset | head -40
После миграции перепишите правила вручную в нативный синтаксис: он короче и понятнее.
NAT и маршрутизация
Для шлюза или контейнерного хоста нужен маскарад — преобразование исходящих адресов.
table ip nat {
chain postrouting {
type nat hook postrouting priority 100;
oifname "eth0" ip saddr 192.168.1.0/24 masquerade
}
chain prerouting {
type nat hook prerouting priority -100;
tcp dport 8080 dnat to 192.168.1.10:80
}
}
# включить форвардинг
echo 1 | sudo tee /proc/sys/net/ipv4/ip_forward
# и сохранить
echo 'net.ipv4.ip_forward=1' | sudo tee /etc/sysctl.d/99-forward.conf
Проверьте правило forward: без разрешённого форвардинга NAT не заработает.
Типичные ошибки
- Откат правил перед отключённым SSH — проверяйте
nft -c. - Отсутствие правила
established— ответы пакетов отклоняются. - Забытый IPv6: правила семейства
ipне действуют наip6. - Конфликт с ufw/firewalld: два файрвола одновременно дают непредсказуемый результат.
- Логирование без ограничений заполняет диск.
# кто управляет правилами
systemctl is-active nftables ufw firewalld 2>/dev/null
# IPv6-правила
sudo nft list table ip6 filter 2>/dev/null
# размер журнала
journalctl --disk-usage
Резервная копия и безопасное применение
Перед любой правкой сохраняйте действующий ruleset: восстановление из файла занимает секунды, а пересобрать правила по памяти после отключения доступа невозможно.
# сохранить текущее состояние
sudo nft list ruleset > /root/nft-backup-$(date +%F).nft
# применить из файла
sudo nft -f /root/nft-backup-$(date +%F).nft
# в конфиге держите отдельный «аварийный» доступ к порту 22
# до тех пор, пока не убедились, что правила рабочие
Практикуйте «двухэтапное» применение: сначала добавьте разрешение для нового порта и убедитесь, что сервис отвечает, затем закрывайте лишнее. Так порядок правил никогда не отрезает вас от сервера.
nftables и контейнеры
Docker и Podman управляют своими цепочками. Если вы используете nft, убедитесь, что правила контейнерного движка не конфликтуют с вашими, иначе проброс портов перестанет работать.
# посмотреть, какие таблицы создают контейнеры
sudo nft list tables
sudo nft list table ip docker 2>/dev/null | head -20
# после остановки Docker правила могут остаться
sudo systemctl status docker --no-pager | head -5
# перепроверка после изменений
curl -I http://localhost:8080 2>/dev/null | head -3
Лучшая практика — не править правила Docker вручную, а размещать собственные ограничения в отдельной таблице и не трогать flush ruleset при обновлениях контейнерной платформы.
Итог
nftables даёт единый конфигурационный файл, атомарное применение, счётчики и метры для лимитов. Начните с правила established, закройте вход, ограничьте SSH и включите выборочное логирование. Обязательно проверяйте конфиг через nft -c и убедитесь, что второй файрвол не работает параллельно.