Содержание
Особенности виртуальных маршрутизаторов и файерволов
Чаще всего программные сетевые устройства создаются в виде виртуальных машин. Использование виртуальных маршрутизаторов и файерволов дает ряд преимуществ:
1. Стоимость. Программный маршрутизатор можно сделать самому и совершенно бесплатно. Имеются и брендовые решения от Cisco, Juniper и др., но и они, как правило стоят дешевле своих аппаратных аналогов.
2. Удобство в управлении и автоматизации.
3. Снижение энергопотребления за счет виртуализации.
4. Гибкость. Например, мы можем выделить виртуальному маршрутизатору столько ресурсов сколько требуется в данный момент.
Но есть и нюансы в виртуальных маршрутизаторах. Один из самых важных - мы не можем полагаться в таких «устройствах» на состояние сетевого интерфейса. В виртуальных машинах виртуальный сетевой интерфейс всегда подключен и никогда не «падает». Теперь представим себе, что у нас есть два виртуальных маршрутизатора созданных на базе ОС Linux, каждый из которых является шлюзом в Интернет, и нам необходимо проверять возможность доступа в Интернет на таких маршрутизаторах.
Условия такие:
• Использовать состояние сетевого интерфейса мы не можем. Маршрутизаторы виртуальные.
• Протокола маршрутизации между маршрутизаторами провайдеров и нами нет.
• Маршрутизаторы анонсируют маршрут по умолчанию внутрь нашей сети посредством протокола OSPF, запущенного демоном FRR.
• Для связи с Интернетом используется статический маршрут по умолчанию.

Если бы это были виртуальные маршрутизаторы Cisco, то проблема решалась бы достаточно просто за счет настройки IP SLA. Но у нас Linux. Поэтому решением является создание своего сервиса проверки доступности интернета похожего на IP SLA.
Создание сервиса проверки доступности интернета
Сначала надо решить, как мы будем проверять доступность Интернета. Самый простой вариант - посылать периодически ICMP эхо запрос на шлюз провайдера, проверяя его доступность. Для этого мы напишем скрипт с именем /usr/local/sbin/pinggw:
#!/bin/bash
# Определяем переменные
# что пингуем передается как аргумент скрипта
IP=$1
# куда записываем результат
STATEFILE=/tmp/target.$IP.status
# Непосредственно проверка. Пингуем 3 раза, т. к.
# 1 раз случайность, 2 тенденция, а 3 закономерность.
# В переменной RSLT будет 0 если хоть 1 раз ответ пришел
# и 1 если ни одного ответа не было получено.
RSLT=$(/bin/ping -c 3 -q -i 1 $IP | grep -c '100% packet loss')
# Записываем результат проверки в журнал
echo "State of $IP is $RSLT" | logger -p local0.info
# Создаем файл с результатами проверки, если его нет
[ -f $STATEFILE ] || echo 0 > $STATEFILE
# Проверяем не изменилось ли состояние
if [ "$(cat $STATEFILE)" -eq 0 -a "$RSLT" -eq 1 ]
then
# Если связь пропала 0->1, то пишем в лог
echo "$IP is NOT reachable now" | logger -p local0.warn
# и запускаем скрипт, который удаляет анонс 0/0
vtysh -c 'configure terminal' -c 'router ospf' -c 'no default-information originate' -c end -c write
elif [ "$(cat $STATEFILE)" -eq 1 -a "$RSLT" -eq 0 ]
then
# Если связь восстановилась 1->0, то пишем в лог
echo "$IP is reachable now" | logger -p local0.warn
# и запускаем скрипт, который восстанавливает анонс 0/0
vtysh -c 'configure terminal' -c 'router ospf' -c 'default-information originate metric-type 1 metric 100' -c end -c write
# Записываем результат последнего теста в файл состояния
echo $RSLT > $STATEFILE
exit 0
Далее такой скрипт нужно периодически запускать. Для этого создаем в планировщике задач CRON (например в файле /etc/cron.d/inet_check) что-то подобное:
*/2 * * * * root /usr/local/sbin/pinggw 203.0.113.1
Выше описан запуск нашего скрипта каждые 2 минуты, где 203.0.113.1 это адрес маршрутизатора провайдера.
Описанное выше решение не является идеальным. К примеру, может быть такая ситуация, что шлюз доступен, но далее выход в Интернет не работает. Или, как показывает практика, провайдер может блокировать слишком большое, по его мнению, количество ICMP запросов. Одним из вариантов решения таких проблем может быть отправка DNS запросов к публичным DNS серверам, как альтернатива пинга или как дополнение к пингу:
RSLT=$(/bin/ping -c 3 -q -i 1 $IP | grep -c '100% packet loss')
# Модификация скрипта с дополнительной проверкой DNS
if [ ${RSLT} -ne 0 ]
then
DNS1=$(dig @8.8.8.8 google.com | grep -c 'no servers could be reached')
DNS2=$(dig @77.88.8.8 yandex.ru | grep -c 'no servers could be reached')
DNS3=$(dig @1.1.1.1 cloudflare.com | grep -c 'no servers could be reached')
# Вычисление общего итога проверки DNS запросов
RSLT=$((RSLT*DNS1*DNS2*DNS3))
fi
Выше в скрипте после неудачного пинга шлюза по умолчанию идет опрос публичных DNS серверов. Результат проверки будет удачный, если хотя бы один DNS сервер будет доступен. Если убрать строки if [ ${RSLT} -ne 0 ]; then ; fi, то каждый раз вместе с пингом шлюза будет проводиться и проверка доступности DNS.
Запись результата в файл, помимо возможности определять факт изменения состояния, дает еще один бонус. Мы с помощью этого файла можем передавать сведения о доступности Интернета на маршрутизаторе в систему мониторинга, например, в Заббикс. Тогда для Заббикса нам надо будет определить пользовательский параметр в конфигурации агента Заббикс:
UserParameter=gw.status[*],/bin/cat /tmp/target.$1.status
А с помощью параметра:
UserParameter=gw.discovery,/usr/sbin/ip -j route show default
еще и обнаруживать адрес шлюза по умолчанию на маршрутизаторе с помощью механизма LLD.
Файл с шаблоном Забикса (lld_gateways.xml) прикреплен к статье ниже. Так же к статье прикреплены и другие файлы: со скриптом и конфигурацией для Заббикс агента.
Описанное выше решение по мониторингу доступности Интернета подойдет не только для программных маршрутизаторов на основе ОС Linux общего назначения, но и для специализированных Linux, таких как Vyos или Openwrt. В таких системах будет своя специфика, но структура основного скрипта для проверки состояния доступности Интернета будет та же. Отличаться будут только строки с реакцией на изменение состояния доступности.
Будьте в курсе всех событий
Подпишись на рассылку актуальных новостей
и читай нас в соц. сетях