Миграция с iptables на nftables: пошаговый план без простоев
Меня зовут Евгений Семёнов, и я директор ITFresh. Сколько раз мне, да и многим нашим инженерам, приходилось переписывать правила для фаервола на Linux-серверах за 15 лет? Сотни, наверное, если не тысячи! Честно признаюсь, долго сопротивлялся переходу с привычного iptables на nftables. Но когда я наконец попробовал, понял: это совершенно другой уровень. Правила читаются несравненно понятнее, производительность заметно выше, а работа с наборами IP-адресов через именованные sets так упрощает жизнь, что порой жалеешь о каждом годе, проведённом с iptables. В этом руководстве я покажу, как мне удалось мигрировать целый сервер без единой минуты простоя, сохранив при этом абсолютно все существующие правила. Звучит фантастично? Да, но это реально.
Почему nftables — это серьёзно
Представьте себе: iptables появился в далеком 2001 году, вместе с выходом Linux 2.4. С тех пор ядро системы изменилось радикально, а вот iptables, к сожалению, остался с прежней архитектурой. До сих пор мы работаем с отдельными командами для IPv4, IPv6, arp и bridge. Каждое правило — это отдельный системный вызов! Попробуйте добавить 10 000 правил — и вам придется подождать несколько минут. Что же nftables? Он пришёл только в 2014 году как единый, современный фреймворк, а с 2019-го уже стал стандартом в большинстве дистрибутивов. Разница, как говорится, налицо.
Что даёт nftables на практике:
- Забудьте о разных командах! Теперь у вас единый синтаксис для всех протоколов. Одна-единственная таблица спокойно обрабатывает и IPv4, и IPv6. Удобно, да?
- Что такое Atomic rule replacement? Это значит, что весь ваш набор правил обновляется одной, цельной транзакцией. Забыли о простоях и нестабильных состояниях!
- Sets и Maps — это, по сути, именованные коллекции для IP-адресов, портов или сетевых интерфейсов. Их главное преимущество? Константное время поиска, а значит, невероятная скорость даже при огромных списках.
- Concatenation? Это когда одно правило может сразу сравнивать несколько разных полей, так называемых 'tuples'. Это сильно упрощает сложную логику, делая её компактнее и понятнее.
- Надоели громоздкие `if-then` цепочки? Мы знаем, как решить эту проблему! Для маршрутизации по ключу мы активно применяем Vmap и словари. Это делает код чище и значительно упрощает логику, позволяя быстро находить нужные данные, без запутанных условий.
Подготовка к миграции
Моё золотое правило номер один, высеченное, что называется, кровью: НИКОГДА не начинайте удалённую миграцию, если у вас нет out-of-band доступа. У нас в ITFresh был поучительный, но очень дорогой случай. Один из наших инженеров, по невнимательности — обычная опечатка в правиле DROP для SSH — начисто потерял доступ к серверу. А он, между прочим, стоял в Нидерландах! Представляете масштаб проблемы? Пришлось срочно отправлять человека в командировку, преодолев 2000 километров, чтобы просто нажать кнопку и исправить правило! С тех пор никаких исключений: перед каждой подобной миграцией мы ВСЕГДА заранее настраиваем KVM-консоль или IPMI. Лучше перебдеть, чем потом платить за билеты в Амстердам, правда?
Сохраняем текущее состояние:
sudo iptables-save > /root/iptables-backup-$(date +%F).rules
sudo ip6tables-save > /root/ip6tables-backup-$(date +%F).rules
# Проверяем, какой backend сейчас используется
update-alternatives --display iptables
# Должно показать /usr/sbin/iptables-legacy или iptables-nft
В современных Ubuntu/Debian команда iptables — это обёртка над nftables (iptables-nft). Правила работают через nftables backend, но синтаксис остаётся старый. Настоящая миграция — это переписать правила на нативный синтаксис nftables.
Автоматическая конвертация
Для стартового скелета используем iptables-restore-translate:
sudo iptables-save > /tmp/iptables.rules
sudo iptables-restore-translate -f /tmp/iptables.rules > /tmp/nftables-draft.nft
cat /tmp/nftables-draft.nft
Есть важный нюанс: после конвертации результат редко бывает готовым к использованию 'как есть'. Почему? Утилита просто делает однозначную конвертацию, но совсем не оптимизирует правила под крутые новые возможности nftables. Поэтому я всегда рассматриваю такой результат как черновик, основу. А дальше начинается самое интересное: я переписываю его вручную, активно применяя sets, maps и вложенные цепочки, чтобы выжать максимум из nftables.
Базовая структура nftables-конфига
Файл /etc/nftables.conf имеет вложенную структуру: таблицы → цепочки → правила.
#!/usr/sbin/nft -f
flush ruleset
table inet filter {
# Общие наборы адресов
set ssh_allowed {
type ipv4_addr
flags interval
elements = {
192.168.10.0/24,
10.10.0.0/16,
203.0.113.45
}
}
chain input {
type filter hook input priority filter; policy drop;
# Loopback
iif lo accept
ct state established,related accept
ct state invalid drop
# ICMP
ip protocol icmp accept
ip6 nexthdr icmpv6 accept
# SSH только с доверенных сетей
tcp dport 22 ip saddr @ssh_allowed accept
tcp dport 22 log prefix "SSH-drop: " drop
# Web
tcp dport {80, 443} accept
# Остальное — лог и drop
counter log prefix "INPUT-drop: " drop
}
chain forward {
type filter hook forward priority filter; policy drop;
}
chain output {
type filter hook output priority filter; policy accept;
}
}
Обратите внимание: одна таблица inet filter обрабатывает и IPv4, и IPv6 одновременно. В iptables для этого пришлось бы делать два параллельных набора правил.
NAT и port forwarding
Если вы работаете с прокси-серверами или NAT-роутерами, знайте: вам понадобится отдельная таблица, где будут именно nat-цепочки.
table inet nat {
chain prerouting {
type nat hook prerouting priority dstnat; policy accept;
# Port forwarding: внешний 2222 -> внутренний 192.168.10.5:22
iif "eth0" tcp dport 2222 dnat ip to 192.168.10.5:22
}
chain postrouting {
type nat hook postrouting priority srcnat; policy accept;
# MASQUERADE для исходящего трафика локальной сети
oif "eth0" ip saddr 192.168.10.0/24 masquerade
}
}
Сравнение синтаксиса iptables vs nftables
| Задача | iptables | nftables |
|---|---|---|
| Разрешить SSH | -A INPUT -p tcp --dport 22 -j ACCEPT | tcp dport 22 accept |
| Множество портов | -m multiport --dports 80,443 | tcp dport {80, 443} accept |
| Лимит на соединения | -m limit --limit 10/min | limit rate 10/minute |
| Сохранение правил | iptables-save | nft list ruleset |
| Добавить IP в блэклист | ipset + iptables -m set | add element inet filter blacklist {1.2.3.4} |
| Логирование | -j LOG --log-prefix | log prefix "..." |
Продвинутые возможности: sets и maps
Sets — это просто находка! Представьте себе именованные коллекции, которые обновляются атомарно. Что это значит для вас? Это идеальное решение для организации динамического блэклиста, например.
table inet filter {
set blacklist_v4 {
type ipv4_addr
flags timeout
}
chain input {
type filter hook input priority filter; policy drop;
ip saddr @blacklist_v4 drop
# ... остальные правила
}
}
# Добавить IP в блэклист с таймаутом 1 час
nft add element inet filter blacklist_v4 { 198.51.100.42 timeout 1h }
# Посмотреть текущий блэклист
nft list set inet filter blacklist_v4
Maps идут ещё дальше, это следующий уровень! С их помощью можно организовать маршрутизацию или даже DNAT прямо по словарю.
map port_forward {
type inet_service : ipv4_addr . inet_service
elements = {
2222 : 192.168.10.5 . 22,
8080 : 192.168.10.6 . 80,
8443 : 192.168.10.7 . 443
}
}
chain prerouting {
type nat hook prerouting priority dstnat;
iif "eth0" tcp dport vmap @port_forward dnat ip to
}
Защита от DDoS и брутфорса
Nftables отлично справляется с самыми популярными сценариями защиты. Вот, к примеру, как легко ограничить попытки SSH-подключения и забанить слишком настойчивые IP-адреса, если лимит превышен:
table inet filter {
set ssh_banned {
type ipv4_addr
flags timeout
timeout 1h
}
chain input {
type filter hook input priority filter; policy drop;
# Забаненные — сразу drop
ip saddr @ssh_banned drop
# Больше 5 новых SSH-соединений в минуту — бан
tcp dport 22 ct state new \
add @ssh_banned { ip saddr limit rate over 5/minute } drop
tcp dport 22 accept
}
}
Кейс: миграция шлюза в офисе на 80 сотрудников
Помните, в феврале 2025 года мы в ITFresh занимались миграцией Linux-шлюза для одного из наших клиентов. Это была московская дизайн-студия на 80 человек. Наша задача: перевести их шлюз с Debian 10 + iptables на новенький Debian 12 + nftables. Что там за железо? Сервер HP ProLiant DL360 Gen9 с процессором Xeon E5-2620 v4, 32 ГБ RAM, размещенный, кстати, в дата-центре МТС. А что на нём крутилось? Стандартный набор: NAT для всей локальной сети 10.20.0.0/16, OpenVPN-сервер, ProxyChains и, конечно, полтора десятка правил port-forward для доступа к внутренним сервисам.
И что мы увидели? Старый конфиг разросся до 340 строк iptables! Причем никто уже не помнил, зачем нужна половина этих правил. Типичная история, правда? Мы использовали `iptables-restore-translate`, чтобы получить первую версию, черновик, на 290 строк. Неплохо, но можно лучше! Всего за 6 часов кропотливой работы мы полностью переписали его уже на 'нативный' nftables, используя sets для белых списков, map для port-forward и единую таблицу inet для IPv4 и IPv6. Результат впечатляет: вместо 340 строк — всего 180, и каждая из них теперь понятно задокументирована. Но это не главное. А что с производительностью? NAT ускорился с 1.8 Гбит/с до 2.4 Гбит/с на том же самом железе! Время применения правил сократилось с 2.3 секунд до невероятных 0.1 секунды. Можете себе такое представить? Важнее всего, конечно, что миграция прошла без единого простоя. Мы просто атомарно подменили весь ruleset в пятницу вечером, и клиент даже ничего не заметил. Кстати, стоимость этих работ составила 35 000 рублей.
Сохранение и автозагрузка
Правила сохраняются в /etc/nftables.conf, служба nftables.service загружает их при старте:
# Применить текущий набор в файл
sudo nft list ruleset > /etc/nftables.conf
# Включить автозагрузку
sudo systemctl enable --now nftables
# Проверка после ребута
sudo nft list ruleset
Грабли и типичные ошибки
- Забыли про IPv6. Если таблица только
ip, IPv6-трафик не фильтруется. Используйтеinetили добавьте таблицуip6. - Policy drop без established. Поставили policy drop на input/forward, забыли про ct state established,related — сервер перестал отвечать на собственные соединения.
- Конфликт с firewalld/ufw. Убедитесь, что высокоуровневые обёртки отключены:
systemctl disable firewalld ufw. - Docker пересобирает свои правила. После перезапуска Docker добавляет свои цепочки. Используйте DOCKER_USER для пользовательских правил.
- Нет счётчиков. Для отладки добавляйте
counterв правила — тогдаnft list rulesetпокажет, какие правила срабатывают и сколько раз.
Мигрируем ваш firewall на nftables без простоев
Перепишем правила iptables на nativный nftables с использованием sets, maps, логированием и счётчиками. Документация, откат-план, нагрузочное тестирование. Работаем с Debian, Ubuntu, Rocky, Alpine.
Телефон: +7 903 729-62-41
Telegram: @ITfresh_Boss
Семёнов Евгений Сергеевич, директор АйТи Фреш
FAQ — частые вопросы о миграции
- Зачем переходить с iptables на nftables?
- Выше производительность, единый синтаксис для IPv4/IPv6, именованные объекты, атомарные обновления.
- Можно ли использовать iptables и nftables одновременно?
- Технически да, но лучше мигрировать полностью — отладка иначе превращается в кошмар.
- Как мигрировать существующие правила iptables?
- iptables-save | iptables-restore-translate -f - > nftables-draft.nft, потом ручная доработка.
- Поддерживают ли Docker и K8s nftables?
- Docker 24+ и K8s 1.29+ имеют nftables backend. По умолчанию многие используют iptables-nft обёртку.
- Как вернуться обратно на iptables при проблемах?
- Сохраните iptables-save в файл, остановите nftables, восстановите старые правила через iptables-restore.
