Категории публикаций
Подписка на рассылку по Email
новости (подписчиков: 3)
комментарии (подписчиков: 2)

Отменить подписку
Популярные публикации
Интересный опрос
Вы используете криптовалюту Bitcoin?

Да, давно использую
Начал использовать
Интересуюсь
Нет, не использую
А что такое Bitcoin?
Поблагодарить автора
donate
1B4ZZ2PXUd9E7AqEB82AqFnkpk2bt5hQG7

Скрипт фаервола IPTables для ipv4 и ipv6 с автозагрузкой в Linux (systemd)

Размещено в категории: Linux

Простой и надежный скрипт для загрузки правил фаервола IPTables в GNU Linux используя сценарий авто-запуска для демона инициализации systemd (новая замена для /sbin/init). Правила загружаются и работают как для протокола IPv4, так и для IPv6.

Содержание статьи:

Немного о systemd и IPv6

Раньше, в одной из статей по Linux, я уже описывал создание простого фаервола для защиты сервера и мониторинга количества "вредных" сетевых пакетов. Для авто-запуска скрипта мы размещали его в папке "/etc/init.d", а также добавляли в автостарт системных процессов используя команду "update-rc.d".

Время идет, технологии меняются и в некоторых дистрибутивах GNU Linux на смену старому демону инициализации /sbin/init пришел новый, более мощный - systemd. Кто-то встретил такое нововведение с недовольством, а кто-то поковырявшись оценил преимущества и новые мощные инструменты.

Также время наложило свой отпечаток и на адресное пространство протокола IPv4, которое уже считается исчерпанным, а внешние IPv4-адреса для арендованных VPS/VDS уже не раздают так просто по несколько штук в одни руки, как это было раньше.

Поскольку я работаю с системами на основе Debian/Ubuntu то мне пришлось познакомиться с новым systemd, а также учесть наличие внешних IPv6-адресов на интерфейсах моих серверов и рабочих станций. Сейчас многие провайдеры при аренде у них VPS/VDS серверов предоставляют один или два IPv4-адреса и целую подсеть адресов IPv6.

К примеру при аренде даже самого бюджетного VPS у Ramnode (15$ в год = 1,25$ в месяц) в придачу к адресу IPv4 вам выделят целую подсеть /64, в которой доступно всего-навсего 18,446,744,073,709,551,616 IPv6-адресов!

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

IPTables и IPv6

Многие кто арендовал себе VPS и настраивают базовую защиту на основе IPTables даже не подозревают что те правила, которые загружаются при помощи команды "iptables" действуют только для входящих-исходящих пакетов с протоколом IPv4, а трафик что приходит и уходит по протоколу IPv6 в таком случае вообще никак не фильтруется.

Давайте для примера рассмотрим небольшую историю: человек арендовал VPS в Германии, настроил на нем связку Apache+PHP+MySQL, ну и прикрутил еще MongoDB для хранения 100000+ однотипных документов, которые плодят его проекты.

Сервис баз данных MongoDB по умолчанию принимает соединения на портах 27017 и 28017 для всех интерфейсов на сервере. Админ это знал, лезть в настройки MongoDB он не хотел, поэтому добавил несколько правил для брандмауэра используя команду "iptables", которые заблокируют все входящие соединения что поступают с внешнего интерфейса (интернет), как исключения разрешил только порты 80 и 433 для подключения к веб-серверу Apache.

И казалось бы все сделано верно, беспокоиться нет причины...но не тут то было! После установки Linux из образа который предоставил провайдер, сервер получил два внешних адреса в интернете: один для протокола IPv4, а другой - для IPv6.

Невнимательный админ забыл о наличии второго адреса и о вообще "забил" на протокол IPv6 (казалось-бы кто им пользуется, он не популярный еще и т.п.). Как результат - сервер взломали, затерли документы и натворили других чудес.

Кто и как взломал сервер? - судя по последствиям после взлома сервер взломали скорее всего для забавы, получив доступ к MongoDB по портам 27017 и 28017, используя для этого внешний адрес сервера с протоколом IPv6.

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

Что можно сделать чтобы подобное не повторилось:

  • Отключить на сервере поддержку протокола IPv6, если в нем нет надобности;
  • Настроить брандмауэр для блокировки нежелательных подключений как для IPv4, так и для IPv6.

При работе с брандмауэром IPTables правила для протокола IPv6 нужно загружать используя бинарник "ip6tables", а для протокола IPv4 - используем бинарный файл "iptables". Таким образом для защиты сервера по двум протоколам нужно загрузить два набора правил, которые для каждого из протоколов имеют свои цепочки и таблички.

Отключение IPv6

Если вы все же решили отключить поддержку протокола IPv6 на сервере под управлением Debian/Ubuntu-подобного GNU Linux, то сделать это можно в несколько простых шагов.

Откроем для редактирования файл с настройками sysctl - sysctl.conf:

nano /etc/sysctl.conf

Добавим в самый низ этого файла следующие строчки:

# IPv6
net.ipv6.conf.all.disable_ipv6 = 1
net.ipv6.conf.default.disable_ipv6 = 1
net.ipv6.conf.lo.disable_ipv6 = 1

Заставим sysctl перечитать настройки из файла sysctl.conf:

sysctl -p

Желательно перезагрузить сервер и все перепроверить. Убедиться в отключенном IPv6 можно посмотрев нет ли адресов c данным протоколом в выводе команды:

ifconfig | grep inet6

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

lsmod | grep ipv6

В выводах приведенных двух команд не должны встречаться упоминания "inet6" и "ipv6", то есть вывод должен быть пуст.

Универсальный скрипт брандмауэра для IPv4 и IPv6

Раньше для автоматической загрузки ранее сохраненных правил в IPTables я использовал пакет "iptables-persistent". В новой версии GNU Debian Linux (9.0 - Stretch) этот пакет уже исключен из репозитория. Теперь всю необходимую работу по организации авто-запуска какого-либо сервиса можно сделать вручную средствами systemd.

Для базовой защиты Linux-сервера или рабочей станции в сети интернет по двум протоколам (IPv4 и IPv6) я написал простой скрипт, который будет автоматически стартовать при загрузке системы используя собственный файл-описание для демона инициализации systemd. Набор правил для каждого из протоколов одинаковый и он определяет вот такую фильтрацию пакетов:

  • Весь ЛОКАЛЬНЫЙ трафик (через виртуальный интерфейс lo0) - разрешен;
  • Все ИСХОДЯЩИЕ пакеты - разрешены;
  • ВХОДЯЩИЕ пакеты, которые относятся к уже установленным соединениям (established) - разрешены;
  • Все остальные ВХОДЯЩИЕ пакеты - логируются и отбрасываются (drop);
  • Все пакеты с перенаправлением (политика forward, для включенной маршрутизации) - логируются и отбрасываются (drop);
  • Блокировка пакетов, которые используются для "тихого" сканирования портов.

Таким образом, мы сможем отправлять с машины любые пакеты (http, ftp, ssh, ping и другие) и получать ответные на них пакеты (что относятся к тому же соединению). Все пакеты что будут приходить снаружи на сервер без предварительно установленного соединения будут писаться в лог системы (смотрим используя journalctl) и отбрасываться.

Такой набор правил отлично подойдет для рабочей станции, удаленный доступ к которой не планируется.

Создадим файл под именем "systemd-iptables.sh" в папке для пользовательских скриптов "/usr/local/sbin/", для этого выполним команду:

nano /usr/local/sbin/systemd-iptables.sh

Скопируем приведенный ниже исходный код скрипта в окно редактора:

#!/bin/sh
# IPTables (ipv4+ipv6) init script for systemd
# 2016 by Ph0en1x (http://ph0en1x.net)

IP4TABLES_BIN=/sbin/iptables
IP6TABLES_BIN=/sbin/ip6tables

# Flush active rules, flush custom tables, and set default policy
Flush_Rules () {
	if [ $1 = "ipv6" ]; then
		IPTABLES=$IP6TABLES_BIN
	else
		IPTABLES=$IP4TABLES_BIN
	fi
	$IPTABLES --flush
	$IPTABLES -t nat --flush
	$IPTABLES -t mangle --flush
	$IPTABLES --delete-chain
	$IPTABLES -t nat --delete-chain
	$IPTABLES -t mangle --delete-chain
	# Set default policies to ACCEPT
	$IPTABLES -P INPUT ACCEPT
	$IPTABLES -P FORWARD ACCEPT
	$IPTABLES -P OUTPUT ACCEPT
}

# Loading rules
Load_Rules () {
	if [ $1 = "ipv6" ]; then
		IPTABLES=$IP6TABLES_BIN
		IPV='IPv6'
	else
		IPTABLES=$IP4TABLES_BIN
		IPV='IPv4'
	fi
	# Flush
	Flush_Rules $1
	# Localhost
	$IPTABLES -A INPUT  -i lo -j ACCEPT
	$IPTABLES -A OUTPUT -o lo -j ACCEPT
	# Default policies
	$IPTABLES -P INPUT DROP
	$IPTABLES -P FORWARD DROP
	$IPTABLES -P OUTPUT ACCEPT
	# Input filter chain
	$IPTABLES -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
	$IPTABLES -A INPUT -j LOG --log-prefix "${IPV}Tables INPUT Dropped:"
	# Forward chain
	$IPTABLES -A FORWARD -j LOG --log-prefix "${IPV}Tables FORWARD Dropped:"
	# disable furtive port scanning
	$IPTABLES -N PORT-SCAN
	$IPTABLES -A PORT-SCAN -p tcp --tcp-flags SYN,ACK,FIN,RST RST -m limit --limit 1/s -j RETURN
	$IPTABLES -A PORT-SCAN -j DROP
	
}

case $1 in
	start)
		Load_Rules ipv4
		Load_Rules ipv6
		echo "IPTables rules loaded."
		;;
	stop)
		Flush_Rules ipv4
		Flush_Rules ipv6
		echo "IPTables rules flushed."
		;;
	restart)
		Flush_Rules ipv4
		Flush_Rules ipv6
		Load_Rules ipv4
		Load_Rules ipv6
		echo "IPTables rules reloaded."
		;;
	*)
		echo "Usage: systemctl {start|stop|restart} iptables.service"
		exit 1
esac

exit 0

Для использования данного скрипта на удаленном сервере (VPS/VDS) нужно открыть возможность принимать входящие соединения, как минимум на порте 22 (SSH, для администрирования). К примеру, для пропускания входящих пакетов на порты 80, 443 и 22 нужно добавить в скрипт ( после правила  "-A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT") следующие строчки:

$IPTABLES -A INPUT -p tcp --dport 22 -j ACCEPT
$IPTABLES -A INPUT -p tcp --dport 80 -j ACCEPT
$IPTABLES -A INPUT -p tcp --dport 433 -j ACCEPT

Также для открытия данных портов можно добавить всего одно правило:

$IPTABLES -A INPUT -p tcp -m state --state NEW -m multiport --dports ssh,http,https -j ACCEPT

Если у вас на сервере несколько сетевых интерфейсов и входящие пакеты на порты 80, 443 и 22 должны проходить только на один из них, то можно указать в правиле интерфейс. Например для сетевого интерфейса "venet0" разрешающее правило будет выглядеть следующим образом:

$IPTABLES -A INPUT -p tcp -i venet0 -m state --state NEW -m multiport --dports ssh,http,https -j ACCEPT

После правки и сохранения содержимого скрипта systemd-iptables.sh ему нужно дать права на выполнение, для этого выполним команду:

chmod +x /usr/local/sbin/systemd-iptables.sh

Теперь перейдем к созданию "сервисного" файла для systemd. В данном файле мы опишем назначение, команды управления и условия запуска нашего скрипта.

nano /etc/systemd/system/iptables.service

Разместим в нем вот такой текст:

[Unit]
Description=IPTables rules
After=network.target

[Service]
Type=oneshot
ExecStart=/usr/local/sbin/systemd-iptables.sh start
ExecStop=/usr/local/sbin/systemd-iptables.sh stop
ExecReload=/usr/local/sbin/systemd-iptables.sh restart
RemainAfterExit=yes

[Install]
WantedBy=multi-user.target

Содержимое данного файла очень напоминает содержимое INI-файлов в Windows. В разделе Unit объявлено описание нового демона (Description), а также название группы демонов (сетевая подсистема - network.target) после инициализации которой должен стартовать наш ново-созданный SH-скрипт. В разделе "Service" описаны опции для запуска и управления демоном. Как видим, здесь мы вызываем наш скрипт с правилами файрвола, передавая ему в качестве аргументов: start, stop, restart.

После сохранения содержимого файла iptables.service мы можем проверить все ли в порядке с его синтаксисом, для этого выполним команду:

systemctl status iptables.service

Если все ОК то укажем systemd что нужно разрешить запуск демона iptables.service:

systemctl enable iptables.service

Теперь мы можем перезагрузить ОС для авто-запуска скриптов или же запустить наш сервис вручную:

systemctl start iptables.service

Полезные инструменты для IPv4 и IPv6

Для управления и мониторинга состояния iptables.service, а также для просмотра правил IPTables (IPv4 и IPv6) используем следующие команды:

systemctl start iptables.service
systemctl stop iptables.service
systemctl restart iptables.service
systemctl status iptables.service
iptables -nvL
ip6tables -nvL

Наблюдать за попаданием пакетов в правила брандмауэра удобно используя утилитку "watch":

watch -n 1 iptables -nvL
watch -n 1 ip6tables -nvL

Пропинговать хосты для каждого из протоколов можно вот так (пингуем публичные DNS-сервера Google):

ping 8.8.8.8
ping6 2001:4860:4860::8888

Смотрим состояние сокетов используя утилиту ss (socket stats), выведем TCP-сокеты которые прослушиваются (listening), а также информацию о процессах которые их открыли для каждого из протоколов IPv4 и IPv6 по отдельности:

ss -tlnp -f inet
ss -tlnp -f inet6

То же самое только для UDP-сокетов:

ss -ulnp -f inet
ss -ulnp -f inet6

Наблюдаем за TCP и UDP портами под номером 44444 на машинах с интернет-адресами IPv4 и IPv6 (используем nmap):

watch -n 5 "nmap -P0 -sU -p44444 123.123.123.1"
watch -n 5 "nmap -6 -P0 -sU -p44444 2504:fd01:1002:81::6"

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

Заключение

Используя приведенный скрипт для брандмауэра можно защитить свой десктоп или выделенный сервер от вторжений снаружи по протоколам IPv4 и IPv6. Он предельно простой и может быть модифицирован под ваши нужды. Демон инициализации systemd имеет очень широкие возможности и содержит целый ряд мощных инструментов.

 (5/5) голосов: 2   просмотров: 271


Тематика:  linux  iptables  firewall


Добавить комментарий captcha