iptables — классический интерфейс к netfilter, подсистеме фильтрации пакетов ядра Linux. Он работает с цепочками правил, которые проверяются по порядку сверху вниз: как только пакет совпал с правилом, дальнейшие правила в этой цепочке не проверяются.
Три основные цепочки
Каждая цепочка проверяется отдельно и не влияет на решения других: разрешив что-то в INPUT, вы не разрешаете это автоматически в FORWARD. На обычном веб-сервере, который не пересылает чужой трафик, цепочка FORWARD может оставаться закрытой полностью — она нужна только когда сервер сам выступает шлюзом или роутером для других машин.
| Цепочка | Когда применяется | Типовая задача |
|---|---|---|
| INPUT | Пакеты, адресованные самому серверу | Разрешить SSH, HTTP, HTTPS; заблокировать остальное |
| OUTPUT | Пакеты, исходящие с сервера | Обычно оставляют ACCEPT, если сервер не проксирует чужой трафик |
| FORWARD | Транзитные пакеты через сервер | Актуально для роутеров, VPN-шлюзов и Docker-хостов |
Базовые правила iptables
#!/bin/bash
# Очищаем все правила
iptables -F
iptables -X
# Политика по умолчанию: блокировать входящий трафик
iptables -P INPUT DROP
iptables -P FORWARD DROP
iptables -P OUTPUT ACCEPT
# Разрешаем loopback
iptables -A INPUT -i lo -j ACCEPT
# Разрешаем установленные соединения
iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
# SSH (замените 22 на свой порт)
iptables -A INPUT -p tcp --dport 22 -j ACCEPT
# HTTP и HTTPS
iptables -A INPUT -p tcp -m multiport --dports 80,443 -j ACCEPT
# ICMP (ping)
iptables -A INPUT -p icmp --icmp-type echo-request -j ACCEPT
Типичные ошибки при первом запуске
Забыли правило для SSH перед политикой DROP
Если выполнить iptables -P INPUT DROP раньше, чем добавлено правило -A INPUT -p tcp --dport 22 -j ACCEPT, активная SSH-сессия оборвётся, а новая не подключится. На VPS без консоли провайдера это означает полную потерю доступа. Правильный порядок — сначала добавить все ACCEPT-правила, политику DROP выставлять последней командой.
Забыли разрешить loopback
Без iptables -A INPUT -i lo -j ACCEPT с политикой DROP на INPUT ломаются локальные соединения между процессами на самом сервере — например, PHP-FPM больше не сможет достучаться до MySQL через 127.0.0.1, хотя порт снаружи никто не трогал.
Защита от сканирования портов
# Блокировка NMAP SYN сканирования
iptables -A INPUT -p tcp --tcp-flags ALL NONE -j DROP
iptables -A INPUT -p tcp --tcp-flags ALL ALL -j DROP
# Ограничение новых соединений (защита от SYN flood)
iptables -A INPUT -p tcp --syn -m limit --limit 1/s --limit-burst 3 -j ACCEPT
Правило с --state ESTABLISHED,RELATED из базового набора опирается на модуль отслеживания соединений conntrack, у которого есть предел размера таблицы. При массовом сканировании портов или флуде новых соединений таблица может переполниться, и в системном логе появится сообщение:
kernel: nf_conntrack: table full, dropping packet
После этого сообщения новые легитимные соединения тоже начинают обрываться — не только атакующие. Лимит новых соединений в правиле выше снижает риск такого переполнения, но при действительно крупной атаке одного iptables недостаточно: нужна фильтрация до сервера, на уровне провайдера или CDN.
Сохранение правил
apt install iptables-persistent -y
netfilter-persistent save
# Правила сохраняются в /etc/iptables/rules.v4
Когда одного iptables недостаточно
- Нужна фильтрация на уровне приложения (анализ HTTP-запросов, а не только портов и IP) — iptables работает на уровне L3/L4, для L7 нужен WAF вроде ModSecurity.
- Много таблиц и цепочек с пересекающейся логикой — современные дистрибутивы постепенно переходят на nftables, у которого более читаемый синтаксис и один набор таблиц вместо отдельных утилит для IPv4 и IPv6.
- Нужна защита от подбора паролей по факту неудачных попыток входа — iptables не читает логи приложений, для этого нужен Fail2ban поверх него.
Проверка, что правила применились
- Выполните
iptables -L -v -n— убедитесь, что цепочка INPUT содержит ожидаемые правила и политика по умолчанию действительно DROP. - С другого устройства проверьте закрытый порт:
nc -zv ВАШ_IP 3306должен завершиться отказом. - Перезагрузите сервер и снова выполните
iptables -L -v -n— если правила исчезли, значитnetfilter-persistent saveне был выполнен или пакетiptables-persistentне установлен. - Проверьте счётчики пакетов в
iptables -L -v -n: растущие значения напротив правила SYN flood подтверждают, что лимит действительно фильтрует трафик, а не просто существует в конфиге.
Более простой интерфейс к тем же правилам — в статье UFW для Ubuntu и Debian, а автоматическая блокировка по логам — в разборе настройка Fail2ban.