Простой Firewall для сервера на основе Linux IPTABLES + скрипт автостарта
Описана реализация простого и в то же время надежного скрипта-файрвола (firewall) для защиты сервера от подключений к критичным приложениям снаружи. Предложенный скрипт подойдет для базовой защиты сервера на Linux, а также может быть использован как основа для построения более сложного файрвола.
Содержание:
Зачем это нужно
Ничего сверхнового не изобретал, суть задачи проста:
- закрыть определенные порты от подключений для наружного(internet) интерфейса;
- добавить дополнительные блокированные порты для мониторинга подключений;
- автозапуск файрвола при старте сервера на Linux.
Допустим что у нас на сервере запущены такие сервисы (в скобках используемые порты):
- http, https (80, 443)
- sshd (22)
- ftp (21)
- pop3 (110)
- imap, imap+ssl (143, 993)
- smtp (25)
- mysql (3306)
- firebird (3050)
- postgresql (5432)
- samba (139, 137, 138, 445)
У вас на реальном сервере может быть запущен другой набор служб и со своими настройками, поэтому желательно просмотреть все порты, которые открыты для приема соединений на сетевом интерфейсе что смотрит в мир (интернет) и проанализировать их доступность.
Для просмотра списка портов которые прослушиваются на сетевых интерфейсах в Linux можно воспользоваться командой:
netstat -na | grep LISTEN
В качестве примера вывода команды разберем тот что на рисунке ниже:
Рис. 1. Список открытых портов, отображаемый при помощи команды netstat с фильтром.
Здесь мы видим что:
- порты 3306, 25, 587, 953 открыты только на локальном интерфейсе (127.0.0.1);
- порты 139 и 445 открыты на всех интерфейсах (0.0.0.0);
- порт 53 кроме локального (127.0.0.1) интерфейса также открыт на наружном интерфейсе (4.44.444.44);
- порт 22 прослушивается на всех интерфейсах в протоколе IPv4(0.0.0.0) и IPv6(:::);
- порт 80 прослушивается на всех интерфейсах в протоколе IPv6 (:::).
Примечание: IP-адрес в примере в таком пространстве IPv4 как 4.44.444.44 не существует, поскольку сегмент 444 в IP адресе не допустим (255 max).
Исходя из того какие службы должны быть доступны извне через интернет, а какие нет, будем строить список правил для будущего файрвола.
Многие приложения (например сервер баз данных PostgreSQL) позволяют в своих настройках указать список интерфейсов на которых они смогут открыть свой порт для прослушивания, а по умолчанию прослушиваются все интерфейсы или только локалхост (127.0.0.1). Поэтому, оставив приложение с настройками по умолчанию и не настроив Firewall вы подвергаете свой сервер опасности взлома и потери данных в следствии действий злоумышленников и вредоносных программ.
Допустим что на сервере должны быть доступны через интернет такие службы как: ssh(22), httpd(80, 443). Все остальные службы работают и связываются через локальный интерфейс (localhost, 127.0.0.1) и также доступны с настройками по умолчанию для других интерфейсов(например при подключении к серверу через свой VPN). Таким образом мы разрешаем то что явно нужно и запрещаем все ненужное для посторонних глаз снаружи из сети Интернет.
Скрипт файрвола
Перед тем как привести полный листинг скрипта хочу рассказать о том как сделать автозапуск правил при старте Linux, а также возможность управления файрволом - Start, Stop.
В Linux есть такая папка как /etc/init.d/ - здесь лежат специально созданные и настроенные скрипты, которые выполняются при старте системы. Для скриптов может быть определен порядок старта, ожидание других служб перед запуском и т.п. Это делает данную папку идеальным местом для запуска нашего скрипта-файрвола.
Итак, откроем пустой файл для редактирования командой:
nano /etc/init.d/iptables
Теперь скопируем в файл листинг скрипта, что предоставлен ниже:
#!/bin/sh
### BEGIN INIT INFO
# Provides: iptables
# Required-Start: $all
# Required-Stop: $all
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# X-Interactive: true
# Short-Description: Apply/clear iptables rules
### END INIT INFO
IPTABLES=/sbin/iptables
iface=eth0
case "" in
start)
echo "Starting iptables..."
# Flushing rules
$IPTABLES -F
$IPTABLES -X
# Setting up default policies
$IPTABLES -P INPUT ACCEPT
$IPTABLES -P OUTPUT ACCEPT
$IPTABLES -P FORWARD ACCEPT
# Closing all, except 80, 443, 22 ports
# Deny FTP (21)
$IPTABLES -A INPUT -p tcp -i $iface --dport 21 -j DROP
# Deny POP3 (110)
$IPTABLES -A INPUT -p tcp -i $iface --dport 110 -j DROP
# Deny IMAP (143)
$IPTABLES -A INPUT -p tcp -i $iface --dport 143 -j DROP
# Deny IMAP+SSL (993)
$IPTABLES -A INPUT -p tcp -i $iface --dport 993 -j DROP
# Deny MYSQL (3306)
$IPTABLES -A INPUT -p tcp -i $iface --dport 3306 -j DROP
# Deny FIREBIRD (3050)
$IPTABLES -A INPUT -p tcp -i $iface --dport 3050 -j DROP
# Deny POSTGRESQL (5432)
$IPTABLES -A INPUT -p tcp -i $iface --dport 5432 -j DROP
# Deny SAMBA (139)
$IPTABLES -A INPUT -p tcp -i $iface --dport 139 -j DROP
# Deny SAMBA (138)
$IPTABLES -A INPUT -p tcp -i $iface --dport 138 -j DROP
# Deny SAMBA (137)
$IPTABLES -A INPUT -p tcp -i $iface --dport 137 -j DROP
# Deny SAMBA (445)
$IPTABLES -A INPUT -p tcp -i $iface --dport 445 -j DROP
;;
stop)
echo "Stopping iptables..."
# Clearing rules
$IPTABLES -F
$IPTABLES -X
# Setting default politics to Accept
$IPTABLES -P INPUT ACCEPT
$IPTABLES -P OUTPUT ACCEPT
$IPTABLES -P FORWARD ACCEPT
;;
*)
echo "Usage: /etc/init.d/iptables {start|stop}"
exit 1
;;
esac
exit 0
Перед сохранением нужно исправить в скрипте значение переменной iface=eth0, в которой указано имя интерфейса который подключен к миру (интернет).
Примечание: для сохранения и выхода из редактора NANO нужно нажать CTRL+X, а потом на запрос о сохранении - Y и Ентер.
Список всех сетевых интерфейсов на Linux-сервере можно посмотреть в новой консоли используя команду:
ifconfig -a
После сохранения изменений в нашем скрипте сделаем его запускаемым и добавим в очередь автозапуска следующими командами:
chmod 755 /etc/init.d/iptables
update-rc.d iptables defaults
Все готово!
Принцип работы скрипта
Прежде чем перейти к запуску и тестированию скрипта распишу немного структуру скрипта.
В шапке есть блок что начинается строкой "### BEGIN INIT INFO" и заканчивается строчкой "### END INIT INFO". В этом блоке указаны настройки инициализации с которыми данный скрипт будет запускаться, а также краткое описание скрипта.
Дальше создаем переменные IPTABLES и iface в которых указываем полный путь к бинарному файлу iptables и имя наружного сетевого интерфейса, соответственно.
После идет основная часть скрипта - условная конструкция на два условия: start и stop.
В первой секции мы подготавливаем и запускаем файрвол. Очищаем правила и устанавливаем политики по умолчанию для разрешения трафика во всех направлениях.
Остальные строчки в секции состоят из правил запрета, где параметры имеют вот такие значения:
- -A INPUT - применять для цепочки входящего трафика;
- -p tcp - применять для протокола TCP. Если для сервиса используется протокол UDP то нужно использовать -p udp;
- -i $iface - применять для имени интерфейса что помещено в переменную $iface;
- --dport 22 - применять если использован указанный порт назначения (destination port), в данном случае 22 (ssh);
- -j DROP - операция, которую нужно произвести с с пакетом, в данном случае отвергаем его (дропаем).
Во второй секции мы очищаем все правила файрвола и возвращаем политики по умолчанию (разрешить все).
В конце exit 0 завершает выполнение скрипта с позитивным результатом (без ошибок).
Запуск и работа
Теперь перейдем к использованию нашего скрипта. Для проверки автозапуска скрипта можно перезагрузить сервер, а можно запустить скрипт вручную используя команду:
service iptables start
Соответственно для останова скрипта-файрвола нужно выполнить команду:
service iptables stop
Чтобы посмотреть список правил нашего файрвола и количество пакетов которое попало в них, используем команду:
iptables -nvL
Пример вывода команды рассмотрим ниже:
Здесь мы можем видеть что на порт 3306 (сервер баз данных MySQL) из интернета кто-то пробовал подключиться примерно 719 раз (отправлено 719 пакетов общим размером 29116 байт). Всего из интернета (цепочка INPUT) на сервер пришло 96 млн пакетов, а размер принятых данных - 21 ГигаБайт. Также из сервера было отправлено 117 млн пакетов, а размер отправленных данных составляет 117 ГигаБайт.
Вот такие вот полезные данные, могут пригодиться как для мониторинга обьемов трафика, так и за тем на какие порты (службы) охотятся снаружи на вашем сервере.
При отладке файрвола может быть удобно и полезно выводить данную команду многократно с небольшой задержкой. Благодаря огромному количеству утилит и программ в Linux это осуществить очень легко:
watch -n 1 iptables -nvL
Здесь используется утилитка под названием "watch" которая в качестве параметра -n принимает значение задержки в секундах( в данном примере 1 секунда), а последний аргумент команды это название программы которую нужно выводить на экран с установленной периодичностью.
Для тестирования файрвола и вывода этой команды можно с другого сервера или компьютера сделать попытку подключения к запрещенному в нашем скрипте порту. К примеру подключимся к серверу на порт 3306:
telnet your_server_ip_or_hostname 3306
Для любителей Windows в этих целях также можно использовать утилиту TELNET.
Примечание: в Windows7+ утилита telnet по умолчанию не установлена, устанавливаем ее вот так: Панель управления - Программы и компоненты - Включение или отключение компонентов Windows - TELNET.
Заключение
Ну вот, пожалуй и все. Вы получили базовые знания и усвоили простые команды для работы с файрволом iptables под операционной системой Линукс. Данный скрипт можно модифицировать для более сложных алгоритмов защиты сетевого трафика. Все реализовано просто и работает как часы!
Полезные ресурсы по iptables:
- Викиучебник - структура, примеры, полезные ссылки и т.п;
- IPTABLES - MAN страничка на английском языке;
- man iptables - команда в консоли, документация которая всегда под рукой.
Я попробовал установить на raspberry pi3 не заработало. Выдало ошибку Job for iptables.service failed. See 'systemctl status iptables.service' and 'journalctl -xn' for details.
sergey, для построения файрвола с автозапуском в Raspbian Jessie, Raspbian Stretch или более новой версии GNU/Debian Linux для Raspberry Pi 2 и 3, лучше воспользоваться таким инструментом как systemd.
Вот статья с более современным подходом, где предоставлен скрипт универсального файрвола для IPv4 и IPv6.