no-style

iptables [установка + теория + практика]


Вступление

Данный пост покажет как быстро и просто можно защитить свой сервер с помощью фаервола iptables.

Хочу сразу предупредить всех читателей, что действия из данного поста вы выполняете на свой страх и риск. Я не несу никакой ответственности за ваши действия.

А тех кто захочет выполнить написанное взываю быть очень внимательными, т.к. вы например можете запросто отрезать себя от ssh в 1 команду если будете не внимательны и потом придётся выкручиваться.







iptables vs nftables

До недавних пор iptables был по стандарту уже установлен по умолчанию в большинстве дистрибутивов.

Время не стоит на месте. И вот уже в некоторых дистрибутивах можно не обнаружить iptables. Вместо него предлагают использовать Nftables. К сожалению информации по Nftables не так много, а защищать сервер надо уже сейчас.

Как по мне iptables обладает более понятным синтаксисом чем nftables. Именно поэтому мы вернём старый надёжный фаервол в систему. Опишу процесс для debian подобных ос.

Приступаем. Подключаемся к нашему серверу по ssh.

Удаляем Nftables шаг 1

sudo apt-get remove --auto-remove nftables

Удаляем Nftables шаг 2

sudo apt-get purge nftables

Обновляемся

sudo apt update

Устанавливаем iptables

sudo apt-get install iptables






iptables chains

В фаерволе iptables пакеты ходят по цепочкам chain. В свою очередь эти цепочки расположены в специальных таблицах Table.

Всего имеется 3 таблицы:

    filter Table [ sudo iptables -t filter -L ]
  • INPUT chain (входящий трафик)
  • OUTPUT chain (исходящий трафик)
  • FORWARD chain (транзитный трафик)

    nat Table [ sudo iptables -t nat -L ]
  • OUTPUT chain
  • PREROUTING chain
  • POSTROUTING chain

    mangle Table [ sudo iptables -t mangle -L ]
  • INPUT chain
  • OUTPUT chain
  • FORWARD chain
  • PREROUTING chain
  • POSTROUTING chain

В рамках данного поста мы будем рассматривать стандартную таблицу Filter. И 2 её цепочки

INPUT - которая отвечает за входящий трафик. И цепочку OUTPUT, которая отвечает за исходящий трафик.







Политика по умолчанию

Так же стоит поговорить про политику по умолчанию, она же default policy. Для этого посмотрим на наши правила

sudo iptables -L -v
iptables basic block clean rules

На скриншоте видно что для всех трёх цепочек INPUT, OUTPUT и FORWARD политика по умолчанию стоит ACCEPT. Это означает что правила в цепочках работают по принципу разрешено всё что не запрещёно.

В случае если политика по умолчанию была бы DROP это бы означало что запрещено всё, кроме того что разрешено.

Политика по умолчанию применяется для каждой цепочки отдельно. Например вот так:

sudo iptables -P INPUT DROP

Данная политика означает что все входящие подключения запрещены. Внимание! Перед тем как применять данную политику, необходимо добавить разрешающее правило для SSH для вашего ip. Если вы этого не сделать, то вас отрежет от сессии SSH и вы не сможете зайти на свой сервер до тех пор пока не перезагрузите его!


Ещё пример

sudo iptables -P OUTPUT ACCEPT

Данная политика означает что все исходящие подключения разрешены. Разумеется если добавите какое то правило которое запрещает какое то исходящее подключение то оно будет заблокировано.







Добавляем правила в iptables

Итак, мы дошли до самого интересного, от теории к практике. Существует несколько способов что то разрешить или запретить.

Следующим правилом мы разрешим все новые и установленные входящие подключения для 22 порта(он же SSH). Для ip адреса xxx.xxx.xxx.xxx/32

sudo iptables -A INPUT -p tcp -s xxx.xxx.xxx.xxx/32 --dport 22 -m conntrack --ctstate NEW,ESTABLISHED -j ACCEPT

Обратите внимание подсеть /32 = 1 ip адрес тут разрешаем только для себя.



Можно немного ускорить предыдущее правило добавив уточнение что блокировать нужно входящий трафик нужно для интерфейса eth0

sudo iptables -A INPUT -i eth0 -p tcp -s xxx.xxx.xxx.xxx/16 --dport 22 -m conntrack --ctstate NEW,ESTABLISHED -j ACCEPT

Обратите внимание подсеть /16 = 65536 ip адресов тут разрешаем уже для большего количества адресов, например сети провайдера



Во время общения сервера и клиента у пакетов есть статус, новые NEW установленные ESTABLISHED и связанные RELATED. Так как правила в фаерволе Iptables читаются сверху-вниз то имеет смысл добавить в самый верх специальное правило, которое будет пропускать пакеты уже установленных соединений, не идя дальше по списку. С помощью этого правила будут экономиться ресурсы сервера, потому что он не будет совершать лишние телодвижения.

sudo iptables -A INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT


Разрешаем входящие соединения для интерфейса lo ( обязательное правило )

sudo iptables -A INPUT -i lo -j ACCEPT


Теперь, когда мы добавили правило разрешающее нам доступ к SSH, мы можем поменять политику по умолчанию для таблицы input на DROP.

Данное правило запрещает всё что не разрешено для таблицы INPUT. !!! Перед этим правилом обязательно применить те правила что выше !!!

sudo iptables -P INPUT DROP


Следующим правилом разрешаем входящий трафик на 80 и 443 порт. То есть разрешаем входящий трафик на http и https для вашего веб сервера.

sudo iptables -A INPUT -p tcp -m multiport --dports 80,443 -m conntrack --ctstate NEW,ESTABLISHED -j ACCEPT


Разрешаем входящий пинг на наш сервер

sudo iptables -A INPUT -p icmp -j ACCEPT


Разрешаем исходящий DNS трафик

sudo iptables -A OUTPUT -p udp --dport 53 -j ACCEPT


А что если нужно открыть сразу несколько портов для протокола TCP для одного ip? Например с 41001 порта по 41500 порт

sudo iptables -A INPUT -i eth0 -s xxx.xxx.xxx.xxx/32 -m multiport -p tcp --dports 41001:41500 -j ACCEPT


Тоже самое для протокола UDP

sudo iptables -A INPUT -i eth0 -s xxx.xxx.xxx.xxx/32 -m multiport -p udp --dports 41001:41500 -j ACCEPT


Тут пожалуй стоит ещё добавить что сами правила могут быть добавлены двумя способами

sudo iptables -A ...

-A сокращение от Append и означает что правило будет добавлено последовательно в самый низ после всех остальных правил.

Либо

sudo iptables -I ...

-I сокращение от Insert и означает что правило будет добавлено в самый верх перех всеми остальными правилами.


Почему это так важно? Дело в том что принцип по которому работает Iptables - first match win. Что означает что фаервол будет идти последовательно по всем правилам сверху - вниз, до тех пор пока не найдёт совпадение. Поэтому лучше ставьте более важные правила выше.

Также следуйте правилу: generic правила, те в которых нет явного уточнения, например sudo iptables -A INPUT -i lo -j ACCEPT следует помещать ниже статичных правил. Статичные правила отличаются тем что там явно прописан ip либо порт.







Удаляем правила из iptables

Самый простой вариант удалить правила по номеру. Для этого сначала отображаем все правила вместе с их порядковым номером

sudo iptables -L -n --line-numbers

Находим номер правила которое хотим удалить. Номер находится в самом первом столбце. И удаляем это правило при помощи такой логики

sudo iptables [-t таблица] -D цепочка номер_правила

Например

sudo iptables -t filter -D INPUT 2

Удалит правило №2 в таблице filter цепочки INPUT



Альтернативный способ удаления правил - по действию. Грубо говоря надо ввести кусок того что делает правило. Логика тут такая

sudo iptables [-t таблица] -D цепочка спецификации_правила

К спецификациям правила может относится IP адрес отправителя либо другие параметры правила, которые явно его определяют (порт, IP адрес назначения, протокол и др.) и выполняемое действие, например, -j ACCEPT.

Например

sudo iptables -t filter -D INPUT -s 192.168.10.0/24 -j ACCEPT






Очистка счётчиков цепочек

Если вы хотите обнулять не сами правила iptables, а только их счётчики то это делается очень просто.

Чтобы очистить счетчики для всех цепочек и правил, используйте опцию -Z отдельно:

sudo iptables --zero

Чтобы очистить счетчики для всех правил конкретной цепочки, используйте опцию -Z и укажите название цепочки:

sudo iptables --zero INPUT

Если вы хотите очистить счетчики для конкретного правила, укажите имя цепочки и номер правила. Например, для обнуления счетчиков первого правила в цепочке INPUT:

sudo iptables --zero INPUT 1






Полная очистка цепочек

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

Меняем стандартную политику для основных цепей на ACCEPT таким образом мы разрешаем весь трафик туда и обратно

sudo iptables -P INPUT ACCEPT
sudo iptables -P FORWARD ACCEPT
sudo iptables -P OUTPUT ACCEPT

Сбрасываем цепочки nat и mangle, а так же сбрасываем все остальные цепочки (-F сокращение от --flush)

sudo iptables -t nat -F
sudo iptables -t mangle -F
sudo iptables -F

Удаляем все цепочки, не используемые по умолчанию

sudo iptables -X






Сохранение и загрузка правил iptables

Ещё раз посмотрим наши правила с помощью

sudo iptables -L -v
iptables basic block added rules

На данный момент правила живут до того как мы не перезагрузим сервер

Первым делом создаём специальную директорию

sudo mkdir -p /scripts/iptables

Делаем текущего юзера (желательно не root) владельцем этой директории

sudo chown -R $USER:$USER /scripts/iptables

Сохраняем все наши правила в эту директорию

sudo iptables-save > /scripts/iptables/iptables-rules

Теперь же мы хотим чтобы все правила грузились при старте системы, поэтому создадим специальный скрипт

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

С таким содержанием

#!/bin/sh

iptables-restore < /scripts/iptables/iptables-rules
exit 0

и обязательно делаем этот скрипт исполняемым

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

Теперь после перезагрузки все наши правила останутся.



В дополнение можно скачать мой скрипт с правилами iptables в ту же самую папку

wget -P /scripts/iptables https://raw.githubusercontent.com/killarbyte/killarbyte-ab-stuff/main/scripts/posts/iptables/iptables.sh

Сделать его исполняемым

chmod +x /scripts/iptables/iptables.sh

Внимательно его изучить и запустить

sudo ./iptables.sh

На этом всё.

Комментарии