====== 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