Шпаргалка по iptables

2023.02.22
Краткая шпаргалка по утилите iptables, ее таблице по умолчанию filter и как вообще с этим работать не ломая голову и сеть

Возможно, это не законченный вариант статьи. Шпаргалка будет обновляться, по мере того как я буду узнавать что-то новое или находить ошибки.

Что это и для чего?

Iptables - утилита командной строки для управления брандмауэром netfilter ядра Linux >=2.4.

В книге "Unix и Linux Руководство системного администратора" дается следующее описание iptables:

Утилита iptables применяет к сетевым пакетам упорядоченные цепочки правил. Наборы цепочек образуют таблицы и используются для обработки определенных видов трафика.

По умолчанию используется таблица filter. Цепочки правил в этой таблице используются для пакетной фильтрации сетевого трафика

Ручная настройка, особенно впервые, вызывает значительные затруднения, авторы указанной книги этого не отрицают.

Терминология

iptables включает следующие таблицы:

Рассматривать мы будем именно filter, которая является таблицей по умолчанию для всех команд утилиты iptables, если иное не сказано явно.

Цепочка - это упорядоченный набор правил.

Цепочки бывают базовые/встроенные и пользовательские (можно создать самому).

К базовым цепочкам относятся:

В новую цепочку можно направлять пакеты чтобы подвергуть их анализу правил. Например для отладки правил или настройки особого движения пакетов как это сделано в Docker.

Правило - состоит из условия/критерия (если нет значит применяется ко всему трафику) действия (может не быть) и счетчика (для учета пакетов попавших под правило).

Условия:

Действия:

Работа с iptables

Правила iptables действуют до перезагрузки системы, так что если было сделано что-то не так, можно перезагрузить машину и правила iptables будут сброшены.

Просмотр

Справка вызывается стандартно:

$ sudo iptables -h

А так можно просмотреть таблицу filter в табличном виде со статистикой и нумерацией правил:

$ sudo iptables -vnL --line-numbers

Просмотр таблицы filter в iptables

Это скриншот правил таблицы filter для vpn сервера, здесь видно что:

Также можно распечатать правила:

$ sudo iptables -S

Вывод:

-P INPUT DROP
-P FORWARD DROP
-P OUTPUT ACCEPT
-A INPUT -p udp -m udp --dport 1194 -j ACCEPT
-A INPUT -i tun+ -j ACCEPT
-A INPUT -p udp -m udp --dport 53 -j ACCEPT
-A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
-A FORWARD -i tun+ -j ACCEPT
-A FORWARD -m state --state RELATED,ESTABLISHED -j ACCEPT

Управление правилами и цепочками

Добавить правило (разрешить весь трафик с tun интерфейсов) в конец цепочки INPUT (-A, --append):

$ sudo iptables -A INPUT -i tun+ -j ACCEPT

Вставить правило в позицию 2 цепочки INPUT (-I, --insert):

$ sudo iptables -I INPUT 2 -i lo -j ACCEPT

Установить политику по умолчанию DROP для цепочки INPUT (-P, --policy):

$ sudo iptables -P INPUT DROP

Создание новой цепочки правил:

$ sudo iptables -N LOGGING

Примеры

Предположим что для цепочки INPUT политика по умолчанию DROP, это значит что все входящие пакеты будут отброшены, но нам нужен некоторый входящий трафик.

Разрешим трафик на локальный DNS сервер, без этого могут быть долгие подключения по ssh:

$ sudo iptables -A INPUT -p udp -m udp --dport 53 -j ACCEPT

Разрешим движение трафика из интерфейсов создаваемых Docker (при политиках по умолчанию DROP, контейнеры не смогут общаться с другими интерфейсами):

$ sudo iptables -A INPUT -i br+ -j ACCEPT

Разрешим любой входящий трафик из localhost и откроем http/https порты (80/443), например для случая когда у нас есть веб-сервер и наши сайты должны быть доступны снаружи:

$ sudo iptables -A INPUT -i lo -j ACCEPT
$ sudo iptables -A INPUT -p tcp --dport 80 -j ACCEPT
$ sudo iptables -A INPUT -p tcp --dport 443 -j ACCEPT

Если не разрешить входящий трафик от localhost то могу быть странные задержки с ответами, а при дебаге можно увидеть отклоенные пакеты от 127.0.0.1

Теперь локальный DNS на 53 порту доступен, docker контейнеры тоже, с localhost трафик разрешен, и для внешнего мира открыты 80 и 443 порты для наших сайтов. Но это все только для установления соединения и рукопожатия. Теперь нам нужно разрешить все установленные и связанные с ними соединения чтобы трафик действительно пошел (еще вот):

$ sudo iptables -A FORWARD -m state --state RELATED,ESTABLISHED -j ACCEPT

Сброс всех правил таблицы filter

# удаление всех цепочек
$ sudo iptables -F

# разрешение всего входящего трафика
$ sudo iptables -P INPUT ACCEPT

# разрешение перенаправление трафика
$ sudo iptables -P FORWARD ACCEPT

# разрешение всего исходящего трафика
$ sudo iptables -P OUTPUT ACCEPT

Отладка

Логирование отклоненных пакетов

Полезно иметь возможно отладить свои правила, экономия времени и iptables становится понятнее.

Суть отладки правил iptables такова:

Создание новой цепочки:

$ sudo iptables -N LOGGING

Добавляем правило логирования каждого пакета с префиксом:

$ sudo iptables -A LOGGING -j LOG --log-prefix  "ipt denied: "

Отклоняем пакет:

$ sudo iptables -A LOGGING -j DROP

В цепочку, откуда будут приходить пакеты для отклонения добавляем новое правило перенаправления в новую цепочку логирования:

$ sudo iptables -A INPUT -j LOGGING

Теперь добавим конфиг rsyslog:

$ sudo nano /etc/rsyslog.d/10-iptables.conf

Вставим следующий текст:

:msg, contains, "ipt denied: " -/var/log/iptables.log
& ~

Сохраним и перезагрузим демона rsyslog:

$ sudo service rsyslog restart

Теперь откроем файл и будем следить за 20 последних строк:

$ sudo echo > /var/log/iptables.log
$ sudo tail -f -n 20 /var/log/iptables.log

Можно наблюдать что-то такое:

Feb 19 17:43:36 logic kernel: [14331.939805] ipt denied: IN=lo OUT= MAC=00:00:00:00:00:00:00:00:00:00:00:00:08:00 SRC=127.0.0.1 DST=127.0.0.1 LEN=60 TOS=0x00 PREC=0x00 TTL=64 ID=20640 DF PROTO=TCP SPT=49104 DPT=6000 WINDOW=65495 RES=0x00 SYN URGP=0 
Feb 19 17:43:44 logic kernel: [14340.132036] ipt denied: IN=lo OUT= MAC=00:00:00:00:00:00:00:00:00:00:00:00:08:00 SRC=127.0.0.1 DST=127.0.0.1 LEN=60 TOS=0x00 PREC=0x00 TTL=64 ID=20641 DF PROTO=TCP SPT=49104 DPT=6000 WINDOW=65495 RES=0x00 SYN URGP=0 
Feb 19 17:43:46 logic kernel: [14342.030775] ipt denied: IN=ens3 OUT= MAC=52:54:00:10:23:3f:4c:96:14:68:fb:f0:08:00 SRC=78.155.213.173 DST=185.105.90.67 LEN=40 TOS=0x00 PREC=0x00 TTL=250 ID=8008 PROTO=TCP SPT=57587 DPT=54402 WINDOW=1024 RES=0x00 SYN URGP=0 
Feb 19 17:43:52 logic kernel: [14348.160719] ipt denied: IN=ens3 OUT= MAC=52:54:00:10:23:3f:4c:96:14:68:fb:f0:08:00 SRC=89.248.165.209 DST=185.105.90.67 LEN=40 TOS=0x00 PREC=0x00 TTL=248 ID=63021 PROTO=TCP SPT=49784 DPT=23988 WINDOW=1024 RES=0x00 SYN URGP=0 

Сохранение

При перезагрузке системы правила iptables будут сброшены.

Чтобы происходило восстановление сохраненных правил нужен пакет iptables-persistent:

$ sudo apt install iptables-persistent

Необходимо проверить работает ли демон systemd:

$ sudo systemctl status netfilter-persistent

Если нет, его нужно запустить:

$ sudo systemctl start netfilter-persistent

После настройки и отладки правил iptables нужно сохранить их в файл /etc/iptables/rules.v4 чтобы при старте системы демон netfilter-persistent загрузил их в iptables.

Сохранение правил iptables в файл:

$ sudo iptables-save > /etc/iptables/rules.v4

Теперь правила должны загружаться после перезагрузки системы.

Для ручной загрузки правил правил из файла в iptables можно сделать так:

$ sudo iptables-restore < /etc/iptables/rules.v4

Литература

Эта шпаргалка не получилась бы без сторонних источников откуда я черпал информацию для изучения. Здесь я узнал про сохранение правил iptables, а в этом руководстве почерпнул много теории (и здесь). На некоторые вопросы дал ответы этот топик, а про локальный dns узнал здесь. Отладку взял отсюда, а доделать правила для vpn помог этот топик.

В телеграм канале DevOps от первого лица можно оставить комментарий или почитать интересные истории из практики DevOps