В статье рассмотрена настройка простого забора-файервола (firewall) вокруг сервера при помощи стандартной для ОС Linux утилиты (драйвера?) iptables. Этот файервол защитит сервер от базовых атак (вроде SYN-флуда и пакетов сканирования) и оставит открытыми только те порты, которые непосредственно используются. Так же эта статья — заметка из разряда «что бы не забыть», так как подобные операции приходится проводить заново время от времени.

Это, разумеется, далеко не исчерпывающее руководство по защите сервера. Оно покажет, как заблокировать разведывательные пакеты (так называемые recon packets) и оставить открытыми только нужные порты: для веб-сервера, SSH, FTP. При этом не блокируя весь исходящий трафик и соединения, инициированные со стороны сервера. Будут использованы лишь несколько самых общих правил, отрезающих сканирование системы на открытые порты, кулхацкеров и ботов, которые ищут уязвимые сервера. Однако, по крайней мере такая базовая защита должна в обязательном порядке присутствовать на любом открытом вовне сервере.

iptables — простой файервол (или «брандмауэр», кому как нравится), установленный на большинстве Linux-систем. Инструкция для iptables говорит о том, что это «инструмент администрирования фильтра пакетов IPv4 и NAT», то есть это инструмент для фильтрации и блокирования интернет-трафика. Данный инструмент, как я уже сказал, включён в большинство Linux систем, в том числе в популярные Debian и CentOS, и настраивается во всех системах абсолютно идентично.

Файервол работает на основе списка достаточно простых «правил», которые он проходит при поступлении нового пакета. Если пакет не выбрасывается ни одним из них, пакет проходит дальше, внутрь системы к нужному сервису или вовне к адресату. Именно набор этих правил и будет рассмотрен ниже.

Важное замечание. Эта заметка рассматривает только работу сети по протоколу IPv4. iptables работает именно с этим протоколом. Если на сервере установлен действующий интерфейс IPv6, то необходимо провести аналогичные действия для него с помощью зеркальной утилиты ip6tables. Если сервер работает с обоими типами сетей, важно защитить оба канала связи.

Определение необходимых для работы портов

Во-первых, прежде всего, необходимо определить, какие именно публичные сервисы будут работать на сервере и какие серверные порты они используют. Для веб-серверов это, обычно: собственно, программа веб-сервера, FTP и SSH (secure shell), по которому осуществляется наше администрирование (и эта настройка).

Прежде и важнее всего служба SSH, без неё невозможно удалённое управление сервером вообще, её порт — 22. Веб-сервер производит приём запросов на порте 80 и 443 (если есть сайты с SSL, это порт HTTPS). Служба FTP-сервера использует порт 22.

Замечание. Если на вашем сервере находится почтовый домен с почтовыми службами, кроме прочего необходимо открыть порты SMTP и POP3/IMAP. Для того, что бы пользователи могли отправлять email’ы необходимо открыть порт 25 (обычный SMTP) и 465 (защищённый SMTP). Для получения почты пользователями по протоколу POP3 необходимо открыть порт 110 (обычный POP3) и 995 (защищённый POP3). Для протокола IMAP — порт 143 и 993 (IMAP over SSL).

Блокирование распространённых атак

Замечание. Все дальнейшие действия должны быть выполнены от пользователя root.

По-умолчанию, все сервера идут с конфигурацией «всё разрешено». Что бы посмотреть список текущих действующих правил, необходимо выполнить:

iptables -L

Если текущие правила отсутствуют, вы увидите три пустых списка для трёх цепей: INPUT (входящие пакеты), OUTPUT (исходящие пакеты) и FORWARD (перенаправление пакетов) с политикой ACCEPT (приём/разрешено) для всех трёх. В конце настройки мы изменим политику для входящей цепи так, что по-умолчанию она будет не пропускать, а сбрасывать пакеты, если не указано иное.

Замечание. Есть два способа отразить пакет — сбросить его (DROP) и отклонить (REJECT). Разница в том, что в первом случае, при сбросе, пакет будет тихо выкинут, как будто его не было. Во втором случае, при отклонении, файервол уведомит отправителя пакета о том, что пакет был отвергнут. В подавляющем большинстве случаев много предпочтительней именно сброс пакета. Не только потому, что это накладывает в разы меньше расходов, но и для предотвращения потенциального участия сервера в зеркальной атаке, когда злоумышленник заставляет ваш сервер отвечать атакуемой машине (при помощи IP-спуфинга), создавая фиктивный трафик.

Далее мы сразу заблокируем несколько типов простейших и распространённых атак. Конечно, это не сможет защитить от полноценной DDoS-атаки, однако уже существенно поднимет безопасность сервера. В том числе, это отрежет сканирующих ботов, которые ищут уязвимые сервера для дальнейшего поиска дыр в безопасности. Прежде всего, блокируем null-пакеты.

iptables -A INPUT -p tcp --tcp-flags ALL NONE -j DROP

Это правило файервола дословно означает: «во входящей цепи (-A INPUT) по протоколу TCP (-p tcp) пакеты со всеми отсутствующими (NONE) флагами (--tcp-flags ALL) сбросить (-j DROP)». Ноль-пакеты заведомо не несут никакой смысловой нагрузки и нужны для проверки портов. Следующее правило блокирует атаки SYN-флуда.

iptables -A INPUT -p tcp ! --syn -m state NEW -j DROP

SYN-флуд — тип DoS-атаки, при которой атакующий открывает соединения, но далее не происходит ничего, соединение остаётся висеть, а атакующие открывают всё новые и новые. Таким образом не только впустую тратятся ресурсы сервера, но и забиваются очереди соединений, что приводит к отказу в обслуживании легитимных клиентов (это и есть DoS — «denial of service»). Теперь мы отсеиваем такие пакеты. Следующим правилом мы отсеем ещё один популярный тип сканирующих пакетов — XMAS пакеты.

iptables -A INPUT -p tcp --tcp-flags ALL ALL -j DROP

Таким образом, мы отфильтровали несколько распространённых типов простых разведывательных атак. Следующим шагом мы закроем заведомо-фиктивные пакеты. Например, пакеты, в которых одновременно установлены флаги SYN и FIN, или SYN и RST. Также пакеты, приходящие с некорректных IP-адресов и, якобы, с локального интерфейса: это верный признак атаки IP-спуфинга (подделки заголовка пакета).

iptables -A INPUT -p tcp --tcp-flags SYN,FIN SYN,FIN -j DROP
iptables -A INPUT -p tcp --tcp-flags SYN,RST SYN,RST -j DROP
iptables -A INPUT -s 169.254.0.0/16 -j DROP
iptables -A INPUT -s 172.16.0.0/16 -j DROP
iptables -A INPUT -s 192.0.2.0/24 -j DROP
iptables -A INPUT -s 192.168.0.0/16 -j DROP
iptables -A INPUT -s 10.0.0.0/8 -j DROP
iptables -A INPUT -s 127.0.0.0/8 -j DROP

Открытие портов выбранных служб

Теперь необходимо добавить к табелю правил разрешающие — для публичных служб, что бы они могли функционировать и сервер не превратился в чёрный ящик. Прежде всего, добавляем разрешающее правило для локального интерфейса.

iptables -A INPUT -i lo -j ACCEPT

Это правило разрешает (ACCEPT) весь трафик с локального интерфейса (lo). Локальный трафик (внутри сервера) очень часто используется для связи между разными службами на одной машине. Далее, открываем TCP порт SSH (21), FTP (22), веб-сервера (80 и 443).

iptables -A INPUT -p tcp -m tcp --dport 21 -j ACCEPT
iptables -A INPUT -p tcp -m tcp --dport 22 -j ACCEPT
iptables -A INPUT -p tcp -m tcp --dport 80 -j ACCEPT
iptables -A INPUT -p tcp -m tcp --dport 443 -j ACCEPT

Можно так же открыть другие необходимые порты, если установлен другой набор служб.

Разрешение исходящих соединений

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

Мы привыкли к тому, что у всех TCP-служб (например, у веб-сервера) есть свой определённый порт, например, 80. Представляется, что этот порт — единственное, что нужно для работы. На самом деле это не так. Этот порт — лишь порт так называемого прослушивающего сокета (listening socket), который принимает новые соединения. После установки соединения для дальнейшего обмена на сервере и клиенте выбираются два случайных порта (обычно числом больше 40000) и уже между ними производится обмен самими данными.

Если мы оставим текущую конфигурацию файервола как есть, сервер будет принимать новые соединения, но в большинстве случаев не сможет ни с кем общаться. Поэтому, необходимо добавить ещё одно правило, которое разрешает соединения в состоянии ESTABLISHED и RELATED (что означает, что соединение новое, но связано с другим установленным соединением).

iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT

Финальным штрихом разрешаем все исходящие соединения и закрываем все входящие: устанавливаем для них политику сброса по-умолчанию. Если для пакета не будет найдено разрешающее правило, он будет сброшен.

iptables -P OUTPUT ACCEPT
iptables -P INPUT DROP

После ввода и исполнения последнего правила в терминале система начала работать.

Сохранение конфигурации

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

iptables -L -n

Задание ключа -n в данной команде приводит к тому, что в выводе команды мы видим числовую конкретику, а не доменные имена и текстовые обозначения портов.

Остался последний нюанс: все заданные правила, если они явно не будут сохранены и так же явно не загружены будут сброшены после первого перезапуска iptables или системы. Для удобного сохранения и загрузки таблицы правил предусмотрены утилиты iptables-save и iptables-restore. Далее, пути дальнейшего сохранения и автовосстановления правил различаются для Debian и CentOS (и, возможно, для других дистрибутивов).

Сохранение конфигурации на CentOS

Сохраним конфигурацию при помощи утилиты в файл.

iptables-save > /etc/sysconfig/iptables

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

service iptables restart

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

Сохранение конфигурации в Debian

В операционных системах Debian сохранение конфигурации файервола чуть сложнее, так как тут нет заготовленного файла для сохранения конфигурации. Придётся создать его самостоятельно. Пусть это будет, например, файл /etc/iptables.up.rules.

iptables-save > /etc/iptables.up.rules

Правила сохранены, теперь необходимо сделать так, что бы они автоматически загружались при старте сервиса iptables. Для этого создадим скрипт загрузки в директории автозагрузки сетевого интерфейса /etc/network/if-pre-up.d/iptables с нижеследующим содержимым.

#!/bin/sh
/sbin/iptables-restore < /etc/iptables.up.rules

И зададим этому скрипту права выполнения +x.

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

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

Заключение

Эта статья, конечно, не является исчерпывающей инструкцией по защите сервера от атак. Более того, многие опытные администраторы применяют более изощрённые правила, например, «умного» детектирования атаки сканирования портов или проброс VPN. К сожалению, iptables работает на довольно низком уровне, что обеспечивает ему скорость, однако сильно ограничивает функционал. Многие атаки могут быть распознаны только на уровне приложения.

При всём этом, рассмотренный набор базовых правил даёт неплохой начальный уровень безопасности для нового сервера.

comments powered by HyperComments