Зачем знать iptables в 2026
RHEL 8/9 и Debian 11/12 формально перешли на nftables, но iptables-команда
на них зачастую - просто frontend (iptables-nft), и старые скрипты
работают. На Alpine, Ubuntu LTS до 22.04, embedded-системах и в куче legacy -
всё ещё чистый iptables. Docker до сих пор пишет правила через iptables.
Знать его - читать прод.
Новый код пиши на [[cmd-nft|nft]]: один синтаксис вместо iptables/ip6tables/arptables/ebtables, поддержка sets, namespaces, atomic update.
Архитектура: таблицы и цепочки
Пакет идёт через netfilter hooks в ядре. iptables навешивает на hook'и цепочки (chains), сгруппированные в таблицы (tables) по предназначению:
| Таблица | Что делает |
|---|---|
| filter | разрешать/блокировать (default) |
| nat | трансляция адресов (SNAT, DNAT, [[nat |
| mangle | модификация заголовков (TOS, TTL, MARK) |
| raw | до conntrack (NOTRACK для исключений) |
| security | SELinux MAC-метки |
Стандартные цепочки и где они срабатывают:
┌─PREROUTING─→─routing─┬─FORWARD──→─POSTROUTING─┐
in iface ────┤ │ ├──→ out iface
└────────────────────────→ INPUT → local proc OUTPUT
- PREROUTING (raw, mangle, nat) - сразу при входе
- INPUT (filter, mangle) - предназначенные локально
- OUTPUT (raw, mangle, nat, filter) - локально сгенерированные
- FORWARD (filter, mangle) - транзитные (нужен ip-forwarding)
- POSTROUTING (mangle, nat) - перед отправкой
Базовый синтаксис
iptables [-t TABLE] -A CHAIN [-s SRC] [-d DST] [-p PROTO] [--dport N] [-i IFACE] -j TARGET
| Опция | Что |
|---|---|
-A CHAIN | append - добавить в конец |
-I CHAIN [N] | insert на позицию N (1 - в начало) |
-D CHAIN N | delete по номеру; или -D CHAIN <правило> точно |
-L [CHAIN] | list (обычно с -n -v --line-numbers) |
-F [CHAIN] | flush - удалить все правила |
-P CHAIN POLICY | дефолтная политика (ACCEPT/DROP) |
-N CHAIN | создать кастомную цепочку |
-X CHAIN | удалить пустую цепочку |
Targets (jump)
| Target | Что |
|---|---|
ACCEPT | пропустить |
DROP | молча отбросить |
REJECT | отбросить и послать ICMP unreachable |
LOG | в dmesg/syslog (--log-prefix) |
MASQUERADE | SNAT с автоопределением src-IP |
SNAT --to-source IP | source NAT |
DNAT --to-destination IP[:PORT] | destination NAT |
MARK --set-mark N | пометить для policy-routing |
<кастомная-цепочка> | jump в свою цепочку |
RETURN | выйти из текущей цепочки |
Простые рецепты
Базовый firewall на хосте
iptables -P INPUT DROP
iptables -P FORWARD DROP
iptables -P OUTPUT ACCEPT
iptables -A INPUT -i lo -j ACCEPT # localhost
iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
iptables -A INPUT -p tcp --dport 22 -j ACCEPT # ssh
iptables -A INPUT -p tcp --dport 443 -j ACCEPT # https
iptables -A INPUT -p icmp --icmp-type echo-request -j ACCEPT # ping
Без conntrack-правила исходящие соединения не получат ответы - первое что забывают.
NAT для контейнерной сети
echo 1 > /proc/sys/net/ipv4/ip_forward # см. [[ip-forwarding]]
iptables -t nat -A POSTROUTING -s 172.17.0.0/16 -o eth0 -j MASQUERADE
Проброс порта
iptables -t nat -A PREROUTING -p tcp --dport 8080 -j DNAT --to-destination 10.0.0.5:80
iptables -A FORWARD -p tcp -d 10.0.0.5 --dport 80 -j ACCEPT
Rate-limit брутфорса
iptables -A INPUT -p tcp --dport 22 -m conntrack --ctstate NEW \
-m recent --set --name SSH
iptables -A INPUT -p tcp --dport 22 -m conntrack --ctstate NEW \
-m recent --update --seconds 60 --hitcount 5 --name SSH -j DROP
Не больше 5 новых SSH-соединений с одного IP за минуту.
Сохранение и восстановление
Изменения через iptables -A живут до перезагрузки. Сохранять надо явно:
iptables-save > /etc/iptables/rules.v4 # экспорт текущего состояния
iptables-restore < /etc/iptables/rules.v4 # импорт (атомарно)
ip6tables-save > /etc/iptables/rules.v6 # IPv6 - отдельная команда!
Distribution-специфика:
- Debian/Ubuntu:
apt install iptables-persistent- сохраняет в/etc/iptables/rules.v[46], грузит на boot - RHEL:
iptables-services,systemctl enable iptables ip6tables
iptables-legacy vs iptables-nft
На современных дистрибутивах команда iptables - shim над nftables:
iptables --version
# iptables v1.8.7 (nf_tables) ← nft бэкенд
# iptables v1.8.7 (legacy) ← старый xt_-бэкенд
Смешивать нельзя: правила в legacy и в nft - разные пространства.
Если Docker и kube-proxy пишут разными - можно получить дыру в файрволе.
Решение: update-alternatives --config iptables либо явный
iptables-legacy / iptables-nft.
ip6tables и ebtables
IPv6 - отдельный набор правил, отдельная команда:
ip6tables -A INPUT -p tcp --dport 22 -j ACCEPT
Ethernet bridge-фильтр - ebtables (на L2). nftables всё это
объединяет в одну nft команду - сильное преимущество.
Когда что-то пошло не так
- Закрыл себе SSH - первое правило
INPUT DROPбез явного разрешения 22-го. Лекарство:at +5 'iptables -F'ДО любого rules-up, или работа через console/serial. Permission denied- iptables нужен root и cap NET_ADMIN.- Правило не срабатывает - проверь порядок:
iptables -L INPUT -n -v --line-numbers. Первый match выигрывает; счётчик байтов покажет что прошло. - NAT не работает - забыли
ip_forward=1, забылиMASQUERADEили забыли разрешить FORWARD. - Conntrack overflow -
dmesg | grep nf_conntrackпоказываетtable full. Увеличьnf_conntrack_maxчерез [[cmd-sysctl|sysctl]] или вынь stateful trackable траф из conntrack через-t raw -j NOTRACK. - iptables-restore тихо не применил часть - синтаксическая ошибка в середине файла; читает построчно, до ошибки применяется атомарно, после - нет. Проверь exit-code.
Альтернативы
- [[cmd-nft|nftables]] - современный преемник
- firewalld - high-level demon, абстракция над nft/iptables (RHEL default)
- ufw - simplified frontend над iptables (Ubuntu)
- shorewall - старый-добрый rules-compiler