====== Iptables ======
===== Управление ======
==== Сохранить правила ====
**iptables-save [-m modprobe] [-c] [-t таблица] [-f имя файла]**
* **-m modproble** - путь к программе modproble, можно пропустить.
* **-c** - включает в поток вывода все счетчики байтов и пакетов.
* **-t таблица** - если указать, выведет только ее.
* **-f имя файла** - файл для сохранения, если не указать, выведет на экран.
# iptables-save -f /etc/iptables-conf/rules.ipv4
==== Загрузить правила ====
**iptables-restore [-chntvV] [-w сек] [-W миллисек] [-M modproble] [-T таблица] [имя файла]**
* **-c** - восстановить значение всех счетчиков.
* **-n** - дописать правила в конец текущей таблицы.
* **-t** - только сборка и тестирование набора из файла, без обновления iptables.
* **-v** - дополнительная информация.
* **-V** - номер версии программы.
* **-w** - дождаться монопольной блокировки xtables.
* **-W** - интервал ожидания для каждой попытке монопольного реж.
* **-T таблица** - восстановит только указанную таблицу.
# iptables-restore -vV /etc/iptables-conf/rules.ipv4
Для автозагрузки правил при включении ОС, можно поместить скрипт в папку **/etc/network/if-pre-up.d/**, назвав его **iptables**, так же, рекомендуется сменить владельца на root и права доступа к файлу 700.
===== Команды =====
* **-F, --flush [цепочка]** - очистить все цепочки в таблице. **Не сбрасывает действие по умолчанию**. По умолчанию выбрана filter (-t для указания табл).
* **-A, --append цепочка правило** - добавление правила в конец цепочки.
* **-I, --insert цепочка [номер-правила] правило** - добавление правила в указанную позицию, №1 по умолчанию.
* **-D, --delete цепочка номер-правила** - удаление указанного правила из цепочки.\\ # iptables -D INPUT 1
* **-P, --policy цепочка цель** - стратегия для цепочки.\\ **Пример:** Действие по умолчанию # iptables -P INPUT DROP
* **-L, --list [цепочка]** - список правил.
* **-N, --new-chain [цепочка]** - создать новую цепочку.
* **-X, --delete-chain [цепочка]** - удалить пользовательскую цепочку.
* **-E, --rename-chain старое новое-имя** - переименовать пользовательскую цепочку.
==== Параметры ====
* **-v, --verbose** - увеличить подробность сообщений.
* **-n, -numeric** - ip-адреса и порты в числовом виде, без DNS.
* **--line-numbers** - номера строк (правил)
==== Расширения ====
* **-m multiport** - позволяет указывать перечень портов (так же, объединить перечень и диапазон)
* ** ** -
===== Критерии =====
В одном правиле можно указать несколько критериев, неявно объединяются логическим **AND**.\\
Многие критерии и параметры можно инвертировать, с помощью восклицательного знака **!** (! -s 127.0.0.1).\\
==== Универсальные критерии ====
* **-p, --protocol протокол** - например tcp, udp, icmp или all (по умолчанию, если не указано явно).
* **-s, --src, --source адрес[/маска]** - адрес (маска) отправителя. При указании нескольких адресов, через запятую, для каждого адреса создается отдельное правило.\\ **Пример:** (eth0 - интерфейс интернета) Из интернета не могут приходить пакеты с адресом из локальной сети. Защита от простейшего спуфинга. # iptables -I INPUT -i eth0 -s 192.168.0.0/16 -j DROP
* **-d, --dst, --destination адрес[/маска]** - адрес получателя (аналогично -s).
* **-i, --in-interface имя_интерфейса** - входящий сетевой интерфейс, если имя заканчивается знаком "+", то соответствуют все интерфейсы начинающиеся на указанное имя.
* **-o, --out-interface имя_интерфейса** - исходящий сетевой интерфейс (аналогично -i).\\ **Пример:** "Маскарадит" весь трафик с eth0.# iptables -t nat -I POSTROUTING -o eth0 -j MASQUERADE
==== Специфичные для протоколов ====
=== TCP ===
* **--sport, --source-port порт[:порт]** - исходящий порт (диапазон портов).\\ **Пример** Блокировать все исходящие соединения по системным портам (они обычно только слушаются службами). # iptables -I INPUT -m conntrack --ctstate NEW -p tcp --sport 0:1023 -j DROP
* **--dport, --destination-port порт[:порт]** - входящие порты (аналогично --sport).\\ **Пример** Разрешить входящие на 80й порт. # iptables -I INPUT -p tcp --dport 80 -j ACCEPT
* **--tcp-flags маска установленные_флаги** - позволяет указать список установленных и снятых TCP-флагов.\\ В "маске" перечисляются все проверяемые флаги (без пробелов), далее, после пробела, те из них, что должны быть установлены. => все остальные должны быть сняты.\\ Возможные флаги SYN, ACK, FIN, RST, URG, PSH (+ псевдо флаги ALL и NONE).\\ **Пример:** Заносим в лог все входящие SYN пакеты (установлен только SYN, остальные сняты) # iptables -I INPUT -p tcp --tcp-flags SYN,RST,ACK,FIN SYN -j LOG --log-level DEBUG --log-prefix "TCP SYN: "
* **--syn** - сокращение предыдущего примера.\\ **Пример:** Блокируем все попытки открыть TCP соединение не с SYN-пакета (возможно ошибка оборудования либо атака)\\ (PS хотя вопрос, понимает ли conntrack что это открытие соединения, не имея пакета SYN ? О_О) # iptables -I INPUT -m conntrack --ctstate NEW -p tcp ! --syn -j DROP
* **--tcp-option номер** - позволяет проверить, используется ли в заголовке TCP-пакета соответствующая опция. [[http://www.iana.org/assignments/tcp-parameters/tcp-parameters.xhtml|Перечень опций]].
**UDP** - (--sport, --dport)
=== IPv4 ===
* **-f, --fragment** - фрагменты пакета (у фрагментов нет заголовков транспортного уровня, номеров портов в т.ч.).\\ **Пример:** Блокирует фрагменты ICMP-пакетов, т.к. обычно они очень небольшие и нормально укладываются в один пакет, наличие их фрагментов - обычно ошибки или атака # iptables -I INPUT -p icmp -f -j DROP
* **addrtype** - позволяет проверить тип адреса источника (назначения) с точки зрения подсистемы маршрутизации сетевого стека ядра.
* **ecn** - позволяет проверять значения битов ECN в заголовках TCP и IPv4.
* **realm** - проверка области маршрутизации пакета.
* **ttl** - проверка поля TTL в заголовке.
=== ICMP ===
Протокол контрольных сообщений IPv4.\\
**--icmp-type тип** - проверка типа ICMP-пакета. Список возможных - iptables -p icmp -h.\\
**Пример:** Пропускать все входящие эхо-запросы.
# iptables -I INPUT -p icmp --icmp-type echo-request -j ACCEPT
==== Критерии состояния (conntack) ====
* **--ctstate маска** - маска содержит возможные состояния (NEW, ESTABLISHED, RELATED, INVALID, UNTRACKED, DNAT, SNAT). [[main:linux:kernel:firewall:conntrack|Описание есть тут]].\\ **Пример:** Разрешаем пакеты в уже установленных соединениях и связанных с ними # iptables -I INPUT -m conntrack --ctstate ESTABLISHED, RELATED -j ACCEPT
* **--ctstatus маска** - статус соединения в системе conntrack (EXPECTED, CONFIRMED, SEEN_REPLY, ASSURED, NONE). [[main:linux:kernel:firewall:conntrack|Описание есть тут]].
* **--ctdir {ORIGINAL|REPLY}** - направление пакетов (original - от инициатора, reply - от отвечающего), по умолчанию все.
* и т.д.
==== Лимитирующие критерии ====
Лимитирующие критерии предназначены главным образом для **ограничения доступа и защите от атак**, для ограничения и приоритезации трафика следует использовать **шейпер ядра**.
* **--limit количество[/second(minute,hour,day)]** - ограничение на кол-во пакетов, сверх - не удовлетворяют критерию. **"Скорость вытекания"**
* **--limit-burst кол-во** - задает длину очереди. **"Объем ведра"**\\ **Пример:** Оба параметра реализуют т.н. модель "дырявого ведра". У каждого такого правила своя очередь. Пакеты сверх очереди - не регистрируются и не удовлетворяют критерию. # iptables -I INPUT -m limit --limit 3/min --limit-burst 5 -j LOG --log-level debug
**Пример:** Ограничиваем скорость открытия новых соединений (32 в сек) # iptables -I INPUT -p tcp --dport 80 -m conntrack --ctstate NEW -m limit --limit 32/sec --limit-burst 32 -j ACCEPT
* **hashlimit** - позволяет применять аналогичные ограничения к группам хостов, подсетей или портов.
* **connlimit** - ограничение кол-ва одновременных соединений с IP-адреса или подсети.
* **connbytes** - ограничение кол-ва переданных байт или пакетов.
* **quota, quota2** - квота в байтах, для каждого правила.
* **length, length2** - размер пакета
===== Доп механизмы обработки =====
==== LOG ====
Позволяет вносить в протокол ядра записи о пакетах, для который указанная данная цель. Протокол ядра доступен по команде **dmesg**. **Не терминальная** цель.
* **--log-level уровень** - степень подробности (см syslog.conf(5)).
* **--log-prefix префикс** - префикс, для выделения записей.
* **--log-uid** - вносить ИД пользователя, которому принадлежит процесс, пославший пакет.
* **--log-tcp-option (--log-ip-option)** - вносить параметры заголовка tcp (ip).
==== REJECT ====
Тоже самое что и **DROP**, только позволяет отправить ответ запросившему хосту. (**--reject-with 'тип ошибки ICMP'**)
===== Критерий recent =====
Позволяет запоминать проходящие через него пакеты (кол-во, время, адреса, ttl) и использовать эту информацию для принятия решений.\\
Имеет ряд доп параметров, рассматривать их здесь не будем, приведем пару интересных примеров.
iptables -F INPUT # Очищаем цепочку INPUT
iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT # Разрешаем пакеты по установленным соединениям
# Если за последний час было 10 или более запросов на нерабочие порты — блокируем
iptables -A INPUT -m recent --rcheck --seconds 3600 --hitcount 10 --rttl -j RETURN
# Если за последнюю минуту было 2 или более запросов на нерабочие порты — блокируем
iptables -A INPUT -m recent --rcheck --seconds 60 --hitcount 2 --rttl -j RETURN
# Разрешаем рабочие порты
iptables -A INPUT -m conntrack --ctstate NEW -p tcp -m multiport --dport 21,25,53,80,110 -j ACCEPT
iptables -A INPUT -m conntrack --ctstate NEW -p udp -m multiport --dport 53,123 -j ACCEPT
# Всех, кто ломится в нерабочие порты — регистрируем
iptables -A INPUT -m recent --set
iptables -P INPUT DROP # Что не разрешено — то запрещено
# Создаем цепочку для проверки на необходимость удаления
iptables -N recent_remove
# Последнее обращение на неиспользуемые порты было менее суток назад
# поэтому оставим-ка пока этот адресок в черном списке
iptables -A recent_remove -m recent --rcheck --seconds 86400 -j RETURN
# Если адрес в есть в списке — удаляем его оттуда
iptables -A recent_remove -m recent --remove
# Вставляем эту проверку вторым правилом (сразу после проверки ctstate)
iptables -I INPUT 2 -j recent_remove
**Открытие порта "по стуку":**\\
Защищаемый порт открывается на 10 секунд после стука в заданный порт, более одного стука в этот порт или стук в соседние, считается ошибкой и сразу закрывает порт.
iptables -N ssh_knock # Создаем цепочку для проверки попыток соединений на защищаемый порт
# Если за последние 60 секунд было 2 и более стука — блокируем, на всякий случай
iptables -A ssh_knock -m recent --rcheck --seconds 60 --hitcount 2 -j RETURN
# Если за последние 10 секунд стук в нужный порт был — разрешить соединение
iptables -A ssh_knock -m recent --rcheck --seconds 10 -j ACCEPT
iptables -F INPUT # Очищаем цепочку INPUT
iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT # Разрешаем пакеты по установленным соединениям
# Все попытки открыть новое соединение по SSH направляем на проверку
iptables -A INPUT -m conntrack --ctstate NEW -p tcp --dport 22 -j ssh_knock
# Здесь мы добавляем правило для регистрации стука
iptables -A INPUT -m conntrack --ctstate NEW -p tcp --dport 27520 -m recent --set
# Опять же на всякий случай — при стуке в соседние порты закрываем SSH
iptables -A INPUT -m conntrack --ctstate NEW -p tcp -m multiport --dport 27519,27521 -m recent --remove
iptables -P INPUT DROP # Что не разрешено — то запрещено
iptables -N reset_knock # Цепочка для сброса процесса стука
iptables -A reset_knock -m recent --name PHASE1 --remove
iptables -A reset_knock -m recent --name PHASE2 --remove
iptables -A reset_knock -m recent --name PHASE3 --remove
iptables -A reset_knock -m recent --name PHASE4 --remove
iptables -N in_phase_2 # Создаем цепочку для фазы 2
iptables -A in_phase_2 -m recent --name PHASE1 --remove # Удаляем запись из списка первой фазы
iptables -A in_phase_2 -m recent --name PHASE2 --set # Добавляем ее в список второй фазы
iptables -N in_phase_3 # Создаем цепочку для фазы 3
iptables -A in_phase_3 -m recent --name PHASE2 --remove # Удаляем запись из списка второй фазы
iptables -A in_phase_3 -m recent --name PHASE3 --set # Добавляем ее в список третьей фазы
iptables -N in_phase_4 # Создаем цепочку для фазы 4
iptables -A in_phase_4 -m recent --name PHASE3 --remove # Удаляем запись из списка третьей фазы
iptables -A in_phase_4 -m recent --name PHASE4 --set # Добавляем ее в список четвертой фазы
iptables -N checked # Для записей, прошедших проверку
iptables -A checked -j reset_knock # Очищаем списки
iptables -A checked -j ACCEPT # Разрешаем пакет
iptables -F INPUT # Очищаем цепочку INPUT
iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT # Разрешаем пакеты по установленным соединениям
# Первая фаза
iptables -A INPUT -p tcp --dport 21210 -m recent --name PHASE1 --set -j RETURN
# Для тех, кто присутствует в списке первой фазы — переход во вторую
iptables -A INPUT -p tcp --dport 11992 -m recent --rcheck --name PHASE1 --seconds 5 -g in_phase_2
# И т.д.
iptables -A INPUT -p tcp --dport 16043 -m recent --rcheck --name PHASE2 --seconds 5 -g in_phase_3
iptables -A INPUT -p tcp --dport 23050 -m recent --rcheck --name PHASE3 --seconds 5 -g in_phase_4
# Если стучатся не в том порядке — сброс
iptables -A INPUT -p tcp -m multiport --dport 21210,11992,16043,23050 -j reset_knock
# Для тех, кто прошел все четыре фазы — разрешаем доступ
iptables -A INPUT -p tcp --dport 22 -m conntrack --ctstate NEW -m recent --rcheck --name PHASE4 --seconds 5 -j checked
iptables -P INPUT DROP # Дефолтное правило цепочки INPUT
Последовательный стук в серию портов можно организовать скриптом, использую утилиту **netcat**
for it in {21210,11992,16043,23050}; do
echo " " | nc -w 1 host $it
done
ssh user@host
===== Примеры =====
**Базовая настройка пустого сервера**. Исполняемый файл - **/etc/network/if-pre-up.d/iptables**, root:root-700
#!/bin/bash
iptables -F
iptables -P INPUT DROP
iptables -P FORWARD DROP
iptables -A INPUT -i lo -j ACCEPT
iptables -A INPUT -m conntrack --ctstate ESTABLISHED -j ACCEPT
iptables -A INPUT -p tcp --dport 22 -j ACCEPT
**Перенаправление всего трафика на другой IP** Софт (браузеры в т.ч.) быстро определяют примитивное перенаправление трафика и блокируют доступ
sysctl net.ipv4.ip_forward=1 # Разрешаем передавать транзитный трафик
iptables -t nat -A PREROUTING -j DNAT --to-destination
iptables -t nat -A POSTROUTING -j SNAT --to-source # Для обратной связи
# или
iptables -t nat -A POSTROUTING -j MASQUERADE # Скорее правильнее будет
**MASQUERADE**. Маскардинг локальной сети, на шлюзе.\\
На шлюзе 2 интерфейса, один из них (eth0) подключен к сети интернет, второй (eth1) к локальной сети. Обеспечение локальным хостам доступа в интернет:
sysctl net.ipv4.ip_forward=1 # Разрешаем шлюзу передавать транзитный трафик
iptables -F FORWARD # На всякий случай очистим цепочку FORWARD
# Разрешаем проходить пакетам по уже установленным соединениям
iptables -A FORWARD -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
# Разрешаем исходящие соединения из локальной сети к интернет-хостам
iptables -A FORWARD -m conntrack --ctstate NEW -i eth1 -s 192.168.1.0/24 -j ACCEPT
iptables -P FORWARD DROP # Весь остальной транзитный трафик — запрещаем.
iptables -t nat -F POSTROUTING # На всякий случай очистим цепочку POSTROUTING таблицы nat
# Маскарадим весь трафик, идущий через eth0
iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
PS. Если имеется статический IP адрес шлюза, целесообразнее использовать **SNAT**, тогда он (адрес) не будет вычисляться каждый раз заново. Тогда в последней строке нужно указать: **"iptables -t nat -A POSTROUTING -o eth0 -j SNAT --to-source `address`[-`address`]"**
Правила NAT\\
# Перечень
iptables -t nat -L -v
# Добавление
iptables -t nat -A POSTROUTING -p udp -o tun1 -j SNAT --to-source 10.200.199.24 (на какой адрес отправлять/или с какого)
iptables -A POSTROUTING -s 192.168.0.0/24 -o eth1 -j SNAT —to-source 10.188.106.33
# Удаление
iptables -D -t nat POSTROUTING 13