iptables

iptables

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 — все прочие пакеты.

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

Ниже приводится листинг разрешительной (не такой жёсткой как запретительная) политики настройки iptables, а также пример оптимизации настроек sysctl. В результате будет ограничено количество одновременных подключений с одного ip адреса на порт веб-сервера, сервера DNS, а также ограничено количество подключений к службе ssh (3 подключения за 5 минут с одного ip-адреса). Будет реализована защита от спуфинга на уровне файрвола, а также на уровне ядра.

# БОРЬБА С DDOS
 
iptables -N ssh_brute_check # Создаем цепочку для проверки попыток соединений на защищаемый порт
# Если за последние 5 минут (300 секунд) с одного адреса было 3 или более новых соединений — блокируем этот адрес
iptables -A ssh_brute_check -m conntrack --ctstate NEW -m recent --update --seconds 300 --hitcount 3 -j DROP
# В противном случае — разрешаем, и при этом заносим в список
iptables -A ssh_brute_check -m recent --set -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_brute_check
# Здесь можно разрешать те порты, для которых такая проверка не нужна. Например, HTTP
iptables -A INPUT -m conntrack --ctstate NEW -p tcp --dport 80 -j ACCEPT
iptables -P INPUT ACCEPT
 
 
# позволяет узнать сколько одновременных подключений на порт с 1 айпи
# netstat -plan | grep :80 | awk '{print $5}' | awk -F: '{print $1}' | sort | uniq -c
# netstat -ntu | awk '{print $5}' | cut -d: -f1 | sort | uniq -c | sort -n
 
# устанавливаем максимальное количество подключений с одного айпи.
# В браузерах эта количество подключений к серверу ограничено 16 соединениями,
# но стоит учитывать тех, кто сидит за NAT, а также что пользователь
# может открыть 2 сайта на разных айпишниках одного и того же сервера.
# Данный параметр подбирается оптимально с помощью предыдущей команды.
iptables -A INPUT -p tcp --dport 80 -m connlimit --connlimit-above 32 -j DROP
iptables -A INPUT -p tcp --dport 80 -j ACCEPT
# то же для DNS
iptables -A INPUT -p udp --dport 53 -m connlimit --connlimit-above 8 -j DROP
iptables -A INPUT -p udp --dport 53 -j ACCEPT
 
# будет препятствовать спуфингу от нашего имени.
# Ведь если мы получаем пакет с установленными флагами SYN и ACK
# (такой комбинацией флагов обладает только ответ на SYN-пакет) по еще не открытому соединению,
# это означает, что кто-то послал другому хосту SYN-пакет от нашего имени, и ответ пришел к нам.
# Конечно, злоумышленнику предстоит еще угадать номер последовательности.
# Согласно приведенному правилу, наш хост ответит RST-пакетом, после получения которого
# атакуемый хост закроет соединение.
iptables -I INPUT -m conntrack --ctstate NEW,INVALID -p tcp --tcp-flags SYN,ACK SYN,ACK -j REJECT --reject-with tcp-reset
 
# Для защиты от SYN атак включаем SYN-cookies
sysctl -w net.ipv4.tcp_syncookies=1
# Увеличиваем размер очереди полуоткрытых соединений (также полезно при SYN флуде) (default 512)
sysctl -w net.ipv4.tcp_max_syn_backlog=4096
# Проверять TCP-соединение каждую минуту. Если на другой стороне - легальная машина, 
# она сразу ответит. Дефолтовое значение - 2 часа.
sysctl -w net.ipv4.tcp_keepalive_time=60
# Повторить пробу через десять секунд
sysctl -w net.ipv4.tcp_keepalive_intvl=10
# Количество проверок перед закрытием соединения
sysctl -w net.ipv4.tcp_keepalive_probes=5
# Фильтр обратного пути, защита от спуфинга (подмены адресов)
sysctl -w net.ipv4.conf.default.rp_filter=1
# Уменьшение времени удержания «полуоткрытых» соединений
# Сделаем так, чтобы перепередача осуществлялась на 3 секунде
# и  полное время хранения полуоткрытых соединений в очереди составило 9 секунд
sysctl -w net.ipv4.tcp_synack_retries=1
# Изменяем время ожидания приема FIN до полного закрытия сокета
sysctl -w net.ipv4.tcp_fin_timeout=10

< Назад к списку новостей