Iptables — утилита командной строки, является стандартным интерфейсом управления работой межсетевого экрана (брандмауэра) Netfilter для ядер Linux, начиная с версии 2.4. С её помощью администраторы создают и изменяют правила, управляющие фильтрацией и перенаправлением пакетов. Для работы с семейством протоколов IPv6 существует отдельная версия утилиты — Ip6tables. Для использования утилиты Iptables требуются привилегии суперпользователя (root).

Основные понятия

Ключевыми понятиями iptables являются:

  1. Правило — состоит из критерия, действия и счетчика. Если пакет соответствует критерию, к нему применяется действие, и он учитывается счетчиком. Критерия может и не быть — тогда неявно предполагается критерий «все пакеты». Указывать действие тоже не обязательно — в отсутствие действия правило будет работать только как счетчик. Правила для каждой цепочки срабатывают в порядке их следования, поэтому порядок важен.
    • Критерий — логическое выражение, анализирующее свойства пакета и/или соединения и определяющее, подпадает ли данный конкретный пакет под действие текущего правила. Критерии соединяются логическим «И».
    • Действие — описание действия, которое нужно проделать с пакетом и/или соединением в том случае, если они подпадают под действие этого правила. О действиях более подробно будет рассказано ниже.
    • Счетчик — компонент правила, обеспечивающий учет количества пакетов, которые попали под критерий данного правила. Также счетчик учитывает суммарный объем таких пакетов в байтах.
  2. Цепочка — упорядоченная последовательность правил. Цепочки можно разделить на пользовательские и базовые.
    • Базовая цепочка — цепочка, создаваемая по умолчанию при инициализации таблицы. Каждый пакет, в зависимости от того, предназначен ли он самому хосту, сгенерирован им или является транзитным, должен пройти положенный ему набор базовых цепочек различных таблиц. Кроме того, базовая цепочка отличается от пользовательской наличием «действия по умолчанию» (default policy). Это действие применяется к тем пакетам, которые не были обработаны другими правилами этой цепочки и вызванных из нее цепочек. Имена базовых цепочек всегда записываются в верхнем регистре (PREROUTING, INPUT, FORWARD, OUTPUT, POSTROUTING).
    • Пользовательская цепочка — цепочка, созданная пользователем. Может использоваться только в пределах своей таблицы. Рекомендуется не использовать для таких цепочек имена в верхнем регистре, чтобы избежать путаницы с базовыми цепочками и встроенными действиями.
  3. Таблица — совокупность базовых и пользовательских цепочек, объединенных общим функциональным назначением. Имена таблиц (как и модулей критериев) записываются в нижнем регистре, так как в принципе не могут конфликтовать с именами пользовательских цепочек. При вызове команды iptables таблица указывается в формате -t имя_таблицы. При отсутствии явного указания, используется таблица filter.

Синтаксический анализ:

# Дамп правил таблицы filter
$ sudo iptables-save -c -t filter
# Таблица filter
*filter
# Цепочки INPUT, FORWARD, OUTPUT, их политики и счётчики
:INPUT ACCEPT [19302:9473669]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [5462736:4247599532]
# Правило: "[17:1020]" - счётчик правила, "-A INPUT" - цепочка, "-i em1 -p tcp -m tcp --dport 22" - критерии, "-j ACCEPT" - действие
[17:1020] -A INPUT -i em1 -p tcp -m tcp --dport 22 -j ACCEPT
COMMIT

Архитектура

В системе netfilter, пакеты пропускаются через цепочки. Цепочка является упорядоченным списком правил, а каждое правило может содержать критерии и действие или переход. Когда пакет проходит через цепочку, система netfilter по очереди проверяет, соответствует ли пакет всем критериям очередного правила, и если так, то выполняет действие (если критериев в правиле нет, то действие выполняется для всех пакетов проходящих через правило). Вариантов возможных критериев очень много. Например, пакет соответствует критерию –source 192.168.1.1 если в заголовке пакета указано, что отправитель — 192.168.1.1. Самый простой тип перехода, –jump, просто пересылает пакет в начало другой цепочки. Также при помощи –jump можно указать действие. Стандартные действия доступные во всех цепочках — ACCEPT (пропустить), DROP (удалить), QUEUE (передать на анализ внешней программе), и RETURN (вернуть на анализ в предыдущую цепочку). Например, команды

iptables -A INPUT --source 192.168.1.1 --jump ACCEPT
iptables -A INPUT --jump other_chain

означают «добавить к концу цепочки INPUT следующие правила: пропустить пакеты из 192.168.1.1, а всё, что останется — отправить на анализ в цепочку other_chain».

Цепочки

Существует 5 типов стандартных цепочек, встроенных в систему:

  • PREROUTING — для изначальной обработки входящих пакетов.
  • INPUT — для входящих пакетов адресованных непосредственно локальному процессу (клиенту или серверу).
  • FORWARD — для входящих пакетов перенаправленных на выход (заметьте, что перенаправляемые пакеты проходят сначала цепь PREROUTING, затем FORWARD и POSTROUTING).
  • OUTPUT — для пакетов генерируемых локальными процессами.
  • POSTROUTING — для окончательной обработки исходящих пакетов.

Также можно создавать и уничтожать собственные цепочки при помощи утилиты iptables.

Таблицы

Цепочки организованны в 4 таблицы:

  • raw — просматривается до передачи пакета системе определения состояний. Используется редко, например для маркировки пакетов, которые НЕ должны обрабатываться системой определения состояний. Для этого в правиле указывается действие NOTRACK. Содержит цепочки PREROUTING и OUTPUT.
  • mangle — содержит правила модификации (обычно заголовка) IP‐пакетов. Среди прочего, поддерживает действия TTL (Time to live), TOS (Type of Service), и MARK (для изменения полей TTL и TOS, и для изменения маркеров пакета). Редко необходима и может быть опасна. Содержит все пять стандартных цепочек.
  • nat — просматривает только пакеты, создающие новое соединение (согласно системе определения состояний). Поддерживает действия DNAT, SNAT, MASQUERADE, REDIRECT. Содержит цепочки PREROUTING, OUTPUT, и POSTROUTING.
  • filter — основная таблица, используется по умолчанию если название таблицы не указано. Содержит цепочки INPUT, FORWARD, и OUTPUT.

Цепочки с одинаковым названием, но в разных таблицах — совершенно независимые объекты. Например, raw PREROUTING и mangle PREROUTING обычно содержат разный набор правил; пакеты сначала проходят через цепочку raw PREROUTING, а потом через mangle PREROUTING.

Состояния

В системе netfilter, каждый пакет проходящий через механизм определения состояний, может иметь одно из четырёх возможных состояний:

  • NEW — пакет открывает новый сеанс. Классический пример — пакет TCP с флагом SYN.
  • ESTABLISHED — пакет является частью уже существующего сеанса.
  • RELATED — пакет открывает новый сеанс, связанный с уже открытым сеансом. Например, во время сеанса пассивного FTP, клиент подсоединяется к порту 21 сервера, сервер сообщает клиенту номер второго, случайно выбранного порта, после чего клиент подсоединяется ко второму порту для передачи файлов. В этом случае второй сеанс (передача файлов по второму порту) связан с уже существующим сеансом (изначальное подсоединение к порту 21).
  • INVALID — все прочие пакеты.

Диаграмма прохождения таблиц и цепочек

Упрощённая диаграмма прохождения таблиц и цепочек:

http://www.rootdir.org/.offload/kptd-simplified-ru.svg

Детальная диаграмма:

http://upload.wikimedia.org/wikipedia/commons/3/37/Netfilter-packet-flow.svg

Базовая конфигурация

Ниже приведён пример базовой статической конфигурации iptables. При сохранении и загрузке подобной конфигурации необходимо принимать во внимание возможность внесения в неё изменений со стороны других сервисов, например Fail2ban. Кроме того, при использовании IPv6-адресации конфигурацию для IPv6 следует выполнять независимо от IPv4.

IPv4

Просмотр текущей конфигурации:

sudo iptables-save

Создаём скрипт с дампом правил iptables:

sudo nano /etc/network/if-up.d/iptables-rules

Копируем следующий код:

#!/sbin/iptables-restore
# Таблица filter и её цепочки
*filter
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
# Разрешаем связанные и установленые соединения
-A INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
# Разрешаем служебный icmp-трафик
-A INPUT -p icmp -j ACCEPT
# Разрешаем доверенный трафик на интерфейс loopback
-A INPUT -i lo -j ACCEPT
# Сюда можно вставлять дополнительные правила для цепочки INPUT
# Запрещаем всё остальное для INPUT
-A INPUT -j REJECT --reject-with icmp-host-prohibited
# Порядок и смысл правил для цепочек FORWARD и OUTPUT аналогичен INPUT
-A FORWARD -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A FORWARD -p icmp -j ACCEPT
-A FORWARD -j REJECT --reject-with icmp-host-prohibited
# Фильтровать цепочку OUTPUT настоятельно не рекомендуется
#-A OUTPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
#-A OUTPUT -p icmp -j ACCEPT
#-A OUTPUT -o lo -j ACCEPT
#-A OUTPUT -j REJECT --reject-with icmp-host-prohibited
COMMIT

Дополняем нужными правилами с учётом iptables-save.

Сохраняем и закрываем: Ctrl+O, Enter, Ctrl+X

Делаем скрипт исполняемым и загружаем правила iptables:

sudo chmod +x /etc/network/if-up.d/iptables-rules
sudo /etc/network/if-up.d/iptables-rules

IPv6

Просмотр текущей конфигурации:

sudo ip6tables-save

Создаём скрипт с дампом правил ip6tables:

sudo nano /etc/network/if-up.d/ip6tables-rules

Копируем следующий код:

#!/sbin/ip6tables-restore
# Таблица filter и её цепочки
*filter
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
# Разрешаем связанные и установленые соединения
-A INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
# Разрешаем служебный icmp-трафик
-A INPUT -p ipv6-icmp -j ACCEPT
# Разрешаем доверенный трафик на интерфейс loopback
-A INPUT -i lo -j ACCEPT
# Сюда можно вставлять дополнительные правила для цепочки INPUT
# Запрещаем всё остальное для INPUT
-A INPUT -j REJECT --reject-with icmp6-adm-prohibited
# Порядок и смысл правил для цепочек FORWARD и OUTPUT аналогичен INPUT
-A FORWARD -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A FORWARD -p ipv6-icmp -j ACCEPT
-A FORWARD -j REJECT --reject-with icmp6-adm-prohibited
# Фильтровать цепочку OUTPUT настоятельно не рекомендуется
#-A OUTPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
#-A OUTPUT -p ipv6-icmp -j ACCEPT
#-A OUTPUT -o lo -j ACCEPT
#-A OUTPUT -j REJECT --reject-with icmp6-adm-prohibited
COMMIT

Дополняем нужными правилами с учётом ip6tables-save.

Сохраняем и закрываем: Ctrl+O, Enter, Ctrl+X

Делаем скрипт исполняемым и загружаем правила iptables:

sudo chmod +x /etc/network/if-up.d/ip6tables-rules
sudo /etc/network/if-up.d/ip6tables-rules

Дополнительные правила

Ниже приведены некоторые сравнительно часто используемые правила. Цепочки INPUT/OUTPUT применяются для фильтрации локального трафика. Для транзитного трафика необходимо использовать цепочку FORWARD.

Удалённый доступ

# remote.ssh
-A INPUT -p tcp -m conntrack --ctstate NEW -m tcp --dport 22 -j ACCEPT
# remote.rdp
-A INPUT -p tcp -m conntrack --ctstate NEW -m tcp --dport 3389 -j ACCEPT
# remote.vnc
-A INPUT -p tcp -m conntrack --ctstate NEW -m tcp --dport 5900 -j ACCEPT

Веб и файловые сервисы

# web.http, web.https
-A INPUT -p tcp -m conntrack --ctstate NEW -m multiport --dports 80,443 -j ACCEPT
# web.ftp + необходима загрузка модуля nf_conntrack_ftp
-A INPUT -p tcp -m conntrack --ctstate NEW -m tcp --dport 21 -j ACCEPT

Почта и мгновенные сообщения

# mail.pop3, mail.pop3s
-A INPUT -p tcp -m conntrack --ctstate NEW -m multiport --dports 110,995 -j ACCEPT
# mail.imap, mail.imaps
-A INPUT -p tcp -m conntrack --ctstate NEW -m multiport --dports 143,993 -j ACCEPT
# mail.smtp, mail.smtps
-A INPUT -p tcp -m conntrack --ctstate NEW -m multiport --dports 25,465 -j ACCEPT
# im.xmpp
-A INPUT -p tcp -m conntrack --ctstate NEW -m multiport --dports 5222,5223  -j ACCEPT
# im.icq.oscar
-A INPUT -p tcp -m conntrack --ctstate NEW -m tcp --dport 5190 -j ACCEPT

Сетевые службы

# network.openvpn.vpn
-A INPUT -p udp -m conntrack --ctstate NEW -m udp --dport 1194 -j ACCEPT
# network.squid.proxy
-A INPUT -p udp -m conntrack --ctstate NEW -m udp --dport 3128 -j ACCEPT
# network.dns
-A INPUT -p tcp -m conntrack --ctstate NEW -m tcp --dport 53 -j ACCEPT
-A INPUT -p udp -m conntrack --ctstate NEW -m udp --dport 53 -j ACCEPT
# network.ntp
-A INPUT -p udp -m conntrack --ctstate NEW -m udp --dport 123 -j ACCEPT
# network.tftp + необходима загрузка модуля nf_conntrack_tftp
-A INPUT -p udp -m conntrack --ctstate NEW -m udp --dport 69 -j ACCEPT
# network.dhserver.dhcp.discover-request
-A INPUT -p udp -m conntrack --ctstate NEW -m udp --sport 68 --dport 67 -j ACCEPT
# network.dhclient.dhcp.discover-request
#-A OUTPUT -p udp -m conntrack --ctstate NEW -m udp --sport 68 --dport 67 -j ACCEPT
# network.dhserver.dhcp.offer-ack
#-A OUTPUT -p udp -m conntrack --ctstate NEW -m udp --sport 67 --dport 68 -j ACCEPT

Тестирование и отладка

Просмотр текущей конфигурации для IPv4 и IPv6:

sudo iptables-save
sudo ip6tables-save

Логирование

FIXME

Трассировка

FIXME

Модули ядра

Просмотр загруженных модулей:

lsmod | grep -E '^ip|^nf' | sort

Для загрузки дополнительных модулей удобно применять автодополнение: 2xTab

sudo modprobe nf
sudo modprobe ip

Часто используемые модули: nf_conntrack_ftp, nf_conntrack_pptp, nf_conntrack_tftp, nf_nat_pptp.

Автозагрузка модулей:

man modules-load.d

Ссылки