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

Предисловие

ISP Redundancy - механизм обеспечения избыточности провайдера, суть которого заключается в следующем (рассмотрим только вариант Active/Backup):

  • Шлюз безопасности/кластер шлюзов имеет два подключения к внешней сети (Primary/Backup).

  • На каждом из подключений мониторится состояние интерфейса, дополнительно же можно указать внешний ресурс, потерю доступности которого можно считать потерей связи с провайдером.

  • В зависимости от указанных приоритетов подключенных провайдеров, потеря Primary ISP Link автоматически включает в работу резервный, меняет маршрут по умолчанию. Внешние ресурсы доступны, но уже через другого провайдера.

Схема сети, для которой все это планировалось претворить в жизнь, обобщенно имеет следующий вид:

Что оказалось не так?

Перекопав все, что удалось найти в sk-шках по ISP Redundancy, ветках форумов, чате комьюнити в Telegram, самым жизнеспособным вариантом оказался только стенд, без кластера, с адресами на физических интерфейсах. Чем больше было попыток приблизить стенд к реальной схеме сети, тем сложнее начиналось заставить механизм работать корректно, да и работать в принципе. Вот основные причины моего случая, которые похоронили надежду на адекватную реализацию:

  • Все интерфейсы кластера - vlan-интерфейсы, являющиеся членами bond'ов. Исключение только Sync и Mgmt. Толковых пояснений на этот случай найти не удалось.

  • Из-за ограниченности адресного пространства некоторых подсетей (в том числе и подсетей провайдеров), IP членов кластера и сам виртуальный кластерный адрес находятся в разных подсетях.

  • Пункт выше приводит к тому, что переключить атрибут "perform_cluster_hide_fold" в '0' не представляется возможным. Суть в том, что он, будучи включен, автоматически транслирует исходящие от членов кластера соединения за виртуальным адресом, а входящие соединения NAT'ятся в адрес соответствующего члена кластера.

Начнем с начала

Оставив попытки справиться с заложенным вендором функционалом, было решено сделать все, что делает механизм ISP Redundancy, но только руками и по своему удобным. В жизнь была воплощена следующая схема:

  1. Выбираем ip-адреса для мониторинга

    У CheckPoint есть функция 'IP Reachability Detection', смысл который понятен из самого названия. По дефолту, для ICMP, интервал пакетов составляет 3 секунды. При желании и необходимости - можно увеличить или уменьшить (возможный диапазон: 1-100 sec). Так же настраивается и счетчик пакетов, по достижению которого адрес считается недоступным. Добавим два адреса (в моем случае - 8.8.4.4 и 4.2.2.2), которые часто (или не часто, но) используются для проверки работоспособности внешней сети.

    CloningGroup:CP‑cluster> set ip-reachability-detection ping address 4.2.2.2 enable-ping on 
    CloningGroup:CP‑cluster> set ip-reachability-detection ping address 8.8.4.4 enable-ping on
    То же в web-консоли Gaia
    То же в web-консоли Gaia
  2. Настройка PBR

    Для того, чтобы выбранные нами адреса мониторились через разных провайдеров, настроим для каждого из них Action Table и Policy Rules:

    # Action Tables
    CloningGroup:CP‑cluster> set pbr table ISP1 static‑route default nexthop gateway address <ISP1_gw_ip> priority 1 
    CloningGroup:CP‑cluster> set pbr table ISP2 static‑route default nexthop gateway address <ISP2_gw_ip> priority 1
    
    # Policy Rules
    CloningGroup:CP‑cluster> set pbr rule priority 1 match to 4.2.2.2/32 
    CloningGroup:CP‑cluster> set pbr rule priority 1 action table ISP1
    CloningGroup:CP‑cluster> set pbr rule priority 2 match to 8.8.4.4/32
    CloningGroup:CP‑cluster> set pbr rule priority 2 action table ISP2
    Если вдруг не в clish
    Если вдруг не в clish
  3. Настройка маршрута по умолчанию

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

    # Для ISP1
    CloningGroup:CP‑cluster> set static-route default nexthop gateway address <ISP1_gw_ip> priority 1 on 
    CloningGroup:CP‑cluster> set static-route default nexthop gateway address <ISP1_gw_ip> monitored-ip 4.2.2.2 on 
    CloningGroup:CP‑cluster> set static-route default nexthop gateway address <ISP1_gw_ip> monitored-ip-option fail-all
    
    # Для ISP2
    CloningGroup:CP‑cluster> set static-route default nexthop gateway address <ISP2_gw_ip> priority 2 on 
    CloningGroup:CP‑cluster> set static-route default nexthop gateway address <ISP2_gw_ip> monitored-ip 8.8.4.4 on 
    CloningGroup:CP‑cluster> set static-route default nexthop gateway address <ISP2_gw_ip> monitored-ip-option fail-all
    Последний раз не CLI
    Последний раз не CLI
  4. Dynamic Objects и Scheduler

    В планируемой реализации имеется в виду, что пользовательские сети, серверная группа и почтовый сервис в отдельности транслируются наружу с различных адресов (так исторически сложилось удобнее для мониторинга и администрирования), использование автоматических правила NAT в настройках самого шлюза, или же включение опции NAT на объектах через SmartConsole - непривлекательно. Мы будем использовать Dynamic Object, значения которого может быть настроено и изменено непосредственно на самом шлюзе/кластере. Данная вещица не требует внесения изменения через SmartConsole, реинсталяции политики, соответственно, занимает меньше времени.

    Однако, первоначально на сервере управления достаточно создать необходимый перечень динамических объектов, добавить или отредактировать правила (Access Rules и/или NAT) с их использованием, после чего установить политику на целевой шлюз, чтобы уже на нем назначить объектам их значения.

    Кратко по команде dynamic_objects:

    #Вывести информацию о динамических объектах:
    dynamic_objects -l
    
    #Вывести информацию о динамических объектах:
    dynamic_objects -n <NAME> -r <From_IP> <To_IP> -a
    
    #Обновить значение объекта (создать, если объект не существует):
    dynamic_objects -u <NAME> -r <From_IP> <To_IP>
    
    #Удалить объект:
    dynamic_objects -do <NAME>

    Подробнее в документации вендора.

    Для того, чтобы смена маршрута по умолчанию меняла значение динамических объектов, оптимальным показалось написать скрипт, запускаемый crontab'ом.

    Job Scheduler в данном случае не подойдет, так как не позволяет указать периодичность чаще, чем раз в день. В свою очередь, работа с заданиями cron у CheckPoint не подразумевается из-под предустановленной учетной записи 'admin', так как задания слетают в случае перезагрузки шлюза. Поэтому была создана отдельная учетная запись, от имени которой добавлена задача по запуску скрипта.

    Содержимое же скрипта выглядит так:

    #!/bin/bash 
    # Импорт переменных окружения для вызова команд Gaia OS, а также других переменных,
    # связанных с проверкой значений маршрута и Dynamic Objects
    source /opt/CPshrd-R80.30/tmp/.CPprofile.sh
    source /home/dynamic/dynamic.env
    
    #Получаем значения маршрута по умолчанию и range из наших объектов
    default_route=$(eval '/sbin/ip route' | grep default | awk '{print $3}')
    users=$(eval "dynamic_objects -l" | grep -A 1 -w "USERS" | awk 'NR==2 {print $4}')
    post=$(eval "dynamic_objects -l" | grep -A 1 -w "POST" | awk 'NR==2 {print $4}')
    server=$(eval "dynamic_objects -l" | grep -A 1 -w "SERVER" | awk 'NR==2 {print $4}')
    
    # Проверяем соответствие дефолтного маршрута и значений динамических объектов
    if  [ "$default_route" = "$ISP_1_ip" ]; then
        if [ "$users" = "$ISP_1_users" ] && [ "$server" = "$ISP_1_server" ] && [ "$post" = "$ISP_1_post" ]; then
            exit
        else
            # если значения объектов не в той же сети, что и default gateway, то  
            # приводим все к одному виду, пишем сообщение о произошедшем в локальный файл
            # и алертим себе в Telegram
            eval "dynamic_objects -u USERS -r  $ISP_1_users $ISP_1_users -a"
            eval "dynamic_objects -u SERVER -r  $ISP_1_server $ISP_1_server -a"
            eval "dynamic_objects -u POST -r  $ISP_1_post $ISP_1_post -a"
            echo "Switching to $ISP_1_name at $(date)" >> /opt/scripts/dynamic_log.txt
            curl_cli -k -X POST "https://api.telegram.org/bot$TG_TOKEN/sendMessage" -d "chat_id=$CHAT_ID&message_thread_id=6&text= %F0%9F%94%8C Default route was switched:%0ANew value: $ISP_1_name%0ATime: $(date "+%H:%M:%S %d.%m.%y")"
        fi
    # Аналогичная проверка в случае, если активным является провайдер ISP-2
    elif [ "$default_route" = "$ISP_2_ip" ]; then
        if [ "$users" = "$ISP_2_users" ] && [ "$server" = "$ISP_2_server" ] && [ "$post" = "$ISP_2_post" ]; then
            exit
        else
            eval "dynamic_objects -u USERS -r  $ISP_2_users $ISP_2_users"
            eval "dynamic_objects -u SERVER -r $ISP_2_server $ISP_2_server"
            eval "dynamic_objects -u POST -r  $ISP_2_post $ISP_2_post -a"
            echo "Switching to $ISP_2_name  at $(date)" >> /opt/scripts/dynamic_log.txt
            curl_cli -k -X POST "https://api.telegram.org/bot$TG_TOKEN/sendMessage" -d "chat_id=$CHAT_ID&message_thread_id=6&text= %F0%9F%94%8C Default route was switched:%0ANew value: $ISP_2_name%0ATime: $(date "+%H:%M:%S %d.%m.%y")"
        fi
    fi

    Пройдя успешную обкатку на стенде, то же было проделано и на боевом кластере.

    Результат

    Имитация потери связи с провайдером проводилась через включение deny-правил на граничном маршрутизаторе для ICMP до 4.2.2.2, который назначен адресом мониторинга для ISP-1. С учетом, что временной интервал для отправки ICMP был выставлен в 1 секунду, все упирается в частоту отработки чудо-скрипта. В пределах статьи остановимся на том, что скрипт отрабатывает каждую минуту.

    Итак, при потере связи с ISP-1 видим, что наши динамические объекты автоматически поменяли свое значение на диапазоны сети второго провайдера:

    Ну и оперативно получаем отстук в чатик мониторинга:

В конечном итоге, мы смогли настроить ISP Redundancy без использования "ISP Redundancy"

P.S.

Не исключаю, что достижение определенных условий позволило бы раскрутить штатный функционал без вышеописанного, но одним из факторов существования данного способа стало как освоение сетевых технологий, так и обучение работы с CheckPoint по «бразильской системе». В общем, буду рад конструктивной критике и обмену опытом:‑)

Комментарии (0)